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
19 #include "wine/test.h"
22 static BOOL
compare_color(D3DCOLOR c1
, D3DCOLOR c2
, BYTE max_diff
)
24 if (abs((c1
& 0xff) - (c2
& 0xff)) > max_diff
) return FALSE
;
26 if (abs((c1
& 0xff) - (c2
& 0xff)) > max_diff
) return FALSE
;
28 if (abs((c1
& 0xff) - (c2
& 0xff)) > max_diff
) return FALSE
;
30 if (abs((c1
& 0xff) - (c2
& 0xff)) > max_diff
) return FALSE
;
34 static D3DCOLOR
get_surface_color(IDirectDrawSurface
*surface
, UINT x
, UINT y
)
36 RECT rect
= {x
, y
, x
+ 1, y
+ 1};
37 DDSURFACEDESC surface_desc
;
41 memset(&surface_desc
, 0, sizeof(surface_desc
));
42 surface_desc
.dwSize
= sizeof(surface_desc
);
44 hr
= IDirectDrawSurface_Lock(surface
, &rect
, &surface_desc
, DDLOCK_READONLY
| DDLOCK_WAIT
, NULL
);
45 ok(SUCCEEDED(hr
), "Failed to lock surface, hr %#x.\n", hr
);
49 color
= *((DWORD
*)surface_desc
.lpSurface
) & 0x00ffffff;
51 hr
= IDirectDrawSurface_Unlock(surface
, NULL
);
52 ok(SUCCEEDED(hr
), "Failed to unlock surface, hr %#x.\n", hr
);
57 static IDirectDraw
*create_ddraw(void)
61 if (FAILED(DirectDrawCreate(NULL
, &ddraw
, NULL
)))
67 static void test_coop_level_create_device_window(void)
69 HWND focus_window
, device_window
;
73 focus_window
= CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW
,
74 0, 0, 640, 480, 0, 0, 0, 0);
75 if (!(ddraw
= create_ddraw()))
77 skip("Failed to create a ddraw object, skipping test.\n");
78 DestroyWindow(focus_window
);
82 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, NULL
, DDSCL_NORMAL
);
83 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
84 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
85 ok(!device_window
, "Unexpected device window found.\n");
86 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, NULL
, DDSCL_CREATEDEVICEWINDOW
);
87 ok(hr
== DDERR_INVALIDPARAMS
, "Got unexpected hr %#x.\n", hr
);
88 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
89 ok(!device_window
, "Unexpected device window found.\n");
90 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, NULL
, DDSCL_CREATEDEVICEWINDOW
| DDSCL_NORMAL
);
91 ok(hr
== DDERR_INVALIDPARAMS
, "Got unexpected hr %#x.\n", hr
);
92 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
93 ok(!device_window
, "Unexpected device window found.\n");
94 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, NULL
, DDSCL_CREATEDEVICEWINDOW
| DDSCL_NORMAL
| DDSCL_FULLSCREEN
);
95 ok(hr
== DDERR_INVALIDPARAMS
, "Got unexpected hr %#x.\n", hr
);
96 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
97 ok(!device_window
, "Unexpected device window found.\n");
98 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, NULL
, DDSCL_CREATEDEVICEWINDOW
| DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
);
99 ok(hr
== DDERR_NOFOCUSWINDOW
|| broken(hr
== DDERR_INVALIDPARAMS
), "Got unexpected hr %#x.\n", hr
);
100 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
101 ok(!device_window
, "Unexpected device window found.\n");
103 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
104 if (broken(hr
== DDERR_INVALIDPARAMS
))
106 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
107 IDirectDraw_Release(ddraw
);
108 DestroyWindow(focus_window
);
112 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, NULL
, DDSCL_NORMAL
);
113 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
114 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
115 ok(!device_window
, "Unexpected device window found.\n");
116 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, focus_window
, DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
);
117 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
118 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
119 ok(!device_window
, "Unexpected device window found.\n");
121 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, NULL
, DDSCL_NORMAL
);
122 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
123 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
124 ok(!device_window
, "Unexpected device window found.\n");
125 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, NULL
, DDSCL_SETFOCUSWINDOW
126 | DDSCL_CREATEDEVICEWINDOW
| DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
);
127 ok(hr
== DDERR_NOHWND
, "Got unexpected hr %#x.\n", hr
);
128 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
129 ok(!!device_window
, "Device window not found.\n");
131 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, NULL
, DDSCL_NORMAL
);
132 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
133 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
134 ok(!device_window
, "Unexpected device window found.\n");
135 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, focus_window
, DDSCL_SETFOCUSWINDOW
136 | DDSCL_CREATEDEVICEWINDOW
| DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
);
137 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
138 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
139 ok(!!device_window
, "Device window not found.\n");
141 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, NULL
, DDSCL_NORMAL
);
142 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
143 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
144 ok(!device_window
, "Unexpected device window found.\n");
145 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, NULL
, DDSCL_CREATEDEVICEWINDOW
| DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
);
146 ok(hr
== DDERR_NOFOCUSWINDOW
, "Got unexpected hr %#x.\n", hr
);
147 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
148 ok(!device_window
, "Unexpected device window found.\n");
149 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, focus_window
, DDSCL_SETFOCUSWINDOW
);
150 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
151 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
152 ok(!device_window
, "Unexpected device window found.\n");
153 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, NULL
, DDSCL_CREATEDEVICEWINDOW
| DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
);
154 ok(hr
== DD_OK
, "Got unexpected hr %#x.\n", hr
);
155 device_window
= FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
156 ok(!!device_window
, "Device window not found.\n");
158 IDirectDraw_Release(ddraw
);
159 DestroyWindow(focus_window
);
162 static void test_clipper_blt(void)
164 IDirectDrawSurface
*src_surface
, *dst_surface
;
165 RECT client_rect
, src_rect
, *rect
;
166 IDirectDrawClipper
*clipper
;
167 DDSURFACEDESC surface_desc
;
168 unsigned int i
, j
, x
, y
;
178 static const D3DCOLOR expected1
[] =
180 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
181 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
182 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
183 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
185 static const D3DCOLOR expected2
[] =
187 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
188 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
189 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
190 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
193 window
= CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW
,
194 10, 10, 640, 480, 0, 0, 0, 0);
195 ShowWindow(window
, SW_SHOW
);
196 if (!(ddraw
= create_ddraw()))
198 skip("Failed to create a ddraw object, skipping test.\n");
199 DestroyWindow(window
);
203 ret
= GetClientRect(window
, &client_rect
);
204 ok(ret
, "Failed to get client rect.\n");
205 ret
= MapWindowPoints(window
, NULL
, (POINT
*)&client_rect
, 2);
206 ok(ret
, "Failed to map client rect.\n");
208 hr
= IDirectDraw_SetCooperativeLevel(ddraw
, window
, DDSCL_NORMAL
);
209 ok(SUCCEEDED(hr
), "Failed to set cooperative level, hr %#x.\n", hr
);
211 hr
= IDirectDraw_CreateClipper(ddraw
, 0, &clipper
, NULL
);
212 ok(SUCCEEDED(hr
), "Failed to create clipper, hr %#x.\n", hr
);
213 hr
= IDirectDrawClipper_GetClipList(clipper
, NULL
, NULL
, &ret
);
214 ok(hr
== DDERR_NOCLIPLIST
, "Got unexpected hr %#x.\n", hr
);
215 hr
= IDirectDrawClipper_SetHWnd(clipper
, 0, window
);
216 ok(SUCCEEDED(hr
), "Failed to set clipper window, hr %#x.\n", hr
);
217 hr
= IDirectDrawClipper_GetClipList(clipper
, NULL
, NULL
, &ret
);
218 ok(SUCCEEDED(hr
), "Failed to get clip list size, hr %#x.\n", hr
);
219 rgn_data
= HeapAlloc(GetProcessHeap(), 0, ret
);
220 hr
= IDirectDrawClipper_GetClipList(clipper
, NULL
, rgn_data
, &ret
);
221 ok(SUCCEEDED(hr
), "Failed to get clip list, hr %#x.\n", hr
);
222 ok(rgn_data
->rdh
.dwSize
== sizeof(rgn_data
->rdh
), "Got unexpected structure size %#x.\n", rgn_data
->rdh
.dwSize
);
223 ok(rgn_data
->rdh
.iType
== RDH_RECTANGLES
, "Got unexpected type %#x.\n", rgn_data
->rdh
.iType
);
224 ok(rgn_data
->rdh
.nCount
== 1, "Got unexpected count %u.\n", rgn_data
->rdh
.nCount
);
225 ok(rgn_data
->rdh
.nRgnSize
== 16 || broken(rgn_data
->rdh
.nRgnSize
== 168 /* NT4 */),
226 "Got unexpected region size %u.\n", rgn_data
->rdh
.nRgnSize
);
227 ok(EqualRect(&rgn_data
->rdh
.rcBound
, &client_rect
),
228 "Got unexpected bounding rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
229 rgn_data
->rdh
.rcBound
.left
, rgn_data
->rdh
.rcBound
.top
,
230 rgn_data
->rdh
.rcBound
.right
, rgn_data
->rdh
.rcBound
.bottom
,
231 client_rect
.left
, client_rect
.top
, client_rect
.right
, client_rect
.bottom
);
232 rect
= (RECT
*)&rgn_data
->Buffer
[0];
233 ok(EqualRect(rect
, &client_rect
),
234 "Got unexpected clip rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
235 rect
->left
, rect
->top
, rect
->right
, rect
->bottom
,
236 client_rect
.left
, client_rect
.top
, client_rect
.right
, client_rect
.bottom
);
237 HeapFree(GetProcessHeap(), 0, rgn_data
);
239 r1
= CreateRectRgn(0, 0, 320, 240);
240 ok(!!r1
, "Failed to create region.\n");
241 r2
= CreateRectRgn(320, 240, 640, 480);
242 ok(!!r2
, "Failed to create region.\n");
243 CombineRgn(r1
, r1
, r2
, RGN_OR
);
244 ret
= GetRegionData(r1
, 0, NULL
);
245 rgn_data
= HeapAlloc(GetProcessHeap(), 0, ret
);
246 ret
= GetRegionData(r1
, ret
, rgn_data
);
247 ok(!!ret
, "Failed to get region data.\n");
252 hr
= IDirectDrawClipper_SetClipList(clipper
, rgn_data
, 0);
253 ok(hr
== DDERR_CLIPPERISUSINGHWND
, "Got unexpected hr %#x.\n", hr
);
254 hr
= IDirectDrawClipper_SetHWnd(clipper
, 0, NULL
);
255 ok(SUCCEEDED(hr
), "Failed to set clipper window, hr %#x.\n", hr
);
256 hr
= IDirectDrawClipper_SetClipList(clipper
, rgn_data
, 0);
257 ok(SUCCEEDED(hr
), "Failed to set clip list, hr %#x.\n", hr
);
259 HeapFree(GetProcessHeap(), 0, rgn_data
);
261 memset(&surface_desc
, 0, sizeof(surface_desc
));
262 surface_desc
.dwSize
= sizeof(surface_desc
);
263 surface_desc
.dwFlags
= DDSD_CAPS
| DDSD_WIDTH
| DDSD_HEIGHT
| DDSD_PIXELFORMAT
;
264 surface_desc
.ddsCaps
.dwCaps
= DDSCAPS_OFFSCREENPLAIN
;
265 surface_desc
.dwWidth
= 640;
266 surface_desc
.dwHeight
= 480;
267 surface_desc
.ddpfPixelFormat
.dwSize
= sizeof(surface_desc
.ddpfPixelFormat
);
268 surface_desc
.ddpfPixelFormat
.dwFlags
= DDPF_RGB
;
269 U1(surface_desc
.ddpfPixelFormat
).dwRGBBitCount
= 32;
270 U2(surface_desc
.ddpfPixelFormat
).dwRBitMask
= 0x00ff0000;
271 U3(surface_desc
.ddpfPixelFormat
).dwGBitMask
= 0x0000ff00;
272 U4(surface_desc
.ddpfPixelFormat
).dwBBitMask
= 0x000000ff;
274 hr
= IDirectDraw_CreateSurface(ddraw
, &surface_desc
, &src_surface
, NULL
);
275 ok(SUCCEEDED(hr
), "Failed to create source surface, hr %#x.\n", hr
);
276 hr
= IDirectDraw_CreateSurface(ddraw
, &surface_desc
, &dst_surface
, NULL
);
277 ok(SUCCEEDED(hr
), "Failed to create destination surface, hr %#x.\n", hr
);
279 memset(&fx
, 0, sizeof(fx
));
280 fx
.dwSize
= sizeof(fx
);
281 hr
= IDirectDrawSurface_Blt(src_surface
, NULL
, NULL
, NULL
, DDBLT_COLORFILL
| DDBLT_WAIT
, &fx
);
282 ok(SUCCEEDED(hr
), "Failed to clear source surface, hr %#x.\n", hr
);
283 hr
= IDirectDrawSurface_Blt(dst_surface
, NULL
, NULL
, NULL
, DDBLT_COLORFILL
| DDBLT_WAIT
, &fx
);
284 ok(SUCCEEDED(hr
), "Failed to clear destination surface, hr %#x.\n", hr
);
286 hr
= IDirectDrawSurface_Lock(src_surface
, NULL
, &surface_desc
, DDLOCK_WAIT
, NULL
);
287 ok(SUCCEEDED(hr
), "Failed to lock source surface, hr %#x.\n", hr
);
288 ((DWORD
*)surface_desc
.lpSurface
)[0] = 0xff0000ff;
289 ((DWORD
*)surface_desc
.lpSurface
)[1] = 0xff00ff00;
290 ((DWORD
*)surface_desc
.lpSurface
)[2] = 0xffff0000;
291 ((DWORD
*)surface_desc
.lpSurface
)[3] = 0xffffffff;
292 hr
= IDirectDrawSurface_Unlock(src_surface
, NULL
);
293 ok(SUCCEEDED(hr
), "Failed to unlock source surface, hr %#x.\n", hr
);
295 hr
= IDirectDrawSurface_SetClipper(dst_surface
, clipper
);
296 ok(SUCCEEDED(hr
), "Failed to set clipper, hr %#x.\n", hr
);
298 SetRect(&src_rect
, 0, 0, 4, 1);
299 hr
= IDirectDrawSurface_Blt(dst_surface
, NULL
, src_surface
, &src_rect
, DDBLT_WAIT
, NULL
);
300 ok(SUCCEEDED(hr
), "Failed to blit, hr %#x.\n", hr
);
301 for (i
= 0; i
< 4; ++i
)
303 for (j
= 0; j
< 4; ++j
)
305 x
= 80 * ((2 * j
) + 1);
306 y
= 60 * ((2 * i
) + 1);
307 color
= get_surface_color(dst_surface
, x
, y
);
308 ok(compare_color(color
, expected1
[i
* 4 + j
], 1),
309 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1
[i
* 4 + j
], x
, y
, color
);
313 U5(fx
).dwFillColor
= 0xff0000ff;
314 hr
= IDirectDrawSurface_Blt(dst_surface
, NULL
, NULL
, NULL
, DDBLT_COLORFILL
| DDBLT_WAIT
, &fx
);
315 ok(SUCCEEDED(hr
), "Failed to clear destination surface, hr %#x.\n", hr
);
316 for (i
= 0; i
< 4; ++i
)
318 for (j
= 0; j
< 4; ++j
)
320 x
= 80 * ((2 * j
) + 1);
321 y
= 60 * ((2 * i
) + 1);
322 color
= get_surface_color(dst_surface
, x
, y
);
323 ok(compare_color(color
, expected2
[i
* 4 + j
], 1),
324 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2
[i
* 4 + j
], x
, y
, color
);
328 hr
= IDirectDrawSurface_BltFast(dst_surface
, 0, 0, src_surface
, NULL
, DDBLTFAST_WAIT
);
329 ok(hr
== DDERR_BLTFASTCANTCLIP
|| broken(hr
== E_NOTIMPL
/* NT4 */), "Got unexpected hr %#x.\n", hr
);
331 hr
= IDirectDrawClipper_SetHWnd(clipper
, 0, window
);
332 ok(SUCCEEDED(hr
), "Failed to set clipper window, hr %#x.\n", hr
);
333 hr
= IDirectDrawClipper_GetClipList(clipper
, NULL
, NULL
, &ret
);
334 ok(SUCCEEDED(hr
), "Failed to get clip list size, hr %#x.\n", hr
);
335 DestroyWindow(window
);
336 hr
= IDirectDrawClipper_GetClipList(clipper
, NULL
, NULL
, &ret
);
337 ok(hr
== E_FAIL
, "Got unexpected hr %#x.\n", hr
);
338 hr
= IDirectDrawClipper_SetHWnd(clipper
, 0, NULL
);
339 ok(SUCCEEDED(hr
), "Failed to set clipper window, hr %#x.\n", hr
);
340 hr
= IDirectDrawClipper_GetClipList(clipper
, NULL
, NULL
, &ret
);
341 ok(SUCCEEDED(hr
), "Failed to get clip list size, hr %#x.\n", hr
);
342 hr
= IDirectDrawClipper_SetClipList(clipper
, NULL
, 0);
343 ok(SUCCEEDED(hr
), "Failed to set clip list, hr %#x.\n", hr
);
344 hr
= IDirectDrawClipper_GetClipList(clipper
, NULL
, NULL
, &ret
);
345 ok(hr
== DDERR_NOCLIPLIST
, "Got unexpected hr %#x.\n", hr
);
346 hr
= IDirectDrawSurface_Blt(dst_surface
, NULL
, NULL
, NULL
, DDBLT_COLORFILL
| DDBLT_WAIT
, &fx
);
347 ok(hr
== DDERR_NOCLIPLIST
, "Got unexpected hr %#x.\n", hr
);
349 IDirectDrawSurface_Release(dst_surface
);
350 IDirectDrawSurface_Release(src_surface
);
351 IDirectDrawClipper_Release(clipper
);
352 IDirectDraw_Release(ddraw
);
357 test_coop_level_create_device_window();