ddraw/tests: Add a small test for redundant mode setting calls.
[wine/multimedia.git] / dlls / ddraw / tests / d3d.c
blobe301fff44f36801f2a01d7b1d3077c72bbcba01c
1 /*
2 * Some unit tests for d3d functions
4 * Copyright (C) 2005 Antoine Chavasse
5 * Copyright (C) 2006 Stefan Dösinger for CodeWeavers
6 * Copyright (C) 2008 Alexander Dorofeyev
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #define COBJMACROS
25 #include <assert.h>
26 #include "wine/test.h"
27 #include "initguid.h"
28 #include "ddraw.h"
29 #include "d3d.h"
30 #include "unknwn.h"
32 static LPDIRECTDRAW7 lpDD = NULL;
33 static LPDIRECT3D7 lpD3D = NULL;
34 static LPDIRECTDRAWSURFACE7 lpDDS = NULL;
35 static LPDIRECTDRAWSURFACE7 lpDDSdepth = NULL;
36 static LPDIRECT3DDEVICE7 lpD3DDevice = NULL;
37 static LPDIRECT3DVERTEXBUFFER7 lpVBufSrc = NULL;
38 static LPDIRECT3DVERTEXBUFFER7 lpVBufDest1 = NULL;
39 static LPDIRECT3DVERTEXBUFFER7 lpVBufDest2 = NULL;
41 static IDirectDraw *DirectDraw1 = NULL;
42 static IDirectDrawSurface *Surface1 = NULL;
43 static IDirect3D *Direct3D1 = NULL;
44 static IDirect3DDevice *Direct3DDevice1 = NULL;
45 static IDirect3DExecuteBuffer *ExecuteBuffer = NULL;
46 static IDirect3DViewport *Viewport = NULL;
47 static IDirect3DLight *Light = NULL;
49 typedef struct {
50 int total;
51 int rgb;
52 int hal;
53 int tnlhal;
54 int unk;
55 } D3D7ETest;
57 /* To compare bad floating point numbers. Not the ideal way to do it,
58 * but it should be enough for here */
59 #define comparefloat(a, b) ( (((a) - (b)) < 0.0001) && (((a) - (b)) > -0.0001) )
61 static HRESULT (WINAPI *pDirectDrawCreateEx)(LPGUID,LPVOID*,REFIID,LPUNKNOWN);
63 typedef struct _VERTEX
65 float x, y, z; /* position */
66 } VERTEX, *LPVERTEX;
68 typedef struct _TVERTEX
70 float x, y, z; /* position */
71 float rhw;
72 } TVERTEX, *LPTVERTEX;
75 static void init_function_pointers(void)
77 HMODULE hmod = GetModuleHandleA("ddraw.dll");
78 pDirectDrawCreateEx = (void*)GetProcAddress(hmod, "DirectDrawCreateEx");
82 static ULONG getRefcount(IUnknown *iface)
84 IUnknown_AddRef(iface);
85 return IUnknown_Release(iface);
89 static BOOL CreateDirect3D(void)
91 HRESULT rc;
92 DDSURFACEDESC2 ddsd;
94 rc = pDirectDrawCreateEx(NULL, (void**)&lpDD,
95 &IID_IDirectDraw7, NULL);
96 ok(rc==DD_OK || rc==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreateEx returned: %x\n", rc);
97 if (!lpDD) {
98 trace("DirectDrawCreateEx() failed with an error %x\n", rc);
99 return FALSE;
102 rc = IDirectDraw_SetCooperativeLevel(lpDD, NULL, DDSCL_NORMAL);
103 ok(rc==DD_OK, "SetCooperativeLevel returned: %x\n", rc);
105 rc = IDirectDraw7_QueryInterface(lpDD, &IID_IDirect3D7, (void**) &lpD3D);
106 if (rc == E_NOINTERFACE) return FALSE;
107 ok(rc==DD_OK, "QueryInterface returned: %x\n", rc);
109 memset(&ddsd, 0, sizeof(ddsd));
110 ddsd.dwSize = sizeof(ddsd);
111 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
112 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
113 ddsd.dwWidth = 256;
114 ddsd.dwHeight = 256;
115 rc = IDirectDraw7_CreateSurface(lpDD, &ddsd, &lpDDS, NULL);
116 if (FAILED(rc))
117 return FALSE;
119 memset(&ddsd, 0, sizeof(ddsd));
120 ddsd.dwSize = sizeof(ddsd);
121 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
122 ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
123 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
124 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
125 U1(U4(ddsd).ddpfPixelFormat).dwZBufferBitDepth = 16;
126 U3(U4(ddsd).ddpfPixelFormat).dwZBitMask = 0x0000FFFF;
127 ddsd.dwWidth = 256;
128 ddsd.dwHeight = 256;
129 rc = IDirectDraw7_CreateSurface(lpDD, &ddsd, &lpDDSdepth, NULL);
130 ok(rc==DD_OK, "CreateSurface returned: %x\n", rc);
131 if (FAILED(rc)) {
132 lpDDSdepth = NULL;
133 } else {
134 rc = IDirectDrawSurface_AddAttachedSurface(lpDDS, lpDDSdepth);
135 ok(rc == DD_OK, "IDirectDrawSurface_AddAttachedSurface returned %x\n", rc);
136 if (FAILED(rc))
137 return FALSE;
140 rc = IDirect3D7_CreateDevice(lpD3D, &IID_IDirect3DTnLHalDevice, lpDDS,
141 &lpD3DDevice);
142 ok(rc==D3D_OK || rc==DDERR_NOPALETTEATTACHED || rc==E_OUTOFMEMORY, "CreateDevice returned: %x\n", rc);
143 if (!lpD3DDevice) {
144 trace("IDirect3D7::CreateDevice() for a TnL Hal device failed with an error %x, trying HAL\n", rc);
145 rc = IDirect3D7_CreateDevice(lpD3D, &IID_IDirect3DHALDevice, lpDDS,
146 &lpD3DDevice);
147 if (!lpD3DDevice) {
148 trace("IDirect3D7::CreateDevice() for a HAL device failed with an error %x, trying RGB\n", rc);
149 rc = IDirect3D7_CreateDevice(lpD3D, &IID_IDirect3DRGBDevice, lpDDS,
150 &lpD3DDevice);
151 if (!lpD3DDevice) {
152 trace("IDirect3D7::CreateDevice() for a RGB device failed with an error %x, giving up\n", rc);
153 return FALSE;
158 return TRUE;
161 static void ReleaseDirect3D(void)
163 if (lpD3DDevice != NULL)
165 IDirect3DDevice7_Release(lpD3DDevice);
166 lpD3DDevice = NULL;
169 if (lpDDSdepth != NULL)
171 IDirectDrawSurface_Release(lpDDSdepth);
172 lpDDSdepth = NULL;
175 if (lpDDS != NULL)
177 IDirectDrawSurface_Release(lpDDS);
178 lpDDS = NULL;
181 if (lpD3D != NULL)
183 IDirect3D7_Release(lpD3D);
184 lpD3D = NULL;
187 if (lpDD != NULL)
189 IDirectDraw_Release(lpDD);
190 lpDD = NULL;
194 static void LightTest(void)
196 HRESULT rc;
197 D3DLIGHT7 light;
198 D3DLIGHT7 defaultlight;
199 BOOL bEnabled = FALSE;
200 float one = 1.0f;
201 float zero= 0.0f;
202 D3DMATERIAL7 mat;
203 BOOL enabled;
204 unsigned int i;
205 D3DDEVICEDESC7 caps;
207 /* Set a few lights with funky indices. */
208 memset(&light, 0, sizeof(light));
209 light.dltType = D3DLIGHT_DIRECTIONAL;
210 U1(light.dcvDiffuse).r = 0.5f;
211 U2(light.dcvDiffuse).g = 0.6f;
212 U3(light.dcvDiffuse).b = 0.7f;
213 U2(light.dvDirection).y = 1.f;
215 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 5, &light);
216 ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
217 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 10, &light);
218 ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
219 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 45, &light);
220 ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
223 /* Try to retrieve a light beyond the indices of the lights that have
224 been set. */
225 rc = IDirect3DDevice7_GetLight(lpD3DDevice, 50, &light);
226 ok(rc==DDERR_INVALIDPARAMS, "GetLight returned: %x\n", rc);
227 rc = IDirect3DDevice7_GetLight(lpD3DDevice, 2, &light);
228 ok(rc==DDERR_INVALIDPARAMS, "GetLight returned: %x\n", rc);
231 /* Try to retrieve one of the lights that have been set */
232 rc = IDirect3DDevice7_GetLight(lpD3DDevice, 10, &light);
233 ok(rc==D3D_OK, "GetLight returned: %x\n", rc);
236 /* Enable a light that have been previously set. */
237 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 10, TRUE);
238 ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
241 /* Enable some lights that have not been previously set, and verify that
242 they have been initialized with proper default values. */
243 memset(&defaultlight, 0, sizeof(D3DLIGHT7));
244 defaultlight.dltType = D3DLIGHT_DIRECTIONAL;
245 U1(defaultlight.dcvDiffuse).r = 1.f;
246 U2(defaultlight.dcvDiffuse).g = 1.f;
247 U3(defaultlight.dcvDiffuse).b = 1.f;
248 U3(defaultlight.dvDirection).z = 1.f;
250 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 20, TRUE);
251 ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
252 memset(&light, 0, sizeof(D3DLIGHT7));
253 rc = IDirect3DDevice7_GetLight(lpD3DDevice, 20, &light);
254 ok(rc==D3D_OK, "GetLight returned: %x\n", rc);
255 ok(!memcmp(&light, &defaultlight, sizeof(D3DLIGHT7)),
256 "light data doesn't match expected default values\n" );
258 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 50, TRUE);
259 ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
260 memset(&light, 0, sizeof(D3DLIGHT7));
261 rc = IDirect3DDevice7_GetLight(lpD3DDevice, 50, &light);
262 ok(rc==D3D_OK, "GetLight returned: %x\n", rc);
263 ok(!memcmp(&light, &defaultlight, sizeof(D3DLIGHT7)),
264 "light data doesn't match expected default values\n" );
267 /* Disable one of the light that have been previously enabled. */
268 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, 20, FALSE);
269 ok(rc==D3D_OK, "LightEnable returned: %x\n", rc);
271 /* Try to retrieve the enable status of some lights */
272 /* Light 20 is supposed to be disabled */
273 rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 20, &bEnabled );
274 ok(rc==D3D_OK, "GetLightEnable returned: %x\n", rc);
275 ok(!bEnabled, "GetLightEnable says the light is enabled\n");
277 /* Light 10 is supposed to be enabled */
278 bEnabled = FALSE;
279 rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 10, &bEnabled );
280 ok(rc==D3D_OK, "GetLightEnable returned: %x\n", rc);
281 ok(bEnabled, "GetLightEnable says the light is disabled\n");
283 /* Light 80 has not been set */
284 rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 80, &bEnabled );
285 ok(rc==DDERR_INVALIDPARAMS, "GetLightEnable returned: %x\n", rc);
287 /* Light 23 has not been set */
288 rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 23, &bEnabled );
289 ok(rc==DDERR_INVALIDPARAMS, "GetLightEnable returned: %x\n", rc);
291 /* Set some lights with invalid parameters */
292 memset(&light, 0, sizeof(D3DLIGHT7));
293 light.dltType = 0;
294 U1(light.dcvDiffuse).r = 1.f;
295 U2(light.dcvDiffuse).g = 1.f;
296 U3(light.dcvDiffuse).b = 1.f;
297 U3(light.dvDirection).z = 1.f;
298 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 100, &light);
299 ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
301 memset(&light, 0, sizeof(D3DLIGHT7));
302 light.dltType = 12345;
303 U1(light.dcvDiffuse).r = 1.f;
304 U2(light.dcvDiffuse).g = 1.f;
305 U3(light.dcvDiffuse).b = 1.f;
306 U3(light.dvDirection).z = 1.f;
307 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 101, &light);
308 ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
310 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 102, NULL);
311 ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
313 memset(&light, 0, sizeof(D3DLIGHT7));
314 light.dltType = D3DLIGHT_SPOT;
315 U1(light.dcvDiffuse).r = 1.f;
316 U2(light.dcvDiffuse).g = 1.f;
317 U3(light.dcvDiffuse).b = 1.f;
318 U3(light.dvDirection).z = 1.f;
320 light.dvAttenuation0 = -one / zero; /* -INFINITY */
321 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
322 ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
324 light.dvAttenuation0 = -1.0;
325 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
326 ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
328 light.dvAttenuation0 = 0.0;
329 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
330 ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
332 light.dvAttenuation0 = 1.0;
333 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
334 ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
336 light.dvAttenuation0 = one / zero; /* +INFINITY */
337 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
338 ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
340 light.dvAttenuation0 = zero / zero; /* NaN */
341 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
342 ok(rc==D3D_OK ||
343 broken(rc==DDERR_INVALIDPARAMS), "SetLight returned: %x\n", rc);
345 /* Directional light ignores attenuation */
346 light.dltType = D3DLIGHT_DIRECTIONAL;
347 light.dvAttenuation0 = -1.0;
348 rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
349 ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
351 memset(&mat, 0, sizeof(mat));
352 rc = IDirect3DDevice7_SetMaterial(lpD3DDevice, &mat);
353 ok(rc == D3D_OK, "IDirect3DDevice7_SetMaterial returned: %x\n", rc);
355 U4(mat).power = 129.0;
356 rc = IDirect3DDevice7_SetMaterial(lpD3DDevice, &mat);
357 ok(rc == D3D_OK, "IDirect3DDevice7_SetMaterial(power = 129.0) returned: %x\n", rc);
358 memset(&mat, 0, sizeof(mat));
359 rc = IDirect3DDevice7_GetMaterial(lpD3DDevice, &mat);
360 ok(rc == D3D_OK, "IDirect3DDevice7_GetMaterial returned: %x\n", rc);
361 ok(U4(mat).power == 129, "Returned power is %f\n", U4(mat).power);
363 U4(mat).power = -1.0;
364 rc = IDirect3DDevice7_SetMaterial(lpD3DDevice, &mat);
365 ok(rc == D3D_OK, "IDirect3DDevice7_SetMaterial(power = -1.0) returned: %x\n", rc);
366 memset(&mat, 0, sizeof(mat));
367 rc = IDirect3DDevice7_GetMaterial(lpD3DDevice, &mat);
368 ok(rc == D3D_OK, "IDirect3DDevice7_GetMaterial returned: %x\n", rc);
369 ok(U4(mat).power == -1, "Returned power is %f\n", U4(mat).power);
371 memset(&caps, 0, sizeof(caps));
372 rc = IDirect3DDevice7_GetCaps(lpD3DDevice, &caps);
373 ok(rc == D3D_OK, "IDirect3DDevice7_GetCaps failed with %x\n", rc);
375 if ( caps.dwMaxActiveLights == (DWORD) -1) {
376 /* Some cards without T&L Support return -1 (Examples: Voodoo Banshee, RivaTNT / NV4) */
377 skip("T&L not supported\n");
378 return;
381 for(i = 1; i <= caps.dwMaxActiveLights; i++) {
382 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i, TRUE);
383 ok(rc == D3D_OK, "Enabling light %u failed with %x\n", i, rc);
384 rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, i, &enabled);
385 ok(rc == D3D_OK, "GetLightEnable on light %u failed with %x\n", i, rc);
386 ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
389 /* TODO: Test the rendering results in this situation */
390 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i + 1, TRUE);
391 ok(rc == D3D_OK, "Enabling one light more than supported returned %x\n", rc);
392 rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, i + 1, &enabled);
393 ok(rc == D3D_OK, "GetLightEnable on light %u failed with %x\n", i + 1, rc);
394 ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
395 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i + 1, FALSE);
396 ok(rc == D3D_OK, "Disabling the additional returned %x\n", rc);
398 for(i = 1; i <= caps.dwMaxActiveLights; i++) {
399 rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i, FALSE);
400 ok(rc == D3D_OK, "Disabling light %u failed with %x\n", i, rc);
404 static void ProcessVerticesTest(void)
406 D3DVERTEXBUFFERDESC desc;
407 HRESULT rc;
408 VERTEX *in;
409 TVERTEX *out;
410 VERTEX *out2;
411 D3DVIEWPORT7 vp;
412 D3DMATRIX view = { 2.0, 0.0, 0.0, 0.0,
413 0.0, -1.0, 0.0, 0.0,
414 0.0, 0.0, 1.0, 0.0,
415 0.0, 0.0, 0.0, 3.0 };
417 D3DMATRIX world = { 0.0, 1.0, 0.0, 0.0,
418 1.0, 0.0, 0.0, 0.0,
419 0.0, 0.0, 0.0, 1.0,
420 0.0, 1.0, 1.0, 1.0 };
422 D3DMATRIX proj = { 1.0, 0.0, 0.0, 1.0,
423 0.0, 1.0, 1.0, 0.0,
424 0.0, 1.0, 1.0, 0.0,
425 1.0, 0.0, 0.0, 1.0 };
426 /* Create some vertex buffers */
428 memset(&desc, 0, sizeof(desc));
429 desc.dwSize = sizeof(desc);
430 desc.dwCaps = 0;
431 desc.dwFVF = D3DFVF_XYZ;
432 desc.dwNumVertices = 16;
433 rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufSrc, 0);
434 ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
435 if (!lpVBufSrc)
437 trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
438 goto out;
441 memset(&desc, 0, sizeof(desc));
442 desc.dwSize = sizeof(desc);
443 desc.dwCaps = 0;
444 desc.dwFVF = D3DFVF_XYZRHW;
445 desc.dwNumVertices = 16;
446 /* Msdn says that the last parameter must be 0 - check that */
447 rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufDest1, 4);
448 ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
449 if (!lpVBufDest1)
451 trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
452 goto out;
455 memset(&desc, 0, sizeof(desc));
456 desc.dwSize = sizeof(desc);
457 desc.dwCaps = 0;
458 desc.dwFVF = D3DFVF_XYZ;
459 desc.dwNumVertices = 16;
460 /* Msdn says that the last parameter must be 0 - check that */
461 rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufDest2, 12345678);
462 ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
463 if (!lpVBufDest2)
465 trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
466 goto out;
469 rc = IDirect3DVertexBuffer7_Lock(lpVBufSrc, 0, (void **) &in, NULL);
470 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
471 if(!in) goto out;
473 /* Check basic transformation */
475 in[0].x = 0.0;
476 in[0].y = 0.0;
477 in[0].z = 0.0;
479 in[1].x = 1.0;
480 in[1].y = 1.0;
481 in[1].z = 1.0;
483 in[2].x = -1.0;
484 in[2].y = -1.0;
485 in[2].z = 0.5;
487 in[3].x = 0.5;
488 in[3].y = -0.5;
489 in[3].z = 0.25;
490 rc = IDirect3DVertexBuffer7_Unlock(lpVBufSrc);
491 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
493 rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest1, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
494 ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
496 rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest2, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
497 ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
499 rc = IDirect3DVertexBuffer7_Lock(lpVBufDest1, 0, (void **) &out, NULL);
500 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
501 if(!out) goto out;
503 /* Check the results */
504 ok( comparefloat(out[0].x, 128.0 ) &&
505 comparefloat(out[0].y, 128.0 ) &&
506 comparefloat(out[0].z, 0.0 ) &&
507 comparefloat(out[0].rhw, 1.0 ),
508 "Output 0 vertex is (%f , %f , %f , %f)\n", out[0].x, out[0].y, out[0].z, out[0].rhw);
510 ok( comparefloat(out[1].x, 256.0 ) &&
511 comparefloat(out[1].y, 0.0 ) &&
512 comparefloat(out[1].z, 1.0 ) &&
513 comparefloat(out[1].rhw, 1.0 ),
514 "Output 1 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
516 ok( comparefloat(out[2].x, 0.0 ) &&
517 comparefloat(out[2].y, 256.0 ) &&
518 comparefloat(out[2].z, 0.5 ) &&
519 comparefloat(out[2].rhw, 1.0 ),
520 "Output 2 vertex is (%f , %f , %f , %f)\n", out[2].x, out[2].y, out[2].z, out[2].rhw);
522 ok( comparefloat(out[3].x, 192.0 ) &&
523 comparefloat(out[3].y, 192.0 ) &&
524 comparefloat(out[3].z, 0.25 ) &&
525 comparefloat(out[3].rhw, 1.0 ),
526 "Output 3 vertex is (%f , %f , %f , %f)\n", out[3].x, out[3].y, out[3].z, out[3].rhw);
528 rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest1);
529 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
530 out = NULL;
532 rc = IDirect3DVertexBuffer7_Lock(lpVBufDest2, 0, (void **) &out2, NULL);
533 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
534 if(!out2) goto out;
535 /* Small thing without much practical meaning, but I stumbled upon it,
536 * so let's check for it: If the output vertex buffer has to RHW value,
537 * The RHW value of the last vertex is written into the next vertex
539 ok( comparefloat(out2[4].x, 1.0 ) &&
540 comparefloat(out2[4].y, 0.0 ) &&
541 comparefloat(out2[4].z, 0.0 ),
542 "Output 4 vertex is (%f , %f , %f)\n", out2[4].x, out2[4].y, out2[4].z);
544 rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest2);
545 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
546 out = NULL;
548 /* Try a more complicated viewport, same vertices */
549 memset(&vp, 0, sizeof(vp));
550 vp.dwX = 10;
551 vp.dwY = 5;
552 vp.dwWidth = 246;
553 vp.dwHeight = 130;
554 vp.dvMinZ = -2.0;
555 vp.dvMaxZ = 4.0;
556 rc = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
557 ok(rc==D3D_OK, "IDirect3DDevice7_SetViewport failed with rc=%x\n", rc);
559 /* Process again */
560 rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest1, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
561 ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
563 rc = IDirect3DVertexBuffer7_Lock(lpVBufDest1, 0, (void **) &out, NULL);
564 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
565 if(!out) goto out;
567 /* Check the results */
568 ok( comparefloat(out[0].x, 133.0 ) &&
569 comparefloat(out[0].y, 70.0 ) &&
570 comparefloat(out[0].z, -2.0 ) &&
571 comparefloat(out[0].rhw, 1.0 ),
572 "Output 0 vertex is (%f , %f , %f , %f)\n", out[0].x, out[0].y, out[0].z, out[0].rhw);
574 ok( comparefloat(out[1].x, 256.0 ) &&
575 comparefloat(out[1].y, 5.0 ) &&
576 comparefloat(out[1].z, 4.0 ) &&
577 comparefloat(out[1].rhw, 1.0 ),
578 "Output 1 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
580 ok( comparefloat(out[2].x, 10.0 ) &&
581 comparefloat(out[2].y, 135.0 ) &&
582 comparefloat(out[2].z, 1.0 ) &&
583 comparefloat(out[2].rhw, 1.0 ),
584 "Output 2 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
586 ok( comparefloat(out[3].x, 194.5 ) &&
587 comparefloat(out[3].y, 102.5 ) &&
588 comparefloat(out[3].z, -0.5 ) &&
589 comparefloat(out[3].rhw, 1.0 ),
590 "Output 3 vertex is (%f , %f , %f , %f)\n", out[3].x, out[3].y, out[3].z, out[3].rhw);
592 rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest1);
593 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
594 out = NULL;
596 /* Play with some matrices. */
598 rc = IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW, &view);
599 ok(rc==D3D_OK, "IDirect3DDevice7_SetTransform failed\n");
601 rc = IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
602 ok(rc==D3D_OK, "IDirect3DDevice7_SetTransform failed\n");
604 rc = IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_WORLD, &world);
605 ok(rc==D3D_OK, "IDirect3DDevice7_SetTransform failed\n");
607 rc = IDirect3DVertexBuffer7_ProcessVertices(lpVBufDest1, D3DVOP_TRANSFORM, 0, 4, lpVBufSrc, 0, lpD3DDevice, 0);
608 ok(rc==D3D_OK , "IDirect3DVertexBuffer::ProcessVertices returned: %x\n", rc);
610 rc = IDirect3DVertexBuffer7_Lock(lpVBufDest1, 0, (void **) &out, NULL);
611 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Lock returned: %x\n", rc);
612 if(!out) goto out;
614 /* Keep the viewport simpler, otherwise we get bad numbers to compare */
615 vp.dwX = 0;
616 vp.dwY = 0;
617 vp.dwWidth = 100;
618 vp.dwHeight = 100;
619 vp.dvMinZ = 1.0;
620 vp.dvMaxZ = 0.0;
621 rc = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
622 ok(rc==D3D_OK, "IDirect3DDevice7_SetViewport failed\n");
624 /* Check the results */
625 ok( comparefloat(out[0].x, 256.0 ) && /* X coordinate is cut at the surface edges */
626 comparefloat(out[0].y, 70.0 ) &&
627 comparefloat(out[0].z, -2.0 ) &&
628 comparefloat(out[0].rhw, (1.0 / 3.0)),
629 "Output 0 vertex is (%f , %f , %f , %f)\n", out[0].x, out[0].y, out[0].z, out[0].rhw);
631 ok( comparefloat(out[1].x, 256.0 ) &&
632 comparefloat(out[1].y, 78.125000 ) &&
633 comparefloat(out[1].z, -2.750000 ) &&
634 comparefloat(out[1].rhw, 0.125000 ),
635 "Output 1 vertex is (%f , %f , %f , %f)\n", out[1].x, out[1].y, out[1].z, out[1].rhw);
637 ok( comparefloat(out[2].x, 256.0 ) &&
638 comparefloat(out[2].y, 44.000000 ) &&
639 comparefloat(out[2].z, 0.400000 ) &&
640 comparefloat(out[2].rhw, 0.400000 ),
641 "Output 2 vertex is (%f , %f , %f , %f)\n", out[2].x, out[2].y, out[2].z, out[2].rhw);
643 ok( comparefloat(out[3].x, 256.0 ) &&
644 comparefloat(out[3].y, 81.818184 ) &&
645 comparefloat(out[3].z, -3.090909 ) &&
646 comparefloat(out[3].rhw, 0.363636 ),
647 "Output 3 vertex is (%f , %f , %f , %f)\n", out[3].x, out[3].y, out[3].z, out[3].rhw);
649 rc = IDirect3DVertexBuffer7_Unlock(lpVBufDest1);
650 ok(rc==D3D_OK , "IDirect3DVertexBuffer::Unlock returned: %x\n", rc);
651 out = NULL;
653 out:
654 IDirect3DVertexBuffer7_Release(lpVBufSrc);
655 IDirect3DVertexBuffer7_Release(lpVBufDest1);
656 IDirect3DVertexBuffer7_Release(lpVBufDest2);
659 static void StateTest( void )
661 HRESULT rc;
663 /* The msdn says its undocumented, does it return an error too? */
664 rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_ZVISIBLE, TRUE);
665 ok(rc == D3D_OK, "IDirect3DDevice7_SetRenderState(D3DRENDERSTATE_ZVISIBLE, TRUE) returned %08x\n", rc);
666 rc = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_ZVISIBLE, FALSE);
667 ok(rc == D3D_OK, "IDirect3DDevice7_SetRenderState(D3DRENDERSTATE_ZVISIBLE, FALSE) returned %08x\n", rc);
671 static void SceneTest(void)
673 HRESULT hr;
675 /* Test an EndScene without beginscene. Should return an error */
676 hr = IDirect3DDevice7_EndScene(lpD3DDevice);
677 ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
679 /* Test a normal BeginScene / EndScene pair, this should work */
680 hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
681 ok(hr == D3D_OK, "IDirect3DDevice7_BeginScene failed with %08x\n", hr);
682 if(SUCCEEDED(hr))
684 DDBLTFX fx;
685 memset(&fx, 0, sizeof(fx));
686 fx.dwSize = sizeof(fx);
688 if(lpDDSdepth) {
689 hr = IDirectDrawSurface7_Blt(lpDDSdepth, NULL, NULL, NULL, DDBLT_DEPTHFILL, &fx);
690 ok(hr == D3D_OK, "Depthfill failed in a BeginScene / EndScene pair\n");
691 } else {
692 skip("Depth stencil creation failed at startup, skipping\n");
694 hr = IDirect3DDevice7_EndScene(lpD3DDevice);
695 ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed with %08x\n", hr);
698 /* Test another EndScene without having begun a new scene. Should return an error */
699 hr = IDirect3DDevice7_EndScene(lpD3DDevice);
700 ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
702 /* Two nested BeginScene and EndScene calls */
703 hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
704 ok(hr == D3D_OK, "IDirect3DDevice7_BeginScene failed with %08x\n", hr);
705 hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
706 ok(hr == D3DERR_SCENE_IN_SCENE, "IDirect3DDevice7_BeginScene returned %08x\n", hr);
707 hr = IDirect3DDevice7_EndScene(lpD3DDevice);
708 ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed with %08x\n", hr);
709 hr = IDirect3DDevice7_EndScene(lpD3DDevice);
710 ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
712 /* TODO: Verify that blitting works in the same way as in d3d9 */
715 static void LimitTest(void)
717 IDirectDrawSurface7 *pTexture = NULL;
718 HRESULT hr;
719 int i;
720 DDSURFACEDESC2 ddsd;
722 memset(&ddsd, 0, sizeof(ddsd));
723 ddsd.dwSize = sizeof(ddsd);
724 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
725 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
726 ddsd.dwWidth = 16;
727 ddsd.dwHeight = 16;
728 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &pTexture, NULL);
729 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
730 if(!pTexture) return;
732 for(i = 0; i < 8; i++) {
733 hr = IDirect3DDevice7_SetTexture(lpD3DDevice, i, pTexture);
734 ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %08x\n", i, hr);
735 hr = IDirect3DDevice7_SetTexture(lpD3DDevice, i, NULL);
736 ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %08x\n", i, hr);
737 hr = IDirect3DDevice7_SetTextureStageState(lpD3DDevice, i, D3DTSS_COLOROP, D3DTOP_ADD);
738 ok(hr == D3D_OK, "IDirect3DDevice8_SetTextureStageState for texture %d failed with %08x\n", i, hr);
741 IDirectDrawSurface7_Release(pTexture);
744 static HRESULT WINAPI enumDevicesCallback(GUID *Guid,LPSTR DeviceDescription,LPSTR DeviceName, D3DDEVICEDESC *hal, D3DDEVICEDESC *hel, VOID *ctx)
746 UINT ver = *((UINT *) ctx);
747 if(IsEqualGUID(&IID_IDirect3DRGBDevice, Guid))
749 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
750 "RGB Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
751 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
752 "RGB Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
753 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
754 "RGB Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
755 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
756 "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
758 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
759 "RGB Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
760 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
761 "RGB Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
762 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
763 "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
764 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
765 "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
767 else if(IsEqualGUID(&IID_IDirect3DHALDevice, Guid))
769 trace("HAL Device %d\n", ver);
771 else if(IsEqualGUID(&IID_IDirect3DRefDevice, Guid))
773 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
774 "REF Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
775 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
776 "REF Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
777 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
778 "REF Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
779 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
780 "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
782 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
783 "REF Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
784 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
785 "REF Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
786 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
787 "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
788 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
789 "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
791 else if(IsEqualGUID(&IID_IDirect3DRampDevice, Guid))
793 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
794 "Ramp Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
795 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
796 "Ramp Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
797 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
798 "Ramp Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
799 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
800 "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
802 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
803 "Ramp Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
804 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
805 "Ramp Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
806 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
807 "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
808 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
809 "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
811 else if(IsEqualGUID(&IID_IDirect3DMMXDevice, Guid))
813 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
814 "MMX Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
815 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0,
816 "MMX Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver);
817 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
818 "MMX Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
819 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2,
820 "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver);
822 ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
823 "MMX Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
824 ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0,
825 "MMX Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
826 ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
827 "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
828 ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE,
829 "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver);
831 else
833 ok(FALSE, "Unexpected device enumerated: \"%s\" \"%s\"\n", DeviceDescription, DeviceName);
834 if(hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hal line has pow2 set\n");
835 else trace("hal line does NOT have pow2 set\n");
836 if(hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hal tri has pow2 set\n");
837 else trace("hal tri does NOT have pow2 set\n");
838 if(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hel line has pow2 set\n");
839 else trace("hel line does NOT have pow2 set\n");
840 if(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hel tri has pow2 set\n");
841 else trace("hel tri does NOT have pow2 set\n");
843 return DDENUMRET_OK;
846 static HRESULT WINAPI enumDevicesCallbackTest7(LPSTR DeviceDescription, LPSTR DeviceName, LPD3DDEVICEDESC7 lpdd7, LPVOID Context)
848 D3D7ETest *d3d7et = Context;
849 if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DRGBDevice))
850 d3d7et->rgb++;
851 else if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DHALDevice))
852 d3d7et->hal++;
853 else if(IsEqualGUID(&lpdd7->deviceGUID, &IID_IDirect3DTnLHalDevice))
854 d3d7et->tnlhal++;
855 else
856 d3d7et->unk++;
858 d3d7et->total++;
860 return DDENUMRET_OK;
864 /* Check the deviceGUID of devices enumerated by
865 IDirect3D7_EnumDevices. */
866 static void D3D7EnumTest(void)
868 D3D7ETest d3d7et;
870 if (!lpD3D) {
871 skip("No Direct3D7 interface.\n");
872 return;
875 memset(&d3d7et, 0, sizeof(d3d7et));
876 IDirect3D7_EnumDevices(lpD3D, enumDevicesCallbackTest7, &d3d7et);
878 /* A couple of games (Delta Force LW and TFD) rely on this behaviour */
879 ok(d3d7et.tnlhal < d3d7et.total, "TnLHal device enumerated as only device.\n");
881 /* We make two additional assumptions. */
882 ok(d3d7et.rgb, "No RGB Device enumerated.\n");
884 if(d3d7et.tnlhal)
885 ok(d3d7et.hal, "TnLHal device enumerated, but no Hal device found.\n");
888 static void CapsTest(void)
890 IDirect3D3 *d3d3;
891 IDirect3D3 *d3d2;
892 IDirectDraw *dd1;
893 HRESULT hr;
894 UINT ver;
896 hr = DirectDrawCreate(NULL, &dd1, NULL);
897 ok(hr == DD_OK, "Cannot create a DirectDraw 1 interface, hr = %08x\n", hr);
898 hr = IDirectDraw_QueryInterface(dd1, &IID_IDirect3D3, (void **) &d3d3);
899 ok(hr == D3D_OK, "IDirectDraw_QueryInterface returned %08x\n", hr);
900 ver = 3;
901 IDirect3D3_EnumDevices(d3d3, enumDevicesCallback, &ver);
903 IDirect3D3_Release(d3d3);
904 IDirectDraw_Release(dd1);
906 hr = DirectDrawCreate(NULL, &dd1, NULL);
907 ok(hr == DD_OK, "Cannot create a DirectDraw 1 interface, hr = %08x\n", hr);
908 hr = IDirectDraw_QueryInterface(dd1, &IID_IDirect3D2, (void **) &d3d2);
909 ok(hr == D3D_OK, "IDirectDraw_QueryInterface returned %08x\n", hr);
910 ver = 2;
911 IDirect3D2_EnumDevices(d3d2, enumDevicesCallback, &ver);
913 IDirect3D2_Release(d3d2);
914 IDirectDraw_Release(dd1);
917 struct v_in {
918 float x, y, z;
920 struct v_out {
921 float x, y, z, rhw;
924 static BOOL D3D1_createObjects(void)
926 HRESULT hr;
927 DDSURFACEDESC ddsd;
928 D3DEXECUTEBUFFERDESC desc;
929 D3DVIEWPORT vp_data;
931 /* An IDirect3DDevice cannot be queryInterfaced from an IDirect3DDevice7 on windows */
932 hr = DirectDrawCreate(NULL, &DirectDraw1, NULL);
933 ok(hr==DD_OK || hr==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreate returned: %x\n", hr);
934 if (!DirectDraw1) {
935 return FALSE;
938 hr = IDirectDraw_SetCooperativeLevel(DirectDraw1, NULL, DDSCL_NORMAL);
939 ok(hr==DD_OK, "SetCooperativeLevel returned: %x\n", hr);
941 hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirect3D, (void**) &Direct3D1);
942 if (hr == E_NOINTERFACE) return FALSE;
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 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 hr = IDirect3D_CreateLight(Direct3D1, &Light, NULL);
1004 ok(hr == D3D_OK, "IDirect3D_CreateLight failed: %08x\n", hr);
1005 if (!Light)
1006 return FALSE;
1008 return TRUE;
1011 static void D3D1_releaseObjects(void)
1013 if (Light) IDirect3DLight_Release(Light);
1014 if (Viewport) IDirect3DViewport_Release(Viewport);
1015 if (ExecuteBuffer) IDirect3DExecuteBuffer_Release(ExecuteBuffer);
1016 if (Direct3DDevice1) IDirect3DDevice_Release(Direct3DDevice1);
1017 if (Surface1) IDirectDrawSurface_Release(Surface1);
1018 if (Direct3D1) IDirect3D_Release(Direct3D1);
1019 if (DirectDraw1) IDirectDraw_Release(DirectDraw1);
1022 static void ViewportTest(void)
1024 HRESULT hr;
1025 LPDIRECT3DVIEWPORT2 Viewport2;
1026 D3DVIEWPORT vp1_data, ret_vp1_data;
1027 D3DVIEWPORT2 vp2_data, ret_vp2_data;
1028 float infinity;
1030 *(DWORD*)&infinity = 0x7f800000;
1032 hr = IDirect3DDevice_AddViewport(Direct3DDevice1, Viewport);
1033 ok(hr == D3D_OK, "IDirect3DDevice_AddViewport returned %08x\n", hr);
1035 hr = IDirect3DViewport_QueryInterface(Viewport, &IID_IDirect3DViewport2, (void**) &Viewport2);
1036 ok(hr==D3D_OK, "QueryInterface returned: %x\n", hr);
1038 vp1_data.dwSize = sizeof(vp1_data);
1039 vp1_data.dwX = 0;
1040 vp1_data.dwY = 1;
1041 vp1_data.dwWidth = 256;
1042 vp1_data.dwHeight = 257;
1043 vp1_data.dvMaxX = 0;
1044 vp1_data.dvMaxY = 0;
1045 vp1_data.dvScaleX = 0;
1046 vp1_data.dvScaleY = 0;
1047 vp1_data.dvMinZ = 0.25;
1048 vp1_data.dvMaxZ = 0.75;
1050 vp2_data.dwSize = sizeof(vp2_data);
1051 vp2_data.dwX = 2;
1052 vp2_data.dwY = 3;
1053 vp2_data.dwWidth = 258;
1054 vp2_data.dwHeight = 259;
1055 vp2_data.dvClipX = 0;
1056 vp2_data.dvClipY = 0;
1057 vp2_data.dvClipWidth = 0;
1058 vp2_data.dvClipHeight = 0;
1059 vp2_data.dvMinZ = 0.1;
1060 vp2_data.dvMaxZ = 0.9;
1062 hr = IDirect3DViewport2_SetViewport(Viewport2, &vp1_data);
1063 ok(hr == D3D_OK, "IDirect3DViewport2_SetViewport returned %08x\n", hr);
1065 memset(&ret_vp1_data, 0xff, sizeof(ret_vp1_data));
1066 ret_vp1_data.dwSize = sizeof(vp1_data);
1068 hr = IDirect3DViewport2_GetViewport(Viewport2, &ret_vp1_data);
1069 ok(hr == D3D_OK, "IDirect3DViewport2_GetViewport returned %08x\n", hr);
1071 ok(ret_vp1_data.dwX == vp1_data.dwX, "dwX is %u, expected %u\n", ret_vp1_data.dwX, vp1_data.dwX);
1072 ok(ret_vp1_data.dwY == vp1_data.dwY, "dwY is %u, expected %u\n", ret_vp1_data.dwY, vp1_data.dwY);
1073 ok(ret_vp1_data.dwWidth == vp1_data.dwWidth, "dwWidth is %u, expected %u\n", ret_vp1_data.dwWidth, vp1_data.dwWidth);
1074 ok(ret_vp1_data.dwHeight == vp1_data.dwHeight, "dwHeight is %u, expected %u\n", ret_vp1_data.dwHeight, vp1_data.dwHeight);
1075 ok(ret_vp1_data.dvMaxX == vp1_data.dvMaxX, "dvMaxX is %f, expected %f\n", ret_vp1_data.dvMaxX, vp1_data.dvMaxX);
1076 ok(ret_vp1_data.dvMaxY == vp1_data.dvMaxY, "dvMaxY is %f, expected %f\n", ret_vp1_data.dvMaxY, vp1_data.dvMaxY);
1077 todo_wine ok(ret_vp1_data.dvScaleX == infinity, "dvScaleX is %f, expected %f\n", ret_vp1_data.dvScaleX, infinity);
1078 todo_wine ok(ret_vp1_data.dvScaleY == infinity, "dvScaleY is %f, expected %f\n", ret_vp1_data.dvScaleY, infinity);
1079 ok(ret_vp1_data.dvMinZ == 0.0, "dvMinZ is %f, expected 0.0\n", ret_vp1_data.dvMinZ);
1080 ok(ret_vp1_data.dvMaxZ == 1.0, "dvMaxZ is %f, expected 1.0\n", ret_vp1_data.dvMaxZ);
1082 hr = IDirect3DViewport2_SetViewport2(Viewport2, &vp2_data);
1083 ok(hr == D3D_OK, "IDirect3DViewport2_SetViewport2 returned %08x\n", hr);
1085 memset(&ret_vp2_data, 0xff, sizeof(ret_vp2_data));
1086 ret_vp2_data.dwSize = sizeof(vp2_data);
1088 hr = IDirect3DViewport2_GetViewport2(Viewport2, &ret_vp2_data);
1089 ok(hr == D3D_OK, "IDirect3DViewport2_GetViewport2 returned %08x\n", hr);
1091 ok(ret_vp2_data.dwX == vp2_data.dwX, "dwX is %u, expected %u\n", ret_vp2_data.dwX, vp2_data.dwX);
1092 ok(ret_vp2_data.dwY == vp2_data.dwY, "dwY is %u, expected %u\n", ret_vp2_data.dwY, vp2_data.dwY);
1093 ok(ret_vp2_data.dwWidth == vp2_data.dwWidth, "dwWidth is %u, expected %u\n", ret_vp2_data.dwWidth, vp2_data.dwWidth);
1094 ok(ret_vp2_data.dwHeight == vp2_data.dwHeight, "dwHeight is %u, expected %u\n", ret_vp2_data.dwHeight, vp2_data.dwHeight);
1095 ok(ret_vp2_data.dvClipX == vp2_data.dvClipX, "dvClipX is %f, expected %f\n", ret_vp2_data.dvClipX, vp2_data.dvClipX);
1096 ok(ret_vp2_data.dvClipY == vp2_data.dvClipY, "dvClipY is %f, expected %f\n", ret_vp2_data.dvClipY, vp2_data.dvClipY);
1097 ok(ret_vp2_data.dvClipWidth == vp2_data.dvClipWidth, "dvClipWidth is %f, expected %f\n",
1098 ret_vp2_data.dvClipWidth, vp2_data.dvClipWidth);
1099 ok(ret_vp2_data.dvClipHeight == vp2_data.dvClipHeight, "dvClipHeight is %f, expected %f\n",
1100 ret_vp2_data.dvClipHeight, vp2_data.dvClipHeight);
1101 ok(ret_vp2_data.dvMinZ == vp2_data.dvMinZ, "dvMinZ is %f, expected %f\n", ret_vp2_data.dvMinZ, vp2_data.dvMinZ);
1102 ok(ret_vp2_data.dvMaxZ == vp2_data.dvMaxZ, "dvMaxZ is %f, expected %f\n", ret_vp2_data.dvMaxZ, vp2_data.dvMaxZ);
1104 memset(&ret_vp1_data, 0xff, sizeof(ret_vp1_data));
1105 ret_vp1_data.dwSize = sizeof(vp1_data);
1107 hr = IDirect3DViewport2_GetViewport(Viewport2, &ret_vp1_data);
1108 ok(hr == D3D_OK, "IDirect3DViewport2_GetViewport returned %08x\n", hr);
1110 ok(ret_vp1_data.dwX == vp2_data.dwX, "dwX is %u, expected %u\n", ret_vp1_data.dwX, vp2_data.dwX);
1111 ok(ret_vp1_data.dwY == vp2_data.dwY, "dwY is %u, expected %u\n", ret_vp1_data.dwY, vp2_data.dwY);
1112 ok(ret_vp1_data.dwWidth == vp2_data.dwWidth, "dwWidth is %u, expected %u\n", ret_vp1_data.dwWidth, vp2_data.dwWidth);
1113 ok(ret_vp1_data.dwHeight == vp2_data.dwHeight, "dwHeight is %u, expected %u\n", ret_vp1_data.dwHeight, vp2_data.dwHeight);
1114 ok(ret_vp1_data.dvMaxX == vp1_data.dvMaxX, "dvMaxX is %f, expected %f\n", ret_vp1_data.dvMaxX, vp1_data.dvMaxX);
1115 ok(ret_vp1_data.dvMaxY == vp1_data.dvMaxY, "dvMaxY is %f, expected %f\n", ret_vp1_data.dvMaxY, vp1_data.dvMaxY);
1116 todo_wine ok(ret_vp1_data.dvScaleX == infinity, "dvScaleX is %f, expected %f\n", ret_vp1_data.dvScaleX, infinity);
1117 todo_wine ok(ret_vp1_data.dvScaleY == infinity, "dvScaleY is %f, expected %f\n", ret_vp1_data.dvScaleY, infinity);
1118 todo_wine ok(ret_vp1_data.dvMinZ == 0.0, "dvMinZ is %f, expected 0.0\n", ret_vp1_data.dvMinZ);
1119 todo_wine ok(ret_vp1_data.dvMaxZ == 1.0, "dvMaxZ is %f, expected 1.0\n", ret_vp1_data.dvMaxZ);
1121 hr = IDirect3DViewport2_SetViewport2(Viewport2, &vp2_data);
1122 ok(hr == D3D_OK, "IDirect3DViewport2_SetViewport2 returned %08x\n", hr);
1124 memset(&ret_vp2_data, 0xff, sizeof(ret_vp2_data));
1125 ret_vp2_data.dwSize = sizeof(vp2_data);
1127 hr = IDirect3DViewport2_GetViewport2(Viewport2, &ret_vp2_data);
1128 ok(hr == D3D_OK, "IDirect3DViewport2_GetViewport2 returned %08x\n", hr);
1130 ok(ret_vp2_data.dwX == vp2_data.dwX, "dwX is %u, expected %u\n", ret_vp2_data.dwX, vp2_data.dwX);
1131 ok(ret_vp2_data.dwY == vp2_data.dwY, "dwY is %u, expected %u\n", ret_vp2_data.dwY, vp2_data.dwY);
1132 ok(ret_vp2_data.dwWidth == vp2_data.dwWidth, "dwWidth is %u, expected %u\n", ret_vp2_data.dwWidth, vp2_data.dwWidth);
1133 ok(ret_vp2_data.dwHeight == vp2_data.dwHeight, "dwHeight is %u, expected %u\n", ret_vp2_data.dwHeight, vp2_data.dwHeight);
1134 ok(ret_vp2_data.dvClipX == vp2_data.dvClipX, "dvClipX is %f, expected %f\n", ret_vp2_data.dvClipX, vp2_data.dvClipX);
1135 ok(ret_vp2_data.dvClipY == vp2_data.dvClipY, "dvClipY is %f, expected %f\n", ret_vp2_data.dvClipY, vp2_data.dvClipY);
1136 ok(ret_vp2_data.dvClipWidth == vp2_data.dvClipWidth, "dvClipWidth is %f, expected %f\n",
1137 ret_vp2_data.dvClipWidth, vp2_data.dvClipWidth);
1138 ok(ret_vp2_data.dvClipHeight == vp2_data.dvClipHeight, "dvClipHeight is %f, expected %f\n",
1139 ret_vp2_data.dvClipHeight, vp2_data.dvClipHeight);
1140 ok(ret_vp2_data.dvMinZ == vp2_data.dvMinZ, "dvMinZ is %f, expected %f\n", ret_vp2_data.dvMinZ, vp2_data.dvMinZ);
1141 ok(ret_vp2_data.dvMaxZ == vp2_data.dvMaxZ, "dvMaxZ is %f, expected %f\n", ret_vp2_data.dvMaxZ, vp2_data.dvMaxZ);
1143 hr = IDirect3DViewport2_SetViewport(Viewport2, &vp1_data);
1144 ok(hr == D3D_OK, "IDirect3DViewport2_SetViewport returned %08x\n", hr);
1146 memset(&ret_vp1_data, 0xff, sizeof(ret_vp1_data));
1147 ret_vp1_data.dwSize = sizeof(vp1_data);
1149 hr = IDirect3DViewport2_GetViewport(Viewport2, &ret_vp1_data);
1150 ok(hr == D3D_OK, "IDirect3DViewport2_GetViewport returned %08x\n", hr);
1152 ok(ret_vp1_data.dwX == vp1_data.dwX, "dwX is %u, expected %u\n", ret_vp1_data.dwX, vp1_data.dwX);
1153 ok(ret_vp1_data.dwY == vp1_data.dwY, "dwY is %u, expected %u\n", ret_vp1_data.dwY, vp1_data.dwY);
1154 ok(ret_vp1_data.dwWidth == vp1_data.dwWidth, "dwWidth is %u, expected %u\n", ret_vp1_data.dwWidth, vp1_data.dwWidth);
1155 ok(ret_vp1_data.dwHeight == vp1_data.dwHeight, "dwHeight is %u, expected %u\n", ret_vp1_data.dwHeight, vp1_data.dwHeight);
1156 ok(ret_vp1_data.dvMaxX == vp1_data.dvMaxX, "dvMaxX is %f, expected %f\n", ret_vp1_data.dvMaxX, vp1_data.dvMaxX);
1157 ok(ret_vp1_data.dvMaxY == vp1_data.dvMaxY, "dvMaxY is %f, expected %f\n", ret_vp1_data.dvMaxY, vp1_data.dvMaxY);
1158 todo_wine ok(ret_vp1_data.dvScaleX == infinity, "dvScaleX is %f, expected %f\n", ret_vp1_data.dvScaleX, infinity);
1159 todo_wine ok(ret_vp1_data.dvScaleY == infinity, "dvScaleY is %f, expected %f\n", ret_vp1_data.dvScaleY, infinity);
1160 ok(ret_vp1_data.dvMinZ == 0.0, "dvMinZ is %f, expected 0.0\n", ret_vp1_data.dvMinZ);
1161 ok(ret_vp1_data.dvMaxZ == 1.0, "dvMaxZ is %f, expected 1.0\n", ret_vp1_data.dvMaxZ);
1163 memset(&ret_vp2_data, 0xff, sizeof(ret_vp2_data));
1164 ret_vp2_data.dwSize = sizeof(vp2_data);
1166 hr = IDirect3DViewport2_GetViewport2(Viewport2, &ret_vp2_data);
1167 ok(hr == D3D_OK, "IDirect3DViewport2_GetViewport2 returned %08x\n", hr);
1169 ok(ret_vp2_data.dwX == vp1_data.dwX, "dwX is %u, expected %u\n", ret_vp2_data.dwX, vp1_data.dwX);
1170 ok(ret_vp2_data.dwY == vp1_data.dwY, "dwY is %u, expected %u\n", ret_vp2_data.dwY, vp1_data.dwY);
1171 ok(ret_vp2_data.dwWidth == vp1_data.dwWidth, "dwWidth is %u, expected %u\n", ret_vp2_data.dwWidth, vp1_data.dwWidth);
1172 ok(ret_vp2_data.dwHeight == vp1_data.dwHeight, "dwHeight is %u, expected %u\n", ret_vp2_data.dwHeight, vp1_data.dwHeight);
1173 ok(ret_vp2_data.dvClipX == vp2_data.dvClipX, "dvClipX is %f, expected %f\n", ret_vp2_data.dvClipX, vp2_data.dvClipX);
1174 ok(ret_vp2_data.dvClipY == vp2_data.dvClipY, "dvClipY is %f, expected %f\n", ret_vp2_data.dvClipY, vp2_data.dvClipY);
1175 ok(ret_vp2_data.dvClipWidth == vp2_data.dvClipWidth, "dvClipWidth is %f, expected %f\n",
1176 ret_vp2_data.dvClipWidth, vp2_data.dvClipWidth);
1177 ok(ret_vp2_data.dvClipHeight == vp2_data.dvClipHeight, "dvClipHeight is %f, expected %f\n",
1178 ret_vp2_data.dvClipHeight, vp2_data.dvClipHeight);
1179 ok(ret_vp2_data.dvMinZ == 0.0, "dvMinZ is %f, expected 0.0\n", ret_vp2_data.dvMinZ);
1180 ok(ret_vp2_data.dvMaxZ == 1.0, "dvMaxZ is %f, expected 1.0\n", ret_vp2_data.dvMaxZ);
1182 IDirect3DViewport2_Release(Viewport2);
1184 hr = IDirect3DDevice_DeleteViewport(Direct3DDevice1, Viewport);
1185 ok(hr == D3D_OK, "IDirect3DDevice_DeleteViewport returned %08x\n", hr);
1188 #define SET_VP_DATA(vp_data) \
1189 vp_data.dwSize = sizeof(vp_data); \
1190 vp_data.dwX = 0; \
1191 vp_data.dwY = 0; \
1192 vp_data.dwWidth = 256; \
1193 vp_data.dwHeight = 256; \
1194 vp_data.dvMaxX = 256; \
1195 vp_data.dvMaxY = 256; \
1196 vp_data.dvScaleX = 5; \
1197 vp_data.dvScaleY = 5; \
1198 vp_data.dvMinZ = -25; \
1199 vp_data.dvMaxZ = 60;
1201 static void Direct3D1Test(void)
1203 HRESULT hr;
1204 D3DEXECUTEBUFFERDESC desc;
1205 D3DVIEWPORT vp_data;
1206 D3DINSTRUCTION *instr;
1207 D3DBRANCH *branch;
1208 IDirect3D *Direct3D_alt;
1209 IDirect3DLight *d3dlight;
1210 ULONG refcount;
1211 unsigned int idx = 0;
1212 static struct v_in testverts[] = {
1213 {0.0, 0.0, 0.0}, { 1.0, 1.0, 1.0}, {-1.0, -1.0, -1.0},
1214 {0.5, 0.5, 0.5}, {-0.5, -0.5, -0.5}, {-0.5, -0.5, 0.0},
1216 static struct v_in cliptest[] = {
1217 {25.59, 25.59, 1.0}, {-25.59, -25.59, 0.0},
1218 {25.61, 25.61, 1.01}, {-25.61, -25.61, -0.01},
1220 static struct v_in offscreentest[] = {
1221 {128.1, 0.0, 0.0},
1223 struct v_out out[sizeof(testverts) / sizeof(testverts[0])];
1224 D3DHVERTEX outH[sizeof(testverts) / sizeof(testverts[0])];
1225 D3DTRANSFORMDATA transformdata;
1226 DWORD i = FALSE;
1228 /* Interface consistency check. */
1229 hr = IDirect3DDevice_GetDirect3D(Direct3DDevice1, &Direct3D_alt);
1230 ok(hr == D3D_OK, "IDirect3DDevice_GetDirect3D failed: %08x\n", hr);
1231 if (hr == D3D_OK)
1232 ok(Direct3D_alt == Direct3D1, "Direct3D1 struct pointer missmatch: %p != %p\n", Direct3D_alt, Direct3D1);
1234 memset(&desc, 0, sizeof(desc));
1235 desc.dwSize = sizeof(desc);
1236 hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1237 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1239 memset(desc.lpData, 0, 128);
1240 instr = desc.lpData;
1241 instr[idx].bOpcode = D3DOP_BRANCHFORWARD;
1242 instr[idx].bSize = sizeof(*branch);
1243 instr[idx].wCount = 1;
1244 idx++;
1245 branch = (D3DBRANCH *) &instr[idx];
1246 branch->dwMask = 0x0;
1247 branch->dwValue = 1;
1248 branch->bNegate = TRUE;
1249 branch->dwOffset = 0;
1250 idx += (sizeof(*branch) / sizeof(*instr));
1251 instr[idx].bOpcode = D3DOP_EXIT;
1252 instr[idx].bSize = 0;
1253 instr[idx].wCount = 0;
1254 hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1255 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1257 hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1258 ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1260 memset(&desc, 0, sizeof(desc));
1261 desc.dwSize = sizeof(desc);
1263 hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1264 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1266 memset(desc.lpData, 0, 128);
1267 instr = desc.lpData;
1268 idx = 0;
1269 instr[idx].bOpcode = D3DOP_BRANCHFORWARD;
1270 instr[idx].bSize = sizeof(*branch);
1271 instr[idx].wCount = 1;
1272 idx++;
1273 branch = (D3DBRANCH *) &instr[idx];
1274 branch->dwMask = 0x0;
1275 branch->dwValue = 1;
1276 branch->bNegate = TRUE;
1277 branch->dwOffset = 64;
1278 instr = (D3DINSTRUCTION*)((char*)desc.lpData + 64);
1279 instr[0].bOpcode = D3DOP_EXIT;
1280 instr[0].bSize = 0;
1281 instr[0].wCount = 0;
1282 hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1283 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1285 hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1286 ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1288 /* Test rendering 0 triangles */
1289 memset(&desc, 0, sizeof(desc));
1290 desc.dwSize = sizeof(desc);
1292 hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &desc);
1293 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed: %08x\n", hr);
1295 memset(desc.lpData, 0, 128);
1296 instr = desc.lpData;
1298 instr->bOpcode = D3DOP_TRIANGLE;
1299 instr->bSize = sizeof(D3DOP_TRIANGLE);
1300 instr->wCount = 0;
1301 instr++;
1302 instr->bOpcode = D3DOP_EXIT;
1303 instr->bSize = 0;
1304 instr->wCount = 0;
1305 hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1306 ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Unlock failed: %08x\n", hr);
1308 hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_CLIPPED);
1309 ok(hr == D3D_OK, "IDirect3DDevice_Execute returned %08x\n", hr);
1311 memset(&transformdata, 0, sizeof(transformdata));
1312 transformdata.dwSize = sizeof(transformdata);
1313 transformdata.lpIn = testverts;
1314 transformdata.dwInSize = sizeof(testverts[0]);
1315 transformdata.lpOut = out;
1316 transformdata.dwOutSize = sizeof(out[0]);
1318 transformdata.lpHOut = NULL;
1319 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1320 &transformdata, D3DTRANSFORM_UNCLIPPED,
1321 &i);
1322 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1324 transformdata.lpHOut = outH;
1325 memset(outH, 0xcc, sizeof(outH));
1326 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1327 &transformdata, D3DTRANSFORM_UNCLIPPED,
1328 &i);
1329 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1330 ok(i == 0, "Offscreen is %d\n", i);
1332 for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1333 static const struct v_out cmp[] = {
1334 {128.0, 128.0, 0.0, 1}, {129.0, 127.0, 1.0, 1}, {127.0, 129.0, -1, 1},
1335 {128.5, 127.5, 0.5, 1}, {127.5, 128.5, -0.5, 1}, {127.5, 128.5, 0, 1}
1338 ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1339 cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1340 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1341 out[i].x, out[i].y, out[i].z, out[i].rhw,
1342 cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1344 for(i = 0; i < sizeof(outH); i++) {
1345 if(((unsigned char *) outH)[i] != 0xcc) {
1346 ok(FALSE, "Homogeneous output was generated despite UNCLIPPED flag\n");
1347 break;
1351 SET_VP_DATA(vp_data);
1352 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1353 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1354 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1355 &transformdata, D3DTRANSFORM_UNCLIPPED,
1356 &i);
1357 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1358 ok(i == 0, "Offscreen is %d\n", i);
1360 for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1361 static const struct v_out cmp[] = {
1362 {128.0, 128.0, 0.0, 1}, {133.0, 123.0, 1.0, 1}, {123.0, 133.0, -1, 1},
1363 {130.5, 125.5, 0.5, 1}, {125.5, 130.5, -0.5, 1}, {125.5, 130.5, 0, 1}
1365 ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1366 cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1367 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1368 out[i].x, out[i].y, out[i].z, out[i].rhw,
1369 cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1372 SET_VP_DATA(vp_data);
1373 vp_data.dwX = 10;
1374 vp_data.dwY = 20;
1375 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1376 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1377 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1378 &transformdata, D3DTRANSFORM_UNCLIPPED,
1379 &i);
1380 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1381 ok(i == 0, "Offscreen is %d\n", i);
1382 for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1383 static const struct v_out cmp[] = {
1384 {138.0, 148.0, 0.0, 1}, {143.0, 143.0, 1.0, 1}, {133.0, 153.0, -1, 1},
1385 {140.5, 145.5, 0.5, 1}, {135.5, 150.5, -0.5, 1}, {135.5, 150.5, 0, 1}
1387 ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1388 cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1389 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1390 out[i].x, out[i].y, out[i].z, out[i].rhw,
1391 cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1394 memset(out, 0xcc, sizeof(out));
1395 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1396 &transformdata, D3DTRANSFORM_CLIPPED,
1397 &i);
1398 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1399 ok(i == 0, "Offscreen is %d\n", i);
1400 for(i = 0; i < sizeof(testverts) / sizeof(testverts[0]); i++) {
1401 static const D3DHVERTEX cmpH[] = {
1402 {0, { 0.0}, { 0.0}, { 0.0}}, {0, { 1.0}, { 1.0}, {1.0}},
1403 {D3DCLIP_FRONT, {-1.0}, {-1.0}, {-1.0}}, {0, { 0.5}, { 0.5}, {0.5}},
1404 {D3DCLIP_FRONT, {-0.5}, {-0.5}, {-0.5}}, {0, {-0.5}, {-0.5}, {0.0}}
1406 ok(U1(cmpH[i]).hx == U1(outH[i]).hx && U2(cmpH[i]).hy == U2(outH[i]).hy &&
1407 U3(cmpH[i]).hz == U3(outH[i]).hz && cmpH[i].dwFlags == outH[i].dwFlags,
1408 "HVertex %d differs. Got %08x %f %f %f, expexted %08x %f %f %f\n", i + 1,
1409 outH[i].dwFlags, U1(outH[i]).hx, U2(outH[i]).hy, U3(outH[i]).hz,
1410 cmpH[i].dwFlags, U1(cmpH[i]).hx, U2(cmpH[i]).hy, U3(cmpH[i]).hz);
1412 /* No scheme has been found behind those return values. It seems to be
1413 * whatever data windows has when throwing the vertex away. Modify the
1414 * input test vertices to test this more. Depending on the input data
1415 * it can happen that the z coord gets written into y, or similar things
1417 if(0)
1419 static const struct v_out cmp[] = {
1420 {138.0, 148.0, 0.0, 1}, {143.0, 143.0, 1.0, 1}, { -1.0, -1.0, 0.5, 1},
1421 {140.5, 145.5, 0.5, 1}, { -0.5, -0.5, -0.5, 1}, {135.5, 150.5, 0.0, 1}
1423 ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y &&
1424 cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw,
1425 "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1,
1426 out[i].x, out[i].y, out[i].z, out[i].rhw,
1427 cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw);
1430 for(i = 0; i < sizeof(out) / sizeof(DWORD); i++) {
1431 ok(((DWORD *) out)[i] != 0xcccccccc,
1432 "Regular output DWORD %d remained untouched\n", i);
1435 transformdata.lpIn = cliptest;
1436 transformdata.dwInSize = sizeof(cliptest[0]);
1437 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1438 &transformdata, D3DTRANSFORM_CLIPPED,
1439 &i);
1440 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1441 ok(i == 0, "Offscreen is %d\n", i);
1442 for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1443 DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1447 D3DCLIP_RIGHT | D3DCLIP_BACK | D3DCLIP_TOP,
1448 D3DCLIP_LEFT | D3DCLIP_BOTTOM | D3DCLIP_FRONT,
1450 ok(Flags[i] == outH[i].dwFlags,
1451 "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1452 outH[i].dwFlags, Flags[i]);
1455 SET_VP_DATA(vp_data);
1456 vp_data.dwWidth = 10;
1457 vp_data.dwHeight = 1000;
1458 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1459 i = 10;
1460 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1461 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1462 &transformdata, D3DTRANSFORM_CLIPPED,
1463 &i);
1464 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1465 ok(i == 0, "Offscreen is %d\n", i);
1466 for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1467 DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1469 D3DCLIP_RIGHT,
1470 D3DCLIP_LEFT,
1471 D3DCLIP_RIGHT | D3DCLIP_BACK,
1472 D3DCLIP_LEFT | D3DCLIP_FRONT,
1474 ok(Flags[i] == outH[i].dwFlags,
1475 "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1476 outH[i].dwFlags, Flags[i]);
1479 SET_VP_DATA(vp_data);
1480 vp_data.dwWidth = 256;
1481 vp_data.dwHeight = 256;
1482 vp_data.dvScaleX = 1;
1483 vp_data.dvScaleY = 1;
1484 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1485 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1486 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(cliptest) / sizeof(cliptest[0]),
1487 &transformdata, D3DTRANSFORM_CLIPPED,
1488 &i);
1489 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1490 ok(i == 0, "Offscreen is %s\n", i ? "TRUE" : "FALSE");
1491 for(i = 0; i < sizeof(cliptest) / sizeof(cliptest[0]); i++) {
1492 DWORD Flags[sizeof(cliptest) / sizeof(cliptest[0])] =
1496 D3DCLIP_BACK,
1497 D3DCLIP_FRONT,
1499 ok(Flags[i] == outH[i].dwFlags,
1500 "Cliptest %d differs. Got %08x expexted %08x\n", i + 1,
1501 outH[i].dwFlags, Flags[i]);
1504 /* Finally try to figure out how the DWORD dwOffscreen works.
1505 * Apparently no vertex is offscreen with clipping off,
1506 * and with clipping on the offscreen flag is set if only one vertex
1507 * is transformed, and this vertex is offscreen.
1509 SET_VP_DATA(vp_data);
1510 vp_data.dwWidth = 5;
1511 vp_data.dwHeight = 5;
1512 vp_data.dvScaleX = 10000;
1513 vp_data.dvScaleY = 10000;
1514 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1515 ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1516 transformdata.lpIn = cliptest;
1517 hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1518 &transformdata, D3DTRANSFORM_UNCLIPPED,
1519 &i);
1520 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1521 ok(i == 0, "Offscreen is %d\n", i);
1522 hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1523 &transformdata, D3DTRANSFORM_CLIPPED,
1524 &i);
1525 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1526 ok(i == (D3DCLIP_RIGHT | D3DCLIP_TOP), "Offscreen is %d\n", i);
1527 hr = IDirect3DViewport_TransformVertices(Viewport, 2,
1528 &transformdata, D3DTRANSFORM_CLIPPED,
1529 &i);
1530 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1531 ok(i == 0, "Offscreen is %d\n", i);
1532 transformdata.lpIn = cliptest + 1;
1533 hr = IDirect3DViewport_TransformVertices(Viewport, 1,
1534 &transformdata, D3DTRANSFORM_CLIPPED,
1535 &i);
1536 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1537 ok(i == (D3DCLIP_BOTTOM | D3DCLIP_LEFT), "Offscreen is %d\n", i);
1539 transformdata.lpIn = offscreentest;
1540 transformdata.dwInSize = sizeof(offscreentest[0]);
1541 SET_VP_DATA(vp_data);
1542 vp_data.dwWidth = 257;
1543 vp_data.dwHeight = 257;
1544 vp_data.dvScaleX = 1;
1545 vp_data.dvScaleY = 1;
1546 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1547 ok(SUCCEEDED(hr), "IDirect3DViewport_SetViewport returned %#x.\n", hr);
1548 i = 12345;
1549 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(offscreentest) / sizeof(offscreentest[0]),
1550 &transformdata, D3DTRANSFORM_CLIPPED,
1551 &i);
1552 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1553 ok(i == 0, "Offscreen is %d\n", i);
1554 vp_data.dwWidth = 256;
1555 vp_data.dwHeight = 256;
1556 hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
1557 ok(SUCCEEDED(hr), "IDirect3DViewport_SetViewport returned %#x.\n", hr);
1558 i = 12345;
1559 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(offscreentest) / sizeof(offscreentest[0]),
1560 &transformdata, D3DTRANSFORM_CLIPPED,
1561 &i);
1562 ok(hr == D3D_OK, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1563 ok(i == D3DCLIP_RIGHT, "Offscreen is %d\n", i);
1565 hr = IDirect3DViewport_TransformVertices(Viewport, sizeof(testverts) / sizeof(testverts[0]),
1566 &transformdata, 0,
1567 &i);
1568 ok(hr == DDERR_INVALIDPARAMS, "IDirect3DViewport_TransformVertices returned %08x\n", hr);
1570 hr = IDirect3DDevice_DeleteViewport(Direct3DDevice1, Viewport);
1571 ok(hr == D3D_OK, "IDirect3DDevice_DeleteViewport returned %08x\n", hr);
1573 hr = IDirect3DViewport_AddLight(Viewport, Light);
1574 ok(hr == D3D_OK, "IDirect3DViewport_AddLight returned %08x\n", hr);
1575 refcount = getRefcount((IUnknown*) Light);
1576 ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
1578 hr = IDirect3DViewport_NextLight(Viewport, NULL, &d3dlight, D3DNEXT_HEAD);
1579 ok(hr == D3D_OK, "IDirect3DViewport_AddLight returned %08x\n", hr);
1580 ok(d3dlight == Light, "Got different light returned %p, expected %p\n", d3dlight, Light);
1581 refcount = getRefcount((IUnknown*) Light);
1582 ok(refcount == 3, "Refcount should be 2, returned is %d\n", refcount);
1584 hr = IDirect3DViewport_DeleteLight(Viewport, Light);
1585 ok(hr == D3D_OK, "IDirect3DViewport_DeleteLight returned %08x\n", hr);
1586 refcount = getRefcount((IUnknown*) Light);
1587 ok(refcount == 2, "Refcount should be 2, returned is %d\n", refcount);
1589 IDirect3DLight_Release(Light);
1592 static BOOL colortables_check_equality(PALETTEENTRY table1[256], PALETTEENTRY table2[256])
1594 int i;
1596 for (i = 0; i < 256; i++) {
1597 if (table1[i].peRed != table2[i].peRed || table1[i].peGreen != table2[i].peGreen ||
1598 table1[i].peBlue != table2[i].peBlue) return FALSE;
1601 return TRUE;
1604 /* test palette handling in IDirect3DTexture_Load */
1605 static void TextureLoadTest(void)
1607 IDirectDrawSurface *TexSurface = NULL;
1608 IDirect3DTexture *Texture = NULL;
1609 IDirectDrawSurface *TexSurface2 = NULL;
1610 IDirect3DTexture *Texture2 = NULL;
1611 IDirectDrawPalette *palette = NULL;
1612 IDirectDrawPalette *palette2 = NULL;
1613 IDirectDrawPalette *palette_tmp = NULL;
1614 PALETTEENTRY table1[256], table2[256], table_tmp[256];
1615 HRESULT hr;
1616 DDSURFACEDESC ddsd;
1617 int i;
1619 memset (&ddsd, 0, sizeof (ddsd));
1620 ddsd.dwSize = sizeof (ddsd);
1621 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
1622 ddsd.dwHeight = 128;
1623 ddsd.dwWidth = 128;
1624 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1625 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1626 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
1627 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 8;
1629 hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface, NULL);
1630 ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1631 if (FAILED(hr)) {
1632 skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1633 goto cleanup;
1636 hr = IDirectDrawSurface_QueryInterface(TexSurface, &IID_IDirect3DTexture,
1637 (void *)&Texture);
1638 ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1639 if (FAILED(hr)) {
1640 skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1641 goto cleanup;
1644 hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface2, NULL);
1645 ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1646 if (FAILED(hr)) {
1647 skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1648 goto cleanup;
1651 hr = IDirectDrawSurface_QueryInterface(TexSurface2, &IID_IDirect3DTexture,
1652 (void *)&Texture2);
1653 ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1654 if (FAILED(hr)) {
1655 skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1656 goto cleanup;
1659 /* test load of Texture to Texture */
1660 hr = IDirect3DTexture_Load(Texture, Texture);
1661 ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1663 /* test Load when both textures have no palette */
1664 hr = IDirect3DTexture_Load(Texture2, Texture);
1665 ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1667 for (i = 0; i < 256; i++) {
1668 table1[i].peRed = i;
1669 table1[i].peGreen = i;
1670 table1[i].peBlue = i;
1671 table1[i].peFlags = 0;
1674 hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &palette, NULL);
1675 ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
1676 if (FAILED(hr)) {
1677 skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
1678 goto cleanup;
1681 /* test Load when source texture has palette and destination has no palette */
1682 hr = IDirectDrawSurface_SetPalette(TexSurface, palette);
1683 ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1684 hr = IDirect3DTexture_Load(Texture2, Texture);
1685 ok(hr == DDERR_NOPALETTEATTACHED, "IDirect3DTexture_Load returned %08x\n", hr);
1687 for (i = 0; i < 256; i++) {
1688 table2[i].peRed = 255 - i;
1689 table2[i].peGreen = 255 - i;
1690 table2[i].peBlue = 255 - i;
1691 table2[i].peFlags = 0;
1694 hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table2, &palette2, NULL);
1695 ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
1696 if (FAILED(hr)) {
1697 skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
1698 goto cleanup;
1701 /* test Load when source has no palette and destination has a palette */
1702 hr = IDirectDrawSurface_SetPalette(TexSurface, NULL);
1703 ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1704 hr = IDirectDrawSurface_SetPalette(TexSurface2, palette2);
1705 ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1706 hr = IDirect3DTexture_Load(Texture2, Texture);
1707 ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1708 hr = IDirectDrawSurface_GetPalette(TexSurface2, &palette_tmp);
1709 ok(hr == DD_OK, "IDirectDrawSurface_GetPalette returned %08x\n", hr);
1710 if (!palette_tmp) {
1711 skip("IDirectDrawSurface_GetPalette failed; skipping color table check\n");
1712 goto cleanup;
1713 } else {
1714 hr = IDirectDrawPalette_GetEntries(palette_tmp, 0, 0, 256, table_tmp);
1715 ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
1716 ok(colortables_check_equality(table2, table_tmp), "Unexpected palettized texture color table\n");
1717 IDirectDrawPalette_Release(palette_tmp);
1720 /* test Load when both textures have palettes */
1721 hr = IDirectDrawSurface_SetPalette(TexSurface, palette);
1722 ok(hr == DD_OK, "IDirectDrawSurface_SetPalette returned %08x\n", hr);
1723 hr = IDirect3DTexture_Load(Texture2, Texture);
1724 ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1725 hr = IDirect3DTexture_Load(Texture2, Texture);
1726 ok(hr == DD_OK, "IDirect3DTexture_Load returned %08x\n", hr);
1727 hr = IDirectDrawSurface_GetPalette(TexSurface2, &palette_tmp);
1728 ok(hr == DD_OK, "IDirectDrawSurface_GetPalette returned %08x\n", hr);
1729 if (!palette_tmp) {
1730 skip("IDirectDrawSurface_GetPalette failed; skipping color table check\n");
1731 goto cleanup;
1732 } else {
1733 hr = IDirectDrawPalette_GetEntries(palette_tmp, 0, 0, 256, table_tmp);
1734 ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
1735 ok(colortables_check_equality(table1, table_tmp), "Unexpected palettized texture color table\n");
1736 IDirectDrawPalette_Release(palette_tmp);
1739 cleanup:
1741 if (palette) IDirectDrawPalette_Release(palette);
1742 if (palette2) IDirectDrawPalette_Release(palette2);
1743 if (TexSurface) IDirectDrawSurface_Release(TexSurface);
1744 if (Texture) IDirect3DTexture_Release(Texture);
1745 if (TexSurface2) IDirectDrawSurface_Release(TexSurface2);
1746 if (Texture2) IDirect3DTexture_Release(Texture2);
1749 static void VertexBufferDescTest(void)
1751 HRESULT rc;
1752 D3DVERTEXBUFFERDESC desc;
1753 union mem_t
1755 D3DVERTEXBUFFERDESC desc2;
1756 unsigned char buffer[512];
1757 } mem;
1759 memset(&desc, 0, sizeof(desc));
1760 desc.dwSize = sizeof(desc);
1761 desc.dwCaps = 0;
1762 desc.dwFVF = D3DFVF_XYZ;
1763 desc.dwNumVertices = 1;
1764 rc = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &lpVBufSrc, 0);
1765 ok(rc==D3D_OK || rc==E_OUTOFMEMORY, "CreateVertexBuffer returned: %x\n", rc);
1766 if (!lpVBufSrc)
1768 trace("IDirect3D7::CreateVertexBuffer() failed with an error %x\n", rc);
1769 goto out;
1772 memset(mem.buffer, 0x12, sizeof(mem.buffer));
1773 mem.desc2.dwSize = sizeof(D3DVERTEXBUFFERDESC)*2;
1774 rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1775 if(rc != D3D_OK)
1776 skip("GetVertexBuffer Failed!\n");
1777 ok( mem.desc2.dwSize == sizeof(D3DVERTEXBUFFERDESC)*2, "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1778 ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was double the size of the struct)\n");
1779 ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1780 ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1781 ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1783 memset(mem.buffer, 0x12, sizeof(mem.buffer));
1784 mem.desc2.dwSize = 0;
1785 rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1786 if(rc != D3D_OK)
1787 skip("GetVertexBuffer Failed!\n");
1788 ok( mem.desc2.dwSize == 0, "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1789 ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was 0)\n");
1790 ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1791 ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1792 ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1794 memset(mem.buffer, 0x12, sizeof(mem.buffer));
1795 mem.desc2.dwSize = sizeof(D3DVERTEXBUFFERDESC);
1796 rc = IDirect3DVertexBuffer7_GetVertexBufferDesc(lpVBufSrc, &mem.desc2);
1797 if(rc != D3D_OK)
1798 skip("GetVertexBuffer Failed!\n");
1799 ok( mem.desc2.dwSize == sizeof(D3DVERTEXBUFFERDESC), "Size returned from GetVertexBufferDesc does not match the value put in\n" );
1800 ok( mem.buffer[sizeof(D3DVERTEXBUFFERDESC)] == 0x12, "GetVertexBufferDesc cleared outside of the struct! (dwSize was the size of the struct)\n");
1801 ok( mem.desc2.dwCaps == desc.dwCaps, "dwCaps returned differs. Got %x, expected %x\n", mem.desc2.dwCaps, desc.dwCaps);
1802 ok( mem.desc2.dwFVF == desc.dwFVF, "dwFVF returned differs. Got %x, expected %x\n", mem.desc2.dwFVF, desc.dwFVF);
1803 ok (mem.desc2.dwNumVertices == desc.dwNumVertices, "dwNumVertices returned differs. Got %x, expected %x\n", mem.desc2.dwNumVertices, desc.dwNumVertices);
1805 out:
1806 IDirect3DVertexBuffer7_Release(lpVBufSrc);
1809 static void D3D7_OldRenderStateTest(void)
1811 HRESULT hr;
1812 DWORD val;
1814 /* Test reaction to some deprecated states in D3D7. */
1815 hr = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1816 ok(hr == DDERR_INVALIDPARAMS, "IDirect3DDevice7_SetRenderState returned %#x.\n", hr);
1817 hr = IDirect3DDevice7_GetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREHANDLE, &val);
1818 ok(hr == DDERR_INVALIDPARAMS, "IDirect3DDevice7_GetRenderState returned %#x.\n", hr);
1819 hr = IDirect3DDevice7_SetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
1820 ok(hr == DDERR_INVALIDPARAMS, "IDirect3DDevice7_SetRenderState returned %#x.\n", hr);
1821 hr = IDirect3DDevice7_GetRenderState(lpD3DDevice, D3DRENDERSTATE_TEXTUREMAPBLEND, &val);
1822 ok(hr == DDERR_INVALIDPARAMS, "IDirect3DDevice7_GetRenderState returned %#x.\n", hr);
1825 #define IS_VALUE_NEAR(a, b) ( ((a) == (b)) || ((a) == (b) - 1) || ((a) == (b) + 1) )
1826 #define MIN(a, b) ((a) < (b) ? (a) : (b))
1828 static void DeviceLoadTest(void)
1830 DDSURFACEDESC2 ddsd;
1831 IDirectDrawSurface7 *texture_levels[2][8];
1832 IDirectDrawSurface7 *cube_face_levels[2][6][8];
1833 DWORD flags;
1834 HRESULT hr;
1835 DDBLTFX ddbltfx;
1836 RECT loadrect;
1837 POINT loadpoint;
1838 int i, i1, i2;
1839 unsigned diff_count = 0, diff_count2 = 0;
1840 unsigned x, y;
1841 BOOL load_mip_subset_broken = FALSE;
1842 IDirectDrawPalette *palettes[5];
1843 PALETTEENTRY table1[256];
1844 DDCOLORKEY ddckey;
1845 D3DDEVICEDESC7 d3dcaps;
1847 /* Test loading of texture subrectangle with a mipmap surface. */
1848 memset(texture_levels, 0, sizeof(texture_levels));
1849 memset(cube_face_levels, 0, sizeof(cube_face_levels));
1850 memset(palettes, 0, sizeof(palettes));
1852 for (i = 0; i < 2; i++)
1854 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1855 ddsd.dwSize = sizeof(ddsd);
1856 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1857 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1858 ddsd.dwWidth = 128;
1859 ddsd.dwHeight = 128;
1860 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1861 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1862 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
1863 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
1864 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
1865 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
1866 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
1867 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1868 if (FAILED(hr)) goto out;
1870 /* Check the number of created mipmaps */
1871 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1872 ddsd.dwSize = sizeof(ddsd);
1873 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
1874 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
1875 ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
1876 if (U2(ddsd).dwMipMapCount != 8) goto out;
1878 for (i1 = 1; i1 < 8; i1++)
1880 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
1881 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1882 if (FAILED(hr)) goto out;
1886 for (i1 = 0; i1 < 8; i1++)
1888 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1889 ddsd.dwSize = sizeof(ddsd);
1890 hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1891 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1892 if (FAILED(hr)) goto out;
1894 for (y = 0 ; y < ddsd.dwHeight; y++)
1896 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1898 for (x = 0; x < ddsd.dwWidth; x++)
1900 /* x stored in green component, y in blue. */
1901 DWORD color = 0xff0000 | (x << 8) | y;
1902 *textureRow++ = color;
1906 hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
1907 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
1910 for (i1 = 0; i1 < 8; i1++)
1912 memset(&ddbltfx, 0, sizeof(ddbltfx));
1913 ddbltfx.dwSize = sizeof(ddbltfx);
1914 U5(ddbltfx).dwFillColor = 0;
1915 hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1916 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
1919 /* First test some broken coordinates. */
1920 loadpoint.x = loadpoint.y = 0;
1921 loadrect.left = 0;
1922 loadrect.top = 0;
1923 loadrect.right = 0;
1924 loadrect.bottom = 0;
1925 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1926 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1928 loadpoint.x = loadpoint.y = 50;
1929 loadrect.left = 0;
1930 loadrect.top = 0;
1931 loadrect.right = 100;
1932 loadrect.bottom = 100;
1933 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1934 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
1936 /* Test actual loading. */
1937 loadpoint.x = loadpoint.y = 31;
1938 loadrect.left = 30;
1939 loadrect.top = 20;
1940 loadrect.right = 93;
1941 loadrect.bottom = 52;
1943 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
1944 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
1946 for (i1 = 0; i1 < 8; i1++)
1948 diff_count = 0;
1949 diff_count2 = 0;
1951 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
1952 ddsd.dwSize = sizeof(ddsd);
1953 hr = IDirectDrawSurface7_Lock(texture_levels[1][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
1954 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
1955 if (FAILED(hr)) goto out;
1957 for (y = 0 ; y < ddsd.dwHeight; y++)
1959 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
1961 for (x = 0; x < ddsd.dwWidth; x++)
1963 DWORD color = *textureRow++;
1965 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
1966 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
1968 if (color & 0xffffff) diff_count++;
1970 else
1972 DWORD r = (color & 0xff0000) >> 16;
1973 DWORD g = (color & 0xff00) >> 8;
1974 DWORD b = (color & 0xff);
1976 if (r != 0xff || g != x + loadrect.left - loadpoint.x || b != y + loadrect.top - loadpoint.y) diff_count++;
1979 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
1980 technically be correct as it's not precisely defined by docs. */
1981 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
1982 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
1984 if (color & 0xffffff) diff_count2++;
1986 else
1988 DWORD r = (color & 0xff0000) >> 16;
1989 DWORD g = (color & 0xff00) >> 8;
1990 DWORD b = (color & 0xff);
1992 if (r != 0xff || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
1993 !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
1998 hr = IDirectDrawSurface7_Unlock(texture_levels[1][i1], NULL);
1999 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2001 ok(diff_count == 0 || diff_count2 == 0, "Unexpected destination texture level pixels; %u differences at %d level\n",
2002 MIN(diff_count, diff_count2), i1);
2004 loadpoint.x /= 2;
2005 loadpoint.y /= 2;
2006 loadrect.top /= 2;
2007 loadrect.left /= 2;
2008 loadrect.right = (loadrect.right + 1) / 2;
2009 loadrect.bottom = (loadrect.bottom + 1) / 2;
2012 /* This crashes on native (tested on real windows XP / directx9 / nvidia and
2013 * qemu Win98 / directx7 / RGB software rasterizer):
2014 * passing non toplevel surfaces (sublevels) to Load (DX7 docs tell not to do this)
2015 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][1], NULL, texture_levels[0][1], NULL, 0);
2018 /* Freed in reverse order as native seems to dislike and crash on freeing top level surface first. */
2019 for (i = 0; i < 2; i++)
2021 for (i1 = 7; i1 >= 0; i1--)
2023 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2026 memset(texture_levels, 0, sizeof(texture_levels));
2028 /* Test texture size mismatch. */
2029 for (i = 0; i < 2; i++)
2031 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2032 ddsd.dwSize = sizeof(ddsd);
2033 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2034 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2035 ddsd.dwWidth = i ? 256 : 128;
2036 ddsd.dwHeight = 128;
2037 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2038 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2039 if (FAILED(hr)) goto out;
2042 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2043 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2045 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[0][0], NULL, texture_levels[1][0], NULL, 0);
2046 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2048 IDirectDrawSurface7_Release(texture_levels[0][0]);
2049 IDirectDrawSurface7_Release(texture_levels[1][0]);
2050 memset(texture_levels, 0, sizeof(texture_levels));
2052 memset(&d3dcaps, 0, sizeof(d3dcaps));
2053 hr = IDirect3DDevice7_GetCaps(lpD3DDevice, &d3dcaps);
2054 ok(hr == D3D_OK, "IDirect3DDevice7_GetCaps returned %08x\n", hr);
2056 if (!(d3dcaps.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP))
2058 skip("No cubemap support\n");
2060 else
2062 /* Test loading mipmapped cubemap texture subrectangle from another similar texture. */
2063 for (i = 0; i < 2; i++)
2065 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2066 ddsd.dwSize = sizeof(ddsd);
2067 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2068 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2069 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
2070 ddsd.dwWidth = 128;
2071 ddsd.dwHeight = 128;
2072 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2073 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2074 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2075 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2076 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2077 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2078 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[i][0][0], NULL);
2079 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2080 if (FAILED(hr)) goto out;
2082 flags = DDSCAPS2_CUBEMAP_NEGATIVEX;
2083 for (i1 = 1; i1 < 6; i1++, flags <<= 1)
2085 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2086 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | flags;
2087 hr = IDirectDrawSurface7_GetAttachedSurface(cube_face_levels[i][0][0], &ddsd.ddsCaps, &cube_face_levels[i][i1][0]);
2088 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2089 if (FAILED(hr)) goto out;
2092 for (i1 = 0; i1 < 6; i1++)
2094 /* Check the number of created mipmaps */
2095 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2096 ddsd.dwSize = sizeof(ddsd);
2097 hr = IDirectDrawSurface7_GetSurfaceDesc(cube_face_levels[i][i1][0], &ddsd);
2098 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2099 ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2100 if (U2(ddsd).dwMipMapCount != 8) goto out;
2102 for (i2 = 1; i2 < 8; i2++)
2104 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
2105 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
2106 hr = IDirectDrawSurface7_GetAttachedSurface(cube_face_levels[i][i1][i2 - 1], &ddsd.ddsCaps, &cube_face_levels[i][i1][i2]);
2107 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2108 if (FAILED(hr)) goto out;
2113 for (i = 0; i < 6; i++)
2114 for (i1 = 0; i1 < 8; i1++)
2116 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2117 ddsd.dwSize = sizeof(ddsd);
2118 hr = IDirectDrawSurface7_Lock(cube_face_levels[0][i][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2119 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2120 if (FAILED(hr)) goto out;
2122 for (y = 0 ; y < ddsd.dwHeight; y++)
2124 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2126 for (x = 0; x < ddsd.dwWidth; x++)
2128 /* face number in low 4 bits of red, x stored in green component, y in blue. */
2129 DWORD color = 0xf00000 | (i << 16) | (x << 8) | y;
2130 *textureRow++ = color;
2134 hr = IDirectDrawSurface7_Unlock(cube_face_levels[0][i][i1], NULL);
2135 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2138 for (i = 0; i < 6; i++)
2139 for (i1 = 0; i1 < 8; i1++)
2141 memset(&ddbltfx, 0, sizeof(ddbltfx));
2142 ddbltfx.dwSize = sizeof(ddbltfx);
2143 U5(ddbltfx).dwFillColor = 0;
2144 hr = IDirectDrawSurface7_Blt(cube_face_levels[1][i][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2145 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2148 loadpoint.x = loadpoint.y = 10;
2149 loadrect.left = 30;
2150 loadrect.top = 20;
2151 loadrect.right = 93;
2152 loadrect.bottom = 52;
2154 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], &loadpoint, cube_face_levels[0][0][0], &loadrect,
2155 DDSCAPS2_CUBEMAP_ALLFACES);
2156 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2158 for (i = 0; i < 6; i++)
2160 loadpoint.x = loadpoint.y = 10;
2161 loadrect.left = 30;
2162 loadrect.top = 20;
2163 loadrect.right = 93;
2164 loadrect.bottom = 52;
2166 for (i1 = 0; i1 < 8; i1++)
2168 diff_count = 0;
2169 diff_count2 = 0;
2171 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2172 ddsd.dwSize = sizeof(ddsd);
2173 hr = IDirectDrawSurface7_Lock(cube_face_levels[1][i][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2174 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2175 if (FAILED(hr)) goto out;
2177 for (y = 0 ; y < ddsd.dwHeight; y++)
2179 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2181 for (x = 0; x < ddsd.dwWidth; x++)
2183 DWORD color = *textureRow++;
2185 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2186 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2188 if (color & 0xffffff) diff_count++;
2190 else
2192 DWORD r = (color & 0xff0000) >> 16;
2193 DWORD g = (color & 0xff00) >> 8;
2194 DWORD b = (color & 0xff);
2196 if (r != (0xf0 | i) || g != x + loadrect.left - loadpoint.x ||
2197 b != y + loadrect.top - loadpoint.y) diff_count++;
2200 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
2201 technically be correct as it's not precisely defined by docs. */
2202 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2203 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
2205 if (color & 0xffffff) diff_count2++;
2207 else
2209 DWORD r = (color & 0xff0000) >> 16;
2210 DWORD g = (color & 0xff00) >> 8;
2211 DWORD b = (color & 0xff);
2213 if (r != (0xf0 | i) || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
2214 !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
2219 hr = IDirectDrawSurface7_Unlock(cube_face_levels[1][i][i1], NULL);
2220 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2222 ok(diff_count == 0 || diff_count2 == 0,
2223 "Unexpected destination texture level pixels; %u differences at face %x level %d\n",
2224 MIN(diff_count, diff_count2), i, i1);
2226 loadpoint.x /= 2;
2227 loadpoint.y /= 2;
2228 loadrect.top /= 2;
2229 loadrect.left /= 2;
2230 loadrect.right = (loadrect.right + 1) / 2;
2231 loadrect.bottom = (loadrect.bottom + 1) / 2;
2235 for (i = 0; i < 2; i++)
2236 for (i1 = 5; i1 >= 0; i1--)
2237 for (i2 = 7; i2 >= 0; i2--)
2239 if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]);
2241 memset(cube_face_levels, 0, sizeof(cube_face_levels));
2243 /* Test cubemap loading from regular texture. */
2244 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2245 ddsd.dwSize = sizeof(ddsd);
2246 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2247 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2248 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
2249 ddsd.dwWidth = 128;
2250 ddsd.dwHeight = 128;
2251 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[0][0][0], NULL);
2252 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2253 if (FAILED(hr)) goto out;
2255 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2256 ddsd.dwSize = sizeof(ddsd);
2257 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2258 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2259 ddsd.dwWidth = 128;
2260 ddsd.dwHeight = 128;
2261 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[0][0], NULL);
2262 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2263 if (FAILED(hr)) goto out;
2265 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, texture_levels[0][0], NULL,
2266 DDSCAPS2_CUBEMAP_ALLFACES);
2267 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2269 IDirectDrawSurface7_Release(cube_face_levels[0][0][0]);
2270 memset(cube_face_levels, 0, sizeof(cube_face_levels));
2271 IDirectDrawSurface7_Release(texture_levels[0][0]);
2272 memset(texture_levels, 0, sizeof(texture_levels));
2274 /* Test cubemap loading from cubemap with different number of faces. */
2275 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2276 ddsd.dwSize = sizeof(ddsd);
2277 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2278 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2279 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX;
2280 ddsd.dwWidth = 128;
2281 ddsd.dwHeight = 128;
2282 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[0][0][0], NULL);
2283 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2284 if (FAILED(hr)) goto out;
2286 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2287 ddsd.dwSize = sizeof(ddsd);
2288 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2289 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2290 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_POSITIVEY;
2291 ddsd.dwWidth = 128;
2292 ddsd.dwHeight = 128;
2293 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &cube_face_levels[1][0][0], NULL);
2294 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2295 if (FAILED(hr)) goto out;
2297 /* INVALIDPARAMS tests currently would fail because wine doesn't support partial cube faces
2298 (the above created cubemaps will have all faces. */
2299 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2300 DDSCAPS2_CUBEMAP_ALLFACES);
2301 todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2303 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2304 DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_POSITIVEY);
2305 todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2307 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[0][0][0], NULL, cube_face_levels[1][0][0], NULL,
2308 DDSCAPS2_CUBEMAP_POSITIVEX);
2309 todo_wine ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2311 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2312 DDSCAPS2_CUBEMAP_ALLFACES);
2313 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2315 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2316 DDSCAPS2_CUBEMAP_POSITIVEX);
2317 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2319 hr = IDirect3DDevice7_Load(lpD3DDevice, cube_face_levels[1][0][0], NULL, cube_face_levels[0][0][0], NULL,
2320 DDSCAPS2_CUBEMAP_POSITIVEZ);
2321 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2323 IDirectDrawSurface7_Release(cube_face_levels[0][0][0]);
2324 IDirectDrawSurface7_Release(cube_face_levels[1][0][0]);
2325 memset(cube_face_levels, 0, sizeof(cube_face_levels));
2328 /* Test texture loading with different mip level count (larger levels match, smaller levels missing in destination. */
2329 for (i = 0; i < 2; i++)
2331 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2332 ddsd.dwSize = sizeof(ddsd);
2333 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_MIPMAPCOUNT;
2334 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2335 ddsd.dwWidth = 128;
2336 ddsd.dwHeight = 128;
2337 U2(ddsd).dwMipMapCount = i ? 4 : 8;
2338 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2339 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2340 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2341 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2342 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2343 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2344 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2345 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2346 if (FAILED(hr)) goto out;
2348 /* Check the number of created mipmaps */
2349 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2350 ddsd.dwSize = sizeof(ddsd);
2351 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2352 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2353 ok(U2(ddsd).dwMipMapCount == (i ? 4 : 8), "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2354 if (U2(ddsd).dwMipMapCount != (i ? 4 : 8)) goto out;
2356 for (i1 = 1; i1 < (i ? 4 : 8); i1++)
2358 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2359 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2360 if (FAILED(hr)) goto out;
2364 for (i1 = 0; i1 < 8; i1++)
2366 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2367 ddsd.dwSize = sizeof(ddsd);
2368 hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2369 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2370 if (FAILED(hr)) goto out;
2372 for (y = 0 ; y < ddsd.dwHeight; y++)
2374 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2376 for (x = 0; x < ddsd.dwWidth; x++)
2378 /* x stored in green component, y in blue. */
2379 DWORD color = 0xf00000 | (i1 << 16) | (x << 8) | y;
2380 *textureRow++ = color;
2384 hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2385 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2388 for (i1 = 0; i1 < 4; i1++)
2390 memset(&ddbltfx, 0, sizeof(ddbltfx));
2391 ddbltfx.dwSize = sizeof(ddbltfx);
2392 U5(ddbltfx).dwFillColor = 0;
2393 hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2394 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2397 loadpoint.x = loadpoint.y = 31;
2398 loadrect.left = 30;
2399 loadrect.top = 20;
2400 loadrect.right = 93;
2401 loadrect.bottom = 52;
2403 /* Destination mip levels are a subset of source mip levels. */
2404 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2405 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2407 for (i1 = 0; i1 < 4; i1++)
2409 diff_count = 0;
2410 diff_count2 = 0;
2412 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2413 ddsd.dwSize = sizeof(ddsd);
2414 hr = IDirectDrawSurface7_Lock(texture_levels[1][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2415 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2416 if (FAILED(hr)) goto out;
2418 for (y = 0 ; y < ddsd.dwHeight; y++)
2420 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2422 for (x = 0; x < ddsd.dwWidth; x++)
2424 DWORD color = *textureRow++;
2426 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2427 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2429 if (color & 0xffffff) diff_count++;
2431 else
2433 DWORD r = (color & 0xff0000) >> 16;
2434 DWORD g = (color & 0xff00) >> 8;
2435 DWORD b = (color & 0xff);
2437 if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x ||
2438 b != y + loadrect.top - loadpoint.y) diff_count++;
2441 /* This codepath is for software RGB device. It has what looks like some weird off by one errors, but may
2442 technically be correct as it's not precisely defined by docs. */
2443 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2444 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top + 1)
2446 if (color & 0xffffff) diff_count2++;
2448 else
2450 DWORD r = (color & 0xff0000) >> 16;
2451 DWORD g = (color & 0xff00) >> 8;
2452 DWORD b = (color & 0xff);
2454 if (r != (0xf0 | i1) || !IS_VALUE_NEAR(g, x + loadrect.left - loadpoint.x) ||
2455 !IS_VALUE_NEAR(b, y + loadrect.top - loadpoint.y)) diff_count2++;
2460 hr = IDirectDrawSurface7_Unlock(texture_levels[1][i1], NULL);
2461 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2463 ok(diff_count == 0 || diff_count2 == 0, "Unexpected destination texture level pixels; %u differences at %d level\n",
2464 MIN(diff_count, diff_count2), i1);
2466 loadpoint.x /= 2;
2467 loadpoint.y /= 2;
2468 loadrect.top /= 2;
2469 loadrect.left /= 2;
2470 loadrect.right = (loadrect.right + 1) / 2;
2471 loadrect.bottom = (loadrect.bottom + 1) / 2;
2474 /* Destination mip levels are a superset of source mip levels (should fail). */
2475 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[0][0], &loadpoint, texture_levels[1][0], &loadrect, 0);
2476 ok(hr==DDERR_INVALIDPARAMS, "IDirect3DDevice7_Load returned: %x\n",hr);
2478 for (i = 0; i < 2; i++)
2480 for (i1 = 7; i1 >= 0; i1--)
2482 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2485 memset(texture_levels, 0, sizeof(texture_levels));
2487 /* Test loading from mipmap texture to a regular texture that matches one sublevel in size. */
2488 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2489 ddsd.dwSize = sizeof(ddsd);
2490 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2491 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2492 ddsd.dwWidth = 128;
2493 ddsd.dwHeight = 128;
2494 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2495 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2496 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2497 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2498 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2499 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2500 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[0][0], NULL);
2501 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2502 if (FAILED(hr)) goto out;
2504 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2505 ddsd.dwSize = sizeof(ddsd);
2506 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2507 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2508 ddsd.dwWidth = 32;
2509 ddsd.dwHeight = 32;
2510 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2511 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2512 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2513 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2514 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2515 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2516 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[1][0], NULL);
2517 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2518 if (FAILED(hr)) goto out;
2520 for (i1 = 1; i1 < 8; i1++)
2522 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[0][i1 - 1], &ddsd.ddsCaps, &texture_levels[0][i1]);
2523 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2524 if (FAILED(hr)) goto out;
2527 for (i1 = 0; i1 < 8; i1++)
2529 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2530 ddsd.dwSize = sizeof(ddsd);
2531 hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2532 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2533 if (FAILED(hr)) goto out;
2535 for (y = 0 ; y < ddsd.dwHeight; y++)
2537 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2539 for (x = 0; x < ddsd.dwWidth; x++)
2541 /* x stored in green component, y in blue. */
2542 DWORD color = 0xf00000 | (i1 << 16) | (x << 8) | y;
2543 *textureRow++ = color;
2547 hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2548 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2551 memset(&ddbltfx, 0, sizeof(ddbltfx));
2552 ddbltfx.dwSize = sizeof(ddbltfx);
2553 U5(ddbltfx).dwFillColor = 0;
2554 hr = IDirectDrawSurface7_Blt(texture_levels[1][0], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2555 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2557 loadpoint.x = loadpoint.y = 32;
2558 loadrect.left = 32;
2559 loadrect.top = 32;
2560 loadrect.right = 96;
2561 loadrect.bottom = 96;
2563 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2564 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2566 loadpoint.x /= 4;
2567 loadpoint.y /= 4;
2568 loadrect.top /= 4;
2569 loadrect.left /= 4;
2570 loadrect.right = (loadrect.right + 3) / 4;
2571 loadrect.bottom = (loadrect.bottom + 3) / 4;
2573 /* NOTE: something in either nvidia driver or directx9 on WinXP appears to be broken:
2574 * this kind of Load calls (to subset with smaller surface(s)) produces wrong results with
2575 * copied subrectangles divided more than needed, without apparent logic. But it works
2576 * as expected on qemu / Win98 / directx7 / RGB device. Some things are broken on XP, e.g.
2577 * some games don't work that worked in Win98, so it is assumed here XP results are wrong.
2578 * The following code attempts to detect broken results, actual tests will then be skipped
2580 load_mip_subset_broken = TRUE;
2581 diff_count = 0;
2583 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2584 ddsd.dwSize = sizeof(ddsd);
2585 hr = IDirectDrawSurface7_Lock(texture_levels[1][0], NULL, &ddsd, DDLOCK_WAIT, NULL);
2586 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2587 if (FAILED(hr)) goto out;
2589 for (y = 0 ; y < ddsd.dwHeight; y++)
2591 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2593 for (x = 0; x < ddsd.dwWidth; x++)
2595 DWORD color = *textureRow++;
2597 if (x < 2 || x >= 2 + 4 ||
2598 y < 2 || y >= 2 + 4)
2600 if (color & 0xffffff) diff_count++;
2602 else
2604 DWORD r = (color & 0xff0000) >> 16;
2606 if ((r & (0xf0)) != 0xf0) diff_count++;
2611 if (diff_count) load_mip_subset_broken = FALSE;
2613 if (load_mip_subset_broken) {
2614 skip("IDirect3DDevice7_Load is broken (happens on some modern Windows installations like XP). Skipping affected tests.\n");
2615 } else {
2616 diff_count = 0;
2618 for (y = 0 ; y < ddsd.dwHeight; y++)
2620 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2622 for (x = 0; x < ddsd.dwWidth; x++)
2624 DWORD color = *textureRow++;
2626 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2627 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2629 if (color & 0xffffff) diff_count++;
2631 else
2633 DWORD r = (color & 0xff0000) >> 16;
2634 DWORD g = (color & 0xff00) >> 8;
2635 DWORD b = (color & 0xff);
2637 if (r != (0xf0 | 2) || g != x + loadrect.left - loadpoint.x ||
2638 b != y + loadrect.top - loadpoint.y) diff_count++;
2644 hr = IDirectDrawSurface7_Unlock(texture_levels[1][0], NULL);
2645 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2647 ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences\n", diff_count);
2649 for (i = 0; i < 2; i++)
2651 for (i1 = 7; i1 >= 0; i1--)
2653 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2656 memset(texture_levels, 0, sizeof(texture_levels));
2658 if (!load_mip_subset_broken)
2660 /* Test loading when destination mip levels are a subset of source mip levels and start from smaller
2661 * surface (than first source mip level)
2663 for (i = 0; i < 2; i++)
2665 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2666 ddsd.dwSize = sizeof(ddsd);
2667 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2668 if (i) ddsd.dwFlags |= DDSD_MIPMAPCOUNT;
2669 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2670 ddsd.dwWidth = i ? 32 : 128;
2671 ddsd.dwHeight = i ? 32 : 128;
2672 if (i) U2(ddsd).dwMipMapCount = 4;
2673 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2674 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2675 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2676 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2677 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2678 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2679 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2680 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2681 if (FAILED(hr)) goto out;
2683 /* Check the number of created mipmaps */
2684 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2685 ddsd.dwSize = sizeof(ddsd);
2686 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2687 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2688 ok(U2(ddsd).dwMipMapCount == (i ? 4 : 8), "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2689 if (U2(ddsd).dwMipMapCount != (i ? 4 : 8)) goto out;
2691 for (i1 = 1; i1 < (i ? 4 : 8); i1++)
2693 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2694 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2695 if (FAILED(hr)) goto out;
2699 for (i1 = 0; i1 < 8; i1++)
2701 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2702 ddsd.dwSize = sizeof(ddsd);
2703 hr = IDirectDrawSurface7_Lock(texture_levels[0][i1], NULL, &ddsd, DDLOCK_WAIT, NULL);
2704 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2705 if (FAILED(hr)) goto out;
2707 for (y = 0 ; y < ddsd.dwHeight; y++)
2709 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2711 for (x = 0; x < ddsd.dwWidth; x++)
2713 /* x stored in green component, y in blue. */
2714 DWORD color = 0xf00000 | (i1 << 16) | (x << 8) | y;
2715 *textureRow++ = color;
2719 hr = IDirectDrawSurface7_Unlock(texture_levels[0][i1], NULL);
2720 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2723 for (i1 = 0; i1 < 4; i1++)
2725 memset(&ddbltfx, 0, sizeof(ddbltfx));
2726 ddbltfx.dwSize = sizeof(ddbltfx);
2727 U5(ddbltfx).dwFillColor = 0;
2728 hr = IDirectDrawSurface7_Blt(texture_levels[1][i1], NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2729 ok(hr == DD_OK, "IDirectDrawSurface7_Blt failed with %08x\n", hr);
2732 loadpoint.x = loadpoint.y = 0;
2733 loadrect.left = 0;
2734 loadrect.top = 0;
2735 loadrect.right = 64;
2736 loadrect.bottom = 64;
2738 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], &loadpoint, texture_levels[0][0], &loadrect, 0);
2739 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2741 i = 0;
2742 for (i1 = 0; i1 < 8 && i < 4; i1++)
2744 DDSURFACEDESC2 ddsd2;
2746 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2747 ddsd.dwSize = sizeof(ddsd);
2748 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[0][i1], &ddsd);
2749 ok(SUCCEEDED(hr), "IDirectDrawSurface7_GetSurfaceDesc returned %#x.\n", hr);
2751 memset(&ddsd2, 0, sizeof(DDSURFACEDESC2));
2752 ddsd2.dwSize = sizeof(ddsd2);
2753 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[1][i], &ddsd2);
2754 ok(SUCCEEDED(hr), "IDirectDrawSurface7_GetSurfaceDesc returned %#x.\n", hr);
2756 if (ddsd.dwWidth == ddsd2.dwWidth && ddsd.dwHeight == ddsd2.dwHeight)
2758 diff_count = 0;
2760 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2761 ddsd.dwSize = sizeof(ddsd);
2762 hr = IDirectDrawSurface7_Lock(texture_levels[1][i], NULL, &ddsd, DDLOCK_WAIT, NULL);
2763 ok(hr==DD_OK, "IDirectDrawSurface7_Lock returned: %x\n",hr);
2764 if (FAILED(hr)) goto out;
2766 for (y = 0 ; y < ddsd.dwHeight; y++)
2768 DWORD *textureRow = (DWORD*)((char*)ddsd.lpSurface + y * U1(ddsd).lPitch);
2770 for (x = 0; x < ddsd.dwWidth; x++)
2772 DWORD color = *textureRow++;
2774 if (x < loadpoint.x || x >= loadpoint.x + loadrect.right - loadrect.left ||
2775 y < loadpoint.y || y >= loadpoint.y + loadrect.bottom - loadrect.top)
2777 if (color & 0xffffff) diff_count++;
2779 else
2781 DWORD r = (color & 0xff0000) >> 16;
2782 DWORD g = (color & 0xff00) >> 8;
2783 DWORD b = (color & 0xff);
2785 if (r != (0xf0 | i1) || g != x + loadrect.left - loadpoint.x ||
2786 b != y + loadrect.top - loadpoint.y) diff_count++;
2791 hr = IDirectDrawSurface7_Unlock(texture_levels[1][i], NULL);
2792 ok(hr==DD_OK, "IDirectDrawSurface7_Unlock returned: %x\n",hr);
2794 ok(diff_count == 0, "Unexpected destination texture level pixels; %u differences at %d level\n", diff_count, i1);
2796 i++;
2799 loadpoint.x /= 2;
2800 loadpoint.y /= 2;
2801 loadrect.top /= 2;
2802 loadrect.left /= 2;
2803 loadrect.right = (loadrect.right + 1) / 2;
2804 loadrect.bottom = (loadrect.bottom + 1) / 2;
2807 for (i = 0; i < 2; i++)
2809 for (i1 = 7; i1 >= 0; i1--)
2811 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2814 memset(texture_levels, 0, sizeof(texture_levels));
2817 /* Test palette copying. */
2818 for (i = 0; i < 2; i++)
2820 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2821 ddsd.dwSize = sizeof(ddsd);
2822 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2823 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2824 ddsd.dwWidth = 128;
2825 ddsd.dwHeight = 128;
2826 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2827 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
2828 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 8;
2829 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &texture_levels[i][0], NULL);
2830 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2831 if (FAILED(hr)) goto out;
2833 /* Check the number of created mipmaps */
2834 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2835 ddsd.dwSize = sizeof(ddsd);
2836 hr = IDirectDrawSurface7_GetSurfaceDesc(texture_levels[i][0], &ddsd);
2837 ok(hr==DD_OK,"IDirectDrawSurface7_GetSurfaceDesc returned: %x\n",hr);
2838 ok(U2(ddsd).dwMipMapCount == 8, "unexpected mip count %u\n", U2(ddsd).dwMipMapCount);
2839 if (U2(ddsd).dwMipMapCount != 8) goto out;
2841 for (i1 = 1; i1 < 8; i1++)
2843 hr = IDirectDrawSurface7_GetAttachedSurface(texture_levels[i][i1 - 1], &ddsd.ddsCaps, &texture_levels[i][i1]);
2844 ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
2845 if (FAILED(hr)) goto out;
2849 memset(table1, 0, sizeof(table1));
2850 for (i = 0; i < 3; i++)
2852 table1[0].peBlue = i + 1;
2853 hr = IDirectDraw7_CreatePalette(lpDD, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &palettes[i], NULL);
2854 ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
2855 if (FAILED(hr))
2857 skip("IDirectDraw7_CreatePalette failed; skipping further tests\n");
2858 goto out;
2862 hr = IDirectDrawSurface7_SetPalette(texture_levels[0][0], palettes[0]);
2863 ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2865 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2866 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2868 hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]);
2869 ok(hr==DDERR_NOPALETTEATTACHED, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2871 hr = IDirectDrawSurface7_SetPalette(texture_levels[0][1], palettes[1]);
2872 todo_wine ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2873 hr = IDirectDrawSurface7_SetPalette(texture_levels[1][0], palettes[2]);
2874 ok(hr==DD_OK, "IDirectDrawSurface7_SetPalette returned: %x\n", hr);
2876 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2877 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2879 memset(table1, 0, sizeof(table1));
2880 hr = IDirectDrawSurface7_GetPalette(texture_levels[1][0], &palettes[4]);
2881 ok(hr==DD_OK, "IDirectDrawSurface7_GetPalette returned: %x\n", hr);
2882 if (SUCCEEDED(hr))
2884 hr = IDirectDrawPalette_GetEntries(palettes[4], 0, 0, 256, table1);
2885 ok(hr == DD_OK, "IDirectDrawPalette_GetEntries returned %08x\n", hr);
2886 ok(table1[0].peBlue == 1, "Unexpected palette color after load: %u\n", (unsigned)table1[0].peBlue);
2889 /* Test colorkey copying. */
2890 ddckey.dwColorSpaceLowValue = ddckey.dwColorSpaceHighValue = 64;
2891 hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][0], DDCKEY_SRCBLT, &ddckey);
2892 ok(hr==DD_OK, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr);
2893 hr = IDirectDrawSurface7_SetColorKey(texture_levels[0][1], DDCKEY_SRCBLT, &ddckey);
2894 todo_wine ok(hr==DDERR_NOTONMIPMAPSUBLEVEL, "IDirectDrawSurface7_SetColorKey returned: %x\n", hr);
2896 hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey);
2897 ok(hr==DDERR_NOCOLORKEY, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr);
2899 hr = IDirect3DDevice7_Load(lpD3DDevice, texture_levels[1][0], NULL, texture_levels[0][0], NULL, 0);
2900 ok(hr==D3D_OK, "IDirect3DDevice7_Load returned: %x\n",hr);
2902 hr = IDirectDrawSurface7_GetColorKey(texture_levels[1][0], DDCKEY_SRCBLT, &ddckey);
2903 ok(hr==DD_OK, "IDirectDrawSurface7_GetColorKey returned: %x\n", hr);
2904 ok(ddckey.dwColorSpaceLowValue == ddckey.dwColorSpaceHighValue && ddckey.dwColorSpaceLowValue == 64,
2905 "Unexpected color key values: %u - %u\n", ddckey.dwColorSpaceLowValue, ddckey.dwColorSpaceHighValue);
2907 out:
2909 for (i = 0; i < 5; i++)
2911 if (palettes[i]) IDirectDrawPalette_Release(palettes[i]);
2914 for (i = 0; i < 2; i++)
2916 for (i1 = 7; i1 >= 0; i1--)
2918 if (texture_levels[i][i1]) IDirectDrawSurface7_Release(texture_levels[i][i1]);
2922 for (i = 0; i < 2; i++)
2923 for (i1 = 5; i1 >= 0; i1--)
2924 for (i2 = 7; i2 >= 0; i2--)
2926 if (cube_face_levels[i][i1][i2]) IDirectDrawSurface7_Release(cube_face_levels[i][i1][i2]);
2930 static void SetMaterialTest(void)
2932 HRESULT rc;
2934 rc =IDirect3DDevice7_SetMaterial(lpD3DDevice, NULL);
2935 ok(rc == DDERR_INVALIDPARAMS, "Expected DDERR_INVALIDPARAMS, got %x\n", rc);
2938 static void ComputeSphereVisibility(void)
2940 D3DMATRIX proj, view, world;
2941 D3DVALUE radius[3];
2942 D3DVECTOR center[3];
2943 DWORD result[3];
2944 HRESULT rc;
2946 world._11=1.0; world._12=0.0; world._13=0.0; world._14=0.0;
2947 world._21=0.0; world._22=1.0; world._23=0.0; world._24=0.0;
2948 world._31=0.0; world._32=0.0; world._33=1.0; world._34=0.0;
2949 world._41=0.0; world._42=0.0; world._43=0.0; world._44=1.0;
2951 view._11=1.000000; view._12=0.000000; view._13=0.000000; view._14=0.000000;
2952 view._21=0.000000; view._22=0.768221; view._23=-0.640185; view._24=0.000000;
2953 view._31=-0.000000; view._32=0.640185; view._33=0.768221; view._34=0.000000;
2954 view._41=-14.852037; view._42=9.857489; view._43=11.600972; view._44=1.000000;
2956 proj._11=1.810660; proj._12=0.000000; proj._13=0.00000; proj._14=0.000000;
2957 proj._21=0.000000; proj._22=2.414213; proj._23=0.000000, proj._24=0.000000;
2958 proj._31=0.000000; proj._32=0.000000; proj._33=1.020408, proj._34=1.000000;
2959 proj._41=0.000000; proj._42=0.000000; proj._43=-0.102041; proj._44=0.000000;
2961 IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_WORLD, &world);
2962 IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW , &view);
2963 IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
2965 U1(center[0]).x=11.461533;
2966 U2(center[0]).y=-4.761727;
2967 U3(center[0]).z=-1.171646;
2969 radius[0]=38.252632;
2971 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
2973 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2974 ok(result[0] == 0x3f, "Expected 0x3f, got %x\n", result[0]);
2976 U1(center[0]).x=-3.515620; U2(center[0]).y=-1.560661; U3(center[0]).z=-12.464638;
2977 radius[0]=4.354097;
2978 U1(center[1]).x=14.290396; U2(center[1]).y=-2.981143; U3(center[1]).z=-24.311312;
2979 radius[1]=12.500704;
2980 U1(center[2]).x=1.461626; U2(center[2]).y=-6.093709; U3(center[2]).z=-13.901010;
2981 radius[2]=17.251318;
2983 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 3, 0, result);
2985 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2986 ok(result[0] == 0x103d, "Expected 0x103d, got %x\n", result[0]);
2987 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2988 ok(result[1] == 0x3f, "Expected 0x3f, got %x\n", result[1]);
2989 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
2990 ok(result[2] == 0x3f, "Expected 0x3f, got %x\n", result[2]);
2992 view._11=1.0; view._12=0.0; view._13=0.0; view._14=0.0;
2993 view._21=0.0; view._22=1.0; view._23=0.0; view._24=0.0;
2994 view._31=0.0; view._32=0.0; view._33=1.0; view._34=0.0;
2995 view._41=0.0; view._42=0.0; view._43=0.0; view._44=1.0;
2997 proj._11=10.0; proj._12=0.0; proj._13=0.0; proj._14=0.0;
2998 proj._21=0.0; proj._22=10.0; proj._23=0.0, proj._24=0.0;
2999 proj._31=0.0; proj._32=0.0; proj._33=10.0, proj._34=0.0;
3000 proj._41=0.0; proj._42=0.0; proj._43=0.0; proj._44=1.0;
3002 U1(center[0]).x=0.0;
3003 U2(center[0]).y=0.0;
3004 U3(center[0]).z=0.05;
3006 radius[0]=0.04;
3008 IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_VIEW , &view);
3009 IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
3011 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3013 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3014 ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
3016 proj._11=1.0; proj._12=0.0; proj._13=0.0; proj._14=0.0;
3017 proj._21=0.0; proj._22=1.0; proj._23=0.0, proj._24=0.0;
3018 proj._31=0.0; proj._32=0.0; proj._33=1.0, proj._34=0.0;
3019 proj._41=0.0; proj._42=0.0; proj._43=0.0; proj._44=1.0;
3021 IDirect3DDevice7_SetTransform(lpD3DDevice, D3DTRANSFORMSTATE_PROJECTION, &proj);
3023 U1(center[0]).x=0.0;
3024 U2(center[0]).y=0.0;
3025 U3(center[0]).z=0.5;
3027 radius[0]=0.5;
3029 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3031 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3032 ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
3034 U1(center[0]).x=0.0;
3035 U2(center[0]).y=0.0;
3036 U3(center[0]).z=0.0;
3038 radius[0]=0.0;
3040 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3042 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3043 ok(result[0] == 0x0, "Expected 0x0, got %x\n", result[0]);
3045 U1(center[0]).x=-1.0;
3046 U2(center[0]).y=-1.0;
3047 U3(center[0]).z=0.50;
3049 radius[0]=0.25;
3051 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3053 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3054 ok(result[0] == 0x9, "Expected 0x9, got %x\n", result[0]);
3056 U1(center[0]).x=-20.0;
3057 U2(center[0]).y=0.0;
3058 U3(center[0]).z=0.50;
3060 radius[0]=3.0;
3062 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3064 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3065 ok(result[0] == 0x103d, "Expected 0x103d, got %x\n", result[0]);
3067 U1(center[0]).x=20.0;
3068 U2(center[0]).y=0.0;
3069 U3(center[0]).z=0.50;
3071 radius[0]=3.0f;
3073 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3075 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3076 ok(result[0] == 0x203e, "Expected 0x203e, got %x\n", result[0]);
3078 U1(center[0]).x=0.0;
3079 U2(center[0]).y=-20.0;
3080 U3(center[0]).z=0.50;
3082 radius[0]=3.0;
3084 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3086 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3087 ok(result[0] == 0x803b, "Expected 0x803b, got %x\n", result[0]);
3089 U1(center[0]).x=0.0;
3090 U2(center[0]).y=20.0;
3091 U3(center[0]).z=0.5;
3093 radius[0]=3.0;
3095 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3097 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3098 ok(result[0] == 0x4037, "Expected 0x4037, got %x\n", result[0]);
3100 U1(center[0]).x=0.0;
3101 U2(center[0]).y=0.0;
3102 U3(center[0]).z=-20;
3104 radius[0]=3.0;
3106 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3108 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3109 ok(result[0] == 0x1001f, "Expected 0x1001f, got %x\n", result[0]);
3111 U1(center[0]).x=0.0;
3112 U2(center[0]).y=0.0;
3113 U3(center[0]).z=20.0;
3115 radius[0]=3.0;
3117 rc = IDirect3DDevice7_ComputeSphereVisibility(lpD3DDevice, center, radius, 1, 0, result);
3119 ok(rc == D3D_OK, "Expected D3D_OK, received %x\n", rc);
3120 ok(result[0] == 0x2002f, "Expected 0x2002f, got %x\n", result[0]);
3123 static void SetRenderTargetTest(void)
3125 HRESULT hr;
3126 IDirectDrawSurface7 *newrt, *failrt, *oldrt;
3127 D3DVIEWPORT7 vp;
3128 DDSURFACEDESC2 ddsd, ddsd2;
3129 DWORD stateblock;
3131 memset(&ddsd, 0, sizeof(ddsd));
3132 ddsd.dwSize = sizeof(ddsd);
3133 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3134 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
3135 ddsd.dwWidth = 64;
3136 ddsd.dwHeight = 64;
3138 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &newrt, NULL);
3139 ok(hr == DD_OK, "IDirectDraw7_CreateSurface failed, hr=0x%08x\n", hr);
3140 if(FAILED(hr))
3142 skip("Skipping SetRenderTarget test\n");
3143 return;
3146 memset(&ddsd2, 0, sizeof(ddsd2));
3147 ddsd2.dwSize = sizeof(ddsd2);
3148 ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
3149 ddsd2.ddsCaps.dwCaps = DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER;
3150 ddsd2.dwWidth = 64;
3151 ddsd2.dwHeight = 64;
3152 U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
3153 U4(ddsd2).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
3154 U1(U4(ddsd2).ddpfPixelFormat).dwZBufferBitDepth = 16;
3155 U3(U4(ddsd2).ddpfPixelFormat).dwZBitMask = 0x0000FFFF;
3157 hr = IDirectDraw7_CreateSurface(lpDD, &ddsd2, &failrt, NULL);
3158 ok(hr == DD_OK, "IDirectDraw7_CreateSurface failed, hr=0x%08x\n", hr);
3160 memset(&vp, 0, sizeof(vp));
3161 vp.dwX = 10;
3162 vp.dwY = 10;
3163 vp.dwWidth = 246;
3164 vp.dwHeight = 246;
3165 vp.dvMinZ = 0.25;
3166 vp.dvMaxZ = 0.75;
3167 hr = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
3168 ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport failed, hr=0x%08x\n", hr);
3170 hr = IDirect3DDevice7_GetRenderTarget(lpD3DDevice, &oldrt);
3171 ok(hr == DD_OK, "IDirect3DDevice7_GetRenderTarget failed, hr=0x%08x\n", hr);
3173 hr = IDirect3DDevice7_SetRenderTarget(lpD3DDevice, failrt, 0);
3174 ok(hr != D3D_OK, "IDirect3DDevice7_SetRenderTarget succeeded\n");
3176 hr = IDirect3DDevice7_SetRenderTarget(lpD3DDevice, newrt, 0);
3177 ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderTarget failed, hr=0x%08x\n", hr);
3178 memset(&vp, 0xff, sizeof(vp));
3179 hr = IDirect3DDevice7_GetViewport(lpD3DDevice, &vp);
3180 ok(hr == D3D_OK, "IDirect3DDevice7_GetViewport failed, hr=0x%08x\n", hr);
3181 ok(vp.dwX == 10, "vp.dwX is %u, expected 10\n", vp.dwX);
3182 ok(vp.dwY == 10, "vp.dwY is %u, expected 10\n", vp.dwY);
3183 ok(vp.dwWidth == 246, "vp.dwWidth is %u, expected 246\n", vp.dwWidth);
3184 ok(vp.dwHeight == 246, "vp.dwHeight is %u, expected 246\n", vp.dwHeight);
3185 ok(vp.dvMinZ == 0.25, "vp.dvMinZ is %f, expected 0.25\n", vp.dvMinZ);
3186 ok(vp.dvMaxZ == 0.75, "vp.dvMaxZ is %f, expected 0.75\n", vp.dvMaxZ);
3188 memset(&vp, 0, sizeof(vp));
3189 vp.dwX = 0;
3190 vp.dwY = 0;
3191 vp.dwWidth = 64;
3192 vp.dwHeight = 64;
3193 vp.dvMinZ = 0.0;
3194 vp.dvMaxZ = 1.0;
3195 hr = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
3196 ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport failed, hr=0x%08x\n", hr);
3198 hr = IDirect3DDevice7_BeginStateBlock(lpD3DDevice);
3199 ok(hr == D3D_OK, "IDirect3DDevice7_BeginStateblock failed, hr=0x%08x\n", hr);
3200 hr = IDirect3DDevice7_SetRenderTarget(lpD3DDevice, oldrt, 0);
3201 ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderTarget failed, hr=0x%08x\n", hr);
3203 /* Check this twice, before and after ending the stateblock */
3204 memset(&vp, 0xff, sizeof(vp));
3205 hr = IDirect3DDevice7_GetViewport(lpD3DDevice, &vp);
3206 ok(hr == D3D_OK, "IDirect3DDevice7_GetViewport failed, hr=0x%08x\n", hr);
3207 ok(vp.dwX == 0, "vp.dwX is %u, expected 0\n", vp.dwX);
3208 ok(vp.dwY == 0, "vp.dwY is %u, expected 0\n", vp.dwY);
3209 ok(vp.dwWidth == 64, "vp.dwWidth is %u, expected 64\n", vp.dwWidth);
3210 ok(vp.dwHeight == 64, "vp.dwHeight is %u, expected 64\n", vp.dwHeight);
3211 ok(vp.dvMinZ == 0.0, "vp.dvMinZ is %f, expected 0.0\n", vp.dvMinZ);
3212 ok(vp.dvMaxZ == 1.0, "vp.dvMaxZ is %f, expected 1.0\n", vp.dvMaxZ);
3214 hr = IDirect3DDevice7_EndStateBlock(lpD3DDevice, &stateblock);
3215 ok(hr == D3D_OK, "IDirect3DDevice7_EndStateblock failed, hr=0x%08x\n", hr);
3217 memset(&vp, 0xff, sizeof(vp));
3218 hr = IDirect3DDevice7_GetViewport(lpD3DDevice, &vp);
3219 ok(hr == D3D_OK, "IDirect3DDevice7_GetViewport failed, hr=0x%08x\n", hr);
3220 ok(vp.dwX == 0, "vp.dwX is %u, expected 0\n", vp.dwX);
3221 ok(vp.dwY == 0, "vp.dwY is %u, expected 0\n", vp.dwY);
3222 ok(vp.dwWidth == 64, "vp.dwWidth is %u, expected 64\n", vp.dwWidth);
3223 ok(vp.dwHeight == 64, "vp.dwHeight is %u, expected 64\n", vp.dwHeight);
3224 ok(vp.dvMinZ == 0.0, "vp.dvMinZ is %f, expected 0.0\n", vp.dvMinZ);
3225 ok(vp.dvMaxZ == 1.0, "vp.dvMaxZ is %f, expected 1.0\n", vp.dvMaxZ);
3227 hr = IDirect3DDevice7_DeleteStateBlock(lpD3DDevice, stateblock);
3228 ok(hr == D3D_OK, "IDirect3DDevice7_DeleteStateblock failed, hr=0x%08x\n", hr);
3230 memset(&vp, 0, sizeof(vp));
3231 vp.dwX = 0;
3232 vp.dwY = 0;
3233 vp.dwWidth = 256;
3234 vp.dwHeight = 256;
3235 vp.dvMinZ = 0.0;
3236 vp.dvMaxZ = 0.0;
3237 hr = IDirect3DDevice7_SetViewport(lpD3DDevice, &vp);
3238 ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport failed, hr=0x%08x\n", hr);
3240 IDirectDrawSurface7_Release(oldrt);
3241 IDirectDrawSurface7_Release(newrt);
3242 IDirectDrawSurface7_Release(failrt);
3245 static const UINT *expect_messages;
3247 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
3249 if (expect_messages && message == *expect_messages) ++expect_messages;
3251 return DefWindowProcA(hwnd, message, wparam, lparam);
3254 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
3255 * interface. This prevents subsequent SetCooperativeLevel() calls on a
3256 * different window from failing with DDERR_HWNDALREADYSET. */
3257 static void fix_wndproc(HWND window, LONG_PTR proc)
3259 IDirectDraw7 *ddraw7;
3260 HRESULT hr;
3262 hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3263 ok(SUCCEEDED(hr), "Failed to create IDirectDraw7 object, hr %#x.\n", hr);
3264 if (FAILED(hr)) return;
3266 SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
3267 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3268 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3269 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
3270 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3272 IDirectDraw7_Release(ddraw7);
3275 static void test_wndproc(void)
3277 LONG_PTR proc, ddraw_proc;
3278 IDirectDraw7 *ddraw7;
3279 WNDCLASSA wc = {0};
3280 HWND window;
3281 HRESULT hr;
3282 ULONG ref;
3284 static const UINT messages[] =
3286 WM_WINDOWPOSCHANGING,
3287 WM_MOVE,
3288 WM_SIZE,
3289 WM_WINDOWPOSCHANGING,
3290 WM_ACTIVATE,
3291 WM_SETFOCUS,
3295 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
3296 hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3297 if (FAILED(hr))
3299 skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3300 return;
3303 wc.lpfnWndProc = test_proc;
3304 wc.lpszClassName = "d3d7_test_wndproc_wc";
3305 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3307 window = CreateWindowA("d3d7_test_wndproc_wc", "d3d7_test",
3308 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
3310 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3311 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3312 (LONG_PTR)test_proc, proc);
3314 expect_messages = messages;
3316 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3317 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3318 if (FAILED(hr))
3320 IDirectDraw7_Release(ddraw7);
3321 goto done;
3324 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
3325 expect_messages = NULL;
3327 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3328 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3329 (LONG_PTR)test_proc, proc);
3331 ref = IDirectDraw7_Release(ddraw7);
3332 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3334 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3335 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3336 (LONG_PTR)test_proc, proc);
3338 /* DDSCL_NORMAL doesn't. */
3339 hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3340 if (FAILED(hr))
3342 skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3343 return;
3346 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3347 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3348 (LONG_PTR)test_proc, proc);
3350 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3351 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3352 if (FAILED(hr))
3354 IDirectDraw7_Release(ddraw7);
3355 goto done;
3358 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3359 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3360 (LONG_PTR)test_proc, proc);
3362 ref = IDirectDraw7_Release(ddraw7);
3363 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3365 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3366 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3367 (LONG_PTR)test_proc, proc);
3369 /* The original window proc is only restored by ddraw if the current
3370 * window proc matches the one ddraw set. This also affects switching
3371 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
3372 hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3373 if (FAILED(hr))
3375 skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3376 return;
3379 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3380 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3381 (LONG_PTR)test_proc, proc);
3383 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3384 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3385 if (FAILED(hr))
3387 IDirectDraw7_Release(ddraw7);
3388 goto done;
3391 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3392 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3393 (LONG_PTR)test_proc, proc);
3394 ddraw_proc = proc;
3396 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
3397 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3398 if (FAILED(hr))
3400 IDirectDraw7_Release(ddraw7);
3401 goto done;
3404 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3405 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3406 (LONG_PTR)test_proc, proc);
3408 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3409 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3410 if (FAILED(hr))
3412 IDirectDraw7_Release(ddraw7);
3413 goto done;
3416 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
3417 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3418 (LONG_PTR)test_proc, proc);
3420 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
3421 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3422 if (FAILED(hr))
3424 IDirectDraw7_Release(ddraw7);
3425 goto done;
3428 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3429 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
3430 (LONG_PTR)DefWindowProcA, proc);
3432 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3433 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3434 if (FAILED(hr))
3436 IDirectDraw7_Release(ddraw7);
3437 goto done;
3440 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc);
3441 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
3442 (LONG_PTR)DefWindowProcA, proc);
3444 ref = IDirectDraw7_Release(ddraw7);
3445 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3447 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3448 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3449 (LONG_PTR)test_proc, proc);
3451 hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3452 if (FAILED(hr))
3454 skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3455 return;
3458 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3459 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3460 (LONG_PTR)test_proc, proc);
3462 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3463 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3464 if (FAILED(hr))
3466 IDirectDraw7_Release(ddraw7);
3467 goto done;
3470 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
3471 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
3472 (LONG_PTR)test_proc, proc);
3474 ref = IDirectDraw7_Release(ddraw7);
3475 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3477 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
3478 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
3479 (LONG_PTR)DefWindowProcA, proc);
3481 done:
3482 fix_wndproc(window, (LONG_PTR)test_proc);
3483 expect_messages = NULL;
3484 DestroyWindow(window);
3485 UnregisterClassA("d3d7_test_wndproc_wc", GetModuleHandleA(NULL));
3488 static void VertexBufferLockRest(void)
3490 D3DVERTEXBUFFERDESC desc;
3491 IDirect3DVertexBuffer7 *buffer;
3492 HRESULT hr;
3493 unsigned int i;
3494 void *data;
3495 const struct
3497 DWORD flags;
3498 const char *debug_string;
3499 HRESULT result;
3501 test_data[] =
3503 {0, "(none)", D3D_OK },
3504 {DDLOCK_WAIT, "DDLOCK_WAIT", D3D_OK },
3505 {DDLOCK_EVENT, "DDLOCK_EVENT", D3D_OK },
3506 {DDLOCK_READONLY, "DDLOCK_READONLY", D3D_OK },
3507 {DDLOCK_WRITEONLY, "DDLOCK_WRITEONLY", D3D_OK },
3508 {DDLOCK_NOSYSLOCK, "DDLOCK_NOSYSLOCK", D3D_OK },
3509 {DDLOCK_NOOVERWRITE, "DDLOCK_NOOVERWRITE", D3D_OK },
3510 {DDLOCK_DISCARDCONTENTS, "DDLOCK_DISCARDCONTENTS", D3D_OK },
3512 {DDLOCK_READONLY | DDLOCK_WRITEONLY, "DDLOCK_READONLY | DDLOCK_WRITEONLY", D3D_OK },
3513 {DDLOCK_READONLY | DDLOCK_DISCARDCONTENTS, "DDLOCK_READONLY | DDLOCK_DISCARDCONTENTS", D3D_OK },
3514 {0xdeadbeef, "0xdeadbeef", D3D_OK },
3517 memset(&desc, 0 , sizeof(desc));
3518 desc.dwSize = sizeof(desc);
3519 desc.dwCaps = 0;
3520 desc.dwFVF = D3DFVF_XYZ;
3521 desc.dwNumVertices = 64;
3522 hr = IDirect3D7_CreateVertexBuffer(lpD3D, &desc, &buffer, 0);
3523 ok(hr == D3D_OK, "IDirect3D7_CreateVertexBuffer failed, 0x%08x\n", hr);
3525 for(i = 0; i < (sizeof(test_data) / sizeof(*test_data)); i++)
3527 hr = IDirect3DVertexBuffer7_Lock(buffer, test_data[i].flags, &data, NULL);
3528 ok(hr == test_data[i].result, "Lock flags %s returned 0x%08x, expected 0x%08x\n",
3529 test_data[i].debug_string, hr, test_data[i].result);
3530 if(SUCCEEDED(hr))
3532 ok(data != NULL, "The data pointer returned by Lock is NULL\n");
3533 hr = IDirect3DVertexBuffer7_Unlock(buffer);
3534 ok(hr == D3D_OK, "IDirect3DVertexBuffer7_Unlock failed, 0x%08x\n", hr);
3538 IDirect3DVertexBuffer7_Release(buffer);
3541 static void FindDevice(void)
3543 static const struct
3545 const GUID *guid;
3546 int todo;
3547 } deviceGUIDs[] =
3549 {&IID_IDirect3DRampDevice, 1},
3550 {&IID_IDirect3DRGBDevice},
3553 static const GUID *nonexistent_deviceGUIDs[] = {&IID_IDirect3DMMXDevice,
3554 &IID_IDirect3DRefDevice,
3555 &IID_IDirect3DTnLHalDevice,
3556 &IID_IDirect3DNullDevice};
3558 D3DFINDDEVICESEARCH search = {0};
3559 D3DFINDDEVICERESULT result = {0};
3560 IDirect3DDevice *d3dhal;
3561 HRESULT hr;
3562 int i;
3564 /* Test invalid parameters. */
3565 hr = IDirect3D_FindDevice(Direct3D1, NULL, NULL);
3566 ok(hr == DDERR_INVALIDPARAMS,
3567 "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3569 hr = IDirect3D_FindDevice(Direct3D1, NULL, &result);
3570 ok(hr == DDERR_INVALIDPARAMS,
3571 "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3573 hr = IDirect3D_FindDevice(Direct3D1, &search, NULL);
3574 ok(hr == DDERR_INVALIDPARAMS,
3575 "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3577 search.dwSize = 0;
3578 result.dwSize = 0;
3580 hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3581 ok(hr == DDERR_INVALIDPARAMS,
3582 "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3584 search.dwSize = sizeof(search) + 1;
3585 result.dwSize = sizeof(result) + 1;
3587 hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3588 ok(hr == DDERR_INVALIDPARAMS,
3589 "Expected IDirect3D1::FindDevice to return DDERR_INVALIDPARAMS, got 0x%08x\n", hr);
3591 /* Specifying no flags is permitted. */
3592 search.dwSize = sizeof(search);
3593 search.dwFlags = 0;
3594 result.dwSize = sizeof(result);
3596 hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3597 ok(hr == D3D_OK,
3598 "Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", hr);
3600 /* Try an arbitrary non-device GUID. */
3601 search.dwSize = sizeof(search);
3602 search.dwFlags = D3DFDS_GUID;
3603 search.guid = IID_IDirect3D;
3604 result.dwSize = sizeof(result);
3606 hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3607 ok(hr == DDERR_NOTFOUND,
3608 "Expected IDirect3D1::FindDevice to return DDERR_NOTFOUND, got 0x%08x\n", hr);
3610 /* These GUIDs appear to be never present. */
3611 for (i = 0; i < sizeof(nonexistent_deviceGUIDs)/sizeof(nonexistent_deviceGUIDs[0]); i++)
3613 search.dwSize = sizeof(search);
3614 search.dwFlags = D3DFDS_GUID;
3615 search.guid = *nonexistent_deviceGUIDs[i];
3616 result.dwSize = sizeof(result);
3618 hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3619 ok(hr == DDERR_NOTFOUND,
3620 "[%d] Expected IDirect3D1::FindDevice to return DDERR_NOTFOUND, got 0x%08x\n", i, hr);
3623 /* The HAL device can only be enumerated if hardware acceleration is present. */
3624 search.dwSize = sizeof(search);
3625 search.dwFlags = D3DFDS_GUID;
3626 search.guid = IID_IDirect3DHALDevice;
3627 result.dwSize = sizeof(result);
3629 hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3630 trace("IDirect3D::FindDevice returned 0x%08x for the HAL device GUID\n", hr);
3631 if (SUCCEEDED(hr))
3633 hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DHALDevice, (void **)&d3dhal);
3634 /* Currently Wine only supports the creation of one Direct3D device
3635 * for a given DirectDraw instance. */
3636 todo_wine
3637 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPIXELFORMAT) /* XP/Win2003 Wow64 on VMware */,
3638 "Expected IDirectDrawSurface::QueryInterface to succeed, got 0x%08x\n", hr);
3640 if (SUCCEEDED(hr))
3641 IDirect3DDevice_Release(d3dhal);
3643 else
3645 hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DHALDevice, (void **)&d3dhal);
3646 ok(FAILED(hr), "Expected IDirectDrawSurface::QueryInterface to fail, got 0x%08x\n", hr);
3648 if (SUCCEEDED(hr))
3649 IDirect3DDevice_Release(d3dhal);
3652 /* These GUIDs appear to be always present. */
3653 for (i = 0; i < sizeof(deviceGUIDs)/sizeof(deviceGUIDs[0]); i++)
3655 search.dwSize = sizeof(search);
3656 search.dwFlags = D3DFDS_GUID;
3657 search.guid = *deviceGUIDs[i].guid;
3658 result.dwSize = sizeof(result);
3660 hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3662 if (deviceGUIDs[i].todo)
3664 todo_wine
3665 ok(hr == D3D_OK,
3666 "[%d] Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", i, hr);
3668 else
3670 ok(hr == D3D_OK,
3671 "[%d] Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", i, hr);
3675 /* Curiously the color model criteria seem to be ignored. */
3676 search.dwSize = sizeof(search);
3677 search.dwFlags = D3DFDS_COLORMODEL;
3678 search.dcmColorModel = 0xdeadbeef;
3679 result.dwSize = sizeof(result);
3681 hr = IDirect3D_FindDevice(Direct3D1, &search, &result);
3682 todo_wine
3683 ok(hr == D3D_OK,
3684 "Expected IDirect3D1::FindDevice to return D3D_OK, got 0x%08x\n", hr);
3687 static void BackBuffer3DCreateSurfaceTest(void)
3689 DDSURFACEDESC ddsd;
3690 DDSURFACEDESC created_ddsd;
3691 DDSURFACEDESC2 ddsd2;
3692 IDirectDrawSurface *surf;
3693 IDirectDrawSurface4 *surf4;
3694 IDirectDrawSurface7 *surf7;
3695 HRESULT hr;
3696 IDirectDraw2 *dd2;
3697 IDirectDraw4 *dd4;
3698 IDirectDraw7 *dd7;
3699 DDCAPS ddcaps;
3700 IDirect3DDevice *d3dhal;
3702 const DWORD caps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE;
3703 const DWORD expected_caps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
3705 memset(&ddcaps, 0, sizeof(ddcaps));
3706 ddcaps.dwSize = sizeof(DDCAPS);
3707 hr = IDirectDraw_GetCaps(DirectDraw1, &ddcaps, NULL);
3708 ok(SUCCEEDED(hr), "DirectDraw_GetCaps failed: 0x%08x\n", hr);
3709 if (!(ddcaps.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
3711 skip("DDraw reported no VIDEOMEMORY cap. Broken video driver? Skipping surface caps tests.\n");
3712 return ;
3715 memset(&ddsd, 0, sizeof(ddsd));
3716 ddsd.dwSize = sizeof(ddsd);
3717 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3718 ddsd.dwWidth = 64;
3719 ddsd.dwHeight = 64;
3720 ddsd.ddsCaps.dwCaps = caps;
3721 memset(&ddsd2, 0, sizeof(ddsd2));
3722 ddsd2.dwSize = sizeof(ddsd2);
3723 ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3724 ddsd2.dwWidth = 64;
3725 ddsd2.dwHeight = 64;
3726 ddsd2.ddsCaps.dwCaps = caps;
3727 memset(&created_ddsd, 0, sizeof(created_ddsd));
3728 created_ddsd.dwSize = sizeof(DDSURFACEDESC);
3730 hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surf, NULL);
3731 ok(SUCCEEDED(hr), "IDirectDraw_CreateSurface failed: 0x%08x\n", hr);
3732 if (surf != NULL)
3734 hr = IDirectDrawSurface_GetSurfaceDesc(surf, &created_ddsd);
3735 ok(SUCCEEDED(hr), "IDirectDraw_GetSurfaceDesc failed: 0x%08x\n", hr);
3736 ok(created_ddsd.ddsCaps.dwCaps == expected_caps,
3737 "GetSurfaceDesc returned caps %x, expected %x\n", created_ddsd.ddsCaps.dwCaps,
3738 expected_caps);
3740 hr = IDirectDrawSurface_QueryInterface(surf, &IID_IDirect3DHALDevice, (void **)&d3dhal);
3741 /* Currently Wine only supports the creation of one Direct3D device
3742 for a given DirectDraw instance. It has been created already
3743 in D3D1_createObjects() - IID_IDirect3DRGBDevice */
3744 todo_wine ok(SUCCEEDED(hr), "Expected IDirectDrawSurface::QueryInterface to succeed, got 0x%08x\n", hr);
3746 if (SUCCEEDED(hr))
3747 IDirect3DDevice_Release(d3dhal);
3749 IDirectDrawSurface_Release(surf);
3752 hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirectDraw2, (void **) &dd2);
3753 ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3755 hr = IDirectDraw2_CreateSurface(dd2, &ddsd, &surf, NULL);
3756 ok(hr == DDERR_INVALIDCAPS, "IDirectDraw2_CreateSurface didn't return %x08x, but %x08x\n",
3757 DDERR_INVALIDCAPS, hr);
3759 IDirectDraw2_Release(dd2);
3761 hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirectDraw4, (void **) &dd4);
3762 ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3764 hr = IDirectDraw4_CreateSurface(dd4, &ddsd2, &surf4, NULL);
3765 ok(hr == DDERR_INVALIDCAPS, "IDirectDraw4_CreateSurface didn't return %x08x, but %x08x\n",
3766 DDERR_INVALIDCAPS, hr);
3768 IDirectDraw4_Release(dd4);
3770 hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirectDraw7, (void **) &dd7);
3771 ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3773 hr = IDirectDraw7_CreateSurface(dd7, &ddsd2, &surf7, NULL);
3774 ok(hr == DDERR_INVALIDCAPS, "IDirectDraw7_CreateSurface didn't return %x08x, but %x08x\n",
3775 DDERR_INVALIDCAPS, hr);
3777 IDirectDraw7_Release(dd7);
3780 static void BackBuffer3DAttachmentTest(void)
3782 HRESULT hr;
3783 IDirectDrawSurface *surface1, *surface2, *surface3, *surface4;
3784 DDSURFACEDESC ddsd;
3785 HWND window = CreateWindow( "static", "ddraw_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
3787 hr = IDirectDraw_SetCooperativeLevel(DirectDraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3788 ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
3790 /* Perform attachment tests on a back-buffer */
3791 memset(&ddsd, 0, sizeof(ddsd));
3792 ddsd.dwSize = sizeof(ddsd);
3793 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3794 ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE;
3795 ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
3796 ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
3797 hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surface2, NULL);
3798 ok(SUCCEEDED(hr), "CreateSurface returned: %x\n",hr);
3800 if (surface2 != NULL)
3802 /* Try a single primary and a two back buffers */
3803 memset(&ddsd, 0, sizeof(ddsd));
3804 ddsd.dwSize = sizeof(ddsd);
3805 ddsd.dwFlags = DDSD_CAPS;
3806 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3807 hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surface1, NULL);
3808 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3810 memset(&ddsd, 0, sizeof(ddsd));
3811 ddsd.dwSize = sizeof(ddsd);
3812 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3813 ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE;
3814 ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
3815 ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
3816 hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surface3, NULL);
3817 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3819 /* This one has a different size */
3820 memset(&ddsd, 0, sizeof(ddsd));
3821 ddsd.dwSize = sizeof(ddsd);
3822 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3823 ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER | DDSCAPS_3DDEVICE;
3824 ddsd.dwWidth = 128;
3825 ddsd.dwHeight = 128;
3826 hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surface4, NULL);
3827 ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3829 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
3830 todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
3831 "Attaching a back buffer to a front buffer returned %08x\n", hr);
3832 if(SUCCEEDED(hr))
3834 /* Try the reverse without detaching first */
3835 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
3836 ok(hr == DDERR_SURFACEALREADYATTACHED, "Attaching an attached surface to its attachee returned %08x\n", hr);
3837 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
3838 ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
3840 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
3841 todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
3842 "Attaching a front buffer to a back buffer returned %08x\n", hr);
3843 if(SUCCEEDED(hr))
3845 /* Try to detach reversed */
3846 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
3847 ok(hr == DDERR_CANNOTDETACHSURFACE, "DeleteAttachedSurface returned %08x\n", hr);
3848 /* Now the proper detach */
3849 hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface1);
3850 ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
3852 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface3);
3853 todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
3854 "Attaching a back buffer to another back buffer returned %08x\n", hr);
3855 if(SUCCEEDED(hr))
3857 hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface3);
3858 ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
3860 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
3861 ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a back buffer to a front buffer of different size returned %08x\n", hr);
3862 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
3863 ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a front buffer to a back buffer of different size returned %08x\n", hr);
3865 IDirectDrawSurface_Release(surface4);
3866 IDirectDrawSurface_Release(surface3);
3867 IDirectDrawSurface_Release(surface2);
3868 IDirectDrawSurface_Release(surface1);
3871 hr =IDirectDraw_SetCooperativeLevel(DirectDraw1, NULL, DDSCL_NORMAL);
3872 ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
3874 DestroyWindow(window);
3877 static void test_window_style(void)
3879 LONG style, exstyle, tmp;
3880 RECT fullscreen_rect, r;
3881 IDirectDraw7 *ddraw7;
3882 HWND window;
3883 HRESULT hr;
3884 ULONG ref;
3886 hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3887 if (FAILED(hr))
3889 skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3890 return;
3893 window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
3894 0, 0, 100, 100, 0, 0, 0, 0);
3896 style = GetWindowLongA(window, GWL_STYLE);
3897 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
3898 SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
3900 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3901 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3902 if (FAILED(hr))
3904 IDirectDraw7_Release(ddraw7);
3905 DestroyWindow(window);
3906 return;
3909 tmp = GetWindowLongA(window, GWL_STYLE);
3910 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
3911 tmp = GetWindowLongA(window, GWL_EXSTYLE);
3912 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
3914 GetWindowRect(window, &r);
3915 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3916 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3917 r.left, r.top, r.right, r.bottom);
3918 GetClientRect(window, &r);
3919 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
3921 ref = IDirectDraw7_Release(ddraw7);
3922 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3924 DestroyWindow(window);
3927 static void test_redundant_mode_set(void)
3929 DDSURFACEDESC2 surface_desc = {0};
3930 IDirectDraw7 *ddraw7;
3931 HWND window;
3932 HRESULT hr;
3933 RECT r, s;
3934 ULONG ref;
3936 hr = pDirectDrawCreateEx(NULL, (void **)&ddraw7, &IID_IDirectDraw7, NULL);
3937 if (FAILED(hr))
3939 skip("Failed to create IDirectDraw7 object (%#x), skipping tests.\n", hr);
3940 return;
3943 window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
3944 0, 0, 100, 100, 0, 0, 0, 0);
3946 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3947 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3948 if (FAILED(hr))
3950 IDirectDraw7_Release(ddraw7);
3951 DestroyWindow(window);
3952 return;
3955 surface_desc.dwSize = sizeof(surface_desc);
3956 hr = IDirectDraw7_GetDisplayMode(ddraw7, &surface_desc);
3957 ok(SUCCEEDED(hr), "GetDipslayMode failed, hr %#x.\n", hr);
3959 hr = IDirectDraw7_SetDisplayMode(ddraw7, surface_desc.dwWidth, surface_desc.dwHeight,
3960 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
3961 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
3963 GetWindowRect(window, &r);
3964 r.right /= 2;
3965 r.bottom /= 2;
3966 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
3967 GetWindowRect(window, &s);
3968 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3969 r.left, r.top, r.right, r.bottom,
3970 s.left, s.top, s.right, s.bottom);
3972 hr = IDirectDraw7_SetDisplayMode(ddraw7, surface_desc.dwWidth, surface_desc.dwHeight,
3973 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
3974 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
3976 GetWindowRect(window, &s);
3977 todo_wine ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3978 r.left, r.top, r.right, r.bottom,
3979 s.left, s.top, s.right, s.bottom);
3981 ref = IDirectDraw7_Release(ddraw7);
3982 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3984 DestroyWindow(window);
3986 START_TEST(d3d)
3988 init_function_pointers();
3989 if(!pDirectDrawCreateEx) {
3990 win_skip("function DirectDrawCreateEx not available\n");
3991 return;
3994 if(!CreateDirect3D()) {
3995 skip("Skipping d3d7 tests\n");
3996 } else {
3997 LightTest();
3998 ProcessVerticesTest();
3999 StateTest();
4000 SceneTest();
4001 LimitTest();
4002 D3D7EnumTest();
4003 SetMaterialTest();
4004 ComputeSphereVisibility();
4005 CapsTest();
4006 VertexBufferDescTest();
4007 D3D7_OldRenderStateTest();
4008 DeviceLoadTest();
4009 SetRenderTargetTest();
4010 VertexBufferLockRest();
4011 ReleaseDirect3D();
4014 if (!D3D1_createObjects()) {
4015 skip("Skipping d3d1 tests\n");
4016 } else {
4017 Direct3D1Test();
4018 TextureLoadTest();
4019 ViewportTest();
4020 FindDevice();
4021 BackBuffer3DCreateSurfaceTest();
4022 BackBuffer3DAttachmentTest();
4023 D3D1_releaseObjects();
4026 test_wndproc();
4027 test_window_style();
4028 test_redundant_mode_set();