2 * Copyright 2011 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "wine/test.h"
23 struct create_window_thread_param
26 HANDLE window_created
;
27 HANDLE destroy_window
;
31 static BOOL
compare_color(D3DCOLOR c1
, D3DCOLOR c2
, BYTE max_diff
)
33 if (abs((c1
& 0xff) - (c2
& 0xff)) > max_diff
) return FALSE
;
35 if (abs((c1
& 0xff) - (c2
& 0xff)) > max_diff
) return FALSE
;
37 if (abs((c1
& 0xff) - (c2
& 0xff)) > max_diff
) return FALSE
;
39 if (abs((c1
& 0xff) - (c2
& 0xff)) > max_diff
) return FALSE
;
43 static DWORD WINAPI
create_window_thread_proc(void *param
)
45 struct create_window_thread_param
*p
= param
;
49 p
->window
= CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW
,
50 0, 0, 640, 480, 0, 0, 0, 0);
51 ret
= SetEvent(p
->window_created
);
52 ok(ret
, "SetEvent failed, last error %#x.\n", GetLastError());
58 while (PeekMessage(&msg
, 0, 0, 0, PM_REMOVE
))
59 DispatchMessage(&msg
);
60 res
= WaitForSingleObject(p
->destroy_window
, 100);
61 if (res
== WAIT_OBJECT_0
)
63 if (res
!= WAIT_TIMEOUT
)
65 ok(0, "Wait failed (%#x), last error %#x.\n", res
, GetLastError());
70 DestroyWindow(p
->window
);
75 static void create_window_thread(struct create_window_thread_param
*p
)
79 p
->window_created
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
80 ok(!!p
->window_created
, "CreateEvent failed, last error %#x.\n", GetLastError());
81 p
->destroy_window
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
82 ok(!!p
->destroy_window
, "CreateEvent failed, last error %#x.\n", GetLastError());
83 p
->thread
= CreateThread(NULL
, 0, create_window_thread_proc
, p
, 0, &tid
);
84 ok(!!p
->thread
, "Failed to create thread, last error %#x.\n", GetLastError());
85 res
= WaitForSingleObject(p
->window_created
, INFINITE
);
86 ok(res
== WAIT_OBJECT_0
, "Wait failed (%#x), last error %#x.\n", res
, GetLastError());
89 static void destroy_window_thread(struct create_window_thread_param
*p
)
91 SetEvent(p
->destroy_window
);
92 WaitForSingleObject(p
->thread
, INFINITE
);
93 CloseHandle(p
->destroy_window
);
94 CloseHandle(p
->window_created
);
95 CloseHandle(p
->thread
);
98 static D3DCOLOR
get_surface_color(IDirectDrawSurface
*surface
, UINT x
, UINT y
)
100 RECT rect
= {x
, y
, x
+ 1, y
+ 1};
101 DDSURFACEDESC surface_desc
;
105 memset(&surface_desc
, 0, sizeof(surface_desc
));
106 surface_desc
.dwSize
= sizeof(surface_desc
);
108 hr
= IDirectDrawSurface_Lock(surface
, &rect
, &surface_desc
, DDLOCK_READONLY
| DDLOCK_WAIT
, NULL
);
109 ok(SUCCEEDED(hr
), "Failed to lock surface, hr %#x.\n", hr
);
113 color
= *((DWORD
*)surface_desc
.lpSurface
) & 0x00ffffff;
115 hr
= IDirectDrawSurface_Unlock(surface
, NULL
);
116 ok(SUCCEEDED(hr
), "Failed to unlock surface, hr %#x.\n", hr
);
121 static HRESULT CALLBACK
enum_z_fmt(GUID
*guid
, char *description
, char *name
,
122 D3DDEVICEDESC
*hal_desc
, D3DDEVICEDESC
*hel_desc
, void *ctx
)
124 DWORD
*z_depth
= ctx
;
126 if (!IsEqualGUID(&IID_IDirect3DHALDevice
, guid
))
127 return D3DENUMRET_OK
;
129 if (hal_desc
->dwDeviceZBufferBitDepth
& DDBD_32
)
131 else if (hal_desc
->dwDeviceZBufferBitDepth
& DDBD_24
)
133 else if (hal_desc
->dwDeviceZBufferBitDepth
& DDBD_16
)
139 static IDirectDraw
*create_ddraw(void)
143 if (FAILED(DirectDrawCreate(NULL
, &ddraw
, NULL
)))
149 static IDirect3DDevice
*create_device(IDirectDraw
*ddraw
, HWND window
, DWORD coop_level
)
151 IDirectDrawSurface
*surface
, *ds
;
152 IDirect3DDevice
*device
= NULL
;
153 DDSURFACEDESC surface_desc
;
158 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, window
, coop_level
);
159 ok(SUCCEEDED(hr
), "Failed to set cooperative level, hr %#x.\n", hr
);
161 memset(&surface_desc
, 0, sizeof(surface_desc
));
162 surface_desc
.dwSize
= sizeof(surface_desc
);
163 surface_desc
.dwFlags
= DDSD_CAPS
| DDSD_WIDTH
| DDSD_HEIGHT
;
164 surface_desc
.ddsCaps
.dwCaps
= DDSCAPS_OFFSCREENPLAIN
| DDSCAPS_3DDEVICE
;
165 surface_desc
.dwWidth
= 640;
166 surface_desc
.dwHeight
= 480;
168 hr
= IDirectDraw_CreateSurface(ddraw
, &surface_desc
, &surface
, NULL
);
169 ok(SUCCEEDED(hr
), "Failed to create surface, hr %#x.\n", hr
);
171 if (coop_level
& DDSCL_NORMAL
)
173 IDirectDrawClipper
*clipper
;
175 hr
= IDirectDraw_CreateClipper(ddraw
, 0, &clipper
, NULL
);
176 ok(SUCCEEDED(hr
), "Failed to create clipper, hr %#x.\n", hr
);
177 hr
= IDirectDrawClipper_SetHWnd(clipper
, 0, window
);
178 ok(SUCCEEDED(hr
), "Failed to set clipper window, hr %#x.\n", hr
);
179 hr
= IDirectDrawSurface_SetClipper(surface
, clipper
);
180 ok(SUCCEEDED(hr
), "Failed to set surface clipper, hr %#x.\n", hr
);
181 IDirectDrawClipper_Release(clipper
);
184 hr
= IDirectDraw_QueryInterface(ddraw
, &IID_IDirect3D
, (void **)&d3d
);
187 IDirectDrawSurface_Release(surface
);
191 hr
= IDirect3D_EnumDevices(d3d
, enum_z_fmt
, &z_depth
);
192 ok(SUCCEEDED(hr
), "Failed to enumerate z-formats, hr %#x.\n", hr
);
193 IDirect3D_Release(d3d
);
194 if (FAILED(hr
) || !z_depth
)
196 IDirectDrawSurface_Release(surface
);
200 memset(&surface_desc
, 0, sizeof(surface_desc
));
201 surface_desc
.dwSize
= sizeof(surface_desc
);
202 surface_desc
.dwFlags
= DDSD_CAPS
| DDSD_ZBUFFERBITDEPTH
| DDSD_WIDTH
| DDSD_HEIGHT
;
203 surface_desc
.ddsCaps
.dwCaps
= DDSCAPS_ZBUFFER
;
204 U2(surface_desc
).dwZBufferBitDepth
= z_depth
;
205 surface_desc
.dwWidth
= 640;
206 surface_desc
.dwHeight
= 480;
207 hr
= IDirectDraw_CreateSurface(ddraw
, &surface_desc
, &ds
, NULL
);
208 ok(SUCCEEDED(hr
), "Failed to create depth buffer, hr %#x.\n", hr
);
211 IDirectDrawSurface_Release(surface
);
215 hr
= IDirectDrawSurface_AddAttachedSurface(surface
, ds
);
216 ok(SUCCEEDED(hr
), "Failed to attach depth buffer, hr %#x.\n", hr
);
217 IDirectDrawSurface_Release(ds
);
220 IDirectDrawSurface_Release(surface
);
224 hr
= IDirectDrawSurface_QueryInterface(surface
, &IID_IDirect3DHALDevice
, (void **)&device
);
225 IDirectDrawSurface_Release(surface
);
232 static HRESULT CALLBACK
restore_callback(IDirectDrawSurface
*surface
, DDSURFACEDESC
*desc
, void *context
)
234 HRESULT hr
= IDirectDrawSurface_Restore(surface
);
235 ok(SUCCEEDED(hr
), "Failed to restore surface, hr %#x.\n", hr
);
236 IDirectDrawSurface_Release(surface
);
241 static HRESULT
restore_surfaces(IDirectDraw
*ddraw
)
243 return IDirectDraw_EnumSurfaces(ddraw
, DDENUMSURFACES_ALL
| DDENUMSURFACES_DOESEXIST
,
244 NULL
, NULL
, restore_callback
);
247 static void test_coop_level_create_device_window(void)
249 HWND focus_window
, device_window
;
253 focus_window
= CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW
,
254 0, 0, 640, 480, 0, 0, 0, 0);
255 if (!(ddraw
= create_ddraw()))
257 skip("Failed to create a ddraw object, skipping test.\n");
258 DestroyWindow(focus_window
);
262 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, NULL
, DDSCL_NORMAL
);
263 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
264 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
265 ok(!device_window
, "Unexpected device window found.\n");
266 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, NULL
, DDSCL_CREATEDEVICEWINDOW
);
267 ok(hr
== DDERR_INVALIDPARAMS
, "Got unexpected hr %#x.\n", hr
);
268 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
269 ok(!device_window
, "Unexpected device window found.\n");
270 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, NULL
, DDSCL_CREATEDEVICEWINDOW
| DDSCL_NORMAL
);
271 ok(hr
== DDERR_INVALIDPARAMS
, "Got unexpected hr %#x.\n", hr
);
272 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
273 ok(!device_window
, "Unexpected device window found.\n");
274 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, NULL
, DDSCL_CREATEDEVICEWINDOW
| DDSCL_NORMAL
| DDSCL_FULLSCREEN
);
275 ok(hr
== DDERR_INVALIDPARAMS
, "Got unexpected hr %#x.\n", hr
);
276 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
277 ok(!device_window
, "Unexpected device window found.\n");
278 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, NULL
, DDSCL_CREATEDEVICEWINDOW
| DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
);
279 ok(hr
== DDERR_NOFOCUSWINDOW
|| broken(hr
== DDERR_INVALIDPARAMS
), "Got unexpected hr %#x.\n", hr
);
280 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
281 ok(!device_window
, "Unexpected device window found.\n");
283 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
284 if (broken(hr
== DDERR_INVALIDPARAMS
))
286 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
287 IDirectDraw_Release(ddraw
);
288 DestroyWindow(focus_window
);
292 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, NULL
, DDSCL_NORMAL
);
293 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
294 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
295 ok(!device_window
, "Unexpected device window found.\n");
296 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, focus_window
, DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
);
297 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
298 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
299 ok(!device_window
, "Unexpected device window found.\n");
301 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, NULL
, DDSCL_NORMAL
);
302 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
303 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
304 ok(!device_window
, "Unexpected device window found.\n");
305 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, NULL
, DDSCL_SETFOCUSWINDOW
306 | DDSCL_CREATEDEVICEWINDOW
| DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
);
307 ok(hr
== DDERR_NOHWND
, "Got unexpected hr %#x.\n", hr
);
308 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
309 ok(!!device_window
, "Device window not found.\n");
311 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, NULL
, DDSCL_NORMAL
);
312 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
313 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
314 ok(!device_window
, "Unexpected device window found.\n");
315 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, focus_window
, DDSCL_SETFOCUSWINDOW
316 | DDSCL_CREATEDEVICEWINDOW
| DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
);
317 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
318 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
319 ok(!!device_window
, "Device window not found.\n");
321 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, NULL
, DDSCL_NORMAL
);
322 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
323 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
324 ok(!device_window
, "Unexpected device window found.\n");
325 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, NULL
, DDSCL_CREATEDEVICEWINDOW
| DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
);
326 ok(hr
== DDERR_NOFOCUSWINDOW
, "Got unexpected hr %#x.\n", hr
);
327 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
328 ok(!device_window
, "Unexpected device window found.\n");
329 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, focus_window
, DDSCL_SETFOCUSWINDOW
);
330 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
331 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
332 ok(!device_window
, "Unexpected device window found.\n");
333 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, NULL
, DDSCL_CREATEDEVICEWINDOW
| DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
);
334 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
335 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
336 ok(!!device_window
, "Device window not found.\n");
338 IDirectDraw_Release(ddraw
);
339 DestroyWindow(focus_window
);
342 static void test_clipper_blt(void)
344 IDirectDrawSurface
*src_surface
, *dst_surface
;
345 RECT client_rect
, src_rect
, *rect
;
346 IDirectDrawClipper
*clipper
;
347 DDSURFACEDESC surface_desc
;
348 unsigned int i
, j
, x
, y
;
359 static const DWORD src_data
[] =
361 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
362 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
363 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
365 static const D3DCOLOR expected1
[] =
367 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
368 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
369 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
370 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
372 static const D3DCOLOR expected2
[] =
374 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
375 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
376 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
377 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
380 window
= CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW
,
381 10, 10, 640, 480, 0, 0, 0, 0);
382 ShowWindow(window
, SW_SHOW
);
383 if (!(ddraw
= create_ddraw()))
385 skip("Failed to create a ddraw object, skipping test.\n");
386 DestroyWindow(window
);
390 ret
= GetClientRect(window
, &client_rect
);
391 ok(ret
, "Failed to get client rect.\n");
392 ret
= MapWindowPoints(window
, NULL
, (POINT
*)&client_rect
, 2);
393 ok(ret
, "Failed to map client rect.\n");
395 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, window
, DDSCL_NORMAL
);
396 ok(SUCCEEDED(hr
), "Failed to set cooperative level, hr %#x.\n", hr
);
398 hr
= IDirectDraw_CreateClipper(ddraw
, 0, &clipper
, NULL
);
399 ok(SUCCEEDED(hr
), "Failed to create clipper, hr %#x.\n", hr
);
400 hr
= IDirectDrawClipper_GetClipList(clipper
, NULL
, NULL
, &ret
);
401 ok(hr
== DDERR_NOCLIPLIST
, "Got unexpected hr %#x.\n", hr
);
402 hr
= IDirectDrawClipper_SetHWnd(clipper
, 0, window
);
403 ok(SUCCEEDED(hr
), "Failed to set clipper window, hr %#x.\n", hr
);
404 hr
= IDirectDrawClipper_GetClipList(clipper
, NULL
, NULL
, &ret
);
405 ok(SUCCEEDED(hr
), "Failed to get clip list size, hr %#x.\n", hr
);
406 rgn_data
= HeapAlloc(GetProcessHeap(), 0, ret
);
407 hr
= IDirectDrawClipper_GetClipList(clipper
, NULL
, rgn_data
, &ret
);
408 ok(SUCCEEDED(hr
), "Failed to get clip list, hr %#x.\n", hr
);
409 ok(rgn_data
->rdh
.dwSize
== sizeof(rgn_data
->rdh
), "Got unexpected structure size %#x.\n", rgn_data
->rdh
.dwSize
);
410 ok(rgn_data
->rdh
.iType
== RDH_RECTANGLES
, "Got unexpected type %#x.\n", rgn_data
->rdh
.iType
);
411 ok(rgn_data
->rdh
.nCount
== 1, "Got unexpected count %u.\n", rgn_data
->rdh
.nCount
);
412 ok(rgn_data
->rdh
.nRgnSize
== 16 || broken(rgn_data
->rdh
.nRgnSize
== 168 /* NT4 */),
413 "Got unexpected region size %u.\n", rgn_data
->rdh
.nRgnSize
);
414 ok(EqualRect(&rgn_data
->rdh
.rcBound
, &client_rect
),
415 "Got unexpected bounding rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
416 rgn_data
->rdh
.rcBound
.left
, rgn_data
->rdh
.rcBound
.top
,
417 rgn_data
->rdh
.rcBound
.right
, rgn_data
->rdh
.rcBound
.bottom
,
418 client_rect
.left
, client_rect
.top
, client_rect
.right
, client_rect
.bottom
);
419 rect
= (RECT
*)&rgn_data
->Buffer
[0];
420 ok(EqualRect(rect
, &client_rect
),
421 "Got unexpected clip rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
422 rect
->left
, rect
->top
, rect
->right
, rect
->bottom
,
423 client_rect
.left
, client_rect
.top
, client_rect
.right
, client_rect
.bottom
);
424 HeapFree(GetProcessHeap(), 0, rgn_data
);
426 r1
= CreateRectRgn(0, 0, 320, 240);
427 ok(!!r1
, "Failed to create region.\n");
428 r2
= CreateRectRgn(320, 240, 640, 480);
429 ok(!!r2
, "Failed to create region.\n");
430 CombineRgn(r1
, r1
, r2
, RGN_OR
);
431 ret
= GetRegionData(r1
, 0, NULL
);
432 rgn_data
= HeapAlloc(GetProcessHeap(), 0, ret
);
433 ret
= GetRegionData(r1
, ret
, rgn_data
);
434 ok(!!ret
, "Failed to get region data.\n");
439 hr
= IDirectDrawClipper_SetClipList(clipper
, rgn_data
, 0);
440 ok(hr
== DDERR_CLIPPERISUSINGHWND
, "Got unexpected hr %#x.\n", hr
);
441 hr
= IDirectDrawClipper_SetHWnd(clipper
, 0, NULL
);
442 ok(SUCCEEDED(hr
), "Failed to set clipper window, hr %#x.\n", hr
);
443 hr
= IDirectDrawClipper_SetClipList(clipper
, rgn_data
, 0);
444 ok(SUCCEEDED(hr
), "Failed to set clip list, hr %#x.\n", hr
);
446 HeapFree(GetProcessHeap(), 0, rgn_data
);
448 memset(&surface_desc
, 0, sizeof(surface_desc
));
449 surface_desc
.dwSize
= sizeof(surface_desc
);
450 surface_desc
.dwFlags
= DDSD_CAPS
| DDSD_WIDTH
| DDSD_HEIGHT
| DDSD_PIXELFORMAT
;
451 surface_desc
.ddsCaps
.dwCaps
= DDSCAPS_OFFSCREENPLAIN
;
452 surface_desc
.dwWidth
= 640;
453 surface_desc
.dwHeight
= 480;
454 surface_desc
.ddpfPixelFormat
.dwSize
= sizeof(surface_desc
.ddpfPixelFormat
);
455 surface_desc
.ddpfPixelFormat
.dwFlags
= DDPF_RGB
;
456 U1(surface_desc
.ddpfPixelFormat
).dwRGBBitCount
= 32;
457 U2(surface_desc
.ddpfPixelFormat
).dwRBitMask
= 0x00ff0000;
458 U3(surface_desc
.ddpfPixelFormat
).dwGBitMask
= 0x0000ff00;
459 U4(surface_desc
.ddpfPixelFormat
).dwBBitMask
= 0x000000ff;
461 hr
= IDirectDraw_CreateSurface(ddraw
, &surface_desc
, &src_surface
, NULL
);
462 ok(SUCCEEDED(hr
), "Failed to create source surface, hr %#x.\n", hr
);
463 hr
= IDirectDraw_CreateSurface(ddraw
, &surface_desc
, &dst_surface
, NULL
);
464 ok(SUCCEEDED(hr
), "Failed to create destination surface, hr %#x.\n", hr
);
466 memset(&fx
, 0, sizeof(fx
));
467 fx
.dwSize
= sizeof(fx
);
468 hr
= IDirectDrawSurface_Blt(src_surface
, NULL
, NULL
, NULL
, DDBLT_COLORFILL
| DDBLT_WAIT
, &fx
);
469 ok(SUCCEEDED(hr
), "Failed to clear source surface, hr %#x.\n", hr
);
470 hr
= IDirectDrawSurface_Blt(dst_surface
, NULL
, NULL
, NULL
, DDBLT_COLORFILL
| DDBLT_WAIT
, &fx
);
471 ok(SUCCEEDED(hr
), "Failed to clear destination surface, hr %#x.\n", hr
);
473 hr
= IDirectDrawSurface_Lock(src_surface
, NULL
, &surface_desc
, DDLOCK_WAIT
, NULL
);
474 ok(SUCCEEDED(hr
), "Failed to lock source surface, hr %#x.\n", hr
);
475 ok(U1(surface_desc
).lPitch
== 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc
).lPitch
);
476 ptr
= surface_desc
.lpSurface
;
477 memcpy(&ptr
[ 0], &src_data
[ 0], 6 * sizeof(DWORD
));
478 memcpy(&ptr
[ 640], &src_data
[ 6], 6 * sizeof(DWORD
));
479 memcpy(&ptr
[1280], &src_data
[12], 6 * sizeof(DWORD
));
480 hr
= IDirectDrawSurface_Unlock(src_surface
, NULL
);
481 ok(SUCCEEDED(hr
), "Failed to unlock source surface, hr %#x.\n", hr
);
483 hr
= IDirectDrawSurface_SetClipper(dst_surface
, clipper
);
484 ok(SUCCEEDED(hr
), "Failed to set clipper, hr %#x.\n", hr
);
486 SetRect(&src_rect
, 1, 1, 5, 2);
487 hr
= IDirectDrawSurface_Blt(dst_surface
, NULL
, src_surface
, &src_rect
, DDBLT_WAIT
, NULL
);
488 ok(SUCCEEDED(hr
), "Failed to blit, hr %#x.\n", hr
);
489 for (i
= 0; i
< 4; ++i
)
491 for (j
= 0; j
< 4; ++j
)
493 x
= 80 * ((2 * j
) + 1);
494 y
= 60 * ((2 * i
) + 1);
495 color
= get_surface_color(dst_surface
, x
, y
);
496 ok(compare_color(color
, expected1
[i
* 4 + j
], 1),
497 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1
[i
* 4 + j
], x
, y
, color
);
501 U5(fx
).dwFillColor
= 0xff0000ff;
502 hr
= IDirectDrawSurface_Blt(dst_surface
, NULL
, NULL
, NULL
, DDBLT_COLORFILL
| DDBLT_WAIT
, &fx
);
503 ok(SUCCEEDED(hr
), "Failed to clear destination surface, hr %#x.\n", hr
);
504 for (i
= 0; i
< 4; ++i
)
506 for (j
= 0; j
< 4; ++j
)
508 x
= 80 * ((2 * j
) + 1);
509 y
= 60 * ((2 * i
) + 1);
510 color
= get_surface_color(dst_surface
, x
, y
);
511 ok(compare_color(color
, expected2
[i
* 4 + j
], 1),
512 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2
[i
* 4 + j
], x
, y
, color
);
516 hr
= IDirectDrawSurface_BltFast(dst_surface
, 0, 0, src_surface
, NULL
, DDBLTFAST_WAIT
);
517 ok(hr
== DDERR_BLTFASTCANTCLIP
|| broken(hr
== E_NOTIMPL
/* NT4 */), "Got unexpected hr %#x.\n", hr
);
519 hr
= IDirectDrawClipper_SetHWnd(clipper
, 0, window
);
520 ok(SUCCEEDED(hr
), "Failed to set clipper window, hr %#x.\n", hr
);
521 hr
= IDirectDrawClipper_GetClipList(clipper
, NULL
, NULL
, &ret
);
522 ok(SUCCEEDED(hr
), "Failed to get clip list size, hr %#x.\n", hr
);
523 DestroyWindow(window
);
524 hr
= IDirectDrawClipper_GetClipList(clipper
, NULL
, NULL
, &ret
);
525 ok(hr
== E_FAIL
, "Got unexpected hr %#x.\n", hr
);
526 hr
= IDirectDrawClipper_SetHWnd(clipper
, 0, NULL
);
527 ok(SUCCEEDED(hr
), "Failed to set clipper window, hr %#x.\n", hr
);
528 hr
= IDirectDrawClipper_GetClipList(clipper
, NULL
, NULL
, &ret
);
529 ok(SUCCEEDED(hr
), "Failed to get clip list size, hr %#x.\n", hr
);
530 hr
= IDirectDrawClipper_SetClipList(clipper
, NULL
, 0);
531 ok(SUCCEEDED(hr
), "Failed to set clip list, hr %#x.\n", hr
);
532 hr
= IDirectDrawClipper_GetClipList(clipper
, NULL
, NULL
, &ret
);
533 ok(hr
== DDERR_NOCLIPLIST
, "Got unexpected hr %#x.\n", hr
);
534 hr
= IDirectDrawSurface_Blt(dst_surface
, NULL
, NULL
, NULL
, DDBLT_COLORFILL
| DDBLT_WAIT
, &fx
);
535 ok(hr
== DDERR_NOCLIPLIST
, "Got unexpected hr %#x.\n", hr
);
537 IDirectDrawSurface_Release(dst_surface
);
538 IDirectDrawSurface_Release(src_surface
);
539 IDirectDrawClipper_Release(clipper
);
540 IDirectDraw_Release(ddraw
);
543 static void test_coop_level_d3d_state(void)
545 D3DRECT clear_rect
= {{0}, {0}, {640}, {480}};
546 D3DMATERIALHANDLE background_handle
;
547 IDirectDrawSurface
*rt
, *surface
;
548 IDirect3DMaterial
*background
;
549 IDirect3DViewport
*viewport
;
550 IDirect3DDevice
*device
;
551 D3DMATERIAL material
;
559 window
= CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW
,
560 0, 0, 640, 480, 0, 0, 0, 0);
561 if (!(ddraw
= create_ddraw()))
563 skip("Failed to create ddraw object, skipping test.\n");
564 DestroyWindow(window
);
567 if (!(device
= create_device(ddraw
, window
, DDSCL_NORMAL
)))
569 skip("Failed to create D3D device, skipping test.\n");
570 IDirectDraw_Release(ddraw
);
571 DestroyWindow(window
);
575 hr
= IDirect3DDevice_GetDirect3D(device
, &d3d
);
576 ok(SUCCEEDED(hr
), "Failed to get d3d interface, hr %#x.\n", hr
);
577 hr
= IDirect3D_CreateViewport(d3d
, &viewport
, NULL
);
578 ok(SUCCEEDED(hr
), "Failed to create viewport, hr %#x.\n", hr
);
579 hr
= IDirect3D_CreateMaterial(d3d
, &background
, NULL
);
580 ok(SUCCEEDED(hr
), "Failed to create material, hr %#x.\n", hr
);
581 IDirect3D_Release(d3d
);
583 hr
= IDirect3DDevice_AddViewport(device
, viewport
);
584 ok(SUCCEEDED(hr
), "Failed to add viewport, hr %#x.\n", hr
);
585 memset(&vp
, 0, sizeof(vp
));
586 vp
.dwSize
= sizeof(vp
);
591 vp
.dvScaleX
= 320.0f
;
592 vp
.dvScaleY
= 240.0f
;
597 hr
= IDirect3DViewport_SetViewport(viewport
, &vp
);
598 ok(SUCCEEDED(hr
), "Failed to set viewport data, hr %#x.\n", hr
);
600 memset(&material
, 0, sizeof(material
));
601 material
.dwSize
= sizeof(material
);
602 U1(U(material
).diffuse
).r
= 1.0f
;
603 U2(U(material
).diffuse
).g
= 0.0f
;
604 U3(U(material
).diffuse
).b
= 0.0f
;
605 U4(U(material
).diffuse
).a
= 1.0f
;
606 hr
= IDirect3DMaterial_SetMaterial(background
, &material
);
607 ok(SUCCEEDED(hr
), "Failed to set material data, hr %#x.\n", hr
);
608 hr
= IDirect3DMaterial_GetHandle(background
, device
, &background_handle
);
609 ok(SUCCEEDED(hr
), "Failed to get material handle, hr %#x.\n", hr
);
610 hr
= IDirect3DViewport_SetBackground(viewport
, background_handle
);
611 ok(SUCCEEDED(hr
), "Failed to set viewport background, hr %#x.\n", hr
);
613 hr
= IDirect3DDevice_QueryInterface(device
, &IID_IDirectDrawSurface
, (void **)&rt
);
614 ok(SUCCEEDED(hr
), "Failed to get render target, hr %#x.\n", hr
);
615 hr
= IDirect3DViewport_Clear(viewport
, 1, &clear_rect
, D3DCLEAR_TARGET
);
616 ok(SUCCEEDED(hr
), "Failed to clear viewport, hr %#x.\n", hr
);
617 color
= get_surface_color(rt
, 320, 240);
618 ok(compare_color(color
, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color
);
620 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, window
, DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
);
621 ok(SUCCEEDED(hr
), "Failed to set cooperative level, hr %#x.\n", hr
);
622 hr
= IDirectDrawSurface_IsLost(rt
);
623 ok(hr
== DDERR_SURFACELOST
, "Got unexpected hr %#x.\n", hr
);
624 hr
= restore_surfaces(ddraw
);
625 ok(SUCCEEDED(hr
), "Failed to restore surfaces, hr %#x.\n", hr
);
627 memset(&material
, 0, sizeof(material
));
628 material
.dwSize
= sizeof(material
);
629 U1(U(material
).diffuse
).r
= 0.0f
;
630 U2(U(material
).diffuse
).g
= 1.0f
;
631 U3(U(material
).diffuse
).b
= 0.0f
;
632 U4(U(material
).diffuse
).a
= 1.0f
;
633 hr
= IDirect3DMaterial_SetMaterial(background
, &material
);
634 ok(SUCCEEDED(hr
), "Failed to set material data, hr %#x.\n", hr
);
636 hr
= IDirect3DDevice_QueryInterface(device
, &IID_IDirectDrawSurface
, (void **)&surface
);
637 ok(SUCCEEDED(hr
), "Failed to get render target, hr %#x.\n", hr
);
638 ok(surface
== rt
, "Got unexpected surface %p.\n", surface
);
639 hr
= IDirect3DViewport_Clear(viewport
, 1, &clear_rect
, D3DCLEAR_TARGET
);
640 ok(SUCCEEDED(hr
), "Failed to clear viewport, hr %#x.\n", hr
);
641 color
= get_surface_color(rt
, 320, 240);
642 ok(compare_color(color
, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color
);
644 hr
= IDirect3DDevice_DeleteViewport(device
, viewport
);
645 ok(SUCCEEDED(hr
), "Failed to delete viewport, hr %#x.\n", hr
);
646 IDirect3DMaterial_Release(background
);
647 IDirect3DViewport_Release(viewport
);
648 IDirectDrawSurface_Release(surface
);
649 IDirectDrawSurface_Release(rt
);
650 IDirect3DDevice_Release(device
);
651 IDirectDraw_Release(ddraw
);
652 DestroyWindow(window
);
655 static void test_surface_interface_mismatch(void)
657 IDirectDraw
*ddraw
= NULL
;
658 IDirect3D
*d3d
= NULL
;
659 IDirectDrawSurface
*surface
= NULL
, *ds
;
660 IDirectDrawSurface3
*surface3
= NULL
;
661 IDirect3DDevice
*device
= NULL
;
662 IDirect3DViewport
*viewport
= NULL
;
663 IDirect3DMaterial
*background
= NULL
;
664 DDSURFACEDESC surface_desc
;
671 D3DMATERIAL material
;
672 D3DMATERIALHANDLE background_handle
;
673 D3DRECT clear_rect
= {{0}, {0}, {640}, {480}};
675 window
= CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW
,
676 0, 0, 640, 480, 0, 0, 0, 0);
678 if (!(ddraw
= create_ddraw()))
680 skip("Failed to create a ddraw object, skipping test.\n");
684 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, window
, DDSCL_NORMAL
);
685 ok(SUCCEEDED(hr
), "Failed to set cooperative level, hr %#x.\n", hr
);
687 memset(&surface_desc
, 0, sizeof(surface_desc
));
688 surface_desc
.dwSize
= sizeof(surface_desc
);
689 surface_desc
.dwFlags
= DDSD_CAPS
| DDSD_WIDTH
| DDSD_HEIGHT
;
690 surface_desc
.ddsCaps
.dwCaps
= DDSCAPS_OFFSCREENPLAIN
| DDSCAPS_3DDEVICE
;
691 surface_desc
.dwWidth
= 640;
692 surface_desc
.dwHeight
= 480;
694 hr
= IDirectDraw_CreateSurface(ddraw
, &surface_desc
, &surface
, NULL
);
695 ok(SUCCEEDED(hr
), "Failed to create surface, hr %#x.\n", hr
);
697 hr
= IDirectDrawSurface_QueryInterface(surface
, &IID_IDirectDrawSurface3
, (void **)&surface3
);
700 skip("Failed to get the IDirectDrawSurface3 interface, skipping test.\n");
704 hr
= IDirectDraw_QueryInterface(ddraw
, &IID_IDirect3D
, (void **)&d3d
);
707 skip("Failed to get the IDirect3D interface, skipping test.\n");
711 hr
= IDirect3D_EnumDevices(d3d
, enum_z_fmt
, &z_depth
);
712 if (FAILED(hr
) || !z_depth
)
714 skip("No depth buffer formats available, skipping test.\n");
718 memset(&surface_desc
, 0, sizeof(surface_desc
));
719 surface_desc
.dwSize
= sizeof(surface_desc
);
720 surface_desc
.dwFlags
= DDSD_CAPS
| DDSD_ZBUFFERBITDEPTH
| DDSD_WIDTH
| DDSD_HEIGHT
;
721 surface_desc
.ddsCaps
.dwCaps
= DDSCAPS_ZBUFFER
;
722 surface_desc
.dwZBufferBitDepth
= z_depth
;
723 surface_desc
.dwWidth
= 640;
724 surface_desc
.dwHeight
= 480;
725 hr
= IDirectDraw_CreateSurface(ddraw
, &surface_desc
, &ds
, NULL
);
726 ok(SUCCEEDED(hr
), "Failed to create depth buffer, hr %#x.\n", hr
);
730 /* Using a different surface interface version still works */
731 hr
= IDirectDrawSurface3_AddAttachedSurface(surface3
, (IDirectDrawSurface3
*)ds
);
732 ok(SUCCEEDED(hr
), "Failed to attach depth buffer, hr %#x.\n", hr
);
733 refcount
= IDirectDrawSurface_Release(ds
);
734 ok(refcount
== 1, "Got unexpected refcount %u.\n", refcount
);
739 hr
= IDirectDrawSurface3_QueryInterface(surface3
, &IID_IDirect3DHALDevice
, (void **)&device
);
740 ok(SUCCEEDED(hr
), "Failed to create d3d device.\n");
744 hr
= IDirect3D_CreateViewport(d3d
, &viewport
, NULL
);
745 ok(SUCCEEDED(hr
), "Failed to create viewport, hr %#x.\n", hr
);
746 hr
= IDirect3D_CreateMaterial(d3d
, &background
, NULL
);
747 ok(SUCCEEDED(hr
), "Failed to create material, hr %#x.\n", hr
);
749 hr
= IDirect3DDevice_AddViewport(device
, viewport
);
750 ok(SUCCEEDED(hr
), "Failed to add viewport, hr %#x.\n", hr
);
751 memset(&vp
, 0, sizeof(vp
));
752 vp
.dwSize
= sizeof(vp
);
757 vp
.dvScaleX
= 320.0f
;
758 vp
.dvScaleY
= 240.0f
;
763 hr
= IDirect3DViewport_SetViewport(viewport
, &vp
);
764 ok(SUCCEEDED(hr
), "Failed to set viewport data, hr %#x.\n", hr
);
766 memset(&material
, 0, sizeof(material
));
767 material
.dwSize
= sizeof(material
);
768 U1(U(material
).diffuse
).r
= 1.0f
;
769 U2(U(material
).diffuse
).g
= 0.0f
;
770 U3(U(material
).diffuse
).b
= 0.0f
;
771 U4(U(material
).diffuse
).a
= 1.0f
;
772 hr
= IDirect3DMaterial_SetMaterial(background
, &material
);
773 ok(SUCCEEDED(hr
), "Failed to set material data, hr %#x.\n", hr
);
774 hr
= IDirect3DMaterial_GetHandle(background
, device
, &background_handle
);
775 ok(SUCCEEDED(hr
), "Failed to get material handle, hr %#x.\n", hr
);
776 hr
= IDirect3DViewport_SetBackground(viewport
, background_handle
);
777 ok(SUCCEEDED(hr
), "Failed to set viewport background, hr %#x.\n", hr
);
779 hr
= IDirect3DViewport_Clear(viewport
, 1, &clear_rect
, D3DCLEAR_TARGET
);
780 ok(SUCCEEDED(hr
), "Failed to clear render target, hr %#x.\n", hr
);
781 color
= get_surface_color(surface
, 320, 240);
782 ok(compare_color(color
, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color
);
787 IDirect3DDevice_DeleteViewport(device
, viewport
);
788 IDirect3DViewport_Release(viewport
);
790 if (background
) IDirect3DMaterial_Release(background
);
791 if (surface3
) IDirectDrawSurface3_Release(surface3
);
792 if (surface
) IDirectDrawSurface_Release(surface
);
793 if (device
) IDirect3DDevice_Release(device
);
794 if (d3d
) IDirect3D_Release(d3d
);
795 if (ddraw
) IDirectDraw_Release(ddraw
);
796 DestroyWindow(window
);
799 static void test_coop_level_threaded(void)
801 struct create_window_thread_param p
;
805 if (!(ddraw
= create_ddraw()))
807 skip("Failed to create a ddraw object, skipping test.\n");
810 create_window_thread(&p
);
812 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, p
.window
, DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
);
813 ok(SUCCEEDED(hr
), "Failed to set cooperative level, hr %#x.\n", hr
);
815 IDirectDraw_Release(ddraw
);
816 destroy_window_thread(&p
);
819 static LONG
get_refcount(IUnknown
*test_iface
)
821 IUnknown_AddRef(test_iface
);
822 return IUnknown_Release(test_iface
);
825 static void test_viewport_interfaces(void)
831 IDirect3DViewport
*viewport
;
832 IDirect3DViewport2
*viewport2
;
833 IDirect3DViewport3
*viewport3
;
834 IDirectDrawGammaControl
*gamma
;
837 if (!(ddraw
= create_ddraw()))
839 skip("Failed to create ddraw object, skipping test.\n");
842 hr
= IDirectDraw_QueryInterface(ddraw
, &IID_IDirect3D
, (void **)&d3d
);
843 ok(SUCCEEDED(hr
) || hr
== E_NOINTERFACE
, "Failed to get d3d interface, hr %#x.\n", hr
);
846 skip("Direct3D not available, skipping tests\n");
847 IDirectDraw_Release(ddraw
);
850 ref
= get_refcount((IUnknown
*)d3d
);
851 ok(ref
== 2, "IDirect3D refcount is %d\n", ref
);
853 hr
= IDirect3D_CreateViewport(d3d
, &viewport
, NULL
);
854 ok(SUCCEEDED(hr
), "Failed to create viewport, hr %#x.\n", hr
);
855 ref
= get_refcount((IUnknown
*)viewport
);
856 ok(ref
== 1, "Initial IDirect3DViewport refcount is %d\n", ref
);
857 ref
= get_refcount((IUnknown
*)d3d
);
858 ok(ref
== 2, "IDirect3D refcount is %d\n", ref
);
860 /* E_FAIL return values are returned by Winetestbot Windows NT machines. While not supporting
861 * newer interfaces is legitimate for old ddraw versions, E_FAIL violates Microsoft's rules
862 * for QueryInterface, hence the broken() */
863 gamma
= (IDirectDrawGammaControl
*)0xdeadbeef;
864 hr
= IDirect3DViewport_QueryInterface(viewport
, &IID_IDirectDrawGammaControl
, (void **)&gamma
);
865 ok(hr
== E_NOINTERFACE
|| broken(hr
== E_FAIL
), "Got unexpected hr %#x.\n", hr
);
866 ok(gamma
== NULL
, "Interface not set to NULL by failed QI call: %p\n", gamma
);
867 if (SUCCEEDED(hr
)) IDirectDrawGammaControl_Release(gamma
);
868 /* NULL iid: Segfaults */
870 hr
= IDirect3DViewport_QueryInterface(viewport
, &IID_IDirect3DViewport2
, (void **)&viewport2
);
871 ok(SUCCEEDED(hr
) || broken(hr
== E_FAIL
), "Failed to QI IDirect3DViewport2, hr %#x.\n", hr
);
874 ref
= get_refcount((IUnknown
*)viewport
);
875 ok(ref
== 2, "IDirect3DViewport refcount is %d\n", ref
);
876 ref
= get_refcount((IUnknown
*)viewport2
);
877 ok(ref
== 2, "IDirect3DViewport2 refcount is %d\n", ref
);
878 IDirect3DViewport2_Release(viewport2
);
882 hr
= IDirect3DViewport_QueryInterface(viewport
, &IID_IDirect3DViewport3
, (void **)&viewport3
);
883 ok(SUCCEEDED(hr
) || broken(hr
== E_FAIL
), "Failed to QI IDirect3DViewport3, hr %#x.\n", hr
);
886 ref
= get_refcount((IUnknown
*)viewport
);
887 ok(ref
== 2, "IDirect3DViewport refcount is %d\n", ref
);
888 ref
= get_refcount((IUnknown
*)viewport3
);
889 ok(ref
== 2, "IDirect3DViewport3 refcount is %d\n", ref
);
890 IDirect3DViewport3_Release(viewport3
);
893 hr
= IDirect3DViewport_QueryInterface(viewport
, &IID_IUnknown
, (void **)&unknown
);
894 ok(SUCCEEDED(hr
), "Failed to QI IUnknown, hr %#x.\n", hr
);
897 ref
= get_refcount((IUnknown
*)viewport
);
898 ok(ref
== 2, "IDirect3DViewport refcount is %d\n", ref
);
899 ref
= get_refcount(unknown
);
900 ok(ref
== 2, "IUnknown refcount is %d\n", ref
);
901 IUnknown_Release(unknown
);
904 IDirect3DViewport_Release(viewport
);
905 IDirect3D_Release(d3d
);
906 IDirectDraw_Release(ddraw
);
911 test_coop_level_create_device_window();
913 test_coop_level_d3d_state();
914 test_surface_interface_mismatch();
915 test_coop_level_threaded();
916 test_viewport_interfaces();