ddraw: Get rid of the local "window" variable in ddraw7_SetCooperativeLevel().
[wine] / dlls / ddraw / tests / ddraw7.c
1 /*
2  * Copyright 2006 Stefan Dösinger for CodeWeavers
3  * Copyright 2011 Henri Verbeet for CodeWeavers
4  *
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.
9  *
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.
14  *
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
18  */
19 #define COBJMACROS
20
21 #include "wine/test.h"
22 #include <limits.h>
23 #include "d3d.h"
24
25 static HRESULT (WINAPI *pDirectDrawCreateEx)(GUID *guid, void **ddraw, REFIID iid, IUnknown *outer_unknown);
26
27 struct vec2
28 {
29     float x, y;
30 };
31
32 struct vec3
33 {
34     float x, y, z;
35 };
36
37 struct vec4
38 {
39     float x, y, z, w;
40 };
41
42 struct create_window_thread_param
43 {
44     HWND window;
45     HANDLE window_created;
46     HANDLE destroy_window;
47     HANDLE thread;
48 };
49
50 static BOOL compare_float(float f, float g, unsigned int ulps)
51 {
52     int x = *(int *)&f;
53     int y = *(int *)&g;
54
55     if (x < 0)
56         x = INT_MIN - x;
57     if (y < 0)
58         y = INT_MIN - y;
59
60     if (abs(x - y) > ulps)
61         return FALSE;
62
63     return TRUE;
64 }
65
66 static BOOL compare_vec3(struct vec3 *vec, float x, float y, float z, unsigned int ulps)
67 {
68     return compare_float(vec->x, x, ulps)
69             && compare_float(vec->y, y, ulps)
70             && compare_float(vec->z, z, ulps);
71 }
72
73 static BOOL compare_vec4(struct vec4 *vec, float x, float y, float z, float w, unsigned int ulps)
74 {
75     return compare_float(vec->x, x, ulps)
76             && compare_float(vec->y, y, ulps)
77             && compare_float(vec->z, z, ulps)
78             && compare_float(vec->w, w, ulps);
79 }
80
81 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
82 {
83     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
84     c1 >>= 8; c2 >>= 8;
85     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
86     c1 >>= 8; c2 >>= 8;
87     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
88     c1 >>= 8; c2 >>= 8;
89     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
90     return TRUE;
91 }
92
93 static DWORD WINAPI create_window_thread_proc(void *param)
94 {
95     struct create_window_thread_param *p = param;
96     DWORD res;
97     BOOL ret;
98
99     p->window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
100             0, 0, 640, 480, 0, 0, 0, 0);
101     ret = SetEvent(p->window_created);
102     ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
103
104     for (;;)
105     {
106         MSG msg;
107
108         while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
109             DispatchMessage(&msg);
110         res = WaitForSingleObject(p->destroy_window, 100);
111         if (res == WAIT_OBJECT_0)
112             break;
113         if (res != WAIT_TIMEOUT)
114         {
115             ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
116             break;
117         }
118     }
119
120     DestroyWindow(p->window);
121
122     return 0;
123 }
124
125 static void create_window_thread(struct create_window_thread_param *p)
126 {
127     DWORD res, tid;
128
129     p->window_created = CreateEvent(NULL, FALSE, FALSE, NULL);
130     ok(!!p->window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
131     p->destroy_window = CreateEvent(NULL, FALSE, FALSE, NULL);
132     ok(!!p->destroy_window, "CreateEvent failed, last error %#x.\n", GetLastError());
133     p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
134     ok(!!p->thread, "Failed to create thread, last error %#x.\n", GetLastError());
135     res = WaitForSingleObject(p->window_created, INFINITE);
136     ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
137 }
138
139 static void destroy_window_thread(struct create_window_thread_param *p)
140 {
141     SetEvent(p->destroy_window);
142     WaitForSingleObject(p->thread, INFINITE);
143     CloseHandle(p->destroy_window);
144     CloseHandle(p->window_created);
145     CloseHandle(p->thread);
146 }
147
148 static IDirectDrawSurface7 *get_depth_stencil(IDirect3DDevice7 *device)
149 {
150     IDirectDrawSurface7 *rt, *ret;
151     DDSCAPS2 caps = {DDSCAPS_ZBUFFER, 0, 0, 0};
152     HRESULT hr;
153
154     hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
155     ok(SUCCEEDED(hr), "Failed to get the render target, hr %#x.\n", hr);
156     hr = IDirectDrawSurface7_GetAttachedSurface(rt, &caps, &ret);
157     ok(SUCCEEDED(hr) || hr == DDERR_NOTFOUND, "Failed to get the z buffer, hr %#x.\n", hr);
158     IDirectDrawSurface7_Release(rt);
159     return ret;
160 }
161
162 static D3DCOLOR get_surface_color(IDirectDrawSurface7 *surface, UINT x, UINT y)
163 {
164     RECT rect = {x, y, x + 1, y + 1};
165     DDSURFACEDESC2 surface_desc;
166     D3DCOLOR color;
167     HRESULT hr;
168
169     memset(&surface_desc, 0, sizeof(surface_desc));
170     surface_desc.dwSize = sizeof(surface_desc);
171
172     hr = IDirectDrawSurface7_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY, NULL);
173     ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
174     if (FAILED(hr))
175         return 0xdeadbeef;
176
177     color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
178
179     hr = IDirectDrawSurface7_Unlock(surface, &rect);
180     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
181
182     return color;
183 }
184
185 static HRESULT CALLBACK enum_z_fmt(DDPIXELFORMAT *format, void *ctx)
186 {
187     DDPIXELFORMAT *z_fmt = ctx;
188
189     if (U1(*format).dwZBufferBitDepth > U1(*z_fmt).dwZBufferBitDepth)
190         *z_fmt = *format;
191
192     return DDENUMRET_OK;
193 }
194
195 static IDirectDraw7 *create_ddraw(void)
196 {
197     IDirectDraw7 *ddraw;
198
199     if (FAILED(pDirectDrawCreateEx(NULL, (void **)&ddraw, &IID_IDirectDraw7, NULL)))
200         return NULL;
201
202     return ddraw;
203 }
204
205 static IDirect3DDevice7 *create_device(HWND window, DWORD coop_level)
206 {
207     IDirectDrawSurface7 *surface, *ds;
208     IDirect3DDevice7 *device = NULL;
209     DDSURFACEDESC2 surface_desc;
210     DDPIXELFORMAT z_fmt;
211     IDirectDraw7 *ddraw;
212     IDirect3D7 *d3d7;
213     HRESULT hr;
214
215     if (!(ddraw = create_ddraw()))
216         return NULL;
217
218     hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, coop_level);
219     ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
220
221     memset(&surface_desc, 0, sizeof(surface_desc));
222     surface_desc.dwSize = sizeof(surface_desc);
223     surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
224     surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
225     surface_desc.dwWidth = 640;
226     surface_desc.dwHeight = 480;
227
228     hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
229     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
230
231     if (coop_level & DDSCL_NORMAL)
232     {
233         IDirectDrawClipper *clipper;
234
235         hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
236         ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
237         hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
238         ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
239         hr = IDirectDrawSurface7_SetClipper(surface, clipper);
240         ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\n", hr);
241         IDirectDrawClipper_Release(clipper);
242     }
243
244     hr = IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d7);
245     IDirectDraw7_Release(ddraw);
246     if (FAILED(hr))
247     {
248         IDirectDrawSurface7_Release(surface);
249         return NULL;
250     }
251
252     memset(&z_fmt, 0, sizeof(z_fmt));
253     hr = IDirect3D7_EnumZBufferFormats(d3d7, &IID_IDirect3DTnLHalDevice, enum_z_fmt, &z_fmt);
254     if (FAILED(hr) || !z_fmt.dwSize)
255     {
256         IDirect3D7_Release(d3d7);
257         IDirectDrawSurface7_Release(surface);
258         return NULL;
259     }
260
261     memset(&surface_desc, 0, sizeof(surface_desc));
262     surface_desc.dwSize = sizeof(surface_desc);
263     surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
264     surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
265     U4(surface_desc).ddpfPixelFormat = z_fmt;
266     surface_desc.dwWidth = 640;
267     surface_desc.dwHeight = 480;
268     hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL);
269     ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
270     if (FAILED(hr))
271     {
272         IDirect3D7_Release(d3d7);
273         IDirectDrawSurface7_Release(surface);
274         return NULL;
275     }
276
277     hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
278     ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
279     IDirectDrawSurface7_Release(ds);
280     if (FAILED(hr))
281     {
282         IDirect3D7_Release(d3d7);
283         IDirectDrawSurface7_Release(surface);
284         return NULL;
285     }
286
287     hr = IDirect3D7_CreateDevice(d3d7, &IID_IDirect3DTnLHalDevice, surface, &device);
288     IDirect3D7_Release(d3d7);
289     IDirectDrawSurface7_Release(surface);
290     if (FAILED(hr))
291         return NULL;
292
293     return device;
294 }
295
296 static const UINT *expect_messages;
297
298 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
299 {
300     if (expect_messages && message == *expect_messages)
301         ++expect_messages;
302
303     return DefWindowProcA(hwnd, message, wparam, lparam);
304 }
305
306 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
307  * interface. This prevents subsequent SetCooperativeLevel() calls on a
308  * different window from failing with DDERR_HWNDALREADYSET. */
309 static void fix_wndproc(HWND window, LONG_PTR proc)
310 {
311     IDirectDraw7 *ddraw;
312     HRESULT hr;
313
314     if (!(ddraw = create_ddraw()))
315         return;
316
317     SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
318     hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
319     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
320     hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
321     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
322
323     IDirectDraw7_Release(ddraw);
324 }
325
326 static void test_process_vertices(void)
327 {
328     IDirect3DVertexBuffer7 *src_vb, *dst_vb1, *dst_vb2;
329     D3DVERTEXBUFFERDESC vb_desc;
330     IDirect3DDevice7 *device;
331     struct vec4 *dst_data;
332     struct vec3 *dst_data2;
333     struct vec3 *src_data;
334     IDirect3D7 *d3d7;
335     D3DVIEWPORT7 vp;
336     HWND window;
337     HRESULT hr;
338
339     static D3DMATRIX world =
340     {
341         0.0f,  1.0f, 0.0f, 0.0f,
342         1.0f,  0.0f, 0.0f, 0.0f,
343         0.0f,  0.0f, 0.0f, 1.0f,
344         0.0f,  1.0f, 1.0f, 1.0f,
345     };
346     static D3DMATRIX view =
347     {
348         2.0f,  0.0f, 0.0f, 0.0f,
349         0.0f, -1.0f, 0.0f, 0.0f,
350         0.0f,  0.0f, 1.0f, 0.0f,
351         0.0f,  0.0f, 0.0f, 3.0f,
352     };
353     static D3DMATRIX proj =
354     {
355         1.0f,  0.0f, 0.0f, 1.0f,
356         0.0f,  1.0f, 1.0f, 0.0f,
357         0.0f,  1.0f, 1.0f, 0.0f,
358         1.0f,  0.0f, 0.0f, 1.0f,
359     };
360
361     window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
362             0, 0, 640, 480, 0, 0, 0, 0);
363     if (!(device = create_device(window, DDSCL_NORMAL)))
364     {
365         skip("Failed to create a ddraw object, skipping test.\n");
366         DestroyWindow(window);
367         return;
368     }
369
370     hr = IDirect3DDevice7_GetDirect3D(device, &d3d7);
371     ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
372
373     memset(&vb_desc, 0, sizeof(vb_desc));
374     vb_desc.dwSize = sizeof(vb_desc);
375     vb_desc.dwFVF = D3DFVF_XYZ;
376     vb_desc.dwNumVertices = 4;
377     hr = IDirect3D7_CreateVertexBuffer(d3d7, &vb_desc, &src_vb, 0);
378     ok(SUCCEEDED(hr), "Failed to create source vertex buffer, hr %#x.\n", hr);
379
380     hr = IDirect3DVertexBuffer7_Lock(src_vb, 0, (void **)&src_data, NULL);
381     ok(SUCCEEDED(hr), "Failed to lock source vertex buffer, hr %#x.\n", hr);
382     src_data[0].x = 0.0f;
383     src_data[0].y = 0.0f;
384     src_data[0].z = 0.0f;
385     src_data[1].x = 1.0f;
386     src_data[1].y = 1.0f;
387     src_data[1].z = 1.0f;
388     src_data[2].x = -1.0f;
389     src_data[2].y = -1.0f;
390     src_data[2].z = 0.5f;
391     src_data[3].x = 0.5f;
392     src_data[3].y = -0.5f;
393     src_data[3].z = 0.25f;
394     hr = IDirect3DVertexBuffer7_Unlock(src_vb);
395     ok(SUCCEEDED(hr), "Failed to unlock source vertex buffer, hr %#x.\n", hr);
396
397     memset(&vb_desc, 0, sizeof(vb_desc));
398     vb_desc.dwSize = sizeof(vb_desc);
399     vb_desc.dwFVF = D3DFVF_XYZRHW;
400     vb_desc.dwNumVertices = 4;
401     /* MSDN says that the last parameter must be 0 - check that. */
402     hr = IDirect3D7_CreateVertexBuffer(d3d7, &vb_desc, &dst_vb1, 4);
403     ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
404
405     memset(&vb_desc, 0, sizeof(vb_desc));
406     vb_desc.dwSize = sizeof(vb_desc);
407     vb_desc.dwFVF = D3DFVF_XYZ;
408     vb_desc.dwNumVertices = 5;
409     /* MSDN says that the last parameter must be 0 - check that. */
410     hr = IDirect3D7_CreateVertexBuffer(d3d7, &vb_desc, &dst_vb2, 12345678);
411     ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
412
413     memset(&vp, 0, sizeof(vp));
414     vp.dwX = 64;
415     vp.dwY = 64;
416     vp.dwWidth = 128;
417     vp.dwHeight = 128;
418     vp.dvMinZ = 0.0f;
419     vp.dvMaxZ = 1.0f;
420     hr = IDirect3DDevice7_SetViewport(device, &vp);
421     ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
422
423     hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
424     ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
425     hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb2, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
426     ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
427
428     hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
429     ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
430     ok(compare_vec4(&dst_data[0], +1.280e+2f, +1.280e+2f, +0.000e+0f, +1.000e+0f, 4096),
431             "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
432             dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
433     ok(compare_vec4(&dst_data[1], +1.920e+2f, +6.400e+1f, +1.000e+0f, +1.000e+0f, 4096),
434             "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
435             dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
436     ok(compare_vec4(&dst_data[2], +6.400e+1f, +1.920e+2f, +5.000e-1f, +1.000e+0f, 4096),
437             "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
438             dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
439     ok(compare_vec4(&dst_data[3], +1.600e+2f, +1.600e+2f, +2.500e-1f, +1.000e+0f, 4096),
440             "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
441             dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
442     hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
443     ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
444
445     hr = IDirect3DVertexBuffer7_Lock(dst_vb2, 0, (void **)&dst_data2, NULL);
446     ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
447     /* Small thing without much practical meaning, but I stumbled upon it,
448      * so let's check for it: If the output vertex buffer has no RHW value,
449      * the RHW value of the last vertex is written into the next vertex. */
450     ok(compare_vec3(&dst_data2[4], +1.000e+0f, +0.000e+0f, +0.000e+0f, 4096),
451             "Got unexpected vertex 4 {%.8e, %.8e, %.8e}.\n",
452             dst_data2[4].x, dst_data2[4].y, dst_data2[4].z);
453     hr = IDirect3DVertexBuffer7_Unlock(dst_vb2);
454     ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
455
456     /* Try a more complicated viewport, same vertices. */
457     memset(&vp, 0, sizeof(vp));
458     vp.dwX = 10;
459     vp.dwY = 5;
460     vp.dwWidth = 246;
461     vp.dwHeight = 130;
462     vp.dvMinZ = -2.0f;
463     vp.dvMaxZ = 4.0f;
464     hr = IDirect3DDevice7_SetViewport(device, &vp);
465     ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
466
467     hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
468     ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
469
470     hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
471     ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
472     ok(compare_vec4(&dst_data[0], +1.330e+2f, +7.000e+1f, -2.000e+0f, +1.000e+0f, 4096),
473             "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
474             dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
475     ok(compare_vec4(&dst_data[1], +2.560e+2f, +5.000e+0f, +4.000e+0f, +1.000e+0f, 4096),
476             "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
477             dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
478     ok(compare_vec4(&dst_data[2], +1.000e+1f, +1.350e+2f, +1.000e+0f, +1.000e+0f, 4096),
479             "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
480             dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
481     ok(compare_vec4(&dst_data[3], +1.945e+2f, +1.025e+2f, -5.000e-1f, +1.000e+0f, 4096),
482             "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
483             dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
484     hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
485     ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
486
487     hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &world);
488     ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
489     hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &view);
490     ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
491     hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &proj);
492     ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
493
494     hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
495     ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
496
497     hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
498     ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
499     ok(compare_vec4(&dst_data[0], +2.560e+2f, +7.000e+1f, -2.000e+0f, +3.333e-1f, 4096),
500             "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
501             dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
502     ok(compare_vec4(&dst_data[1], +2.560e+2f, +7.813e+1f, -2.750e+0f, +1.250e-1f, 4096),
503             "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
504             dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
505     ok(compare_vec4(&dst_data[2], +2.560e+2f, +4.400e+1f, +4.000e-1f, +4.000e-1f, 4096),
506             "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
507             dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
508     ok(compare_vec4(&dst_data[3], +2.560e+2f, +8.182e+1f, -3.091e+0f, +3.636e-1f, 4096),
509             "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
510             dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
511     hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
512     ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
513
514     IDirect3DVertexBuffer7_Release(dst_vb2);
515     IDirect3DVertexBuffer7_Release(dst_vb1);
516     IDirect3DVertexBuffer7_Release(src_vb);
517     IDirect3D7_Release(d3d7);
518     IDirect3DDevice7_Release(device);
519     DestroyWindow(window);
520 }
521
522 static void test_coop_level_create_device_window(void)
523 {
524     HWND focus_window, device_window;
525     IDirectDraw7 *ddraw;
526     HRESULT hr;
527
528     focus_window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
529             0, 0, 640, 480, 0, 0, 0, 0);
530     if (!(ddraw = create_ddraw()))
531     {
532         skip("Failed to create a 3D device, skipping test.\n");
533         DestroyWindow(focus_window);
534         return;
535     }
536
537     hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
538     ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
539     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
540     ok(!device_window, "Unexpected device window found.\n");
541     hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
542     ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
543     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
544     ok(!device_window, "Unexpected device window found.\n");
545     hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
546     ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
547     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
548     ok(!device_window, "Unexpected device window found.\n");
549     hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
550     ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
551     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
552     ok(!device_window, "Unexpected device window found.\n");
553     hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
554     ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
555     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
556     ok(!device_window, "Unexpected device window found.\n");
557
558     /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
559     if (broken(hr == DDERR_INVALIDPARAMS))
560     {
561         win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
562         IDirectDraw7_Release(ddraw);
563         DestroyWindow(focus_window);
564         return;
565     }
566
567     hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
568     ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
569     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
570     ok(!device_window, "Unexpected device window found.\n");
571     hr = IDirectDraw7_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
572     ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
573     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
574     ok(!device_window, "Unexpected device window found.\n");
575
576     hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
577     ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
578     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
579     ok(!device_window, "Unexpected device window found.\n");
580     hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
581             | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
582     ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
583     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
584     ok(!!device_window, "Device window not found.\n");
585
586     hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
587     ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
588     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
589     ok(!device_window, "Unexpected device window found.\n");
590     hr = IDirectDraw7_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
591             | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
592     ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
593     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
594     ok(!!device_window, "Device window not found.\n");
595
596     hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
597     ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
598     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
599     ok(!device_window, "Unexpected device window found.\n");
600     hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
601     ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
602     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
603     ok(!device_window, "Unexpected device window found.\n");
604     hr = IDirectDraw7_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
605     ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
606     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
607     ok(!device_window, "Unexpected device window found.\n");
608     hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
609     ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
610     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
611     ok(!!device_window, "Device window not found.\n");
612
613     IDirectDraw7_Release(ddraw);
614     DestroyWindow(focus_window);
615 }
616
617 static void test_clipper_blt(void)
618 {
619     IDirectDrawSurface7 *src_surface, *dst_surface;
620     RECT client_rect, src_rect;
621     IDirectDrawClipper *clipper;
622     DDSURFACEDESC2 surface_desc;
623     unsigned int i, j, x, y;
624     IDirectDraw7 *ddraw;
625     RGNDATA *rgn_data;
626     D3DCOLOR color;
627     HRGN r1, r2;
628     HWND window;
629     DDBLTFX fx;
630     HRESULT hr;
631     DWORD *ptr;
632     DWORD ret;
633
634     static const DWORD src_data[] =
635     {
636         0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
637         0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
638         0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
639     };
640     static const D3DCOLOR expected1[] =
641     {
642         0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
643         0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
644         0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
645         0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
646     };
647     static const D3DCOLOR expected2[] =
648     {
649         0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
650         0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
651         0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
652         0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
653     };
654
655     window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
656             10, 10, 640, 480, 0, 0, 0, 0);
657     ShowWindow(window, SW_SHOW);
658     if (!(ddraw = create_ddraw()))
659     {
660         skip("Failed to create a ddraw object, skipping test.\n");
661         DestroyWindow(window);
662         return;
663     }
664
665     ret = GetClientRect(window, &client_rect);
666     ok(ret, "Failed to get client rect.\n");
667     ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
668     ok(ret, "Failed to map client rect.\n");
669
670     hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
671     ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
672
673     hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
674     ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
675     hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
676     ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
677     hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
678     ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
679     hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
680     ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
681     rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
682     hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
683     ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
684     ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
685     ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
686     ok(rgn_data->rdh.nCount >= 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
687     ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
688             "Got unexpected bounding rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
689             rgn_data->rdh.rcBound.left, rgn_data->rdh.rcBound.top,
690             rgn_data->rdh.rcBound.right, rgn_data->rdh.rcBound.bottom,
691             client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
692     HeapFree(GetProcessHeap(), 0, rgn_data);
693
694     r1 = CreateRectRgn(0, 0, 320, 240);
695     ok(!!r1, "Failed to create region.\n");
696     r2 = CreateRectRgn(320, 240, 640, 480);
697     ok(!!r2, "Failed to create region.\n");
698     CombineRgn(r1, r1, r2, RGN_OR);
699     ret = GetRegionData(r1, 0, NULL);
700     rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
701     ret = GetRegionData(r1, ret, rgn_data);
702     ok(!!ret, "Failed to get region data.\n");
703
704     DeleteObject(r2);
705     DeleteObject(r1);
706
707     hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
708     ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
709     hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
710     ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
711     hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
712     ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
713
714     HeapFree(GetProcessHeap(), 0, rgn_data);
715
716     memset(&surface_desc, 0, sizeof(surface_desc));
717     surface_desc.dwSize = sizeof(surface_desc);
718     surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
719     surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
720     surface_desc.dwWidth = 640;
721     surface_desc.dwHeight = 480;
722     U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
723     U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
724     U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
725     U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
726     U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
727     U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
728
729     hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
730     ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
731     hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
732     ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
733
734     memset(&fx, 0, sizeof(fx));
735     fx.dwSize = sizeof(fx);
736     hr = IDirectDrawSurface7_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
737     ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
738     hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
739     ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
740
741     hr = IDirectDrawSurface7_Lock(src_surface, NULL, &surface_desc, 0, NULL);
742     ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
743     ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
744     ptr = surface_desc.lpSurface;
745     memcpy(&ptr[   0], &src_data[ 0], 6 * sizeof(DWORD));
746     memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
747     memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
748     hr = IDirectDrawSurface7_Unlock(src_surface, NULL);
749     ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
750
751     hr = IDirectDrawSurface7_SetClipper(dst_surface, clipper);
752     ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
753
754     SetRect(&src_rect, 1, 1, 5, 2);
755     hr = IDirectDrawSurface7_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
756     ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
757     for (i = 0; i < 4; ++i)
758     {
759         for (j = 0; j < 4; ++j)
760         {
761             x = 80 * ((2 * j) + 1);
762             y = 60 * ((2 * i) + 1);
763             color = get_surface_color(dst_surface, x, y);
764             ok(compare_color(color, expected1[i * 4 + j], 1),
765                     "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
766         }
767     }
768
769     U5(fx).dwFillColor = 0xff0000ff;
770     hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
771     ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
772     for (i = 0; i < 4; ++i)
773     {
774         for (j = 0; j < 4; ++j)
775         {
776             x = 80 * ((2 * j) + 1);
777             y = 60 * ((2 * i) + 1);
778             color = get_surface_color(dst_surface, x, y);
779             ok(compare_color(color, expected2[i * 4 + j], 1),
780                     "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
781         }
782     }
783
784     hr = IDirectDrawSurface7_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
785     ok(hr == DDERR_BLTFASTCANTCLIP, "Got unexpected hr %#x.\n", hr);
786
787     hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
788     ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
789     hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
790     ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
791     DestroyWindow(window);
792     hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
793     ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
794     hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
795     ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
796     hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
797     ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
798     hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
799     ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
800     hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
801     ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
802     hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
803     ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
804
805     IDirectDrawSurface7_Release(dst_surface);
806     IDirectDrawSurface7_Release(src_surface);
807     IDirectDrawClipper_Release(clipper);
808     IDirectDraw7_Release(ddraw);
809 }
810
811 static void test_coop_level_d3d_state(void)
812 {
813     IDirectDrawSurface7 *rt, *surface;
814     IDirect3DDevice7 *device;
815     IDirectDraw7 *ddraw;
816     IDirect3D7 *d3d;
817     D3DCOLOR color;
818     DWORD value;
819     HWND window;
820     HRESULT hr;
821
822     window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
823             0, 0, 640, 480, 0, 0, 0, 0);
824     if (!(device = create_device(window, DDSCL_NORMAL)))
825     {
826         skip("Failed to create D3D device, skipping test.\n");
827         DestroyWindow(window);
828         return;
829     }
830
831     hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
832     ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
833     hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
834     ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
835     ok(!!value, "Got unexpected z-enable state %#x.\n", value);
836     hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
837     ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
838     ok(!value, "Got unexpected alpha blend enable state %#x.\n", value);
839     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
840     ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
841     hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
842     ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
843     color = get_surface_color(rt, 320, 240);
844     ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
845
846     hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
847     ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
848     hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
849     ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
850     IDirect3D7_Release(d3d);
851     hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
852     ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
853     hr = IDirectDrawSurface7_IsLost(rt);
854     ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
855     hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
856     ok(SUCCEEDED(hr), "Failed to restore surfaces, hr %#x.\n", hr);
857     IDirectDraw7_Release(ddraw);
858
859     hr = IDirect3DDevice7_GetRenderTarget(device, &surface);
860     ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
861     ok(surface == rt, "Got unexpected surface %p.\n", surface);
862     hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
863     ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
864     ok(!!value, "Got unexpected z-enable state %#x.\n", value);
865     hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
866     ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
867     ok(!!value, "Got unexpected alpha blend enable state %#x.\n", value);
868     hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
869     ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
870     color = get_surface_color(rt, 320, 240);
871     ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
872
873     IDirectDrawSurface7_Release(surface);
874     IDirectDrawSurface7_Release(rt);
875     IDirect3DDevice7_Release(device);
876     DestroyWindow(window);
877 }
878
879 static void test_surface_interface_mismatch(void)
880 {
881     IDirectDraw7 *ddraw = NULL;
882     IDirect3D7 *d3d = NULL;
883     IDirectDrawSurface7 *surface = NULL, *ds;
884     IDirectDrawSurface3 *surface3 = NULL;
885     IDirect3DDevice7 *device = NULL;
886     DDSURFACEDESC2 surface_desc;
887     DDPIXELFORMAT z_fmt;
888     ULONG refcount;
889     HRESULT hr;
890     D3DCOLOR color;
891     HWND window;
892
893     window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
894             0, 0, 640, 480, 0, 0, 0, 0);
895
896     if (!(ddraw = create_ddraw()))
897     {
898         skip("Failed to create a ddraw object, skipping test.\n");
899         goto cleanup;
900     }
901
902     hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
903     ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
904
905     memset(&surface_desc, 0, sizeof(surface_desc));
906     surface_desc.dwSize = sizeof(surface_desc);
907     surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
908     surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
909     surface_desc.dwWidth = 640;
910     surface_desc.dwHeight = 480;
911
912     hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
913     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
914
915     hr = IDirectDrawSurface7_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
916     ok(SUCCEEDED(hr), "Failed to QI IDirectDrawSurface3, hr %#x.\n", hr);
917
918     hr = IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d);
919     if (FAILED(hr))
920     {
921         skip("Failed to get the IDirect3D7 interface, skipping test.\n");
922         goto cleanup;
923     }
924
925     memset(&z_fmt, 0, sizeof(z_fmt));
926     hr = IDirect3D7_EnumZBufferFormats(d3d, &IID_IDirect3DTnLHalDevice, enum_z_fmt, &z_fmt);
927     if (FAILED(hr) || !z_fmt.dwSize)
928     {
929         skip("No depth buffer formats available, skipping test.\n");
930         goto cleanup;
931     }
932
933     memset(&surface_desc, 0, sizeof(surface_desc));
934     surface_desc.dwSize = sizeof(surface_desc);
935     surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
936     surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
937     U4(surface_desc).ddpfPixelFormat = z_fmt;
938     surface_desc.dwWidth = 640;
939     surface_desc.dwHeight = 480;
940     hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL);
941     ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
942     if (FAILED(hr))
943         goto cleanup;
944
945     /* Using a different surface interface version still works */
946     hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
947     ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
948     refcount = IDirectDrawSurface7_Release(ds);
949     ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
950     if (FAILED(hr))
951         goto cleanup;
952
953     /* Here too */
954     hr = IDirect3D7_CreateDevice(d3d, &IID_IDirect3DTnLHalDevice, (IDirectDrawSurface7 *)surface3, &device);
955     ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
956     if (FAILED(hr))
957         goto cleanup;
958
959     hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
960     ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
961     color = get_surface_color(surface, 320, 240);
962     ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
963
964 cleanup:
965     if (surface3) IDirectDrawSurface3_Release(surface3);
966     if (surface) IDirectDrawSurface7_Release(surface);
967     if (device) IDirect3DDevice7_Release(device);
968     if (d3d) IDirect3D7_Release(d3d);
969     if (ddraw) IDirectDraw7_Release(ddraw);
970     DestroyWindow(window);
971 }
972
973 static void test_coop_level_threaded(void)
974 {
975     struct create_window_thread_param p;
976     IDirectDraw7 *ddraw;
977     HRESULT hr;
978
979     if (!(ddraw = create_ddraw()))
980     {
981         skip("Failed to create a ddraw object, skipping test.\n");
982         return;
983     }
984     create_window_thread(&p);
985
986     hr = IDirectDraw7_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
987     ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
988
989     IDirectDraw7_Release(ddraw);
990     destroy_window_thread(&p);
991 }
992
993 static void test_depth_blit(void)
994 {
995     IDirect3DDevice7 *device;
996     static struct
997     {
998         float x, y, z;
999         DWORD color;
1000     }
1001     quad1[] =
1002     {
1003         { -1.0,  1.0, 0.50f, 0xff00ff00},
1004         {  1.0,  1.0, 0.50f, 0xff00ff00},
1005         { -1.0, -1.0, 0.50f, 0xff00ff00},
1006         {  1.0, -1.0, 0.50f, 0xff00ff00},
1007     };
1008     static const D3DCOLOR expected_colors[4][4] =
1009     {
1010         {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1011         {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1012         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1013         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1014     };
1015     DDSURFACEDESC2 ddsd_new, ddsd_existing;
1016
1017     IDirectDrawSurface7 *ds1, *ds2, *ds3, *rt;
1018     RECT src_rect, dst_rect;
1019     unsigned int i, j;
1020     D3DCOLOR color;
1021     HRESULT hr;
1022     IDirect3D7 *d3d;
1023     IDirectDraw7 *ddraw;
1024     DDBLTFX fx;
1025     HWND window;
1026
1027     window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1028             0, 0, 640, 480, 0, 0, 0, 0);
1029     if (!(device = create_device(window, DDSCL_NORMAL)))
1030     {
1031         skip("Failed to create D3D device, skipping test.\n");
1032         DestroyWindow(window);
1033         return;
1034     }
1035
1036     hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1037     ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
1038     hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1039     ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
1040     IDirect3D7_Release(d3d);
1041
1042     ds1 = get_depth_stencil(device);
1043
1044     memset(&ddsd_new, 0, sizeof(ddsd_new));
1045     ddsd_new.dwSize = sizeof(ddsd_new);
1046     memset(&ddsd_existing, 0, sizeof(ddsd_existing));
1047     ddsd_existing.dwSize = sizeof(ddsd_existing);
1048     hr = IDirectDrawSurface7_GetSurfaceDesc(ds1, &ddsd_existing);
1049     ddsd_new.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1050     ddsd_new.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1051     ddsd_new.dwWidth = ddsd_existing.dwWidth;
1052     ddsd_new.dwHeight = ddsd_existing.dwHeight;
1053     U4(ddsd_new).ddpfPixelFormat = U4(ddsd_existing).ddpfPixelFormat;
1054     hr = IDirectDraw7_CreateSurface(ddraw, &ddsd_new, &ds2, NULL);
1055     ok(SUCCEEDED(hr), "Failed to create a z buffer, hr %#x.\n", hr);
1056     hr = IDirectDraw7_CreateSurface(ddraw, &ddsd_new, &ds3, NULL);
1057     ok(SUCCEEDED(hr), "Failed to create a z buffer, hr %#x.\n", hr);
1058     IDirectDraw7_Release(ddraw);
1059
1060     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
1061     ok(SUCCEEDED(hr), "Failed to enable z testing, hr %#x.\n", hr);
1062     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
1063     ok(SUCCEEDED(hr), "Failed to set the z function, hr %#x.\n", hr);
1064     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
1065     ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
1066
1067     hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
1068     ok(SUCCEEDED(hr), "Failed to clear the z buffer, hr %#x.\n", hr);
1069
1070     /* Partial blit. */
1071     SetRect(&src_rect, 0, 0, 320, 240);
1072     SetRect(&dst_rect, 0, 0, 320, 240);
1073     hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1074     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1075     /* Different locations. */
1076     SetRect(&src_rect, 0, 0, 320, 240);
1077     SetRect(&dst_rect, 320, 240, 640, 480);
1078     hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1079     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1080     /* Streched. */
1081     SetRect(&src_rect, 0, 0, 320, 240);
1082     SetRect(&dst_rect, 0, 0, 640, 480);
1083     hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1084     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1085     /* Flipped. */
1086     SetRect(&src_rect, 0, 480, 640, 0);
1087     SetRect(&dst_rect, 0, 0, 640, 480);
1088     hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1089     ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1090     SetRect(&src_rect, 0, 0, 640, 480);
1091     SetRect(&dst_rect, 0, 480, 640, 0);
1092     hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1093     ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1094     /* Full, explicit. */
1095     SetRect(&src_rect, 0, 0, 640, 480);
1096     SetRect(&dst_rect, 0, 0, 640, 480);
1097     hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1098     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1099     /* Depth -> color blit: Succeeds on Win7 + Radeon HD 5700, fails on WinXP + Radeon X1600 */
1100
1101     /* Depth blit inside a BeginScene / EndScene pair */
1102     hr = IDirect3DDevice7_BeginScene(device);
1103     ok(SUCCEEDED(hr), "Failed to start scene, hr %#x.\n", hr);
1104     /* From the current depth stencil */
1105     hr = IDirectDrawSurface7_Blt(ds2, NULL, ds1, NULL, DDBLT_WAIT, NULL);
1106     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1107     /* To the current depth stencil */
1108     hr = IDirectDrawSurface7_Blt(ds1, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1109     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1110     /* Between unbound surfaces */
1111     hr = IDirectDrawSurface7_Blt(ds3, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1112     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1113     hr = IDirect3DDevice7_EndScene(device);
1114     ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1115
1116     /* Avoid changing the depth stencil, it doesn't work properly on Windows.
1117      * Instead use DDBLT_DEPTHFILL to clear the depth stencil. Unfortunately
1118      * drivers disagree on the meaning of dwFillDepth. Only 0 seems to produce
1119      * a reliable result(z = 0.0) */
1120     memset(&fx, 0, sizeof(fx));
1121     fx.dwSize = sizeof(fx);
1122     hr = IDirectDrawSurface7_Blt(ds2, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
1123     ok(SUCCEEDED(hr), "Failed to clear the source z buffer, hr %#x.\n", hr);
1124
1125     hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET, 0xffff0000, 1.0f, 0);
1126     ok(SUCCEEDED(hr), "Failed to clear the color and z buffers, hr %#x.\n", hr);
1127     SetRect(&dst_rect, 0, 0, 320, 240);
1128     hr = IDirectDrawSurface7_Blt(ds1, &dst_rect, ds2, NULL, DDBLT_WAIT, NULL);
1129     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1130     IDirectDrawSurface7_Release(ds3);
1131     IDirectDrawSurface7_Release(ds2);
1132     IDirectDrawSurface7_Release(ds1);
1133
1134     hr = IDirect3DDevice7_BeginScene(device);
1135     ok(SUCCEEDED(hr), "Failed to start scene, hr %#x.\n", hr);
1136     hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
1137             quad1, 4, 0);
1138     ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1139     hr = IDirect3DDevice7_EndScene(device);
1140     ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1141
1142     hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1143     ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1144     for (i = 0; i < 4; ++i)
1145     {
1146         for (j = 0; j < 4; ++j)
1147         {
1148             unsigned int x = 80 * ((2 * j) + 1);
1149             unsigned int y = 60 * ((2 * i) + 1);
1150             color = get_surface_color(rt, x, y);
1151             ok(compare_color(color, expected_colors[i][j], 1),
1152                     "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
1153         }
1154     }
1155
1156     IDirectDrawSurface7_Release(rt);
1157     IDirect3DDevice7_Release(device);
1158     DestroyWindow(window);
1159 }
1160
1161 static void test_texture_load_ckey(void)
1162 {
1163     HWND window;
1164     IDirect3DDevice7 *device;
1165     IDirectDraw7 *ddraw;
1166     IDirectDrawSurface7 *src;
1167     IDirectDrawSurface7 *dst;
1168     DDSURFACEDESC2 ddsd;
1169     HRESULT hr;
1170     DDCOLORKEY ckey;
1171     IDirect3D7 *d3d;
1172
1173     window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1174             0, 0, 640, 480, 0, 0, 0, 0);
1175     if (!(device = create_device(window, DDSCL_NORMAL)))
1176     {
1177         skip("Failed to create D3D device, skipping test.\n");
1178         DestroyWindow(window);
1179         return;
1180     }
1181
1182     hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1183     ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
1184     hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1185     ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
1186     IDirect3D7_Release(d3d);
1187
1188     memset(&ddsd, 0, sizeof(ddsd));
1189     ddsd.dwSize = sizeof(ddsd);
1190     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
1191     ddsd.dwHeight = 128;
1192     ddsd.dwWidth = 128;
1193     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
1194     hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &src, NULL);
1195     ok(SUCCEEDED(hr), "Failed to create source texture, hr %#x.\n", hr);
1196     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1197     hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &dst, NULL);
1198     ok(SUCCEEDED(hr), "Failed to create destination texture, hr %#x.\n", hr);
1199
1200     /* No surface has a color key */
1201     hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1202     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1203     ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0xdeadbeef;
1204     hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1205     ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1206     ok(ckey.dwColorSpaceLowValue == 0xdeadbeef, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1207     ok(ckey.dwColorSpaceHighValue == 0xdeadbeef, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1208
1209     /* Source surface has a color key */
1210     ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
1211     hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
1212     ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1213     hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1214     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1215     hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1216     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1217     ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1218     ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1219
1220     /* Both surfaces have a color key: Dest ckey is overwritten */
1221     ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x000000ff;
1222     hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1223     ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1224     hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1225     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1226     hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1227     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1228     ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1229     ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1230
1231     /* Only the destination has a color key: It is deleted. This behavior differs from
1232      * IDirect3DTexture(2)::Load */
1233     hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, NULL);
1234     ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1235     hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
1236     ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1237     hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1238     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1239     hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1240     todo_wine ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1241
1242     IDirectDrawSurface7_Release(dst);
1243     IDirectDrawSurface7_Release(src);
1244     IDirectDraw7_Release(ddraw);
1245     IDirect3DDevice7_Release(device);
1246 }
1247
1248 static void test_zenable(void)
1249 {
1250     static struct
1251     {
1252         struct vec4 position;
1253         D3DCOLOR diffuse;
1254     }
1255     tquad[] =
1256     {
1257         {{  0.0f, 480.0f, -0.5f, 1.0f}, 0xff00ff00},
1258         {{  0.0f,   0.0f, -0.5f, 1.0f}, 0xff00ff00},
1259         {{640.0f, 480.0f,  1.5f, 1.0f}, 0xff00ff00},
1260         {{640.0f,   0.0f,  1.5f, 1.0f}, 0xff00ff00},
1261     };
1262     IDirect3DDevice7 *device;
1263     IDirectDrawSurface7 *rt;
1264     D3DCOLOR color;
1265     HWND window;
1266     HRESULT hr;
1267     UINT x, y;
1268     UINT i, j;
1269
1270     window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1271             0, 0, 640, 480, 0, 0, 0, 0);
1272     if (!(device = create_device(window, DDSCL_NORMAL)))
1273     {
1274         skip("Failed to create D3D device, skipping test.\n");
1275         DestroyWindow(window);
1276         return;
1277     }
1278
1279     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1280     ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
1281
1282     hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 0.0f, 0);
1283     ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1284     hr = IDirect3DDevice7_BeginScene(device);
1285     ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1286     hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_DIFFUSE, tquad, 4, 0);
1287     ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1288     hr = IDirect3DDevice7_EndScene(device);
1289     ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1290
1291     hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1292     ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1293     for (i = 0; i < 4; ++i)
1294     {
1295         for (j = 0; j < 4; ++j)
1296         {
1297             x = 80 * ((2 * j) + 1);
1298             y = 60 * ((2 * i) + 1);
1299             color = get_surface_color(rt, x, y);
1300             ok(compare_color(color, 0x0000ff00, 1),
1301                     "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1302         }
1303     }
1304     IDirectDrawSurface7_Release(rt);
1305
1306     IDirect3DDevice7_Release(device);
1307     DestroyWindow(window);
1308 }
1309
1310 static void test_ck_rgba(void)
1311 {
1312     static struct
1313     {
1314         struct vec4 position;
1315         struct vec2 texcoord;
1316     }
1317     tquad[] =
1318     {
1319         {{  0.0f, 480.0f, 0.25f, 1.0f}, {0.0f, 0.0f}},
1320         {{  0.0f,   0.0f, 0.25f, 1.0f}, {0.0f, 1.0f}},
1321         {{640.0f, 480.0f, 0.25f, 1.0f}, {1.0f, 0.0f}},
1322         {{640.0f,   0.0f, 0.25f, 1.0f}, {1.0f, 1.0f}},
1323         {{  0.0f, 480.0f, 0.75f, 1.0f}, {0.0f, 0.0f}},
1324         {{  0.0f,   0.0f, 0.75f, 1.0f}, {0.0f, 1.0f}},
1325         {{640.0f, 480.0f, 0.75f, 1.0f}, {1.0f, 0.0f}},
1326         {{640.0f,   0.0f, 0.75f, 1.0f}, {1.0f, 1.0f}},
1327     };
1328     static const struct
1329     {
1330         D3DCOLOR fill_color;
1331         BOOL color_key;
1332         BOOL blend;
1333         D3DCOLOR result1;
1334         D3DCOLOR result2;
1335     }
1336     tests[] =
1337     {
1338         {0xff00ff00, TRUE,  TRUE,  0x00ff0000, 0x000000ff},
1339         {0xff00ff00, TRUE,  FALSE, 0x00ff0000, 0x000000ff},
1340         {0xff00ff00, FALSE, TRUE,  0x0000ff00, 0x0000ff00},
1341         {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00},
1342         {0x7f00ff00, TRUE,  TRUE,  0x00807f00, 0x00807f00},
1343         {0x7f00ff00, TRUE,  FALSE, 0x0000ff00, 0x0000ff00},
1344         {0x7f00ff00, FALSE, TRUE,  0x00807f00, 0x00807f00},
1345         {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00},
1346     };
1347
1348     IDirectDrawSurface7 *texture;
1349     DDSURFACEDESC2 surface_desc;
1350     IDirect3DDevice7 *device;
1351     IDirectDrawSurface7 *rt;
1352     IDirectDraw7 *ddraw;
1353     IDirect3D7 *d3d;
1354     D3DCOLOR color;
1355     HWND window;
1356     DDBLTFX fx;
1357     HRESULT hr;
1358     UINT i;
1359
1360     window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1361             0, 0, 640, 480, 0, 0, 0, 0);
1362     if (!(device = create_device(window, DDSCL_NORMAL)))
1363     {
1364         skip("Failed to create D3D device, skipping test.\n");
1365         DestroyWindow(window);
1366         return;
1367     }
1368
1369     hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1370     ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1371     hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1372     ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1373     IDirect3D7_Release(d3d);
1374
1375     memset(&surface_desc, 0, sizeof(surface_desc));
1376     surface_desc.dwSize = sizeof(surface_desc);
1377     surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1378     surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1379     surface_desc.dwWidth = 256;
1380     surface_desc.dwHeight = 256;
1381     U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1382     U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1383     U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1384     U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1385     U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1386     U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1387     U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1388     surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1389     surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1390     hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
1391     ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1392
1393     hr = IDirect3DDevice7_SetTexture(device, 0, texture);
1394     ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1395     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1396     ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1397     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1398     ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1399
1400     hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1401     ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1402
1403     for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
1404     {
1405         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1406         ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1407         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1408         ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1409
1410         memset(&fx, 0, sizeof(fx));
1411         fx.dwSize = sizeof(fx);
1412         U5(fx).dwFillColor = tests[i].fill_color;
1413         hr = IDirectDrawSurface7_Blt(texture, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1414         ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1415
1416         hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 1.0f, 0);
1417         ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1418         hr = IDirect3DDevice7_BeginScene(device);
1419         ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1420         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1421         ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1422         hr = IDirect3DDevice7_EndScene(device);
1423         ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1424
1425         color = get_surface_color(rt, 320, 240);
1426         if (i == 2)
1427             todo_wine ok(compare_color(color, tests[i].result1, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1428                     tests[i].result1, i, color);
1429         else
1430             ok(compare_color(color, tests[i].result1, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1431                     tests[i].result1, i, color);
1432
1433         U5(fx).dwFillColor = 0xff0000ff;
1434         hr = IDirectDrawSurface7_Blt(texture, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1435         ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1436
1437         hr = IDirect3DDevice7_BeginScene(device);
1438         ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1439         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[4], 4, 0);
1440         ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1441         hr = IDirect3DDevice7_EndScene(device);
1442         ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1443
1444         /* This tests that fragments that are masked out by the color key are
1445          * discarded, instead of just fully transparent. */
1446         color = get_surface_color(rt, 320, 240);
1447         if (i == 2)
1448             todo_wine ok(compare_color(color, tests[i].result2, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1449                     tests[i].result2, i, color);
1450         else
1451             ok(compare_color(color, tests[i].result2, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1452                     tests[i].result2, i, color);
1453     }
1454
1455     IDirectDrawSurface7_Release(rt);
1456     IDirectDrawSurface7_Release(texture);
1457     IDirectDraw7_Release(ddraw);
1458     IDirect3DDevice7_Release(device);
1459     DestroyWindow(window);
1460 }
1461
1462 static void test_ck_default(void)
1463 {
1464     static struct
1465     {
1466         struct vec4 position;
1467         struct vec2 texcoord;
1468     }
1469     tquad[] =
1470     {
1471         {{  0.0f, 480.0f, 0.0f, 1.0f}, {0.0f, 0.0f}},
1472         {{  0.0f,   0.0f, 0.0f, 1.0f}, {0.0f, 1.0f}},
1473         {{640.0f, 480.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
1474         {{640.0f,   0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
1475     };
1476     IDirectDrawSurface7 *surface, *rt;
1477     DDSURFACEDESC2 surface_desc;
1478     IDirect3DDevice7 *device;
1479     IDirectDraw7 *ddraw;
1480     IDirect3D7 *d3d;
1481     D3DCOLOR color;
1482     DWORD value;
1483     HWND window;
1484     DDBLTFX fx;
1485     HRESULT hr;
1486
1487     window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1488             0, 0, 640, 480, 0, 0, 0, 0);
1489
1490     if (!(device = create_device(window, DDSCL_NORMAL)))
1491     {
1492         skip("Failed to create D3D device, skipping test.\n");
1493         DestroyWindow(window);
1494         return;
1495     }
1496
1497     hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1498     ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1499     hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1500     ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1501     IDirect3D7_Release(d3d);
1502
1503     hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1504     ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1505
1506     memset(&surface_desc, 0, sizeof(surface_desc));
1507     surface_desc.dwSize = sizeof(surface_desc);
1508     surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1509     surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1510     surface_desc.dwWidth = 256;
1511     surface_desc.dwHeight = 256;
1512     U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1513     U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
1514     U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1515     U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1516     U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1517     U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1518     surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
1519     surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
1520     hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1521     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1522     hr = IDirect3DDevice7_SetTexture(device, 0, surface);
1523     ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1524
1525     memset(&fx, 0, sizeof(fx));
1526     fx.dwSize = sizeof(fx);
1527     U5(fx).dwFillColor = 0x000000ff;
1528     hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1529     ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
1530
1531     hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
1532     ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1533     hr = IDirect3DDevice7_BeginScene(device);
1534     ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1535     hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1536     ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1537     ok(!value, "Got unexpected color keying state %#x.\n", value);
1538     hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1539     ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1540     hr = IDirect3DDevice7_EndScene(device);
1541     ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1542     color = get_surface_color(rt, 320, 240);
1543     ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1544
1545     hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
1546     ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1547     hr = IDirect3DDevice7_BeginScene(device);
1548     ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1549     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
1550     ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1551     hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1552     ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1553     hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1554     ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1555     ok(!!value, "Got unexpected color keying state %#x.\n", value);
1556     hr = IDirect3DDevice7_EndScene(device);
1557     ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1558     color = get_surface_color(rt, 320, 240);
1559     ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1560
1561     IDirectDrawSurface7_Release(surface);
1562     IDirectDrawSurface7_Release(rt);
1563     IDirect3DDevice7_Release(device);
1564     IDirectDraw7_Release(ddraw);
1565     DestroyWindow(window);
1566 }
1567
1568 struct qi_test
1569 {
1570     REFIID iid;
1571     REFIID refcount_iid;
1572     HRESULT hr;
1573 };
1574
1575 static void test_qi(const char *test_name, IUnknown *base_iface,
1576         REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
1577 {
1578     ULONG refcount, expected_refcount;
1579     IUnknown *iface1, *iface2;
1580     HRESULT hr;
1581     UINT i, j;
1582
1583     for (i = 0; i < entry_count; ++i)
1584     {
1585         hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
1586         ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
1587         if (SUCCEEDED(hr))
1588         {
1589             for (j = 0; j < entry_count; ++j)
1590             {
1591                 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
1592                 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
1593                 if (SUCCEEDED(hr))
1594                 {
1595                     expected_refcount = 0;
1596                     if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
1597                         ++expected_refcount;
1598                     if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
1599                         ++expected_refcount;
1600                     refcount = IUnknown_Release(iface2);
1601                     ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
1602                             refcount, test_name, i, j, expected_refcount);
1603                 }
1604             }
1605
1606             expected_refcount = 0;
1607             if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
1608                 ++expected_refcount;
1609             refcount = IUnknown_Release(iface1);
1610             ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
1611                     refcount, test_name, i, expected_refcount);
1612         }
1613     }
1614 }
1615
1616 static void test_surface_qi(void)
1617 {
1618     static const struct qi_test tests[] =
1619     {
1620         {&IID_IDirect3DTexture2,        NULL,                           E_NOINTERFACE},
1621         {&IID_IDirect3DTexture,         NULL,                           E_NOINTERFACE},
1622         {&IID_IDirectDrawGammaControl,  &IID_IDirectDrawGammaControl,   S_OK         },
1623         {&IID_IDirectDrawColorControl,  NULL,                           E_NOINTERFACE},
1624         {&IID_IDirectDrawSurface7,      &IID_IDirectDrawSurface7,       S_OK         },
1625         {&IID_IDirectDrawSurface4,      &IID_IDirectDrawSurface4,       S_OK         },
1626         {&IID_IDirectDrawSurface3,      &IID_IDirectDrawSurface3,       S_OK         },
1627         {&IID_IDirectDrawSurface2,      &IID_IDirectDrawSurface2,       S_OK         },
1628         {&IID_IDirectDrawSurface,       &IID_IDirectDrawSurface,        S_OK         },
1629         {&IID_IDirect3DDevice7,         NULL,                           E_NOINTERFACE},
1630         {&IID_IDirect3DDevice3,         NULL,                           E_NOINTERFACE},
1631         {&IID_IDirect3DDevice2,         NULL,                           E_NOINTERFACE},
1632         {&IID_IDirect3DDevice,          NULL,                           E_NOINTERFACE},
1633         {&IID_IDirect3DRampDevice,      NULL,                           E_NOINTERFACE},
1634         {&IID_IDirect3DRGBDevice,       NULL,                           E_NOINTERFACE},
1635         {&IID_IDirect3DHALDevice,       NULL,                           E_NOINTERFACE},
1636         {&IID_IDirect3DMMXDevice,       NULL,                           E_NOINTERFACE},
1637         {&IID_IDirect3DRefDevice,       NULL,                           E_NOINTERFACE},
1638         {&IID_IDirect3DTnLHalDevice,    NULL,                           E_NOINTERFACE},
1639         {&IID_IDirect3DNullDevice,      NULL,                           E_NOINTERFACE},
1640         {&IID_IDirect3D7,               NULL,                           E_NOINTERFACE},
1641         {&IID_IDirect3D3,               NULL,                           E_NOINTERFACE},
1642         {&IID_IDirect3D2,               NULL,                           E_NOINTERFACE},
1643         {&IID_IDirect3D,                NULL,                           E_NOINTERFACE},
1644         {&IID_IDirectDraw7,             NULL,                           E_NOINTERFACE},
1645         {&IID_IDirectDraw4,             NULL,                           E_NOINTERFACE},
1646         {&IID_IDirectDraw3,             NULL,                           E_NOINTERFACE},
1647         {&IID_IDirectDraw2,             NULL,                           E_NOINTERFACE},
1648         {&IID_IDirectDraw,              NULL,                           E_NOINTERFACE},
1649         {&IID_IDirect3DLight,           NULL,                           E_NOINTERFACE},
1650         {&IID_IDirect3DMaterial,        NULL,                           E_NOINTERFACE},
1651         {&IID_IDirect3DMaterial2,       NULL,                           E_NOINTERFACE},
1652         {&IID_IDirect3DMaterial3,       NULL,                           E_NOINTERFACE},
1653         {&IID_IDirect3DExecuteBuffer,   NULL,                           E_NOINTERFACE},
1654         {&IID_IDirect3DViewport,        NULL,                           E_NOINTERFACE},
1655         {&IID_IDirect3DViewport2,       NULL,                           E_NOINTERFACE},
1656         {&IID_IDirect3DViewport3,       NULL,                           E_NOINTERFACE},
1657         {&IID_IDirect3DVertexBuffer,    NULL,                           E_NOINTERFACE},
1658         {&IID_IDirect3DVertexBuffer7,   NULL,                           E_NOINTERFACE},
1659         {&IID_IDirectDrawPalette,       NULL,                           E_NOINTERFACE},
1660         {&IID_IDirectDrawClipper,       NULL,                           E_NOINTERFACE},
1661         {&IID_IUnknown,                 &IID_IDirectDrawSurface,        S_OK         },
1662     };
1663
1664     IDirectDrawSurface7 *surface;
1665     DDSURFACEDESC2 surface_desc;
1666     IDirect3DDevice7 *device;
1667     IDirectDraw7 *ddraw;
1668     HWND window;
1669     HRESULT hr;
1670
1671     window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1672             0, 0, 640, 480, 0, 0, 0, 0);
1673     /* Try to create a D3D device to see if the ddraw implementation supports
1674      * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
1675      * doesn't support e.g. the IDirect3DTexture interfaces. */
1676     if (!(device = create_device(window, DDSCL_NORMAL)))
1677     {
1678         skip("Failed to create D3D device, skipping test.\n");
1679         DestroyWindow(window);
1680         return;
1681     }
1682     IDirect3DDevice_Release(device);
1683     if (!(ddraw = create_ddraw()))
1684     {
1685         skip("Failed to create a ddraw object, skipping test.\n");
1686         DestroyWindow(window);
1687         return;
1688     }
1689     hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1690     ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1691
1692     memset(&surface_desc, 0, sizeof(surface_desc));
1693     surface_desc.dwSize = sizeof(surface_desc);
1694     surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1695     surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1696     surface_desc.dwWidth = 512;
1697     surface_desc.dwHeight = 512;
1698     hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1699     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1700
1701     test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface7, tests, sizeof(tests) / sizeof(*tests));
1702
1703     IDirectDrawSurface7_Release(surface);
1704     IDirectDraw7_Release(ddraw);
1705     DestroyWindow(window);
1706 }
1707
1708 static void test_device_qi(void)
1709 {
1710     static const struct qi_test tests[] =
1711     {
1712         {&IID_IDirect3DTexture2,        NULL,                           E_NOINTERFACE},
1713         {&IID_IDirect3DTexture,         NULL,                           E_NOINTERFACE},
1714         {&IID_IDirectDrawGammaControl,  NULL,                           E_NOINTERFACE},
1715         {&IID_IDirectDrawColorControl,  NULL,                           E_NOINTERFACE},
1716         {&IID_IDirectDrawSurface7,      NULL,                           E_NOINTERFACE},
1717         {&IID_IDirectDrawSurface4,      NULL,                           E_NOINTERFACE},
1718         {&IID_IDirectDrawSurface3,      NULL,                           E_NOINTERFACE},
1719         {&IID_IDirectDrawSurface2,      NULL,                           E_NOINTERFACE},
1720         {&IID_IDirectDrawSurface,       NULL,                           E_NOINTERFACE},
1721         {&IID_IDirect3DDevice7,         &IID_IDirect3DDevice7,          S_OK         },
1722         {&IID_IDirect3DDevice3,         NULL,                           E_NOINTERFACE},
1723         {&IID_IDirect3DDevice2,         NULL,                           E_NOINTERFACE},
1724         {&IID_IDirect3DDevice,          NULL,                           E_NOINTERFACE},
1725         {&IID_IDirect3DRampDevice,      NULL,                           E_NOINTERFACE},
1726         {&IID_IDirect3DRGBDevice,       NULL,                           E_NOINTERFACE},
1727         {&IID_IDirect3DHALDevice,       NULL,                           E_NOINTERFACE},
1728         {&IID_IDirect3DMMXDevice,       NULL,                           E_NOINTERFACE},
1729         {&IID_IDirect3DRefDevice,       NULL,                           E_NOINTERFACE},
1730         {&IID_IDirect3DTnLHalDevice,    NULL,                           E_NOINTERFACE},
1731         {&IID_IDirect3DNullDevice,      NULL,                           E_NOINTERFACE},
1732         {&IID_IDirect3D7,               NULL,                           E_NOINTERFACE},
1733         {&IID_IDirect3D3,               NULL,                           E_NOINTERFACE},
1734         {&IID_IDirect3D2,               NULL,                           E_NOINTERFACE},
1735         {&IID_IDirect3D,                NULL,                           E_NOINTERFACE},
1736         {&IID_IDirectDraw7,             NULL,                           E_NOINTERFACE},
1737         {&IID_IDirectDraw4,             NULL,                           E_NOINTERFACE},
1738         {&IID_IDirectDraw3,             NULL,                           E_NOINTERFACE},
1739         {&IID_IDirectDraw2,             NULL,                           E_NOINTERFACE},
1740         {&IID_IDirectDraw,              NULL,                           E_NOINTERFACE},
1741         {&IID_IDirect3DLight,           NULL,                           E_NOINTERFACE},
1742         {&IID_IDirect3DMaterial,        NULL,                           E_NOINTERFACE},
1743         {&IID_IDirect3DMaterial2,       NULL,                           E_NOINTERFACE},
1744         {&IID_IDirect3DMaterial3,       NULL,                           E_NOINTERFACE},
1745         {&IID_IDirect3DExecuteBuffer,   NULL,                           E_NOINTERFACE},
1746         {&IID_IDirect3DViewport,        NULL,                           E_NOINTERFACE},
1747         {&IID_IDirect3DViewport2,       NULL,                           E_NOINTERFACE},
1748         {&IID_IDirect3DViewport3,       NULL,                           E_NOINTERFACE},
1749         {&IID_IDirect3DVertexBuffer,    NULL,                           E_NOINTERFACE},
1750         {&IID_IDirect3DVertexBuffer7,   NULL,                           E_NOINTERFACE},
1751         {&IID_IDirectDrawPalette,       NULL,                           E_NOINTERFACE},
1752         {&IID_IDirectDrawClipper,       NULL,                           E_NOINTERFACE},
1753         {&IID_IUnknown,                 &IID_IDirect3DDevice7,          S_OK         },
1754     };
1755
1756     IDirect3DDevice7 *device;
1757     HWND window;
1758
1759     window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1760             0, 0, 640, 480, 0, 0, 0, 0);
1761     if (!(device = create_device(window, DDSCL_NORMAL)))
1762     {
1763         skip("Failed to create D3D device, skipping test.\n");
1764         DestroyWindow(window);
1765         return;
1766     }
1767
1768     test_qi("device_qi", (IUnknown *)device, &IID_IDirect3DDevice7, tests, sizeof(tests) / sizeof(*tests));
1769
1770     IDirect3DDevice7_Release(device);
1771     DestroyWindow(window);
1772 }
1773
1774 static void test_wndproc(void)
1775 {
1776     LONG_PTR proc, ddraw_proc;
1777     IDirectDraw7 *ddraw;
1778     WNDCLASSA wc = {0};
1779     HWND window;
1780     HRESULT hr;
1781     ULONG ref;
1782
1783     static const UINT messages[] =
1784     {
1785         WM_WINDOWPOSCHANGING,
1786         WM_MOVE,
1787         WM_SIZE,
1788         WM_WINDOWPOSCHANGING,
1789         WM_ACTIVATE,
1790         WM_SETFOCUS,
1791         0,
1792     };
1793
1794     /* DDSCL_EXCLUSIVE replaces the window's window proc. */
1795     if (!(ddraw = create_ddraw()))
1796     {
1797         skip("Failed to create IDirectDraw7 object, skipping tests.\n");
1798         return;
1799     }
1800
1801     wc.lpfnWndProc = test_proc;
1802     wc.lpszClassName = "ddraw_test_wndproc_wc";
1803     ok(RegisterClassA(&wc), "Failed to register window class.\n");
1804
1805     window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
1806             WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
1807
1808     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1809     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1810             (LONG_PTR)test_proc, proc);
1811     expect_messages = messages;
1812     hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1813     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1814     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
1815     expect_messages = NULL;
1816     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1817     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1818             (LONG_PTR)test_proc, proc);
1819     ref = IDirectDraw7_Release(ddraw);
1820     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1821     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1822     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1823             (LONG_PTR)test_proc, proc);
1824
1825     /* DDSCL_NORMAL doesn't. */
1826     ddraw = create_ddraw();
1827     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1828     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1829             (LONG_PTR)test_proc, proc);
1830     hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
1831     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1832     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1833     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1834             (LONG_PTR)test_proc, proc);
1835     ref = IDirectDraw7_Release(ddraw);
1836     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1837     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1838     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1839             (LONG_PTR)test_proc, proc);
1840
1841     /* The original window proc is only restored by ddraw if the current
1842      * window proc matches the one ddraw set. This also affects switching
1843      * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
1844     ddraw = create_ddraw();
1845     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1846     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1847             (LONG_PTR)test_proc, proc);
1848     hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1849     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1850     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1851     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1852             (LONG_PTR)test_proc, proc);
1853     ddraw_proc = proc;
1854     hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1855     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1856     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1857     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1858             (LONG_PTR)test_proc, proc);
1859     hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1860     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1861     proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
1862     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1863             (LONG_PTR)test_proc, proc);
1864     hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1865     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1866     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1867     ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
1868             (LONG_PTR)DefWindowProcA, proc);
1869     hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1870     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1871     proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc);
1872     ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
1873             (LONG_PTR)DefWindowProcA, proc);
1874     ref = IDirectDraw7_Release(ddraw);
1875     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1876     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1877     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1878             (LONG_PTR)test_proc, proc);
1879
1880     ddraw = create_ddraw();
1881     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1882     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1883             (LONG_PTR)test_proc, proc);
1884     hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1885     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1886     proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
1887     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1888             (LONG_PTR)test_proc, proc);
1889     ref = IDirectDraw7_Release(ddraw);
1890     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1891     proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1892     ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
1893             (LONG_PTR)DefWindowProcA, proc);
1894
1895     fix_wndproc(window, (LONG_PTR)test_proc);
1896     expect_messages = NULL;
1897     DestroyWindow(window);
1898     UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
1899 }
1900
1901 static void test_window_style(void)
1902 {
1903     LONG style, exstyle, tmp;
1904     RECT fullscreen_rect, r;
1905     IDirectDraw7 *ddraw;
1906     HWND window;
1907     HRESULT hr;
1908     ULONG ref;
1909
1910     window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1911             0, 0, 100, 100, 0, 0, 0, 0);
1912     if (!(ddraw = create_ddraw()))
1913     {
1914         skip("Failed to create a ddraw object, skipping test.\n");
1915         DestroyWindow(window);
1916         return;
1917     }
1918
1919     style = GetWindowLongA(window, GWL_STYLE);
1920     exstyle = GetWindowLongA(window, GWL_EXSTYLE);
1921     SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
1922
1923     hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1924     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1925
1926     tmp = GetWindowLongA(window, GWL_STYLE);
1927     todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
1928     tmp = GetWindowLongA(window, GWL_EXSTYLE);
1929     todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
1930
1931     GetWindowRect(window, &r);
1932     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
1933             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
1934             r.left, r.top, r.right, r.bottom);
1935     GetClientRect(window, &r);
1936     todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
1937
1938     ref = IDirectDraw7_Release(ddraw);
1939     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1940
1941     DestroyWindow(window);
1942 }
1943
1944 static void test_redundant_mode_set(void)
1945 {
1946     DDSURFACEDESC2 surface_desc = {0};
1947     IDirectDraw7 *ddraw;
1948     HWND window;
1949     HRESULT hr;
1950     RECT r, s;
1951     ULONG ref;
1952
1953     window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1954             0, 0, 100, 100, 0, 0, 0, 0);
1955     if (!(ddraw = create_ddraw()))
1956     {
1957         skip("Failed to create a ddraw object, skipping test.\n");
1958         DestroyWindow(window);
1959         return;
1960     }
1961
1962     hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1963     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1964
1965     surface_desc.dwSize = sizeof(surface_desc);
1966     hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
1967     ok(SUCCEEDED(hr), "GetDipslayMode failed, hr %#x.\n", hr);
1968
1969     hr = IDirectDraw7_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
1970             U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
1971     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
1972
1973     GetWindowRect(window, &r);
1974     r.right /= 2;
1975     r.bottom /= 2;
1976     SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
1977     GetWindowRect(window, &s);
1978     ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
1979             r.left, r.top, r.right, r.bottom,
1980             s.left, s.top, s.right, s.bottom);
1981
1982     hr = IDirectDraw7_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
1983             U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
1984     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
1985
1986     GetWindowRect(window, &s);
1987     ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
1988             r.left, r.top, r.right, r.bottom,
1989             s.left, s.top, s.right, s.bottom);
1990
1991     ref = IDirectDraw7_Release(ddraw);
1992     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1993
1994     DestroyWindow(window);
1995 }
1996
1997 static SIZE screen_size;
1998
1999 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2000 {
2001     if (message == WM_SIZE)
2002     {
2003         screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2004         screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2005     }
2006
2007     return test_proc(hwnd, message, wparam, lparam);
2008 }
2009
2010 static void test_coop_level_mode_set(void)
2011 {
2012     IDirectDrawSurface7 *primary;
2013     RECT fullscreen_rect, r, s;
2014     IDirectDraw7 *ddraw;
2015     DDSURFACEDESC2 ddsd;
2016     WNDCLASSA wc = {0};
2017     HWND window;
2018     HRESULT hr;
2019     ULONG ref;
2020
2021     static const UINT exclusive_messages[] =
2022     {
2023         WM_WINDOWPOSCHANGING,
2024         WM_WINDOWPOSCHANGED,
2025         WM_SIZE,
2026         WM_DISPLAYCHANGE,
2027         0,
2028     };
2029
2030     static const UINT normal_messages[] =
2031     {
2032         WM_DISPLAYCHANGE,
2033         0,
2034     };
2035
2036     if (!(ddraw = create_ddraw()))
2037     {
2038         skip("Failed to create a ddraw object, skipping test.\n");
2039         return;
2040     }
2041
2042     wc.lpfnWndProc = mode_set_proc;
2043     wc.lpszClassName = "ddraw_test_wndproc_wc";
2044     ok(RegisterClassA(&wc), "Failed to register window class.\n");
2045
2046     window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
2047             0, 0, 100, 100, 0, 0, 0, 0);
2048
2049     SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2050     SetRect(&s, 0, 0, 640, 480);
2051
2052     hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2053     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2054
2055     GetWindowRect(window, &r);
2056     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2057             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2058             r.left, r.top, r.right, r.bottom);
2059
2060     memset(&ddsd, 0, sizeof(ddsd));
2061     ddsd.dwSize = sizeof(ddsd);
2062     ddsd.dwFlags = DDSD_CAPS;
2063     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2064
2065     hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2066     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2067     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2068     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2069     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2070             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2071     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2072             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2073
2074     GetWindowRect(window, &r);
2075     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2076             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2077             r.left, r.top, r.right, r.bottom);
2078
2079     expect_messages = exclusive_messages;
2080     screen_size.cx = 0;
2081     screen_size.cy = 0;
2082
2083     hr = IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 32, 0, 0);
2084     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2085
2086     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2087     expect_messages = NULL;
2088     ok(screen_size.cx == s.right && screen_size.cy == s.bottom,
2089             "Expected screen size %ux%u, got %ux%u.\n",
2090             s.right, s.bottom, screen_size.cx, screen_size.cy);
2091
2092     GetWindowRect(window, &r);
2093     ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2094             s.left, s.top, s.right, s.bottom,
2095             r.left, r.top, r.right, r.bottom);
2096
2097     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2098     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2099     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2100             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2101     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2102             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2103     IDirectDrawSurface7_Release(primary);
2104
2105     memset(&ddsd, 0, sizeof(ddsd));
2106     ddsd.dwSize = sizeof(ddsd);
2107     ddsd.dwFlags = DDSD_CAPS;
2108     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2109
2110     hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2111     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2112     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2113     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2114     ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2115             s.right - s.left, ddsd.dwWidth);
2116     ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2117             s.bottom - s.top, ddsd.dwHeight);
2118
2119     GetWindowRect(window, &r);
2120     ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2121             s.left, s.top, s.right, s.bottom,
2122             r.left, r.top, r.right, r.bottom);
2123
2124     expect_messages = exclusive_messages;
2125     screen_size.cx = 0;
2126     screen_size.cy = 0;
2127
2128     hr = IDirectDraw_RestoreDisplayMode(ddraw);
2129     ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2130
2131     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2132     expect_messages = NULL;
2133     ok(screen_size.cx == fullscreen_rect.right && screen_size.cy == fullscreen_rect.bottom,
2134             "Expected screen size %ux%u, got %ux%u.\n",
2135             fullscreen_rect.right, fullscreen_rect.bottom, screen_size.cx, screen_size.cy);
2136
2137     GetWindowRect(window, &r);
2138     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2139             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2140             r.left, r.top, r.right, r.bottom);
2141
2142     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2143     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2144     ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2145             s.right - s.left, ddsd.dwWidth);
2146     ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2147             s.bottom - s.top, ddsd.dwHeight);
2148     IDirectDrawSurface7_Release(primary);
2149
2150     memset(&ddsd, 0, sizeof(ddsd));
2151     ddsd.dwSize = sizeof(ddsd);
2152     ddsd.dwFlags = DDSD_CAPS;
2153     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2154
2155     hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2156     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2157     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2158     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2159     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2160             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2161     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2162             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2163
2164     GetWindowRect(window, &r);
2165     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2166             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2167             r.left, r.top, r.right, r.bottom);
2168
2169     hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2170     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2171
2172     GetWindowRect(window, &r);
2173     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2174             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2175             r.left, r.top, r.right, r.bottom);
2176
2177     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2178     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2179     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2180             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2181     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2182             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2183     IDirectDrawSurface7_Release(primary);
2184
2185     memset(&ddsd, 0, sizeof(ddsd));
2186     ddsd.dwSize = sizeof(ddsd);
2187     ddsd.dwFlags = DDSD_CAPS;
2188     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2189
2190     hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2191     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2192     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2193     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2194     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2195             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2196     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2197             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2198
2199     GetWindowRect(window, &r);
2200     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2201             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2202             r.left, r.top, r.right, r.bottom);
2203
2204     expect_messages = normal_messages;
2205     screen_size.cx = 0;
2206     screen_size.cy = 0;
2207
2208     hr = IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 32, 0, 0);
2209     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2210
2211     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2212     expect_messages = NULL;
2213     ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2214
2215     GetWindowRect(window, &r);
2216     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2217             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2218             r.left, r.top, r.right, r.bottom);
2219
2220     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2221     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2222     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2223             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2224     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2225             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2226     IDirectDrawSurface7_Release(primary);
2227
2228     memset(&ddsd, 0, sizeof(ddsd));
2229     ddsd.dwSize = sizeof(ddsd);
2230     ddsd.dwFlags = DDSD_CAPS;
2231     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2232
2233     hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2234     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2235     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2236     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2237     ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2238             s.right - s.left, ddsd.dwWidth);
2239     ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2240             s.bottom - s.top, ddsd.dwHeight);
2241
2242     GetWindowRect(window, &r);
2243     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2244             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2245             r.left, r.top, r.right, r.bottom);
2246
2247     expect_messages = normal_messages;
2248     screen_size.cx = 0;
2249     screen_size.cy = 0;
2250
2251     hr = IDirectDraw_RestoreDisplayMode(ddraw);
2252     ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2253
2254     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2255     expect_messages = NULL;
2256     ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2257
2258     GetWindowRect(window, &r);
2259     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2260             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2261             r.left, r.top, r.right, r.bottom);
2262
2263     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2264     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2265     ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2266             s.right - s.left, ddsd.dwWidth);
2267     ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2268             s.bottom - s.top, ddsd.dwHeight);
2269     IDirectDrawSurface7_Release(primary);
2270
2271     memset(&ddsd, 0, sizeof(ddsd));
2272     ddsd.dwSize = sizeof(ddsd);
2273     ddsd.dwFlags = DDSD_CAPS;
2274     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2275
2276     hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2277     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2278     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2279     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2280     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2281             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2282     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2283             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2284
2285     GetWindowRect(window, &r);
2286     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2287             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2288             r.left, r.top, r.right, r.bottom);
2289
2290     /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
2291      * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
2292      * not DDSCL_FULLSCREEN. */
2293     hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2294     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2295
2296     GetWindowRect(window, &r);
2297     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2298             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2299             r.left, r.top, r.right, r.bottom);
2300
2301     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2302     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2303     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2304             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2305     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2306             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2307     IDirectDrawSurface7_Release(primary);
2308
2309     memset(&ddsd, 0, sizeof(ddsd));
2310     ddsd.dwSize = sizeof(ddsd);
2311     ddsd.dwFlags = DDSD_CAPS;
2312     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2313
2314     hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2315     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2316     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2317     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2318     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2319             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2320     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2321             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2322
2323     GetWindowRect(window, &r);
2324     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2325             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2326             r.left, r.top, r.right, r.bottom);
2327
2328     expect_messages = normal_messages;
2329     screen_size.cx = 0;
2330     screen_size.cy = 0;
2331
2332     hr = IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 32, 0, 0);
2333     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2334
2335     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2336     expect_messages = NULL;
2337     ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2338
2339     GetWindowRect(window, &r);
2340     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2341             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2342             r.left, r.top, r.right, r.bottom);
2343
2344     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2345     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2346     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2347             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2348     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2349             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2350     IDirectDrawSurface7_Release(primary);
2351
2352     memset(&ddsd, 0, sizeof(ddsd));
2353     ddsd.dwSize = sizeof(ddsd);
2354     ddsd.dwFlags = DDSD_CAPS;
2355     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2356
2357     hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2358     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2359     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2360     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2361     ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2362             s.right - s.left, ddsd.dwWidth);
2363     ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2364             s.bottom - s.top, ddsd.dwHeight);
2365
2366     GetWindowRect(window, &r);
2367     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2368             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2369             r.left, r.top, r.right, r.bottom);
2370
2371     expect_messages = normal_messages;
2372     screen_size.cx = 0;
2373     screen_size.cy = 0;
2374
2375     hr = IDirectDraw_RestoreDisplayMode(ddraw);
2376     ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2377
2378     ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2379     expect_messages = NULL;
2380     ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2381
2382     GetWindowRect(window, &r);
2383     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2384             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2385             r.left, r.top, r.right, r.bottom);
2386
2387     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2388     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2389     ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2390             s.right - s.left, ddsd.dwWidth);
2391     ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2392             s.bottom - s.top, ddsd.dwHeight);
2393     IDirectDrawSurface7_Release(primary);
2394
2395     memset(&ddsd, 0, sizeof(ddsd));
2396     ddsd.dwSize = sizeof(ddsd);
2397     ddsd.dwFlags = DDSD_CAPS;
2398     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2399
2400     hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2401     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2402     hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2403     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2404     ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2405             fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2406     ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2407             fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2408     IDirectDrawSurface7_Release(primary);
2409
2410     GetWindowRect(window, &r);
2411     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2412             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2413             r.left, r.top, r.right, r.bottom);
2414
2415     ref = IDirectDraw7_Release(ddraw);
2416     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2417
2418     GetWindowRect(window, &r);
2419     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2420             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2421             r.left, r.top, r.right, r.bottom);
2422
2423     expect_messages = NULL;
2424     DestroyWindow(window);
2425     UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2426 }
2427
2428 static void test_coop_level_mode_set_multi(void)
2429 {
2430     IDirectDraw7 *ddraw1, *ddraw2;
2431     UINT orig_w, orig_h, w, h;
2432     HWND window;
2433     HRESULT hr;
2434     ULONG ref;
2435
2436     if (!(ddraw1 = create_ddraw()))
2437     {
2438         skip("Failed to create a ddraw object, skipping test.\n");
2439         return;
2440     }
2441
2442     window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2443             0, 0, 100, 100, 0, 0, 0, 0);
2444
2445     orig_w = GetSystemMetrics(SM_CXSCREEN);
2446     orig_h = GetSystemMetrics(SM_CYSCREEN);
2447
2448     /* With just a single ddraw object, the display mode is restored on
2449      * release. */
2450     hr = IDirectDraw7_SetDisplayMode(ddraw1, 800, 600, 32, 0, 0);
2451     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2452     w = GetSystemMetrics(SM_CXSCREEN);
2453     ok(w == 800, "Got unexpected screen width %u.\n", w);
2454     h = GetSystemMetrics(SM_CYSCREEN);
2455     ok(h == 600, "Got unexpected screen height %u.\n", h);
2456
2457     ref = IDirectDraw7_Release(ddraw1);
2458     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2459     w = GetSystemMetrics(SM_CXSCREEN);
2460     ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2461     h = GetSystemMetrics(SM_CYSCREEN);
2462     ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2463
2464     /* When there are multiple ddraw objects, the display mode is restored to
2465      * the initial mode, before the first SetDisplayMode() call. */
2466     ddraw1 = create_ddraw();
2467     hr = IDirectDraw7_SetDisplayMode(ddraw1, 800, 600, 32, 0, 0);
2468     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2469     w = GetSystemMetrics(SM_CXSCREEN);
2470     ok(w == 800, "Got unexpected screen width %u.\n", w);
2471     h = GetSystemMetrics(SM_CYSCREEN);
2472     ok(h == 600, "Got unexpected screen height %u.\n", h);
2473
2474     ddraw2 = create_ddraw();
2475     hr = IDirectDraw7_SetDisplayMode(ddraw2, 640, 480, 32, 0, 0);
2476     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2477     w = GetSystemMetrics(SM_CXSCREEN);
2478     ok(w == 640, "Got unexpected screen width %u.\n", w);
2479     h = GetSystemMetrics(SM_CYSCREEN);
2480     ok(h == 480, "Got unexpected screen height %u.\n", h);
2481
2482     ref = IDirectDraw7_Release(ddraw2);
2483     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2484     w = GetSystemMetrics(SM_CXSCREEN);
2485     ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2486     h = GetSystemMetrics(SM_CYSCREEN);
2487     ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2488
2489     ref = IDirectDraw7_Release(ddraw1);
2490     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2491     w = GetSystemMetrics(SM_CXSCREEN);
2492     ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2493     h = GetSystemMetrics(SM_CYSCREEN);
2494     ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2495
2496     /* Regardless of release ordering. */
2497     ddraw1 = create_ddraw();
2498     hr = IDirectDraw7_SetDisplayMode(ddraw1, 800, 600, 32, 0, 0);
2499     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2500     w = GetSystemMetrics(SM_CXSCREEN);
2501     ok(w == 800, "Got unexpected screen width %u.\n", w);
2502     h = GetSystemMetrics(SM_CYSCREEN);
2503     ok(h == 600, "Got unexpected screen height %u.\n", h);
2504
2505     ddraw2 = create_ddraw();
2506     hr = IDirectDraw7_SetDisplayMode(ddraw2, 640, 480, 32, 0, 0);
2507     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2508     w = GetSystemMetrics(SM_CXSCREEN);
2509     ok(w == 640, "Got unexpected screen width %u.\n", w);
2510     h = GetSystemMetrics(SM_CYSCREEN);
2511     ok(h == 480, "Got unexpected screen height %u.\n", h);
2512
2513     ref = IDirectDraw7_Release(ddraw1);
2514     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2515     w = GetSystemMetrics(SM_CXSCREEN);
2516     ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2517     h = GetSystemMetrics(SM_CYSCREEN);
2518     ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2519
2520     ref = IDirectDraw7_Release(ddraw2);
2521     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2522     w = GetSystemMetrics(SM_CXSCREEN);
2523     ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2524     h = GetSystemMetrics(SM_CYSCREEN);
2525     ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2526
2527     /* But only for ddraw objects that called SetDisplayMode(). */
2528     ddraw1 = create_ddraw();
2529     ddraw2 = create_ddraw();
2530     hr = IDirectDraw7_SetDisplayMode(ddraw2, 640, 480, 32, 0, 0);
2531     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2532     w = GetSystemMetrics(SM_CXSCREEN);
2533     ok(w == 640, "Got unexpected screen width %u.\n", w);
2534     h = GetSystemMetrics(SM_CYSCREEN);
2535     ok(h == 480, "Got unexpected screen height %u.\n", h);
2536
2537     ref = IDirectDraw7_Release(ddraw1);
2538     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2539     w = GetSystemMetrics(SM_CXSCREEN);
2540     ok(w == 640, "Got unexpected screen width %u.\n", w);
2541     h = GetSystemMetrics(SM_CYSCREEN);
2542     ok(h == 480, "Got unexpected screen height %u.\n", h);
2543
2544     ref = IDirectDraw7_Release(ddraw2);
2545     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2546     w = GetSystemMetrics(SM_CXSCREEN);
2547     ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2548     h = GetSystemMetrics(SM_CYSCREEN);
2549     ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2550
2551     /* If there's a ddraw object that's currently in exclusive mode, it blocks
2552      * restoring the display mode. */
2553     ddraw1 = create_ddraw();
2554     hr = IDirectDraw7_SetDisplayMode(ddraw1, 800, 600, 32, 0, 0);
2555     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2556     w = GetSystemMetrics(SM_CXSCREEN);
2557     ok(w == 800, "Got unexpected screen width %u.\n", w);
2558     h = GetSystemMetrics(SM_CYSCREEN);
2559     ok(h == 600, "Got unexpected screen height %u.\n", h);
2560
2561     ddraw2 = create_ddraw();
2562     hr = IDirectDraw7_SetDisplayMode(ddraw2, 640, 480, 32, 0, 0);
2563     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2564     w = GetSystemMetrics(SM_CXSCREEN);
2565     ok(w == 640, "Got unexpected screen width %u.\n", w);
2566     h = GetSystemMetrics(SM_CYSCREEN);
2567     ok(h == 480, "Got unexpected screen height %u.\n", h);
2568
2569     hr = IDirectDraw7_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2570     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2571
2572     ref = IDirectDraw7_Release(ddraw1);
2573     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2574     w = GetSystemMetrics(SM_CXSCREEN);
2575     ok(w == 640, "Got unexpected screen width %u.\n", w);
2576     h = GetSystemMetrics(SM_CYSCREEN);
2577     ok(h == 480, "Got unexpected screen height %u.\n", h);
2578
2579     ref = IDirectDraw7_Release(ddraw2);
2580     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2581     w = GetSystemMetrics(SM_CXSCREEN);
2582     ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2583     h = GetSystemMetrics(SM_CYSCREEN);
2584     ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2585
2586     /* Exclusive mode blocks mode setting on other ddraw objects in general. */
2587     ddraw1 = create_ddraw();
2588     hr = IDirectDraw7_SetDisplayMode(ddraw1, 800, 600, 32, 0, 0);
2589     ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2590     w = GetSystemMetrics(SM_CXSCREEN);
2591     ok(w == 800, "Got unexpected screen width %u.\n", w);
2592     h = GetSystemMetrics(SM_CYSCREEN);
2593     ok(h == 600, "Got unexpected screen height %u.\n", h);
2594
2595     hr = IDirectDraw7_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2596     ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2597
2598     ddraw2 = create_ddraw();
2599     hr = IDirectDraw7_SetDisplayMode(ddraw2, 640, 480, 32, 0, 0);
2600     ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
2601
2602     ref = IDirectDraw7_Release(ddraw1);
2603     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2604     w = GetSystemMetrics(SM_CXSCREEN);
2605     ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2606     h = GetSystemMetrics(SM_CYSCREEN);
2607     ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2608
2609     ref = IDirectDraw7_Release(ddraw2);
2610     ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2611     w = GetSystemMetrics(SM_CXSCREEN);
2612     ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2613     h = GetSystemMetrics(SM_CYSCREEN);
2614     ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2615
2616     DestroyWindow(window);
2617 }
2618
2619 static void test_initialize(void)
2620 {
2621     IDirectDraw7 *ddraw;
2622     HRESULT hr;
2623
2624     if (!(ddraw = create_ddraw()))
2625     {
2626         skip("Failed to create a ddraw object, skipping test.\n");
2627         return;
2628     }
2629
2630     hr = IDirectDraw7_Initialize(ddraw, NULL);
2631     ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
2632     IDirectDraw7_Release(ddraw);
2633
2634     CoInitialize(NULL);
2635     hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw7, (void **)&ddraw);
2636     ok(SUCCEEDED(hr), "Failed to create IDirectDraw7 instance, hr %#x.\n", hr);
2637     hr = IDirectDraw7_Initialize(ddraw, NULL);
2638     ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
2639     hr = IDirectDraw7_Initialize(ddraw, NULL);
2640     ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
2641     IDirectDraw7_Release(ddraw);
2642     CoUninitialize();
2643 }
2644
2645 static void test_coop_level_surf_create(void)
2646 {
2647     IDirectDrawSurface7 *surface;
2648     IDirectDraw7 *ddraw;
2649     DDSURFACEDESC2 ddsd;
2650     HRESULT hr;
2651
2652     if (!(ddraw = create_ddraw()))
2653     {
2654         skip("Failed to create a ddraw object, skipping test.\n");
2655         return;
2656     }
2657
2658     memset(&ddsd, 0, sizeof(ddsd));
2659     ddsd.dwSize = sizeof(ddsd);
2660     ddsd.dwFlags = DDSD_CAPS;
2661     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2662     hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
2663     ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
2664
2665     IDirectDraw7_Release(ddraw);
2666 }
2667
2668 static void test_vb_discard(void)
2669 {
2670     static const struct vec4 quad[] =
2671     {
2672         {  0.0f, 480.0f, 0.0f, 1.0f},
2673         {  0.0f,   0.0f, 0.0f, 1.0f},
2674         {640.0f, 480.0f, 0.0f, 1.0f},
2675         {640.0f,   0.0f, 0.0f, 1.0f},
2676     };
2677
2678     IDirect3DDevice7 *device;
2679     IDirect3D7 *d3d;
2680     IDirect3DVertexBuffer7 *buffer;
2681     HWND window;
2682     HRESULT hr;
2683     D3DVERTEXBUFFERDESC desc;
2684     BYTE *data;
2685     static const unsigned int vbsize = 16;
2686     unsigned int i;
2687
2688     window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2689             0, 0, 640, 480, 0, 0, 0, 0);
2690
2691     if (!(device = create_device(window, DDSCL_NORMAL)))
2692     {
2693         skip("Failed to create D3D device, skipping test.\n");
2694         DestroyWindow(window);
2695         return;
2696     }
2697
2698     hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
2699     ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
2700
2701     memset(&desc, 0, sizeof(desc));
2702     desc.dwSize = sizeof(desc);
2703     desc.dwCaps = D3DVBCAPS_WRITEONLY;
2704     desc.dwFVF = D3DFVF_XYZRHW;
2705     desc.dwNumVertices = vbsize;
2706     hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &buffer, 0);
2707     ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
2708
2709     hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
2710     ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
2711     memcpy(data, quad, sizeof(quad));
2712     hr = IDirect3DVertexBuffer7_Unlock(buffer);
2713     ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
2714
2715     hr = IDirect3DDevice7_BeginScene(device);
2716     ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
2717     hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
2718     ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
2719     hr = IDirect3DDevice7_EndScene(device);
2720     ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
2721
2722     hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
2723     ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
2724     memset(data, 0xaa, sizeof(struct vec4) * vbsize);
2725     hr = IDirect3DVertexBuffer7_Unlock(buffer);
2726     ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
2727
2728     hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
2729     ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
2730     for (i = 0; i < sizeof(struct vec4) * vbsize; i++)
2731     {
2732         if (data[i] != 0xaa)
2733         {
2734             ok(FALSE, "Vertex buffer data byte %u is 0x%02x, expected 0xaa\n", i, data[i]);
2735             break;
2736         }
2737     }
2738     hr = IDirect3DVertexBuffer7_Unlock(buffer);
2739     ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
2740
2741     IDirect3DVertexBuffer7_Release(buffer);
2742     IDirect3D7_Release(d3d);
2743     IDirect3DDevice7_Release(device);
2744     DestroyWindow(window);
2745 }
2746
2747 static void test_coop_level_multi_window(void)
2748 {
2749     HWND window1, window2;
2750     IDirectDraw7 *ddraw;
2751     HRESULT hr;
2752
2753     window1 = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
2754             0, 0, 640, 480, 0, 0, 0, 0);
2755     window2 = CreateWindowA("static", "ddraw_test2", WS_OVERLAPPEDWINDOW,
2756             0, 0, 640, 480, 0, 0, 0, 0);
2757     if (!(ddraw = create_ddraw()))
2758     {
2759         skip("Failed to create a ddraw object, skipping test.\n");
2760         DestroyWindow(window2);
2761         DestroyWindow(window1);
2762         return;
2763     }
2764
2765     hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
2766     ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2767     hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
2768     ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2769     ok(IsWindow(window1), "Window 1 was destroyed.\n");
2770     ok(IsWindow(window2), "Window 2 was destroyed.\n");
2771
2772     IDirectDraw7_Release(ddraw);
2773     DestroyWindow(window2);
2774     DestroyWindow(window1);
2775 }
2776
2777 START_TEST(ddraw7)
2778 {
2779     HMODULE module = GetModuleHandleA("ddraw.dll");
2780
2781     if (!(pDirectDrawCreateEx = (void *)GetProcAddress(module, "DirectDrawCreateEx")))
2782     {
2783         win_skip("DirectDrawCreateEx not available, skipping tests.\n");
2784         return;
2785     }
2786
2787     test_process_vertices();
2788     test_coop_level_create_device_window();
2789     test_clipper_blt();
2790     test_coop_level_d3d_state();
2791     test_surface_interface_mismatch();
2792     test_coop_level_threaded();
2793     test_depth_blit();
2794     test_texture_load_ckey();
2795     test_zenable();
2796     test_ck_rgba();
2797     test_ck_default();
2798     test_surface_qi();
2799     test_device_qi();
2800     test_wndproc();
2801     test_window_style();
2802     test_redundant_mode_set();
2803     test_coop_level_mode_set();
2804     test_coop_level_mode_set_multi();
2805     test_initialize();
2806     test_coop_level_surf_create();
2807     test_vb_discard();
2808     test_coop_level_multi_window();
2809 }