winealsa: Fix AudioRenderClient Get/ReleaseBuffer protocol.
[wine] / dlls / ddraw / tests / ddraw2.c
1 /*
2  * Copyright 2011 Henri Verbeet for CodeWeavers
3  *
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.
8  *
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.
13  *
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
17  */
18
19 #include "wine/test.h"
20 #include "d3d.h"
21
22 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
23 {
24     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
25     c1 >>= 8; c2 >>= 8;
26     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
27     c1 >>= 8; c2 >>= 8;
28     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
29     c1 >>= 8; c2 >>= 8;
30     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
31     return TRUE;
32 }
33
34 static D3DCOLOR get_surface_color(IDirectDrawSurface *surface, UINT x, UINT y)
35 {
36     RECT rect = {x, y, x + 1, y + 1};
37     DDSURFACEDESC surface_desc;
38     D3DCOLOR color;
39     HRESULT hr;
40
41     memset(&surface_desc, 0, sizeof(surface_desc));
42     surface_desc.dwSize = sizeof(surface_desc);
43
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);
46     if (FAILED(hr))
47         return 0xdeadbeef;
48
49     color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
50
51     hr = IDirectDrawSurface_Unlock(surface, NULL);
52     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
53
54     return color;
55 }
56
57 static IDirectDraw2 *create_ddraw(void)
58 {
59     IDirectDraw2 *ddraw2;
60     IDirectDraw *ddraw1;
61     HRESULT hr;
62
63     if (FAILED(DirectDrawCreate(NULL, &ddraw1, NULL)))
64         return NULL;
65
66     hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw2, (void **)&ddraw2);
67     IDirectDraw_Release(ddraw1);
68     if (FAILED(hr))
69         return NULL;
70
71     return ddraw2;
72 }
73
74 static void test_coop_level_create_device_window(void)
75 {
76     HWND focus_window, device_window;
77     IDirectDraw2 *ddraw;
78     HRESULT hr;
79
80     focus_window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
81             0, 0, 640, 480, 0, 0, 0, 0);
82     if (!(ddraw = create_ddraw()))
83     {
84         skip("Failed to create a ddraw object, skipping test.\n");
85         DestroyWindow(focus_window);
86         return;
87     }
88
89     hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
90     ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
91     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
92     ok(!device_window, "Unexpected device window found.\n");
93     hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
94     ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
95     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
96     ok(!device_window, "Unexpected device window found.\n");
97     hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
98     ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
99     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
100     ok(!device_window, "Unexpected device window found.\n");
101     hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
102     ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
103     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
104     ok(!device_window, "Unexpected device window found.\n");
105     hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
106     ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
107     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
108     ok(!device_window, "Unexpected device window found.\n");
109
110     /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
111     if (broken(hr == DDERR_INVALIDPARAMS))
112     {
113         win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
114         IDirectDraw2_Release(ddraw);
115         DestroyWindow(focus_window);
116         return;
117     }
118
119     hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
120     ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
121     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
122     ok(!device_window, "Unexpected device window found.\n");
123     hr = IDirectDraw2_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
124     ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
125     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
126     ok(!device_window, "Unexpected device window found.\n");
127
128     hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
129     ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
130     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
131     ok(!device_window, "Unexpected device window found.\n");
132     hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
133             | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
134     ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
135     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
136     ok(!!device_window, "Device window not found.\n");
137
138     hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
139     ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
140     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
141     ok(!device_window, "Unexpected device window found.\n");
142     hr = IDirectDraw2_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
143             | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
144     ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
145     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
146     ok(!!device_window, "Device window not found.\n");
147
148     hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
149     ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
150     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
151     ok(!device_window, "Unexpected device window found.\n");
152     hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
153     ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
154     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
155     ok(!device_window, "Unexpected device window found.\n");
156     hr = IDirectDraw2_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
157     ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
158     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
159     ok(!device_window, "Unexpected device window found.\n");
160     hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
161     ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
162     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
163     ok(!!device_window, "Device window not found.\n");
164
165     IDirectDraw2_Release(ddraw);
166     DestroyWindow(focus_window);
167 }
168
169 static void test_clipper_blt(void)
170 {
171     IDirectDrawSurface *src_surface, *dst_surface;
172     RECT client_rect, src_rect, *rect;
173     IDirectDrawClipper *clipper;
174     DDSURFACEDESC surface_desc;
175     unsigned int i, j, x, y;
176     IDirectDraw2 *ddraw;
177     RGNDATA *rgn_data;
178     D3DCOLOR color;
179     HRGN r1, r2;
180     HWND window;
181     DDBLTFX fx;
182     HRESULT hr;
183     DWORD ret;
184
185     static const D3DCOLOR expected1[] =
186     {
187         0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
188         0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
189         0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
190         0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
191     };
192     static const D3DCOLOR expected2[] =
193     {
194         0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
195         0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
196         0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
197         0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
198     };
199
200     window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
201             10, 10, 640, 480, 0, 0, 0, 0);
202     ShowWindow(window, SW_SHOW);
203     if (!(ddraw = create_ddraw()))
204     {
205         skip("Failed to create a ddraw object, skipping test.\n");
206         DestroyWindow(window);
207         return;
208     }
209
210     ret = GetClientRect(window, &client_rect);
211     ok(ret, "Failed to get client rect.\n");
212     ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
213     ok(ret, "Failed to map client rect.\n");
214
215     hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
216     ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
217
218     hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
219     ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
220     hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
221     ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
222     hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
223     ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
224     hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
225     ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
226     rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
227     hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
228     ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
229     ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
230     ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
231     ok(rgn_data->rdh.nCount == 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
232     ok(rgn_data->rdh.nRgnSize == 16 || broken(rgn_data->rdh.nRgnSize == 168 /* NT4 */),
233             "Got unexpected region size %u.\n", rgn_data->rdh.nRgnSize);
234     ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
235             "Got unexpected bounding rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
236             rgn_data->rdh.rcBound.left, rgn_data->rdh.rcBound.top,
237             rgn_data->rdh.rcBound.right, rgn_data->rdh.rcBound.bottom,
238             client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
239     rect = (RECT *)&rgn_data->Buffer[0];
240     ok(EqualRect(rect, &client_rect),
241             "Got unexpected clip rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
242             rect->left, rect->top, rect->right, rect->bottom,
243             client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
244     HeapFree(GetProcessHeap(), 0, rgn_data);
245
246     r1 = CreateRectRgn(0, 0, 320, 240);
247     ok(!!r1, "Failed to create region.\n");
248     r2 = CreateRectRgn(320, 240, 640, 480);
249     ok(!!r2, "Failed to create region.\n");
250     CombineRgn(r1, r1, r2, RGN_OR);
251     ret = GetRegionData(r1, 0, NULL);
252     rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
253     ret = GetRegionData(r1, ret, rgn_data);
254     ok(!!ret, "Failed to get region data.\n");
255
256     DeleteObject(r2);
257     DeleteObject(r1);
258
259     hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
260     ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
261     hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
262     ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
263     hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
264     ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
265
266     HeapFree(GetProcessHeap(), 0, rgn_data);
267
268     memset(&surface_desc, 0, sizeof(surface_desc));
269     surface_desc.dwSize = sizeof(surface_desc);
270     surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
271     surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
272     surface_desc.dwWidth = 640;
273     surface_desc.dwHeight = 480;
274     surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
275     surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
276     U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
277     U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
278     U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
279     U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
280
281     hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
282     ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
283     hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
284     ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
285
286     memset(&fx, 0, sizeof(fx));
287     fx.dwSize = sizeof(fx);
288     hr = IDirectDrawSurface_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
289     ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
290     hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
291     ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
292
293     hr = IDirectDrawSurface_Lock(src_surface, NULL, &surface_desc, 0, NULL);
294     ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
295     ((DWORD *)surface_desc.lpSurface)[0] = 0xff0000ff;
296     ((DWORD *)surface_desc.lpSurface)[1] = 0xff00ff00;
297     ((DWORD *)surface_desc.lpSurface)[2] = 0xffff0000;
298     ((DWORD *)surface_desc.lpSurface)[3] = 0xffffffff;
299     hr = IDirectDrawSurface_Unlock(src_surface, NULL);
300     ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
301
302     hr = IDirectDrawSurface_SetClipper(dst_surface, clipper);
303     ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
304
305     SetRect(&src_rect, 0, 0, 4, 1);
306     hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
307     ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
308     for (i = 0; i < 4; ++i)
309     {
310         for (j = 0; j < 4; ++j)
311         {
312             x = 80 * ((2 * j) + 1);
313             y = 60 * ((2 * i) + 1);
314             color = get_surface_color(dst_surface, x, y);
315             ok(compare_color(color, expected1[i * 4 + j], 1),
316                     "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
317         }
318     }
319
320     U5(fx).dwFillColor = 0xff0000ff;
321     hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
322     ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
323     for (i = 0; i < 4; ++i)
324     {
325         for (j = 0; j < 4; ++j)
326         {
327             x = 80 * ((2 * j) + 1);
328             y = 60 * ((2 * i) + 1);
329             color = get_surface_color(dst_surface, x, y);
330             ok(compare_color(color, expected2[i * 4 + j], 1),
331                     "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
332         }
333     }
334
335     hr = IDirectDrawSurface_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
336     ok(hr == DDERR_BLTFASTCANTCLIP || broken(hr == E_NOTIMPL /* NT4 */), "Got unexpected hr %#x.\n", hr);
337
338     hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
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     DestroyWindow(window);
343     hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
344     ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
345     hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
346     ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
347     hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
348     ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
349     hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
350     ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
351     hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
352     ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
353     hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
354     ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
355
356     IDirectDrawSurface_Release(dst_surface);
357     IDirectDrawSurface_Release(src_surface);
358     IDirectDrawClipper_Release(clipper);
359     IDirectDraw2_Release(ddraw);
360 }
361
362 START_TEST(ddraw2)
363 {
364     test_coop_level_create_device_window();
365     test_clipper_blt();
366 }