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 IDirectDraw7
*create_ddraw(void)
106 if (FAILED(pDirectDrawCreateEx(NULL
, (void **)&ddraw
, &IID_IDirectDraw7
, NULL
)))
112 static IDirect3DDevice7
*create_device(HWND window
, DWORD coop_level
)
114 IDirect3DDevice7
*device
= NULL
;
115 IDirectDrawSurface7
*surface
;
116 DDSURFACEDESC2 surface_desc
;
121 if (!(ddraw
= create_ddraw()))
124 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, window
, coop_level
);
125 ok(SUCCEEDED(hr
), "Failed to set cooperative level, hr %#x.\n", hr
);
127 memset(&surface_desc
, 0, sizeof(surface_desc
));
128 surface_desc
.dwSize
= sizeof(surface_desc
);
129 surface_desc
.dwFlags
= DDSD_CAPS
| DDSD_WIDTH
| DDSD_HEIGHT
;
130 surface_desc
.ddsCaps
.dwCaps
= DDSCAPS_OFFSCREENPLAIN
| DDSCAPS_3DDEVICE
;
131 surface_desc
.dwWidth
= 640;
132 surface_desc
.dwHeight
= 480;
134 hr
= IDirectDraw7_CreateSurface(ddraw
, &surface_desc
, &surface
, NULL
);
135 ok(SUCCEEDED(hr
), "Failed to create surface, hr %#x.\n", hr
);
137 if (coop_level
& DDSCL_NORMAL
)
139 IDirectDrawClipper
*clipper
;
141 hr
= IDirectDraw7_CreateClipper(ddraw
, 0, &clipper
, NULL
);
142 ok(SUCCEEDED(hr
), "Failed to create clipper, hr %#x.\n", hr
);
143 hr
= IDirectDrawClipper_SetHWnd(clipper
, 0, window
);
144 ok(SUCCEEDED(hr
), "Failed to set clipper window, hr %#x.\n", hr
);
145 hr
= IDirectDrawSurface7_SetClipper(surface
, clipper
);
146 ok(SUCCEEDED(hr
), "Failed to set surface clipper, hr %#x.\n", hr
);
147 IDirectDrawClipper_Release(clipper
);
150 hr
= IDirectDraw7_QueryInterface(ddraw
, &IID_IDirect3D7
, (void **)&d3d7
);
151 IDirectDraw7_Release(ddraw
);
154 IDirectDrawSurface7_Release(surface
);
158 hr
= IDirect3D7_CreateDevice(d3d7
, &IID_IDirect3DTnLHalDevice
, surface
, &device
);
159 IDirect3D7_Release(d3d7
);
160 IDirectDrawSurface7_Release(surface
);
167 static void test_process_vertices(void)
169 IDirect3DVertexBuffer7
*src_vb
, *dst_vb1
, *dst_vb2
;
170 D3DVERTEXBUFFERDESC vb_desc
;
171 IDirect3DDevice7
*device
;
172 struct vec4
*dst_data
;
173 struct vec3
*dst_data2
;
174 struct vec3
*src_data
;
180 static D3DMATRIX world
=
182 0.0f
, 1.0f
, 0.0f
, 0.0f
,
183 1.0f
, 0.0f
, 0.0f
, 0.0f
,
184 0.0f
, 0.0f
, 0.0f
, 1.0f
,
185 0.0f
, 1.0f
, 1.0f
, 1.0f
,
187 static D3DMATRIX view
=
189 2.0f
, 0.0f
, 0.0f
, 0.0f
,
190 0.0f
, -1.0f
, 0.0f
, 0.0f
,
191 0.0f
, 0.0f
, 1.0f
, 0.0f
,
192 0.0f
, 0.0f
, 0.0f
, 3.0f
,
194 static D3DMATRIX proj
=
196 1.0f
, 0.0f
, 0.0f
, 1.0f
,
197 0.0f
, 1.0f
, 1.0f
, 0.0f
,
198 0.0f
, 1.0f
, 1.0f
, 0.0f
,
199 1.0f
, 0.0f
, 0.0f
, 1.0f
,
202 window
= CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW
,
203 0, 0, 640, 480, 0, 0, 0, 0);
204 if (!(device
= create_device(window
, DDSCL_NORMAL
)))
206 skip("Failed to create a ddraw object, skipping test.\n");
207 DestroyWindow(window
);
211 hr
= IDirect3DDevice7_GetDirect3D(device
, &d3d7
);
212 ok(SUCCEEDED(hr
), "Failed to get Direct3D7 interface, hr %#x.\n", hr
);
214 memset(&vb_desc
, 0, sizeof(vb_desc
));
215 vb_desc
.dwSize
= sizeof(vb_desc
);
216 vb_desc
.dwFVF
= D3DFVF_XYZ
;
217 vb_desc
.dwNumVertices
= 4;
218 hr
= IDirect3D7_CreateVertexBuffer(d3d7
, &vb_desc
, &src_vb
, 0);
219 ok(SUCCEEDED(hr
), "Failed to create source vertex buffer, hr %#x.\n", hr
);
221 hr
= IDirect3DVertexBuffer7_Lock(src_vb
, 0, (void **)&src_data
, NULL
);
222 ok(SUCCEEDED(hr
), "Failed to lock source vertex buffer, hr %#x.\n", hr
);
223 src_data
[0].x
= 0.0f
;
224 src_data
[0].y
= 0.0f
;
225 src_data
[0].z
= 0.0f
;
226 src_data
[1].x
= 1.0f
;
227 src_data
[1].y
= 1.0f
;
228 src_data
[1].z
= 1.0f
;
229 src_data
[2].x
= -1.0f
;
230 src_data
[2].y
= -1.0f
;
231 src_data
[2].z
= 0.5f
;
232 src_data
[3].x
= 0.5f
;
233 src_data
[3].y
= -0.5f
;
234 src_data
[3].z
= 0.25f
;
235 hr
= IDirect3DVertexBuffer7_Unlock(src_vb
);
236 ok(SUCCEEDED(hr
), "Failed to unlock source vertex buffer, hr %#x.\n", hr
);
238 memset(&vb_desc
, 0, sizeof(vb_desc
));
239 vb_desc
.dwSize
= sizeof(vb_desc
);
240 vb_desc
.dwFVF
= D3DFVF_XYZRHW
;
241 vb_desc
.dwNumVertices
= 4;
242 /* MSDN says that the last parameter must be 0 - check that. */
243 hr
= IDirect3D7_CreateVertexBuffer(d3d7
, &vb_desc
, &dst_vb1
, 4);
244 ok(SUCCEEDED(hr
), "Failed to create vertex buffer, hr %#x.\n", hr
);
246 memset(&vb_desc
, 0, sizeof(vb_desc
));
247 vb_desc
.dwSize
= sizeof(vb_desc
);
248 vb_desc
.dwFVF
= D3DFVF_XYZ
;
249 vb_desc
.dwNumVertices
= 5;
250 /* MSDN says that the last parameter must be 0 - check that. */
251 hr
= IDirect3D7_CreateVertexBuffer(d3d7
, &vb_desc
, &dst_vb2
, 12345678);
252 ok(SUCCEEDED(hr
), "Failed to create vertex buffer, hr %#x.\n", hr
);
254 memset(&vp
, 0, sizeof(vp
));
261 hr
= IDirect3DDevice7_SetViewport(device
, &vp
);
262 ok(SUCCEEDED(hr
), "Failed to set viewport, hr %#x.\n", hr
);
264 hr
= IDirect3DVertexBuffer7_ProcessVertices(dst_vb1
, D3DVOP_TRANSFORM
, 0, 4, src_vb
, 0, device
, 0);
265 ok(SUCCEEDED(hr
), "Failed to process vertices, hr %#x.\n", hr
);
266 hr
= IDirect3DVertexBuffer7_ProcessVertices(dst_vb2
, D3DVOP_TRANSFORM
, 0, 4, src_vb
, 0, device
, 0);
267 ok(SUCCEEDED(hr
), "Failed to process vertices, hr %#x.\n", hr
);
269 hr
= IDirect3DVertexBuffer7_Lock(dst_vb1
, 0, (void **)&dst_data
, NULL
);
270 ok(SUCCEEDED(hr
), "Failed to lock destination vertex buffer, hr %#x.\n", hr
);
271 ok(compare_vec4(&dst_data
[0], +1.280e+2f
, +1.280e+2f
, +0.000e+0f
, +1.000e+0f
, 4096),
272 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
273 dst_data
[0].x
, dst_data
[0].y
, dst_data
[0].z
, dst_data
[0].w
);
274 ok(compare_vec4(&dst_data
[1], +1.920e+2f
, +6.400e+1f
, +1.000e+0f
, +1.000e+0f
, 4096),
275 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
276 dst_data
[1].x
, dst_data
[1].y
, dst_data
[1].z
, dst_data
[1].w
);
277 ok(compare_vec4(&dst_data
[2], +6.400e+1f
, +1.920e+2f
, +5.000e-1f
, +1.000e+0f
, 4096),
278 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
279 dst_data
[2].x
, dst_data
[2].y
, dst_data
[2].z
, dst_data
[2].w
);
280 ok(compare_vec4(&dst_data
[3], +1.600e+2f
, +1.600e+2f
, +2.500e-1f
, +1.000e+0f
, 4096),
281 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
282 dst_data
[3].x
, dst_data
[3].y
, dst_data
[3].z
, dst_data
[3].w
);
283 hr
= IDirect3DVertexBuffer7_Unlock(dst_vb1
);
284 ok(SUCCEEDED(hr
), "Failed to unlock destination vertex buffer, hr %#x.\n", hr
);
286 hr
= IDirect3DVertexBuffer7_Lock(dst_vb2
, 0, (void **)&dst_data2
, NULL
);
287 ok(SUCCEEDED(hr
), "Failed to lock destination vertex buffer, hr %#x.\n", hr
);
288 /* Small thing without much practical meaning, but I stumbled upon it,
289 * so let's check for it: If the output vertex buffer has no RHW value,
290 * the RHW value of the last vertex is written into the next vertex. */
291 ok(compare_vec3(&dst_data2
[4], +1.000e+0f
, +0.000e+0f
, +0.000e+0f
, 4096),
292 "Got unexpected vertex 4 {%.8e, %.8e, %.8e}.\n",
293 dst_data2
[4].x
, dst_data2
[4].y
, dst_data2
[4].z
);
294 hr
= IDirect3DVertexBuffer7_Unlock(dst_vb2
);
295 ok(SUCCEEDED(hr
), "Failed to unlock destination vertex buffer, hr %#x.\n", hr
);
297 /* Try a more complicated viewport, same vertices. */
298 memset(&vp
, 0, sizeof(vp
));
305 hr
= IDirect3DDevice7_SetViewport(device
, &vp
);
306 ok(SUCCEEDED(hr
), "Failed to set viewport, hr %#x.\n", hr
);
308 hr
= IDirect3DVertexBuffer7_ProcessVertices(dst_vb1
, D3DVOP_TRANSFORM
, 0, 4, src_vb
, 0, device
, 0);
309 ok(SUCCEEDED(hr
), "Failed to process vertices, hr %#x.\n", hr
);
311 hr
= IDirect3DVertexBuffer7_Lock(dst_vb1
, 0, (void **)&dst_data
, NULL
);
312 ok(SUCCEEDED(hr
), "Failed to lock destination vertex buffer, hr %#x.\n", hr
);
313 ok(compare_vec4(&dst_data
[0], +1.330e+2f
, +7.000e+1f
, -2.000e+0f
, +1.000e+0f
, 4096),
314 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
315 dst_data
[0].x
, dst_data
[0].y
, dst_data
[0].z
, dst_data
[0].w
);
316 ok(compare_vec4(&dst_data
[1], +2.560e+2f
, +5.000e+0f
, +4.000e+0f
, +1.000e+0f
, 4096),
317 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
318 dst_data
[1].x
, dst_data
[1].y
, dst_data
[1].z
, dst_data
[1].w
);
319 ok(compare_vec4(&dst_data
[2], +1.000e+1f
, +1.350e+2f
, +1.000e+0f
, +1.000e+0f
, 4096),
320 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
321 dst_data
[2].x
, dst_data
[2].y
, dst_data
[2].z
, dst_data
[2].w
);
322 ok(compare_vec4(&dst_data
[3], +1.945e+2f
, +1.025e+2f
, -5.000e-1f
, +1.000e+0f
, 4096),
323 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
324 dst_data
[3].x
, dst_data
[3].y
, dst_data
[3].z
, dst_data
[3].w
);
325 hr
= IDirect3DVertexBuffer7_Unlock(dst_vb1
);
326 ok(SUCCEEDED(hr
), "Failed to unlock destination vertex buffer, hr %#x.\n", hr
);
328 hr
= IDirect3DDevice7_SetTransform(device
, D3DTRANSFORMSTATE_WORLD
, &world
);
329 ok(SUCCEEDED(hr
), "Failed to set world transform, hr %#x.\n", hr
);
330 hr
= IDirect3DDevice7_SetTransform(device
, D3DTRANSFORMSTATE_VIEW
, &view
);
331 ok(SUCCEEDED(hr
), "Failed to set view transform, hr %#x.\n", hr
);
332 hr
= IDirect3DDevice7_SetTransform(device
, D3DTRANSFORMSTATE_PROJECTION
, &proj
);
333 ok(SUCCEEDED(hr
), "Failed to set projection transform, hr %#x.\n", hr
);
335 hr
= IDirect3DVertexBuffer7_ProcessVertices(dst_vb1
, D3DVOP_TRANSFORM
, 0, 4, src_vb
, 0, device
, 0);
336 ok(SUCCEEDED(hr
), "Failed to process vertices, hr %#x.\n", hr
);
338 hr
= IDirect3DVertexBuffer7_Lock(dst_vb1
, 0, (void **)&dst_data
, NULL
);
339 ok(SUCCEEDED(hr
), "Failed to lock destination vertex buffer, hr %#x.\n", hr
);
340 ok(compare_vec4(&dst_data
[0], +2.560e+2f
, +7.000e+1f
, -2.000e+0f
, +3.333e-1f
, 4096),
341 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
342 dst_data
[0].x
, dst_data
[0].y
, dst_data
[0].z
, dst_data
[0].w
);
343 ok(compare_vec4(&dst_data
[1], +2.560e+2f
, +7.813e+1f
, -2.750e+0f
, +1.250e-1f
, 4096),
344 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
345 dst_data
[1].x
, dst_data
[1].y
, dst_data
[1].z
, dst_data
[1].w
);
346 ok(compare_vec4(&dst_data
[2], +2.560e+2f
, +4.400e+1f
, +4.000e-1f
, +4.000e-1f
, 4096),
347 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
348 dst_data
[2].x
, dst_data
[2].y
, dst_data
[2].z
, dst_data
[2].w
);
349 ok(compare_vec4(&dst_data
[3], +2.560e+2f
, +8.182e+1f
, -3.091e+0f
, +3.636e-1f
, 4096),
350 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
351 dst_data
[3].x
, dst_data
[3].y
, dst_data
[3].z
, dst_data
[3].w
);
352 hr
= IDirect3DVertexBuffer7_Unlock(dst_vb1
);
353 ok(SUCCEEDED(hr
), "Failed to unlock destination vertex buffer, hr %#x.\n", hr
);
355 IDirect3DVertexBuffer7_Release(dst_vb2
);
356 IDirect3DVertexBuffer7_Release(dst_vb1
);
357 IDirect3DVertexBuffer7_Release(src_vb
);
358 IDirect3D7_Release(d3d7
);
359 IDirect3DDevice7_Release(device
);
360 DestroyWindow(window
);
363 static void test_coop_level_create_device_window(void)
365 HWND focus_window
, device_window
;
369 focus_window
= CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW
,
370 0, 0, 640, 480, 0, 0, 0, 0);
371 if (!(ddraw
= create_ddraw()))
373 skip("Failed to create a 3D device, skipping test.\n");
374 DestroyWindow(focus_window
);
378 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, NULL
, DDSCL_NORMAL
);
379 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
380 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
381 ok(!device_window
, "Unexpected device window found.\n");
382 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, NULL
, DDSCL_CREATEDEVICEWINDOW
);
383 ok(hr
== DDERR_INVALIDPARAMS
, "Got unexpected hr %#x.\n", hr
);
384 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
385 ok(!device_window
, "Unexpected device window found.\n");
386 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, NULL
, DDSCL_CREATEDEVICEWINDOW
| DDSCL_NORMAL
);
387 ok(hr
== DDERR_INVALIDPARAMS
, "Got unexpected hr %#x.\n", hr
);
388 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
389 ok(!device_window
, "Unexpected device window found.\n");
390 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, NULL
, DDSCL_CREATEDEVICEWINDOW
| DDSCL_NORMAL
| DDSCL_FULLSCREEN
);
391 ok(hr
== DDERR_INVALIDPARAMS
, "Got unexpected hr %#x.\n", hr
);
392 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
393 ok(!device_window
, "Unexpected device window found.\n");
394 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, NULL
, DDSCL_CREATEDEVICEWINDOW
| DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
);
395 ok(hr
== DDERR_NOFOCUSWINDOW
|| broken(hr
== DDERR_INVALIDPARAMS
), "Got unexpected hr %#x.\n", hr
);
396 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
397 ok(!device_window
, "Unexpected device window found.\n");
399 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
400 if (broken(hr
== DDERR_INVALIDPARAMS
))
402 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
403 IDirectDraw7_Release(ddraw
);
404 DestroyWindow(focus_window
);
408 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, NULL
, DDSCL_NORMAL
);
409 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
410 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
411 ok(!device_window
, "Unexpected device window found.\n");
412 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, focus_window
, DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
);
413 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
414 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
415 ok(!device_window
, "Unexpected device window found.\n");
417 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, NULL
, DDSCL_NORMAL
);
418 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
419 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
420 ok(!device_window
, "Unexpected device window found.\n");
421 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, NULL
, DDSCL_SETFOCUSWINDOW
422 | DDSCL_CREATEDEVICEWINDOW
| DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
);
423 ok(hr
== DDERR_NOHWND
, "Got unexpected hr %#x.\n", hr
);
424 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
425 ok(!!device_window
, "Device window not found.\n");
427 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, NULL
, DDSCL_NORMAL
);
428 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
429 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
430 ok(!device_window
, "Unexpected device window found.\n");
431 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, focus_window
, DDSCL_SETFOCUSWINDOW
432 | DDSCL_CREATEDEVICEWINDOW
| DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
);
433 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
434 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
435 ok(!!device_window
, "Device window not found.\n");
437 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, NULL
, DDSCL_NORMAL
);
438 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
439 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
440 ok(!device_window
, "Unexpected device window found.\n");
441 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, NULL
, DDSCL_CREATEDEVICEWINDOW
| DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
);
442 ok(hr
== DDERR_NOFOCUSWINDOW
, "Got unexpected hr %#x.\n", hr
);
443 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
444 ok(!device_window
, "Unexpected device window found.\n");
445 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, focus_window
, DDSCL_SETFOCUSWINDOW
);
446 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
447 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
448 ok(!device_window
, "Unexpected device window found.\n");
449 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, NULL
, DDSCL_CREATEDEVICEWINDOW
| DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
);
450 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
451 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
452 ok(!!device_window
, "Device window not found.\n");
454 IDirectDraw7_Release(ddraw
);
455 DestroyWindow(focus_window
);
458 static void test_clipper_blt(void)
460 IDirectDrawSurface7
*src_surface
, *dst_surface
;
461 RECT client_rect
, src_rect
, *rect
;
462 IDirectDrawClipper
*clipper
;
463 DDSURFACEDESC2 surface_desc
;
464 unsigned int i
, j
, x
, y
;
474 static const D3DCOLOR expected1
[] =
476 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
477 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
478 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
479 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
481 static const D3DCOLOR expected2
[] =
483 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
484 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
485 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
486 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
489 window
= CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW
,
490 10, 10, 640, 480, 0, 0, 0, 0);
491 ShowWindow(window
, SW_SHOW
);
492 if (!(ddraw
= create_ddraw()))
494 skip("Failed to create a ddraw object, skipping test.\n");
495 DestroyWindow(window
);
499 ret
= GetClientRect(window
, &client_rect
);
500 ok(ret
, "Failed to get client rect.\n");
501 ret
= MapWindowPoints(window
, NULL
, (POINT
*)&client_rect
, 2);
502 ok(ret
, "Failed to map client rect.\n");
504 hr
= IDirectDraw7_SetCooperativeLevel(ddraw
, window
, DDSCL_NORMAL
);
505 ok(SUCCEEDED(hr
), "Failed to set cooperative level, hr %#x.\n", hr
);
507 hr
= IDirectDraw7_CreateClipper(ddraw
, 0, &clipper
, NULL
);
508 ok(SUCCEEDED(hr
), "Failed to create clipper, hr %#x.\n", hr
);
509 hr
= IDirectDrawClipper_GetClipList(clipper
, NULL
, NULL
, &ret
);
510 ok(hr
== DDERR_NOCLIPLIST
, "Got unexpected hr %#x.\n", hr
);
511 hr
= IDirectDrawClipper_SetHWnd(clipper
, 0, window
);
512 ok(SUCCEEDED(hr
), "Failed to set clipper window, hr %#x.\n", hr
);
513 hr
= IDirectDrawClipper_GetClipList(clipper
, NULL
, NULL
, &ret
);
514 ok(SUCCEEDED(hr
), "Failed to get clip list size, hr %#x.\n", hr
);
515 rgn_data
= HeapAlloc(GetProcessHeap(), 0, ret
);
516 hr
= IDirectDrawClipper_GetClipList(clipper
, NULL
, rgn_data
, &ret
);
517 ok(SUCCEEDED(hr
), "Failed to get clip list, hr %#x.\n", hr
);
518 ok(rgn_data
->rdh
.dwSize
== sizeof(rgn_data
->rdh
), "Got unexpected structure size %#x.\n", rgn_data
->rdh
.dwSize
);
519 ok(rgn_data
->rdh
.iType
== RDH_RECTANGLES
, "Got unexpected type %#x.\n", rgn_data
->rdh
.iType
);
520 ok(rgn_data
->rdh
.nCount
== 1, "Got unexpected count %u.\n", rgn_data
->rdh
.nCount
);
521 ok(rgn_data
->rdh
.nRgnSize
== 16, "Got unexpected region size %u.\n", rgn_data
->rdh
.nRgnSize
);
522 ok(EqualRect(&rgn_data
->rdh
.rcBound
, &client_rect
),
523 "Got unexpected bounding rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
524 rgn_data
->rdh
.rcBound
.left
, rgn_data
->rdh
.rcBound
.top
,
525 rgn_data
->rdh
.rcBound
.right
, rgn_data
->rdh
.rcBound
.bottom
,
526 client_rect
.left
, client_rect
.top
, client_rect
.right
, client_rect
.bottom
);
527 rect
= (RECT
*)&rgn_data
->Buffer
[0];
528 ok(EqualRect(rect
, &client_rect
),
529 "Got unexpected clip rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
530 rect
->left
, rect
->top
, rect
->right
, rect
->bottom
,
531 client_rect
.left
, client_rect
.top
, client_rect
.right
, client_rect
.bottom
);
532 HeapFree(GetProcessHeap(), 0, rgn_data
);
534 r1
= CreateRectRgn(0, 0, 320, 240);
535 ok(!!r1
, "Failed to create region.\n");
536 r2
= CreateRectRgn(320, 240, 640, 480);
537 ok(!!r2
, "Failed to create region.\n");
538 CombineRgn(r1
, r1
, r2
, RGN_OR
);
539 ret
= GetRegionData(r1
, 0, NULL
);
540 rgn_data
= HeapAlloc(GetProcessHeap(), 0, ret
);
541 ret
= GetRegionData(r1
, ret
, rgn_data
);
542 ok(!!ret
, "Failed to get region data.\n");
547 hr
= IDirectDrawClipper_SetClipList(clipper
, rgn_data
, 0);
548 ok(hr
== DDERR_CLIPPERISUSINGHWND
, "Got unexpected hr %#x.\n", hr
);
549 hr
= IDirectDrawClipper_SetHWnd(clipper
, 0, NULL
);
550 ok(SUCCEEDED(hr
), "Failed to set clipper window, hr %#x.\n", hr
);
551 hr
= IDirectDrawClipper_SetClipList(clipper
, rgn_data
, 0);
552 ok(SUCCEEDED(hr
), "Failed to set clip list, hr %#x.\n", hr
);
554 HeapFree(GetProcessHeap(), 0, rgn_data
);
556 memset(&surface_desc
, 0, sizeof(surface_desc
));
557 surface_desc
.dwSize
= sizeof(surface_desc
);
558 surface_desc
.dwFlags
= DDSD_CAPS
| DDSD_WIDTH
| DDSD_HEIGHT
| DDSD_PIXELFORMAT
;
559 surface_desc
.ddsCaps
.dwCaps
= DDSCAPS_OFFSCREENPLAIN
;
560 surface_desc
.dwWidth
= 640;
561 surface_desc
.dwHeight
= 480;
562 U4(surface_desc
).ddpfPixelFormat
.dwSize
= sizeof(U4(surface_desc
).ddpfPixelFormat
);
563 U4(surface_desc
).ddpfPixelFormat
.dwFlags
= DDPF_RGB
;
564 U1(U4(surface_desc
).ddpfPixelFormat
).dwRGBBitCount
= 32;
565 U2(U4(surface_desc
).ddpfPixelFormat
).dwRBitMask
= 0x00ff0000;
566 U3(U4(surface_desc
).ddpfPixelFormat
).dwGBitMask
= 0x0000ff00;
567 U4(U4(surface_desc
).ddpfPixelFormat
).dwBBitMask
= 0x000000ff;
569 hr
= IDirectDraw7_CreateSurface(ddraw
, &surface_desc
, &src_surface
, NULL
);
570 ok(SUCCEEDED(hr
), "Failed to create source surface, hr %#x.\n", hr
);
571 hr
= IDirectDraw7_CreateSurface(ddraw
, &surface_desc
, &dst_surface
, NULL
);
572 ok(SUCCEEDED(hr
), "Failed to create destination surface, hr %#x.\n", hr
);
574 memset(&fx
, 0, sizeof(fx
));
575 fx
.dwSize
= sizeof(fx
);
576 hr
= IDirectDrawSurface7_Blt(src_surface
, NULL
, NULL
, NULL
, DDBLT_COLORFILL
| DDBLT_WAIT
, &fx
);
577 ok(SUCCEEDED(hr
), "Failed to clear source surface, hr %#x.\n", hr
);
578 hr
= IDirectDrawSurface7_Blt(dst_surface
, NULL
, NULL
, NULL
, DDBLT_COLORFILL
| DDBLT_WAIT
, &fx
);
579 ok(SUCCEEDED(hr
), "Failed to clear destination surface, hr %#x.\n", hr
);
581 hr
= IDirectDrawSurface7_Lock(src_surface
, NULL
, &surface_desc
, 0, NULL
);
582 ok(SUCCEEDED(hr
), "Failed to lock source surface, hr %#x.\n", hr
);
583 ((DWORD
*)surface_desc
.lpSurface
)[0] = 0xff0000ff;
584 ((DWORD
*)surface_desc
.lpSurface
)[1] = 0xff00ff00;
585 ((DWORD
*)surface_desc
.lpSurface
)[2] = 0xffff0000;
586 ((DWORD
*)surface_desc
.lpSurface
)[3] = 0xffffffff;
587 hr
= IDirectDrawSurface7_Unlock(src_surface
, NULL
);
588 ok(SUCCEEDED(hr
), "Failed to unlock source surface, hr %#x.\n", hr
);
590 hr
= IDirectDrawSurface7_SetClipper(dst_surface
, clipper
);
591 ok(SUCCEEDED(hr
), "Failed to set clipper, hr %#x.\n", hr
);
593 SetRect(&src_rect
, 0, 0, 4, 1);
594 hr
= IDirectDrawSurface7_Blt(dst_surface
, NULL
, src_surface
, &src_rect
, DDBLT_WAIT
, NULL
);
595 ok(SUCCEEDED(hr
), "Failed to blit, hr %#x.\n", hr
);
596 for (i
= 0; i
< 4; ++i
)
598 for (j
= 0; j
< 4; ++j
)
600 x
= 80 * ((2 * j
) + 1);
601 y
= 60 * ((2 * i
) + 1);
602 color
= get_surface_color(dst_surface
, x
, y
);
603 ok(compare_color(color
, expected1
[i
* 4 + j
], 1),
604 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1
[i
* 4 + j
], x
, y
, color
);
608 U5(fx
).dwFillColor
= 0xff0000ff;
609 hr
= IDirectDrawSurface7_Blt(dst_surface
, NULL
, NULL
, NULL
, DDBLT_COLORFILL
| DDBLT_WAIT
, &fx
);
610 ok(SUCCEEDED(hr
), "Failed to clear destination surface, hr %#x.\n", hr
);
611 for (i
= 0; i
< 4; ++i
)
613 for (j
= 0; j
< 4; ++j
)
615 x
= 80 * ((2 * j
) + 1);
616 y
= 60 * ((2 * i
) + 1);
617 color
= get_surface_color(dst_surface
, x
, y
);
618 ok(compare_color(color
, expected2
[i
* 4 + j
], 1),
619 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2
[i
* 4 + j
], x
, y
, color
);
623 hr
= IDirectDrawSurface7_BltFast(dst_surface
, 0, 0, src_surface
, NULL
, DDBLTFAST_WAIT
);
624 ok(hr
== DDERR_BLTFASTCANTCLIP
, "Got unexpected hr %#x.\n", hr
);
626 hr
= IDirectDrawClipper_SetHWnd(clipper
, 0, window
);
627 ok(SUCCEEDED(hr
), "Failed to set clipper window, hr %#x.\n", hr
);
628 hr
= IDirectDrawClipper_GetClipList(clipper
, NULL
, NULL
, &ret
);
629 ok(SUCCEEDED(hr
), "Failed to get clip list size, hr %#x.\n", hr
);
630 DestroyWindow(window
);
631 hr
= IDirectDrawClipper_GetClipList(clipper
, NULL
, NULL
, &ret
);
632 ok(hr
== E_FAIL
, "Got unexpected hr %#x.\n", hr
);
633 hr
= IDirectDrawClipper_SetHWnd(clipper
, 0, NULL
);
634 ok(SUCCEEDED(hr
), "Failed to set clipper window, hr %#x.\n", hr
);
635 hr
= IDirectDrawClipper_GetClipList(clipper
, NULL
, NULL
, &ret
);
636 ok(SUCCEEDED(hr
), "Failed to get clip list size, hr %#x.\n", hr
);
637 hr
= IDirectDrawClipper_SetClipList(clipper
, NULL
, 0);
638 ok(SUCCEEDED(hr
), "Failed to set clip list, hr %#x.\n", hr
);
639 hr
= IDirectDrawClipper_GetClipList(clipper
, NULL
, NULL
, &ret
);
640 ok(hr
== DDERR_NOCLIPLIST
, "Got unexpected hr %#x.\n", hr
);
641 hr
= IDirectDrawSurface7_Blt(dst_surface
, NULL
, NULL
, NULL
, DDBLT_COLORFILL
| DDBLT_WAIT
, &fx
);
642 ok(hr
== DDERR_NOCLIPLIST
, "Got unexpected hr %#x.\n", hr
);
644 IDirectDrawSurface7_Release(dst_surface
);
645 IDirectDrawSurface7_Release(src_surface
);
646 IDirectDrawClipper_Release(clipper
);
647 IDirectDraw7_Release(ddraw
);
652 HMODULE module
= GetModuleHandleA("ddraw.dll");
654 if (!(pDirectDrawCreateEx
= (void *)GetProcAddress(module
, "DirectDrawCreateEx")))
656 win_skip("DirectDrawCreateEx not available, skipping tests.\n");
660 test_process_vertices();
661 test_coop_level_create_device_window();