2 * Copyright 2006 Stefan Dösinger for CodeWeavers
3 * Copyright 2011 Henri Verbeet for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "wine/test.h"
24 static HRESULT (WINAPI
*pDirectDrawCreateEx
)(GUID
*guid
, void **ddraw
, REFIID iid
, IUnknown
*outer_unknown
);
36 static BOOL
compare_float(float f
, float g
, unsigned int ulps
)
46 if (abs(x
- y
) > ulps
)
52 static BOOL
compare_vec3(struct vec3
*vec
, float x
, float y
, float z
, unsigned int ulps
)
54 return compare_float(vec
->x
, x
, ulps
)
55 && compare_float(vec
->y
, y
, ulps
)
56 && compare_float(vec
->z
, z
, ulps
);
59 static BOOL
compare_vec4(struct vec4
*vec
, float x
, float y
, float z
, float w
, unsigned int ulps
)
61 return compare_float(vec
->x
, x
, ulps
)
62 && compare_float(vec
->y
, y
, ulps
)
63 && compare_float(vec
->z
, z
, ulps
)
64 && compare_float(vec
->w
, w
, ulps
);
67 static BOOL
compare_color(D3DCOLOR c1
, D3DCOLOR c2
, BYTE max_diff
)
69 if (abs((c1
& 0xff) - (c2
& 0xff)) > max_diff
) return FALSE
;
71 if (abs((c1
& 0xff) - (c2
& 0xff)) > max_diff
) return FALSE
;
73 if (abs((c1
& 0xff) - (c2
& 0xff)) > max_diff
) return FALSE
;
75 if (abs((c1
& 0xff) - (c2
& 0xff)) > max_diff
) return FALSE
;
79 static D3DCOLOR
get_surface_color(IDirectDrawSurface7
*surface
, UINT x
, UINT y
)
81 RECT rect
= {x
, y
, x
+ 1, y
+ 1};
82 DDSURFACEDESC2 surface_desc
;
86 memset(&surface_desc
, 0, sizeof(surface_desc
));
87 surface_desc
.dwSize
= sizeof(surface_desc
);
89 hr
= IDirectDrawSurface7_Lock(surface
, &rect
, &surface_desc
, DDLOCK_READONLY
, NULL
);
90 ok(SUCCEEDED(hr
), "Failed to lock surface, hr %#x.\n", hr
);
94 color
= *((DWORD
*)surface_desc
.lpSurface
) & 0x00ffffff;
96 hr
= IDirectDrawSurface7_Unlock(surface
, &rect
);
97 ok(SUCCEEDED(hr
), "Failed to unlock surface, hr %#x.\n", hr
);
102 static HRESULT CALLBACK
enum_z_fmt(DDPIXELFORMAT
*format
, void *ctx
)
104 DDPIXELFORMAT
*z_fmt
= ctx
;
106 if (U1(*format
).dwZBufferBitDepth
> U1(*z_fmt
).dwZBufferBitDepth
)
112 static IDirectDraw7
*create_ddraw(void)
116 if (FAILED(pDirectDrawCreateEx(NULL
, (void **)&ddraw
, &IID_IDirectDraw7
, NULL
)))
122 static IDirect3DDevice7
*create_device(HWND window
, DWORD coop_level
)
124 IDirectDrawSurface7
*surface
, *ds
;
125 IDirect3DDevice7
*device
= NULL
;
126 DDSURFACEDESC2 surface_desc
;
132 if (!(ddraw
= create_ddraw()))
135 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, window
, coop_level
);
136 ok(SUCCEEDED(hr
), "Failed to set cooperative level, hr %#x.\n", hr
);
138 memset(&surface_desc
, 0, sizeof(surface_desc
));
139 surface_desc
.dwSize
= sizeof(surface_desc
);
140 surface_desc
.dwFlags
= DDSD_CAPS
| DDSD_WIDTH
| DDSD_HEIGHT
;
141 surface_desc
.ddsCaps
.dwCaps
= DDSCAPS_OFFSCREENPLAIN
| DDSCAPS_3DDEVICE
;
142 surface_desc
.dwWidth
= 640;
143 surface_desc
.dwHeight
= 480;
145 hr
= IDirectDraw7_CreateSurface(ddraw
, &surface_desc
, &surface
, NULL
);
146 ok(SUCCEEDED(hr
), "Failed to create surface, hr %#x.\n", hr
);
148 if (coop_level
& DDSCL_NORMAL
)
150 IDirectDrawClipper
*clipper
;
152 hr
= IDirectDraw7_CreateClipper(ddraw
, 0, &clipper
, NULL
);
153 ok(SUCCEEDED(hr
), "Failed to create clipper, hr %#x.\n", hr
);
154 hr
= IDirectDrawClipper_SetHWnd(clipper
, 0, window
);
155 ok(SUCCEEDED(hr
), "Failed to set clipper window, hr %#x.\n", hr
);
156 hr
= IDirectDrawSurface7_SetClipper(surface
, clipper
);
157 ok(SUCCEEDED(hr
), "Failed to set surface clipper, hr %#x.\n", hr
);
158 IDirectDrawClipper_Release(clipper
);
161 hr
= IDirectDraw7_QueryInterface(ddraw
, &IID_IDirect3D7
, (void **)&d3d7
);
162 IDirectDraw7_Release(ddraw
);
165 IDirectDrawSurface7_Release(surface
);
169 memset(&z_fmt
, 0, sizeof(z_fmt
));
170 hr
= IDirect3D7_EnumZBufferFormats(d3d7
, &IID_IDirect3DTnLHalDevice
, enum_z_fmt
, &z_fmt
);
171 if (FAILED(hr
) || !z_fmt
.dwSize
)
173 IDirect3D7_Release(d3d7
);
174 IDirectDrawSurface7_Release(surface
);
178 memset(&surface_desc
, 0, sizeof(surface_desc
));
179 surface_desc
.dwSize
= sizeof(surface_desc
);
180 surface_desc
.dwFlags
= DDSD_CAPS
| DDSD_PIXELFORMAT
| DDSD_WIDTH
| DDSD_HEIGHT
;
181 surface_desc
.ddsCaps
.dwCaps
= DDSCAPS_ZBUFFER
;
182 U4(surface_desc
).ddpfPixelFormat
= z_fmt
;
183 surface_desc
.dwWidth
= 640;
184 surface_desc
.dwHeight
= 480;
185 hr
= IDirectDraw7_CreateSurface(ddraw
, &surface_desc
, &ds
, NULL
);
186 ok(SUCCEEDED(hr
), "Failed to create depth buffer, hr %#x.\n", hr
);
189 IDirect3D7_Release(d3d7
);
190 IDirectDrawSurface7_Release(surface
);
194 hr
= IDirectDrawSurface_AddAttachedSurface(surface
, ds
);
195 ok(SUCCEEDED(hr
), "Failed to attach depth buffer, hr %#x.\n", hr
);
196 IDirectDrawSurface7_Release(ds
);
199 IDirect3D7_Release(d3d7
);
200 IDirectDrawSurface7_Release(surface
);
204 hr
= IDirect3D7_CreateDevice(d3d7
, &IID_IDirect3DTnLHalDevice
, surface
, &device
);
205 IDirect3D7_Release(d3d7
);
206 IDirectDrawSurface7_Release(surface
);
213 static void test_process_vertices(void)
215 IDirect3DVertexBuffer7
*src_vb
, *dst_vb1
, *dst_vb2
;
216 D3DVERTEXBUFFERDESC vb_desc
;
217 IDirect3DDevice7
*device
;
218 struct vec4
*dst_data
;
219 struct vec3
*dst_data2
;
220 struct vec3
*src_data
;
226 static D3DMATRIX world
=
228 0.0f
, 1.0f
, 0.0f
, 0.0f
,
229 1.0f
, 0.0f
, 0.0f
, 0.0f
,
230 0.0f
, 0.0f
, 0.0f
, 1.0f
,
231 0.0f
, 1.0f
, 1.0f
, 1.0f
,
233 static D3DMATRIX view
=
235 2.0f
, 0.0f
, 0.0f
, 0.0f
,
236 0.0f
, -1.0f
, 0.0f
, 0.0f
,
237 0.0f
, 0.0f
, 1.0f
, 0.0f
,
238 0.0f
, 0.0f
, 0.0f
, 3.0f
,
240 static D3DMATRIX proj
=
242 1.0f
, 0.0f
, 0.0f
, 1.0f
,
243 0.0f
, 1.0f
, 1.0f
, 0.0f
,
244 0.0f
, 1.0f
, 1.0f
, 0.0f
,
245 1.0f
, 0.0f
, 0.0f
, 1.0f
,
248 window
= CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW
,
249 0, 0, 640, 480, 0, 0, 0, 0);
250 if (!(device
= create_device(window
, DDSCL_NORMAL
)))
252 skip("Failed to create a ddraw object, skipping test.\n");
253 DestroyWindow(window
);
257 hr
= IDirect3DDevice7_GetDirect3D(device
, &d3d7
);
258 ok(SUCCEEDED(hr
), "Failed to get Direct3D7 interface, hr %#x.\n", hr
);
260 memset(&vb_desc
, 0, sizeof(vb_desc
));
261 vb_desc
.dwSize
= sizeof(vb_desc
);
262 vb_desc
.dwFVF
= D3DFVF_XYZ
;
263 vb_desc
.dwNumVertices
= 4;
264 hr
= IDirect3D7_CreateVertexBuffer(d3d7
, &vb_desc
, &src_vb
, 0);
265 ok(SUCCEEDED(hr
), "Failed to create source vertex buffer, hr %#x.\n", hr
);
267 hr
= IDirect3DVertexBuffer7_Lock(src_vb
, 0, (void **)&src_data
, NULL
);
268 ok(SUCCEEDED(hr
), "Failed to lock source vertex buffer, hr %#x.\n", hr
);
269 src_data
[0].x
= 0.0f
;
270 src_data
[0].y
= 0.0f
;
271 src_data
[0].z
= 0.0f
;
272 src_data
[1].x
= 1.0f
;
273 src_data
[1].y
= 1.0f
;
274 src_data
[1].z
= 1.0f
;
275 src_data
[2].x
= -1.0f
;
276 src_data
[2].y
= -1.0f
;
277 src_data
[2].z
= 0.5f
;
278 src_data
[3].x
= 0.5f
;
279 src_data
[3].y
= -0.5f
;
280 src_data
[3].z
= 0.25f
;
281 hr
= IDirect3DVertexBuffer7_Unlock(src_vb
);
282 ok(SUCCEEDED(hr
), "Failed to unlock source vertex buffer, hr %#x.\n", hr
);
284 memset(&vb_desc
, 0, sizeof(vb_desc
));
285 vb_desc
.dwSize
= sizeof(vb_desc
);
286 vb_desc
.dwFVF
= D3DFVF_XYZRHW
;
287 vb_desc
.dwNumVertices
= 4;
288 /* MSDN says that the last parameter must be 0 - check that. */
289 hr
= IDirect3D7_CreateVertexBuffer(d3d7
, &vb_desc
, &dst_vb1
, 4);
290 ok(SUCCEEDED(hr
), "Failed to create vertex buffer, hr %#x.\n", hr
);
292 memset(&vb_desc
, 0, sizeof(vb_desc
));
293 vb_desc
.dwSize
= sizeof(vb_desc
);
294 vb_desc
.dwFVF
= D3DFVF_XYZ
;
295 vb_desc
.dwNumVertices
= 5;
296 /* MSDN says that the last parameter must be 0 - check that. */
297 hr
= IDirect3D7_CreateVertexBuffer(d3d7
, &vb_desc
, &dst_vb2
, 12345678);
298 ok(SUCCEEDED(hr
), "Failed to create vertex buffer, hr %#x.\n", hr
);
300 memset(&vp
, 0, sizeof(vp
));
307 hr
= IDirect3DDevice7_SetViewport(device
, &vp
);
308 ok(SUCCEEDED(hr
), "Failed to set viewport, hr %#x.\n", hr
);
310 hr
= IDirect3DVertexBuffer7_ProcessVertices(dst_vb1
, D3DVOP_TRANSFORM
, 0, 4, src_vb
, 0, device
, 0);
311 ok(SUCCEEDED(hr
), "Failed to process vertices, hr %#x.\n", hr
);
312 hr
= IDirect3DVertexBuffer7_ProcessVertices(dst_vb2
, D3DVOP_TRANSFORM
, 0, 4, src_vb
, 0, device
, 0);
313 ok(SUCCEEDED(hr
), "Failed to process vertices, hr %#x.\n", hr
);
315 hr
= IDirect3DVertexBuffer7_Lock(dst_vb1
, 0, (void **)&dst_data
, NULL
);
316 ok(SUCCEEDED(hr
), "Failed to lock destination vertex buffer, hr %#x.\n", hr
);
317 ok(compare_vec4(&dst_data
[0], +1.280e+2f
, +1.280e+2f
, +0.000e+0f
, +1.000e+0f
, 4096),
318 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
319 dst_data
[0].x
, dst_data
[0].y
, dst_data
[0].z
, dst_data
[0].w
);
320 ok(compare_vec4(&dst_data
[1], +1.920e+2f
, +6.400e+1f
, +1.000e+0f
, +1.000e+0f
, 4096),
321 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
322 dst_data
[1].x
, dst_data
[1].y
, dst_data
[1].z
, dst_data
[1].w
);
323 ok(compare_vec4(&dst_data
[2], +6.400e+1f
, +1.920e+2f
, +5.000e-1f
, +1.000e+0f
, 4096),
324 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
325 dst_data
[2].x
, dst_data
[2].y
, dst_data
[2].z
, dst_data
[2].w
);
326 ok(compare_vec4(&dst_data
[3], +1.600e+2f
, +1.600e+2f
, +2.500e-1f
, +1.000e+0f
, 4096),
327 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
328 dst_data
[3].x
, dst_data
[3].y
, dst_data
[3].z
, dst_data
[3].w
);
329 hr
= IDirect3DVertexBuffer7_Unlock(dst_vb1
);
330 ok(SUCCEEDED(hr
), "Failed to unlock destination vertex buffer, hr %#x.\n", hr
);
332 hr
= IDirect3DVertexBuffer7_Lock(dst_vb2
, 0, (void **)&dst_data2
, NULL
);
333 ok(SUCCEEDED(hr
), "Failed to lock destination vertex buffer, hr %#x.\n", hr
);
334 /* Small thing without much practical meaning, but I stumbled upon it,
335 * so let's check for it: If the output vertex buffer has no RHW value,
336 * the RHW value of the last vertex is written into the next vertex. */
337 ok(compare_vec3(&dst_data2
[4], +1.000e+0f
, +0.000e+0f
, +0.000e+0f
, 4096),
338 "Got unexpected vertex 4 {%.8e, %.8e, %.8e}.\n",
339 dst_data2
[4].x
, dst_data2
[4].y
, dst_data2
[4].z
);
340 hr
= IDirect3DVertexBuffer7_Unlock(dst_vb2
);
341 ok(SUCCEEDED(hr
), "Failed to unlock destination vertex buffer, hr %#x.\n", hr
);
343 /* Try a more complicated viewport, same vertices. */
344 memset(&vp
, 0, sizeof(vp
));
351 hr
= IDirect3DDevice7_SetViewport(device
, &vp
);
352 ok(SUCCEEDED(hr
), "Failed to set viewport, hr %#x.\n", hr
);
354 hr
= IDirect3DVertexBuffer7_ProcessVertices(dst_vb1
, D3DVOP_TRANSFORM
, 0, 4, src_vb
, 0, device
, 0);
355 ok(SUCCEEDED(hr
), "Failed to process vertices, hr %#x.\n", hr
);
357 hr
= IDirect3DVertexBuffer7_Lock(dst_vb1
, 0, (void **)&dst_data
, NULL
);
358 ok(SUCCEEDED(hr
), "Failed to lock destination vertex buffer, hr %#x.\n", hr
);
359 ok(compare_vec4(&dst_data
[0], +1.330e+2f
, +7.000e+1f
, -2.000e+0f
, +1.000e+0f
, 4096),
360 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
361 dst_data
[0].x
, dst_data
[0].y
, dst_data
[0].z
, dst_data
[0].w
);
362 ok(compare_vec4(&dst_data
[1], +2.560e+2f
, +5.000e+0f
, +4.000e+0f
, +1.000e+0f
, 4096),
363 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
364 dst_data
[1].x
, dst_data
[1].y
, dst_data
[1].z
, dst_data
[1].w
);
365 ok(compare_vec4(&dst_data
[2], +1.000e+1f
, +1.350e+2f
, +1.000e+0f
, +1.000e+0f
, 4096),
366 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
367 dst_data
[2].x
, dst_data
[2].y
, dst_data
[2].z
, dst_data
[2].w
);
368 ok(compare_vec4(&dst_data
[3], +1.945e+2f
, +1.025e+2f
, -5.000e-1f
, +1.000e+0f
, 4096),
369 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
370 dst_data
[3].x
, dst_data
[3].y
, dst_data
[3].z
, dst_data
[3].w
);
371 hr
= IDirect3DVertexBuffer7_Unlock(dst_vb1
);
372 ok(SUCCEEDED(hr
), "Failed to unlock destination vertex buffer, hr %#x.\n", hr
);
374 hr
= IDirect3DDevice7_SetTransform(device
, D3DTRANSFORMSTATE_WORLD
, &world
);
375 ok(SUCCEEDED(hr
), "Failed to set world transform, hr %#x.\n", hr
);
376 hr
= IDirect3DDevice7_SetTransform(device
, D3DTRANSFORMSTATE_VIEW
, &view
);
377 ok(SUCCEEDED(hr
), "Failed to set view transform, hr %#x.\n", hr
);
378 hr
= IDirect3DDevice7_SetTransform(device
, D3DTRANSFORMSTATE_PROJECTION
, &proj
);
379 ok(SUCCEEDED(hr
), "Failed to set projection transform, hr %#x.\n", hr
);
381 hr
= IDirect3DVertexBuffer7_ProcessVertices(dst_vb1
, D3DVOP_TRANSFORM
, 0, 4, src_vb
, 0, device
, 0);
382 ok(SUCCEEDED(hr
), "Failed to process vertices, hr %#x.\n", hr
);
384 hr
= IDirect3DVertexBuffer7_Lock(dst_vb1
, 0, (void **)&dst_data
, NULL
);
385 ok(SUCCEEDED(hr
), "Failed to lock destination vertex buffer, hr %#x.\n", hr
);
386 ok(compare_vec4(&dst_data
[0], +2.560e+2f
, +7.000e+1f
, -2.000e+0f
, +3.333e-1f
, 4096),
387 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
388 dst_data
[0].x
, dst_data
[0].y
, dst_data
[0].z
, dst_data
[0].w
);
389 ok(compare_vec4(&dst_data
[1], +2.560e+2f
, +7.813e+1f
, -2.750e+0f
, +1.250e-1f
, 4096),
390 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
391 dst_data
[1].x
, dst_data
[1].y
, dst_data
[1].z
, dst_data
[1].w
);
392 ok(compare_vec4(&dst_data
[2], +2.560e+2f
, +4.400e+1f
, +4.000e-1f
, +4.000e-1f
, 4096),
393 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
394 dst_data
[2].x
, dst_data
[2].y
, dst_data
[2].z
, dst_data
[2].w
);
395 ok(compare_vec4(&dst_data
[3], +2.560e+2f
, +8.182e+1f
, -3.091e+0f
, +3.636e-1f
, 4096),
396 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
397 dst_data
[3].x
, dst_data
[3].y
, dst_data
[3].z
, dst_data
[3].w
);
398 hr
= IDirect3DVertexBuffer7_Unlock(dst_vb1
);
399 ok(SUCCEEDED(hr
), "Failed to unlock destination vertex buffer, hr %#x.\n", hr
);
401 IDirect3DVertexBuffer7_Release(dst_vb2
);
402 IDirect3DVertexBuffer7_Release(dst_vb1
);
403 IDirect3DVertexBuffer7_Release(src_vb
);
404 IDirect3D7_Release(d3d7
);
405 IDirect3DDevice7_Release(device
);
406 DestroyWindow(window
);
409 static void test_coop_level_create_device_window(void)
411 HWND focus_window
, device_window
;
415 focus_window
= CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW
,
416 0, 0, 640, 480, 0, 0, 0, 0);
417 if (!(ddraw
= create_ddraw()))
419 skip("Failed to create a 3D device, skipping test.\n");
420 DestroyWindow(focus_window
);
424 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, NULL
, DDSCL_NORMAL
);
425 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
426 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
427 ok(!device_window
, "Unexpected device window found.\n");
428 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, NULL
, DDSCL_CREATEDEVICEWINDOW
);
429 ok(hr
== DDERR_INVALIDPARAMS
, "Got unexpected hr %#x.\n", hr
);
430 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
431 ok(!device_window
, "Unexpected device window found.\n");
432 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, NULL
, DDSCL_CREATEDEVICEWINDOW
| DDSCL_NORMAL
);
433 ok(hr
== DDERR_INVALIDPARAMS
, "Got unexpected hr %#x.\n", hr
);
434 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
435 ok(!device_window
, "Unexpected device window found.\n");
436 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, NULL
, DDSCL_CREATEDEVICEWINDOW
| DDSCL_NORMAL
| DDSCL_FULLSCREEN
);
437 ok(hr
== DDERR_INVALIDPARAMS
, "Got unexpected hr %#x.\n", hr
);
438 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
439 ok(!device_window
, "Unexpected device window found.\n");
440 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, NULL
, DDSCL_CREATEDEVICEWINDOW
| DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
);
441 ok(hr
== DDERR_NOFOCUSWINDOW
|| broken(hr
== DDERR_INVALIDPARAMS
), "Got unexpected hr %#x.\n", hr
);
442 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
443 ok(!device_window
, "Unexpected device window found.\n");
445 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
446 if (broken(hr
== DDERR_INVALIDPARAMS
))
448 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
449 IDirectDraw7_Release(ddraw
);
450 DestroyWindow(focus_window
);
454 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, NULL
, DDSCL_NORMAL
);
455 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
456 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
457 ok(!device_window
, "Unexpected device window found.\n");
458 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, focus_window
, DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
);
459 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
460 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
461 ok(!device_window
, "Unexpected device window found.\n");
463 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, NULL
, DDSCL_NORMAL
);
464 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
465 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
466 ok(!device_window
, "Unexpected device window found.\n");
467 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, NULL
, DDSCL_SETFOCUSWINDOW
468 | DDSCL_CREATEDEVICEWINDOW
| DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
);
469 ok(hr
== DDERR_NOHWND
, "Got unexpected hr %#x.\n", hr
);
470 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
471 ok(!!device_window
, "Device window not found.\n");
473 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, NULL
, DDSCL_NORMAL
);
474 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
475 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
476 ok(!device_window
, "Unexpected device window found.\n");
477 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, focus_window
, DDSCL_SETFOCUSWINDOW
478 | DDSCL_CREATEDEVICEWINDOW
| DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
);
479 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
480 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
481 ok(!!device_window
, "Device window not found.\n");
483 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, NULL
, DDSCL_NORMAL
);
484 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
485 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
486 ok(!device_window
, "Unexpected device window found.\n");
487 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, NULL
, DDSCL_CREATEDEVICEWINDOW
| DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
);
488 ok(hr
== DDERR_NOFOCUSWINDOW
, "Got unexpected hr %#x.\n", hr
);
489 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
490 ok(!device_window
, "Unexpected device window found.\n");
491 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, focus_window
, DDSCL_SETFOCUSWINDOW
);
492 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
493 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
494 ok(!device_window
, "Unexpected device window found.\n");
495 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, NULL
, DDSCL_CREATEDEVICEWINDOW
| DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
);
496 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
497 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
498 ok(!!device_window
, "Device window not found.\n");
500 IDirectDraw7_Release(ddraw
);
501 DestroyWindow(focus_window
);
504 static void test_clipper_blt(void)
506 IDirectDrawSurface7
*src_surface
, *dst_surface
;
507 RECT client_rect
, src_rect
, *rect
;
508 IDirectDrawClipper
*clipper
;
509 DDSURFACEDESC2 surface_desc
;
510 unsigned int i
, j
, x
, y
;
521 static const DWORD src_data
[] =
523 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
524 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
525 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
527 static const D3DCOLOR expected1
[] =
529 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
530 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
531 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
532 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
534 static const D3DCOLOR expected2
[] =
536 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
537 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
538 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
539 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
542 window
= CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW
,
543 10, 10, 640, 480, 0, 0, 0, 0);
544 ShowWindow(window
, SW_SHOW
);
545 if (!(ddraw
= create_ddraw()))
547 skip("Failed to create a ddraw object, skipping test.\n");
548 DestroyWindow(window
);
552 ret
= GetClientRect(window
, &client_rect
);
553 ok(ret
, "Failed to get client rect.\n");
554 ret
= MapWindowPoints(window
, NULL
, (POINT
*)&client_rect
, 2);
555 ok(ret
, "Failed to map client rect.\n");
557 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, window
, DDSCL_NORMAL
);
558 ok(SUCCEEDED(hr
), "Failed to set cooperative level, hr %#x.\n", hr
);
560 hr
= IDirectDraw7_CreateClipper(ddraw
, 0, &clipper
, NULL
);
561 ok(SUCCEEDED(hr
), "Failed to create clipper, hr %#x.\n", hr
);
562 hr
= IDirectDrawClipper_GetClipList(clipper
, NULL
, NULL
, &ret
);
563 ok(hr
== DDERR_NOCLIPLIST
, "Got unexpected hr %#x.\n", hr
);
564 hr
= IDirectDrawClipper_SetHWnd(clipper
, 0, window
);
565 ok(SUCCEEDED(hr
), "Failed to set clipper window, hr %#x.\n", hr
);
566 hr
= IDirectDrawClipper_GetClipList(clipper
, NULL
, NULL
, &ret
);
567 ok(SUCCEEDED(hr
), "Failed to get clip list size, hr %#x.\n", hr
);
568 rgn_data
= HeapAlloc(GetProcessHeap(), 0, ret
);
569 hr
= IDirectDrawClipper_GetClipList(clipper
, NULL
, rgn_data
, &ret
);
570 ok(SUCCEEDED(hr
), "Failed to get clip list, hr %#x.\n", hr
);
571 ok(rgn_data
->rdh
.dwSize
== sizeof(rgn_data
->rdh
), "Got unexpected structure size %#x.\n", rgn_data
->rdh
.dwSize
);
572 ok(rgn_data
->rdh
.iType
== RDH_RECTANGLES
, "Got unexpected type %#x.\n", rgn_data
->rdh
.iType
);
573 ok(rgn_data
->rdh
.nCount
== 1, "Got unexpected count %u.\n", rgn_data
->rdh
.nCount
);
574 ok(rgn_data
->rdh
.nRgnSize
== 16, "Got unexpected region size %u.\n", rgn_data
->rdh
.nRgnSize
);
575 ok(EqualRect(&rgn_data
->rdh
.rcBound
, &client_rect
),
576 "Got unexpected bounding rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
577 rgn_data
->rdh
.rcBound
.left
, rgn_data
->rdh
.rcBound
.top
,
578 rgn_data
->rdh
.rcBound
.right
, rgn_data
->rdh
.rcBound
.bottom
,
579 client_rect
.left
, client_rect
.top
, client_rect
.right
, client_rect
.bottom
);
580 rect
= (RECT
*)&rgn_data
->Buffer
[0];
581 ok(EqualRect(rect
, &client_rect
),
582 "Got unexpected clip rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
583 rect
->left
, rect
->top
, rect
->right
, rect
->bottom
,
584 client_rect
.left
, client_rect
.top
, client_rect
.right
, client_rect
.bottom
);
585 HeapFree(GetProcessHeap(), 0, rgn_data
);
587 r1
= CreateRectRgn(0, 0, 320, 240);
588 ok(!!r1
, "Failed to create region.\n");
589 r2
= CreateRectRgn(320, 240, 640, 480);
590 ok(!!r2
, "Failed to create region.\n");
591 CombineRgn(r1
, r1
, r2
, RGN_OR
);
592 ret
= GetRegionData(r1
, 0, NULL
);
593 rgn_data
= HeapAlloc(GetProcessHeap(), 0, ret
);
594 ret
= GetRegionData(r1
, ret
, rgn_data
);
595 ok(!!ret
, "Failed to get region data.\n");
600 hr
= IDirectDrawClipper_SetClipList(clipper
, rgn_data
, 0);
601 ok(hr
== DDERR_CLIPPERISUSINGHWND
, "Got unexpected hr %#x.\n", hr
);
602 hr
= IDirectDrawClipper_SetHWnd(clipper
, 0, NULL
);
603 ok(SUCCEEDED(hr
), "Failed to set clipper window, hr %#x.\n", hr
);
604 hr
= IDirectDrawClipper_SetClipList(clipper
, rgn_data
, 0);
605 ok(SUCCEEDED(hr
), "Failed to set clip list, hr %#x.\n", hr
);
607 HeapFree(GetProcessHeap(), 0, rgn_data
);
609 memset(&surface_desc
, 0, sizeof(surface_desc
));
610 surface_desc
.dwSize
= sizeof(surface_desc
);
611 surface_desc
.dwFlags
= DDSD_CAPS
| DDSD_WIDTH
| DDSD_HEIGHT
| DDSD_PIXELFORMAT
;
612 surface_desc
.ddsCaps
.dwCaps
= DDSCAPS_OFFSCREENPLAIN
;
613 surface_desc
.dwWidth
= 640;
614 surface_desc
.dwHeight
= 480;
615 U4(surface_desc
).ddpfPixelFormat
.dwSize
= sizeof(U4(surface_desc
).ddpfPixelFormat
);
616 U4(surface_desc
).ddpfPixelFormat
.dwFlags
= DDPF_RGB
;
617 U1(U4(surface_desc
).ddpfPixelFormat
).dwRGBBitCount
= 32;
618 U2(U4(surface_desc
).ddpfPixelFormat
).dwRBitMask
= 0x00ff0000;
619 U3(U4(surface_desc
).ddpfPixelFormat
).dwGBitMask
= 0x0000ff00;
620 U4(U4(surface_desc
).ddpfPixelFormat
).dwBBitMask
= 0x000000ff;
622 hr
= IDirectDraw7_CreateSurface(ddraw
, &surface_desc
, &src_surface
, NULL
);
623 ok(SUCCEEDED(hr
), "Failed to create source surface, hr %#x.\n", hr
);
624 hr
= IDirectDraw7_CreateSurface(ddraw
, &surface_desc
, &dst_surface
, NULL
);
625 ok(SUCCEEDED(hr
), "Failed to create destination surface, hr %#x.\n", hr
);
627 memset(&fx
, 0, sizeof(fx
));
628 fx
.dwSize
= sizeof(fx
);
629 hr
= IDirectDrawSurface7_Blt(src_surface
, NULL
, NULL
, NULL
, DDBLT_COLORFILL
| DDBLT_WAIT
, &fx
);
630 ok(SUCCEEDED(hr
), "Failed to clear source surface, hr %#x.\n", hr
);
631 hr
= IDirectDrawSurface7_Blt(dst_surface
, NULL
, NULL
, NULL
, DDBLT_COLORFILL
| DDBLT_WAIT
, &fx
);
632 ok(SUCCEEDED(hr
), "Failed to clear destination surface, hr %#x.\n", hr
);
634 hr
= IDirectDrawSurface7_Lock(src_surface
, NULL
, &surface_desc
, 0, NULL
);
635 ok(SUCCEEDED(hr
), "Failed to lock source surface, hr %#x.\n", hr
);
636 ok(surface_desc
.lPitch
== 2560, "Got unexpected surface pitch %u.\n", surface_desc
.lPitch
);
637 ptr
= surface_desc
.lpSurface
;
638 memcpy(&ptr
[ 0], &src_data
[ 0], 6 * sizeof(DWORD
));
639 memcpy(&ptr
[ 640], &src_data
[ 6], 6 * sizeof(DWORD
));
640 memcpy(&ptr
[1280], &src_data
[12], 6 * sizeof(DWORD
));
641 hr
= IDirectDrawSurface7_Unlock(src_surface
, NULL
);
642 ok(SUCCEEDED(hr
), "Failed to unlock source surface, hr %#x.\n", hr
);
644 hr
= IDirectDrawSurface7_SetClipper(dst_surface
, clipper
);
645 ok(SUCCEEDED(hr
), "Failed to set clipper, hr %#x.\n", hr
);
647 SetRect(&src_rect
, 1, 1, 5, 2);
648 hr
= IDirectDrawSurface7_Blt(dst_surface
, NULL
, src_surface
, &src_rect
, DDBLT_WAIT
, NULL
);
649 ok(SUCCEEDED(hr
), "Failed to blit, hr %#x.\n", hr
);
650 for (i
= 0; i
< 4; ++i
)
652 for (j
= 0; j
< 4; ++j
)
654 x
= 80 * ((2 * j
) + 1);
655 y
= 60 * ((2 * i
) + 1);
656 color
= get_surface_color(dst_surface
, x
, y
);
657 ok(compare_color(color
, expected1
[i
* 4 + j
], 1),
658 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1
[i
* 4 + j
], x
, y
, color
);
662 U5(fx
).dwFillColor
= 0xff0000ff;
663 hr
= IDirectDrawSurface7_Blt(dst_surface
, NULL
, NULL
, NULL
, DDBLT_COLORFILL
| DDBLT_WAIT
, &fx
);
664 ok(SUCCEEDED(hr
), "Failed to clear destination surface, hr %#x.\n", hr
);
665 for (i
= 0; i
< 4; ++i
)
667 for (j
= 0; j
< 4; ++j
)
669 x
= 80 * ((2 * j
) + 1);
670 y
= 60 * ((2 * i
) + 1);
671 color
= get_surface_color(dst_surface
, x
, y
);
672 ok(compare_color(color
, expected2
[i
* 4 + j
], 1),
673 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2
[i
* 4 + j
], x
, y
, color
);
677 hr
= IDirectDrawSurface7_BltFast(dst_surface
, 0, 0, src_surface
, NULL
, DDBLTFAST_WAIT
);
678 ok(hr
== DDERR_BLTFASTCANTCLIP
, "Got unexpected hr %#x.\n", hr
);
680 hr
= IDirectDrawClipper_SetHWnd(clipper
, 0, window
);
681 ok(SUCCEEDED(hr
), "Failed to set clipper window, hr %#x.\n", hr
);
682 hr
= IDirectDrawClipper_GetClipList(clipper
, NULL
, NULL
, &ret
);
683 ok(SUCCEEDED(hr
), "Failed to get clip list size, hr %#x.\n", hr
);
684 DestroyWindow(window
);
685 hr
= IDirectDrawClipper_GetClipList(clipper
, NULL
, NULL
, &ret
);
686 ok(hr
== E_FAIL
, "Got unexpected hr %#x.\n", hr
);
687 hr
= IDirectDrawClipper_SetHWnd(clipper
, 0, NULL
);
688 ok(SUCCEEDED(hr
), "Failed to set clipper window, hr %#x.\n", hr
);
689 hr
= IDirectDrawClipper_GetClipList(clipper
, NULL
, NULL
, &ret
);
690 ok(SUCCEEDED(hr
), "Failed to get clip list size, hr %#x.\n", hr
);
691 hr
= IDirectDrawClipper_SetClipList(clipper
, NULL
, 0);
692 ok(SUCCEEDED(hr
), "Failed to set clip list, hr %#x.\n", hr
);
693 hr
= IDirectDrawClipper_GetClipList(clipper
, NULL
, NULL
, &ret
);
694 ok(hr
== DDERR_NOCLIPLIST
, "Got unexpected hr %#x.\n", hr
);
695 hr
= IDirectDrawSurface7_Blt(dst_surface
, NULL
, NULL
, NULL
, DDBLT_COLORFILL
| DDBLT_WAIT
, &fx
);
696 ok(hr
== DDERR_NOCLIPLIST
, "Got unexpected hr %#x.\n", hr
);
698 IDirectDrawSurface7_Release(dst_surface
);
699 IDirectDrawSurface7_Release(src_surface
);
700 IDirectDrawClipper_Release(clipper
);
701 IDirectDraw7_Release(ddraw
);
704 static void test_coop_level_d3d_state(void)
706 IDirectDrawSurface7
*rt
, *surface
;
707 IDirect3DDevice7
*device
;
715 window
= CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW
,
716 0, 0, 640, 480, 0, 0, 0, 0);
717 if (!(device
= create_device(window
, DDSCL_NORMAL
)))
719 skip("Failed to create D3D device, skipping test.\n");
720 DestroyWindow(window
);
724 hr
= IDirect3DDevice7_GetRenderTarget(device
, &rt
);
725 ok(SUCCEEDED(hr
), "Failed to get render target, hr %#x.\n", hr
);
726 hr
= IDirect3DDevice7_GetRenderState(device
, D3DRENDERSTATE_ZENABLE
, &value
);
727 ok(SUCCEEDED(hr
), "Failed to get render state, hr %#x.\n", hr
);
728 ok(!!value
, "Got unexpected z-enable state %#x.\n", value
);
729 hr
= IDirect3DDevice7_GetRenderState(device
, D3DRENDERSTATE_ALPHABLENDENABLE
, &value
);
730 ok(SUCCEEDED(hr
), "Failed to get render state, hr %#x.\n", hr
);
731 ok(!value
, "Got unexpected alpha blend enable state %#x.\n", value
);
732 hr
= IDirect3DDevice7_SetRenderState(device
, D3DRENDERSTATE_ALPHABLENDENABLE
, TRUE
);
733 ok(SUCCEEDED(hr
), "Failed to set render state, hr %#x.\n", hr
);
734 hr
= IDirect3DDevice7_Clear(device
, 0, NULL
, D3DCLEAR_TARGET
, 0xffff0000, 0.0f
, 0);
735 ok(SUCCEEDED(hr
), "Failed to clear render target, hr %#x.\n", hr
);
736 color
= get_surface_color(rt
, 320, 240);
737 ok(compare_color(color
, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color
);
739 hr
= IDirect3DDevice7_GetDirect3D(device
, &d3d
);
740 ok(SUCCEEDED(hr
), "Failed to get d3d interface, hr %#x.\n", hr
);
741 hr
= IDirect3D7_QueryInterface(d3d
, &IID_IDirectDraw7
, (void **)&ddraw
);
742 ok(SUCCEEDED(hr
), "Failed to get ddraw interface, hr %#x.\n", hr
);
743 IDirect3D7_Release(d3d
);
744 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, window
, DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
);
745 ok(SUCCEEDED(hr
), "Failed to set cooperative level, hr %#x.\n", hr
);
746 hr
= IDirectDrawSurface7_IsLost(rt
);
747 ok(hr
== DDERR_SURFACELOST
, "Got unexpected hr %#x.\n", hr
);
748 hr
= IDirectDraw7_RestoreAllSurfaces(ddraw
);
749 ok(SUCCEEDED(hr
), "Failed to restore surfaces, hr %#x.\n", hr
);
750 IDirectDraw7_Release(ddraw
);
752 hr
= IDirect3DDevice7_GetRenderTarget(device
, &surface
);
753 ok(SUCCEEDED(hr
), "Failed to get render target, hr %#x.\n", hr
);
754 ok(surface
== rt
, "Got unexpected surface %p.\n", surface
);
755 hr
= IDirect3DDevice7_GetRenderState(device
, D3DRENDERSTATE_ZENABLE
, &value
);
756 ok(SUCCEEDED(hr
), "Failed to get render state, hr %#x.\n", hr
);
757 todo_wine
ok(!!value
, "Got unexpected z-enable state %#x.\n", value
);
758 hr
= IDirect3DDevice7_GetRenderState(device
, D3DRENDERSTATE_ALPHABLENDENABLE
, &value
);
759 ok(SUCCEEDED(hr
), "Failed to get render state, hr %#x.\n", hr
);
760 todo_wine
ok(!!value
, "Got unexpected alpha blend enable state %#x.\n", value
);
761 hr
= IDirect3DDevice7_Clear(device
, 0, NULL
, D3DCLEAR_TARGET
, 0xff00ff00, 0.0f
, 0);
762 ok(SUCCEEDED(hr
), "Failed to clear render target, hr %#x.\n", hr
);
763 color
= get_surface_color(rt
, 320, 240);
764 todo_wine
ok(compare_color(color
, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color
);
766 IDirectDrawSurface7_Release(surface
);
767 IDirectDrawSurface7_Release(rt
);
768 IDirect3DDevice7_Release(device
);
769 DestroyWindow(window
);
774 HMODULE module
= GetModuleHandleA("ddraw.dll");
776 if (!(pDirectDrawCreateEx
= (void *)GetProcAddress(module
, "DirectDrawCreateEx")))
778 win_skip("DirectDrawCreateEx not available, skipping tests.\n");
782 test_process_vertices();
783 test_coop_level_create_device_window();
785 test_coop_level_d3d_state();