kernel32: GetModuleHandleEx already clears the module handle on failure.
[wine] / dlls / ddraw / tests / ddraw2.c
1 /*
2  * Copyright 2011-2012 Henri Verbeet for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 #define COBJMACROS
19
20 #include "wine/test.h"
21 #include "d3d.h"
22
23 struct create_window_thread_param
24 {
25     HWND window;
26     HANDLE window_created;
27     HANDLE destroy_window;
28     HANDLE thread;
29 };
30
31 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
32 {
33     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
34     c1 >>= 8; c2 >>= 8;
35     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
36     c1 >>= 8; c2 >>= 8;
37     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
38     c1 >>= 8; c2 >>= 8;
39     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
40     return TRUE;
41 }
42
43 static DWORD WINAPI create_window_thread_proc(void *param)
44 {
45     struct create_window_thread_param *p = param;
46     DWORD res;
47     BOOL ret;
48
49     p->window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
50             0, 0, 640, 480, 0, 0, 0, 0);
51     ret = SetEvent(p->window_created);
52     ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
53
54     for (;;)
55     {
56         MSG msg;
57
58         while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
59             DispatchMessage(&msg);
60         res = WaitForSingleObject(p->destroy_window, 100);
61         if (res == WAIT_OBJECT_0)
62             break;
63         if (res != WAIT_TIMEOUT)
64         {
65             ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
66             break;
67         }
68     }
69
70     DestroyWindow(p->window);
71
72     return 0;
73 }
74
75 static void create_window_thread(struct create_window_thread_param *p)
76 {
77     DWORD res, tid;
78
79     p->window_created = CreateEvent(NULL, FALSE, FALSE, NULL);
80     ok(!!p->window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
81     p->destroy_window = CreateEvent(NULL, FALSE, FALSE, NULL);
82     ok(!!p->destroy_window, "CreateEvent failed, last error %#x.\n", GetLastError());
83     p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
84     ok(!!p->thread, "Failed to create thread, last error %#x.\n", GetLastError());
85     res = WaitForSingleObject(p->window_created, INFINITE);
86     ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
87 }
88
89 static void destroy_window_thread(struct create_window_thread_param *p)
90 {
91     SetEvent(p->destroy_window);
92     WaitForSingleObject(p->thread, INFINITE);
93     CloseHandle(p->destroy_window);
94     CloseHandle(p->window_created);
95     CloseHandle(p->thread);
96 }
97
98 static IDirectDrawSurface *get_depth_stencil(IDirect3DDevice2 *device)
99 {
100     IDirectDrawSurface *rt, *ret;
101     DDSCAPS caps = {DDSCAPS_ZBUFFER};
102     HRESULT hr;
103
104     hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
105     ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
106     hr = IDirectDrawSurface_GetAttachedSurface(rt, &caps, &ret);
107     ok(SUCCEEDED(hr) || hr == DDERR_NOTFOUND, "Failed to get the z buffer, hr %#x.\n", hr);
108     IDirectDrawSurface_Release(rt);
109     return ret;
110 }
111
112 static D3DCOLOR get_surface_color(IDirectDrawSurface *surface, UINT x, UINT y)
113 {
114     RECT rect = {x, y, x + 1, y + 1};
115     DDSURFACEDESC surface_desc;
116     D3DCOLOR color;
117     HRESULT hr;
118
119     memset(&surface_desc, 0, sizeof(surface_desc));
120     surface_desc.dwSize = sizeof(surface_desc);
121
122     hr = IDirectDrawSurface_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
123     ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
124     if (FAILED(hr))
125         return 0xdeadbeef;
126
127     color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
128
129     hr = IDirectDrawSurface_Unlock(surface, NULL);
130     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
131
132     return color;
133 }
134
135 static HRESULT CALLBACK enum_z_fmt(GUID *guid, char *description, char *name,
136         D3DDEVICEDESC *hal_desc, D3DDEVICEDESC *hel_desc, void *ctx)
137 {
138     DWORD *z_depth = ctx;
139
140     if (!IsEqualGUID(&IID_IDirect3DHALDevice, guid))
141         return D3DENUMRET_OK;
142
143     if (hal_desc->dwDeviceZBufferBitDepth & DDBD_32)
144         *z_depth = 32;
145     else if (hal_desc->dwDeviceZBufferBitDepth & DDBD_24)
146         *z_depth = 24;
147     else if (hal_desc->dwDeviceZBufferBitDepth & DDBD_16)
148         *z_depth = 16;
149
150     return DDENUMRET_OK;
151 }
152
153 static IDirectDraw2 *create_ddraw(void)
154 {
155     IDirectDraw2 *ddraw2;
156     IDirectDraw *ddraw1;
157     HRESULT hr;
158
159     if (FAILED(DirectDrawCreate(NULL, &ddraw1, NULL)))
160         return NULL;
161
162     hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw2, (void **)&ddraw2);
163     IDirectDraw_Release(ddraw1);
164     if (FAILED(hr))
165         return NULL;
166
167     return ddraw2;
168 }
169
170 static IDirect3DDevice2 *create_device(IDirectDraw2 *ddraw, HWND window, DWORD coop_level)
171 {
172     IDirectDrawSurface *surface, *ds;
173     IDirect3DDevice2 *device = NULL;
174     DDSURFACEDESC surface_desc;
175     DWORD z_depth = 0;
176     IDirect3D2 *d3d;
177     HRESULT hr;
178
179     hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, coop_level);
180     ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
181
182     memset(&surface_desc, 0, sizeof(surface_desc));
183     surface_desc.dwSize = sizeof(surface_desc);
184     surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
185     surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
186     surface_desc.dwWidth = 640;
187     surface_desc.dwHeight = 480;
188
189     hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
190     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
191
192     if (coop_level & DDSCL_NORMAL)
193     {
194         IDirectDrawClipper *clipper;
195
196         hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
197         ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
198         hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
199         ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
200         hr = IDirectDrawSurface_SetClipper(surface, clipper);
201         ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\n", hr);
202         IDirectDrawClipper_Release(clipper);
203     }
204
205     hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d);
206     if (FAILED(hr))
207     {
208         IDirectDrawSurface_Release(surface);
209         return NULL;
210     }
211
212     hr = IDirect3D2_EnumDevices(d3d, enum_z_fmt, &z_depth);
213     ok(SUCCEEDED(hr), "Failed to enumerate z-formats, hr %#x.\n", hr);
214     if (FAILED(hr) || !z_depth)
215     {
216         IDirect3D2_Release(d3d);
217         IDirectDrawSurface_Release(surface);
218         return NULL;
219     }
220
221     memset(&surface_desc, 0, sizeof(surface_desc));
222     surface_desc.dwSize = sizeof(surface_desc);
223     surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
224     surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
225     U2(surface_desc).dwZBufferBitDepth = z_depth;
226     surface_desc.dwWidth = 640;
227     surface_desc.dwHeight = 480;
228     hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &ds, NULL);
229     ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
230     if (FAILED(hr))
231     {
232         IDirect3D2_Release(d3d);
233         IDirectDrawSurface_Release(surface);
234         return NULL;
235     }
236
237     hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
238     ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
239     IDirectDrawSurface_Release(ds);
240     if (FAILED(hr))
241     {
242         IDirect3D2_Release(d3d);
243         IDirectDrawSurface_Release(surface);
244         return NULL;
245     }
246
247     hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device);
248     IDirect3D2_Release(d3d);
249     IDirectDrawSurface_Release(surface);
250     if (FAILED(hr))
251         return NULL;
252
253     return device;
254 }
255
256 static IDirect3DViewport2 *create_viewport(IDirect3DDevice2 *device, UINT x, UINT y, UINT w, UINT h)
257 {
258     IDirect3DViewport2 *viewport;
259     D3DVIEWPORT2 vp;
260     IDirect3D2 *d3d;
261     HRESULT hr;
262
263     hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
264     ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
265     hr = IDirect3D2_CreateViewport(d3d, &viewport, NULL);
266     ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
267     hr = IDirect3DDevice2_AddViewport(device, viewport);
268     ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
269     memset(&vp, 0, sizeof(vp));
270     vp.dwSize = sizeof(vp);
271     vp.dwX = x;
272     vp.dwY = y;
273     vp.dwWidth = w;
274     vp.dwHeight = h;
275     vp.dvClipX = -1.0f;
276     vp.dvClipY =  1.0f;
277     vp.dvClipWidth = 2.0f;
278     vp.dvClipHeight = 2.0f;
279     vp.dvMinZ = 0.0f;
280     vp.dvMaxZ = 1.0f;
281     hr = IDirect3DViewport2_SetViewport2(viewport, &vp);
282     ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
283     IDirect3D2_Release(d3d);
284
285     return viewport;
286 }
287
288 static void destroy_viewport(IDirect3DDevice2 *device, IDirect3DViewport2 *viewport)
289 {
290     HRESULT hr;
291
292     hr = IDirect3DDevice2_DeleteViewport(device, viewport);
293     ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
294     IDirect3DViewport2_Release(viewport);
295 }
296
297 static HRESULT CALLBACK restore_callback(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
298 {
299     HRESULT hr = IDirectDrawSurface_Restore(surface);
300     ok(SUCCEEDED(hr), "Failed to restore surface, hr %#x.\n", hr);
301     IDirectDrawSurface_Release(surface);
302
303     return DDENUMRET_OK;
304 }
305
306 static HRESULT restore_surfaces(IDirectDraw2 *ddraw)
307 {
308     return IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
309             NULL, NULL, restore_callback);
310 }
311
312 static void test_coop_level_create_device_window(void)
313 {
314     HWND focus_window, device_window;
315     IDirectDraw2 *ddraw;
316     HRESULT hr;
317
318     focus_window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
319             0, 0, 640, 480, 0, 0, 0, 0);
320     if (!(ddraw = create_ddraw()))
321     {
322         skip("Failed to create a ddraw object, skipping test.\n");
323         DestroyWindow(focus_window);
324         return;
325     }
326
327     hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
328     ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
329     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
330     ok(!device_window, "Unexpected device window found.\n");
331     hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
332     ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
333     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
334     ok(!device_window, "Unexpected device window found.\n");
335     hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
336     ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
337     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
338     ok(!device_window, "Unexpected device window found.\n");
339     hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
340     ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
341     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
342     ok(!device_window, "Unexpected device window found.\n");
343     hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
344     ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
345     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
346     ok(!device_window, "Unexpected device window found.\n");
347
348     /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
349     if (broken(hr == DDERR_INVALIDPARAMS))
350     {
351         win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
352         IDirectDraw2_Release(ddraw);
353         DestroyWindow(focus_window);
354         return;
355     }
356
357     hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
358     ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
359     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
360     ok(!device_window, "Unexpected device window found.\n");
361     hr = IDirectDraw2_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
362     ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
363     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
364     ok(!device_window, "Unexpected device window found.\n");
365
366     hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
367     ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
368     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
369     ok(!device_window, "Unexpected device window found.\n");
370     hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
371             | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
372     ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
373     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
374     ok(!!device_window, "Device window not found.\n");
375
376     hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
377     ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
378     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
379     ok(!device_window, "Unexpected device window found.\n");
380     hr = IDirectDraw2_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
381             | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
382     ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
383     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
384     ok(!!device_window, "Device window not found.\n");
385
386     hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
387     ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
388     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
389     ok(!device_window, "Unexpected device window found.\n");
390     hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
391     ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
392     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
393     ok(!device_window, "Unexpected device window found.\n");
394     hr = IDirectDraw2_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
395     ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
396     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
397     ok(!device_window, "Unexpected device window found.\n");
398     hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
399     ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
400     device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
401     ok(!!device_window, "Device window not found.\n");
402
403     IDirectDraw2_Release(ddraw);
404     DestroyWindow(focus_window);
405 }
406
407 static void test_clipper_blt(void)
408 {
409     IDirectDrawSurface *src_surface, *dst_surface;
410     RECT client_rect, src_rect, *rect;
411     IDirectDrawClipper *clipper;
412     DDSURFACEDESC surface_desc;
413     unsigned int i, j, x, y;
414     IDirectDraw2 *ddraw;
415     RGNDATA *rgn_data;
416     D3DCOLOR color;
417     HRGN r1, r2;
418     HWND window;
419     DDBLTFX fx;
420     HRESULT hr;
421     DWORD *ptr;
422     DWORD ret;
423
424     static const DWORD src_data[] =
425     {
426         0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
427         0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
428         0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
429     };
430     static const D3DCOLOR expected1[] =
431     {
432         0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
433         0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
434         0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
435         0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
436     };
437     static const D3DCOLOR expected2[] =
438     {
439         0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
440         0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
441         0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
442         0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
443     };
444
445     window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
446             10, 10, 640, 480, 0, 0, 0, 0);
447     ShowWindow(window, SW_SHOW);
448     if (!(ddraw = create_ddraw()))
449     {
450         skip("Failed to create a ddraw object, skipping test.\n");
451         DestroyWindow(window);
452         return;
453     }
454
455     ret = GetClientRect(window, &client_rect);
456     ok(ret, "Failed to get client rect.\n");
457     ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
458     ok(ret, "Failed to map client rect.\n");
459
460     hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
461     ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
462
463     hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
464     ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
465     hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
466     ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
467     hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
468     ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
469     hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
470     ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
471     rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
472     hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
473     ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
474     ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
475     ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
476     ok(rgn_data->rdh.nCount == 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
477     ok(rgn_data->rdh.nRgnSize == 16 || broken(rgn_data->rdh.nRgnSize == 168 /* NT4 */),
478             "Got unexpected region size %u.\n", rgn_data->rdh.nRgnSize);
479     ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
480             "Got unexpected bounding rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
481             rgn_data->rdh.rcBound.left, rgn_data->rdh.rcBound.top,
482             rgn_data->rdh.rcBound.right, rgn_data->rdh.rcBound.bottom,
483             client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
484     rect = (RECT *)&rgn_data->Buffer[0];
485     ok(EqualRect(rect, &client_rect),
486             "Got unexpected clip rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
487             rect->left, rect->top, rect->right, rect->bottom,
488             client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
489     HeapFree(GetProcessHeap(), 0, rgn_data);
490
491     r1 = CreateRectRgn(0, 0, 320, 240);
492     ok(!!r1, "Failed to create region.\n");
493     r2 = CreateRectRgn(320, 240, 640, 480);
494     ok(!!r2, "Failed to create region.\n");
495     CombineRgn(r1, r1, r2, RGN_OR);
496     ret = GetRegionData(r1, 0, NULL);
497     rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
498     ret = GetRegionData(r1, ret, rgn_data);
499     ok(!!ret, "Failed to get region data.\n");
500
501     DeleteObject(r2);
502     DeleteObject(r1);
503
504     hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
505     ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
506     hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
507     ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
508     hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
509     ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
510
511     HeapFree(GetProcessHeap(), 0, rgn_data);
512
513     memset(&surface_desc, 0, sizeof(surface_desc));
514     surface_desc.dwSize = sizeof(surface_desc);
515     surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
516     surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
517     surface_desc.dwWidth = 640;
518     surface_desc.dwHeight = 480;
519     surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
520     surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
521     U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
522     U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
523     U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
524     U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
525
526     hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
527     ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
528     hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
529     ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
530
531     memset(&fx, 0, sizeof(fx));
532     fx.dwSize = sizeof(fx);
533     hr = IDirectDrawSurface_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
534     ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
535     hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
536     ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
537
538     hr = IDirectDrawSurface_Lock(src_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
539     ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
540     ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
541     ptr = surface_desc.lpSurface;
542     memcpy(&ptr[   0], &src_data[ 0], 6 * sizeof(DWORD));
543     memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
544     memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
545     hr = IDirectDrawSurface_Unlock(src_surface, NULL);
546     ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
547
548     hr = IDirectDrawSurface_SetClipper(dst_surface, clipper);
549     ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
550
551     SetRect(&src_rect, 1, 1, 5, 2);
552     hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
553     ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
554     for (i = 0; i < 4; ++i)
555     {
556         for (j = 0; j < 4; ++j)
557         {
558             x = 80 * ((2 * j) + 1);
559             y = 60 * ((2 * i) + 1);
560             color = get_surface_color(dst_surface, x, y);
561             ok(compare_color(color, expected1[i * 4 + j], 1),
562                     "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
563         }
564     }
565
566     U5(fx).dwFillColor = 0xff0000ff;
567     hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
568     ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
569     for (i = 0; i < 4; ++i)
570     {
571         for (j = 0; j < 4; ++j)
572         {
573             x = 80 * ((2 * j) + 1);
574             y = 60 * ((2 * i) + 1);
575             color = get_surface_color(dst_surface, x, y);
576             ok(compare_color(color, expected2[i * 4 + j], 1),
577                     "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
578         }
579     }
580
581     hr = IDirectDrawSurface_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
582     ok(hr == DDERR_BLTFASTCANTCLIP || broken(hr == E_NOTIMPL /* NT4 */), "Got unexpected hr %#x.\n", hr);
583
584     hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
585     ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
586     hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
587     ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
588     DestroyWindow(window);
589     hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
590     ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
591     hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
592     ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
593     hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
594     ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
595     hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
596     ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
597     hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
598     ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
599     hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
600     ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
601
602     IDirectDrawSurface_Release(dst_surface);
603     IDirectDrawSurface_Release(src_surface);
604     IDirectDrawClipper_Release(clipper);
605     IDirectDraw2_Release(ddraw);
606 }
607
608 static void test_coop_level_d3d_state(void)
609 {
610     D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
611     D3DMATERIALHANDLE background_handle;
612     IDirectDrawSurface *rt, *surface;
613     IDirect3DMaterial2 *background;
614     IDirect3DViewport2 *viewport;
615     IDirect3DDevice2 *device;
616     D3DMATERIAL material;
617     IDirectDraw2 *ddraw;
618     IDirect3D2 *d3d;
619     D3DCOLOR color;
620     DWORD value;
621     HWND window;
622     HRESULT hr;
623
624     window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
625             0, 0, 640, 480, 0, 0, 0, 0);
626     if (!(ddraw = create_ddraw()))
627     {
628         skip("Failed to create ddraw object, skipping test.\n");
629         DestroyWindow(window);
630         return;
631     }
632     if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
633     {
634         skip("Failed to create D3D device, skipping test.\n");
635         IDirectDraw2_Release(ddraw);
636         DestroyWindow(window);
637         return;
638     }
639
640     hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
641     ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
642     hr = IDirect3D2_CreateMaterial(d3d, &background, NULL);
643     ok(SUCCEEDED(hr), "Failed to create material, hr %#x.\n", hr);
644     IDirect3D2_Release(d3d);
645
646     viewport = create_viewport(device, 0, 0, 640, 480);
647
648     memset(&material, 0, sizeof(material));
649     material.dwSize = sizeof(material);
650     U1(U(material).diffuse).r = 1.0f;
651     U2(U(material).diffuse).g = 0.0f;
652     U3(U(material).diffuse).b = 0.0f;
653     U4(U(material).diffuse).a = 1.0f;
654     hr = IDirect3DMaterial2_SetMaterial(background, &material);
655     ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
656     hr = IDirect3DMaterial2_GetHandle(background, device, &background_handle);
657     ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
658     hr = IDirect3DViewport2_SetBackground(viewport, background_handle);
659     ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
660
661     hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
662     ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
663     hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
664     ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
665     ok(!!value, "Got unexpected z-enable state %#x.\n", value);
666     hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
667     ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
668     ok(!value, "Got unexpected alpha blend enable state %#x.\n", value);
669     hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
670     ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
671     hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
672     ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
673     color = get_surface_color(rt, 320, 240);
674     ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
675
676     hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
677     ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
678     hr = IDirectDrawSurface_IsLost(rt);
679     ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
680     hr = restore_surfaces(ddraw);
681     ok(SUCCEEDED(hr), "Failed to restore surfaces, hr %#x.\n", hr);
682
683     memset(&material, 0, sizeof(material));
684     material.dwSize = sizeof(material);
685     U1(U(material).diffuse).r = 0.0f;
686     U2(U(material).diffuse).g = 1.0f;
687     U3(U(material).diffuse).b = 0.0f;
688     U4(U(material).diffuse).a = 1.0f;
689     hr = IDirect3DMaterial2_SetMaterial(background, &material);
690     ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
691
692     hr = IDirect3DDevice2_GetRenderTarget(device, &surface);
693     ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
694     ok(surface == rt, "Got unexpected surface %p.\n", surface);
695     hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
696     ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
697     ok(!!value, "Got unexpected z-enable state %#x.\n", value);
698     hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
699     ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
700     ok(!!value, "Got unexpected alpha blend enable state %#x.\n", value);
701     hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
702     ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
703     color = get_surface_color(rt, 320, 240);
704     ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
705
706     destroy_viewport(device, viewport);
707     IDirect3DMaterial2_Release(background);
708     IDirectDrawSurface_Release(surface);
709     IDirectDrawSurface_Release(rt);
710     IDirect3DDevice2_Release(device);
711     IDirectDraw2_Release(ddraw);
712     DestroyWindow(window);
713 }
714
715 static void test_surface_interface_mismatch(void)
716 {
717     IDirectDraw2 *ddraw = NULL;
718     IDirect3D2 *d3d = NULL;
719     IDirectDrawSurface *surface = NULL, *ds;
720     IDirectDrawSurface3 *surface3 = NULL;
721     IDirect3DDevice2 *device = NULL;
722     IDirect3DViewport2 *viewport = NULL;
723     IDirect3DMaterial2 *background = NULL;
724     DDSURFACEDESC surface_desc;
725     DWORD z_depth = 0;
726     ULONG refcount;
727     HRESULT hr;
728     D3DCOLOR color;
729     HWND window;
730     D3DMATERIAL material;
731     D3DMATERIALHANDLE background_handle;
732     D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
733
734     window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
735             0, 0, 640, 480, 0, 0, 0, 0);
736
737     if (!(ddraw = create_ddraw()))
738     {
739         skip("Failed to create a ddraw object, skipping test.\n");
740         goto cleanup;
741     }
742
743     hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
744     ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
745
746     memset(&surface_desc, 0, sizeof(surface_desc));
747     surface_desc.dwSize = sizeof(surface_desc);
748     surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
749     surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
750     surface_desc.dwWidth = 640;
751     surface_desc.dwHeight = 480;
752
753     hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
754     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
755
756     hr = IDirectDrawSurface2_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
757     if (FAILED(hr))
758     {
759         skip("Failed to get the IDirectDrawSurface3 interface, skipping test.\n");
760         goto cleanup;
761     }
762
763     hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d);
764     if (FAILED(hr))
765     {
766         skip("Failed to get the IDirect3D2 interface, skipping test.\n");
767         goto cleanup;
768     }
769
770     hr = IDirect3D2_EnumDevices(d3d, enum_z_fmt, &z_depth);
771     if (FAILED(hr) || !z_depth)
772     {
773         skip("No depth buffer formats available, skipping test.\n");
774         goto cleanup;
775     }
776
777     memset(&surface_desc, 0, sizeof(surface_desc));
778     surface_desc.dwSize = sizeof(surface_desc);
779     surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
780     surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
781     U2(surface_desc).dwZBufferBitDepth = z_depth;
782     surface_desc.dwWidth = 640;
783     surface_desc.dwHeight = 480;
784     hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &ds, NULL);
785     ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
786     if (FAILED(hr))
787         goto cleanup;
788
789     /* Using a different surface interface version still works */
790     hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
791     ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
792     refcount = IDirectDrawSurface_Release(ds);
793     ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
794     if (FAILED(hr))
795         goto cleanup;
796
797     /* Here too */
798     hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, (IDirectDrawSurface *)surface3, &device);
799     ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
800     if (FAILED(hr))
801         goto cleanup;
802
803     hr = IDirect3D2_CreateMaterial(d3d, &background, NULL);
804     ok(SUCCEEDED(hr), "Failed to create material, hr %#x.\n", hr);
805
806     viewport = create_viewport(device, 0, 0, 640, 480);
807
808     memset(&material, 0, sizeof(material));
809     material.dwSize = sizeof(material);
810     U1(U(material).diffuse).r = 1.0f;
811     U2(U(material).diffuse).g = 0.0f;
812     U3(U(material).diffuse).b = 0.0f;
813     U4(U(material).diffuse).a = 1.0f;
814     hr = IDirect3DMaterial2_SetMaterial(background, &material);
815     ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
816     hr = IDirect3DMaterial2_GetHandle(background, device, &background_handle);
817     ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
818     hr = IDirect3DViewport2_SetBackground(viewport, background_handle);
819     ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
820
821     hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
822     ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
823     color = get_surface_color(surface, 320, 240);
824     ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
825
826 cleanup:
827     if (viewport)
828         destroy_viewport(device, viewport);
829     if (background) IDirect3DMaterial2_Release(background);
830     if (surface3) IDirectDrawSurface3_Release(surface3);
831     if (surface) IDirectDrawSurface_Release(surface);
832     if (device) IDirect3DDevice2_Release(device);
833     if (d3d) IDirect3D2_Release(d3d);
834     if (ddraw) IDirectDraw2_Release(ddraw);
835     DestroyWindow(window);
836 }
837
838 static void test_coop_level_threaded(void)
839 {
840     struct create_window_thread_param p;
841     IDirectDraw2 *ddraw;
842     HRESULT hr;
843
844     if (!(ddraw = create_ddraw()))
845     {
846         skip("Failed to create a ddraw object, skipping test.\n");
847         return;
848     }
849     create_window_thread(&p);
850
851     hr = IDirectDraw2_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
852     ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
853
854     IDirectDraw2_Release(ddraw);
855     destroy_window_thread(&p);
856 }
857
858 static void test_depth_blit(void)
859 {
860     static D3DLVERTEX quad1[] =
861     {
862         {{-1.0}, { 1.0}, {0.50f}, 0, {0xff00ff00}},
863         {{ 1.0}, { 1.0}, {0.50f}, 0, {0xff00ff00}},
864         {{-1.0}, {-1.0}, {0.50f}, 0, {0xff00ff00}},
865         {{ 1.0}, {-1.0}, {0.50f}, 0, {0xff00ff00}},
866     };
867     static const D3DCOLOR expected_colors[4][4] =
868     {
869         {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
870         {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
871         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
872         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
873     };
874     static const BOOL todo[4][4] =
875     {
876         {FALSE, FALSE, TRUE, TRUE},
877         {FALSE, FALSE, TRUE, TRUE},
878         {TRUE,  TRUE,  TRUE, TRUE},
879         {TRUE,  TRUE,  TRUE, TRUE},
880     };
881     DDSURFACEDESC ddsd_new, ddsd_existing;
882
883     IDirect3DDevice2 *device;
884     IDirectDrawSurface *ds1, *ds2, *ds3, *rt;
885     IDirect3DViewport2 *viewport;
886     RECT src_rect, dst_rect;
887     unsigned int i, j;
888     D3DCOLOR color;
889     HRESULT hr;
890     IDirect3D2 *d3d;
891     IDirectDraw2 *ddraw;
892     DDBLTFX fx;
893     HWND window;
894     D3DRECT d3drect;
895     IDirect3DMaterial2 *background;
896     D3DMATERIALHANDLE background_handle;
897     D3DMATERIAL material;
898
899     window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
900             0, 0, 640, 480, 0, 0, 0, 0);
901     if (!(ddraw = create_ddraw()))
902     {
903         skip("Failed to create ddraw object, skipping test.\n");
904         DestroyWindow(window);
905         return;
906     }
907     if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
908     {
909         skip("Failed to create D3D device, skipping test.\n");
910         IDirectDraw2_Release(ddraw);
911         DestroyWindow(window);
912         return;
913     }
914
915     hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d);
916     ok(SUCCEEDED(hr), "Failed to get Direct3D2 interface, hr %#x.\n", hr);
917     hr = IDirect3D2_CreateMaterial(d3d, &background, NULL);
918     ok(SUCCEEDED(hr), "Failed to create a material, hr %#x.\n", hr);
919
920     ds1 = get_depth_stencil(device);
921
922     memset(&ddsd_new, 0, sizeof(ddsd_new));
923     ddsd_new.dwSize = sizeof(ddsd_new);
924     memset(&ddsd_existing, 0, sizeof(ddsd_existing));
925     ddsd_existing.dwSize = sizeof(ddsd_existing);
926     hr = IDirectDrawSurface_GetSurfaceDesc(ds1, &ddsd_existing);
927     ddsd_new.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
928     ddsd_new.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
929     ddsd_new.dwWidth = ddsd_existing.dwWidth;
930     ddsd_new.dwHeight = ddsd_existing.dwHeight;
931     ddsd_new.ddpfPixelFormat = ddsd_existing.ddpfPixelFormat;
932     hr = IDirectDraw2_CreateSurface(ddraw, &ddsd_new, &ds2, NULL);
933     ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
934     hr = IDirectDraw2_CreateSurface(ddraw, &ddsd_new, &ds3, NULL);
935     ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
936
937     viewport = create_viewport(device, 0, 0, ddsd_existing.dwWidth, ddsd_existing.dwHeight);
938     hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
939     ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
940
941     memset(&material, 0, sizeof(material));
942     material.dwSize = sizeof(material);
943     U1(U(material).diffuse).r = 1.0f;
944     U2(U(material).diffuse).g = 0.0f;
945     U3(U(material).diffuse).b = 0.0f;
946     U4(U(material).diffuse).a = 1.0f;
947     hr = IDirect3DMaterial2_SetMaterial(background, &material);
948     ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
949     hr = IDirect3DMaterial2_GetHandle(background, device, &background_handle);
950     ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
951     hr = IDirect3DViewport2_SetBackground(viewport, background_handle);
952     ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
953
954     hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
955     ok(SUCCEEDED(hr), "Failed to enable z testing, hr %#x.\n", hr);
956     hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
957     ok(SUCCEEDED(hr), "Failed to set the z function, hr %#x.\n", hr);
958
959     U1(d3drect).x1 = U2(d3drect).y1 = 0;
960     U3(d3drect).x2 = ddsd_existing.dwWidth; U4(d3drect).y2 = ddsd_existing.dwHeight;
961     hr = IDirect3DViewport2_Clear(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER);
962     ok(SUCCEEDED(hr), "Failed to clear the z buffer, hr %#x.\n", hr);
963
964     /* Partial blit. */
965     SetRect(&src_rect, 0, 0, 320, 240);
966     SetRect(&dst_rect, 0, 0, 320, 240);
967     hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
968     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
969     /* Different locations. */
970     SetRect(&src_rect, 0, 0, 320, 240);
971     SetRect(&dst_rect, 320, 240, 640, 480);
972     hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
973     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
974     /* Streched. */
975     SetRect(&src_rect, 0, 0, 320, 240);
976     SetRect(&dst_rect, 0, 0, 640, 480);
977     hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
978     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
979     /* Flipped. */
980     SetRect(&src_rect, 0, 480, 640, 0);
981     SetRect(&dst_rect, 0, 0, 640, 480);
982     hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
983     ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
984     SetRect(&src_rect, 0, 0, 640, 480);
985     SetRect(&dst_rect, 0, 480, 640, 0);
986     hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
987     ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
988     /* Full, explicit. */
989     SetRect(&src_rect, 0, 0, 640, 480);
990     SetRect(&dst_rect, 0, 0, 640, 480);
991     hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
992     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
993     /* Depth -> color blit: Succeeds on Win7 + Radeon HD 5700, fails on WinXP + Radeon X1600 */
994
995     /* Depth blit inside a BeginScene / EndScene pair */
996     hr = IDirect3DDevice2_BeginScene(device);
997     ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
998     /* From the current depth stencil */
999     hr = IDirectDrawSurface_Blt(ds2, NULL, ds1, NULL, DDBLT_WAIT, NULL);
1000     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1001     /* To the current depth stencil */
1002     hr = IDirectDrawSurface_Blt(ds1, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1003     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1004     /* Between unbound surfaces */
1005     hr = IDirectDrawSurface_Blt(ds3, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1006     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1007     hr = IDirect3DDevice2_EndScene(device);
1008     ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1009
1010     /* Avoid changing the depth stencil, it doesn't work properly on Windows.
1011      * Instead use DDBLT_DEPTHFILL to clear the depth stencil. Unfortunately
1012      * drivers disagree on the meaning of dwFillDepth. Only 0 seems to produce
1013      * a reliable result(z = 0.0) */
1014     memset(&fx, 0, sizeof(fx));
1015     fx.dwSize = sizeof(fx);
1016     U5(fx).dwFillDepth = 0;
1017     hr = IDirectDrawSurface_Blt(ds2, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
1018     ok(SUCCEEDED(hr), "Failed to clear the source z buffer, hr %#x.\n", hr);
1019
1020     /* This clears the Z buffer with 1.0 */
1021     hr = IDirect3DViewport2_Clear(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET);
1022     ok(SUCCEEDED(hr), "Failed to clear the color and z buffers, hr %#x.\n", hr);
1023
1024     SetRect(&dst_rect, 0, 0, 320, 240);
1025     hr = IDirectDrawSurface_Blt(ds1, &dst_rect, ds2, NULL, DDBLT_WAIT, NULL);
1026     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1027     IDirectDrawSurface_Release(ds3);
1028     IDirectDrawSurface_Release(ds2);
1029     IDirectDrawSurface_Release(ds1);
1030
1031     hr = IDirect3DDevice2_BeginScene(device);
1032     ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
1033     hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad1, 4, 0);
1034     ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1035     hr = IDirect3DDevice2_EndScene(device);
1036     ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1037
1038     hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1039     ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1040     for (i = 0; i < 4; ++i)
1041     {
1042         for (j = 0; j < 4; ++j)
1043         {
1044             unsigned int x = 80 * ((2 * j) + 1);
1045             unsigned int y = 60 * ((2 * i) + 1);
1046             color = get_surface_color(rt, x, y);
1047             if (todo[i][j])
1048                 todo_wine ok(compare_color(color, expected_colors[i][j], 1),
1049                         "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
1050             else
1051                 ok(compare_color(color, expected_colors[i][j], 1),
1052                         "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
1053         }
1054     }
1055     IDirectDrawSurface_Release(rt);
1056
1057     destroy_viewport(device, viewport);
1058     IDirect3DMaterial2_Release(background);
1059     IDirect3D2_Release(d3d);
1060     IDirect3DDevice2_Release(device);
1061     IDirectDraw2_Release(ddraw);
1062     DestroyWindow(window);
1063 }
1064
1065 static void test_texture_load_ckey(void)
1066 {
1067     IDirectDraw2 *ddraw = NULL;
1068     IDirectDrawSurface *src = NULL;
1069     IDirectDrawSurface *dst = NULL;
1070     IDirect3DTexture *src_tex = NULL;
1071     IDirect3DTexture *dst_tex = NULL;
1072     DDSURFACEDESC ddsd;
1073     HRESULT hr;
1074     DDCOLORKEY ckey;
1075
1076     if (!(ddraw = create_ddraw()))
1077     {
1078         skip("Failed to create ddraw object, skipping test.\n");
1079         return;
1080     }
1081     hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
1082     ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1083
1084     memset(&ddsd, 0, sizeof(ddsd));
1085     ddsd.dwSize = sizeof(ddsd);
1086     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
1087     ddsd.dwHeight = 128;
1088     ddsd.dwWidth = 128;
1089     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
1090     hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &src, NULL);
1091     ok(SUCCEEDED(hr), "Failed to create source texture, hr %#x.\n", hr);
1092     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1093     hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &dst, NULL);
1094     ok(SUCCEEDED(hr), "Failed to create destination texture, hr %#x.\n", hr);
1095
1096     hr = IDirectDrawSurface_QueryInterface(src, &IID_IDirect3DTexture, (void **)&src_tex);
1097     ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get Direct3DTexture interface, hr %#x.\n", hr);
1098     if (FAILED(hr))
1099     {
1100         /* 64 bit ddraw does not support d3d */
1101         skip("Could not get Direct3DTexture interface, skipping texture::Load color keying tests.\n");
1102         goto done;
1103     }
1104     hr = IDirectDrawSurface_QueryInterface(dst, &IID_IDirect3DTexture, (void **)&dst_tex);
1105     ok(SUCCEEDED(hr), "Failed to get Direct3DTexture interface, hr %#x.\n", hr);
1106
1107     /* No surface has a color key */
1108     hr = IDirect3DTexture_Load(dst_tex, src_tex);
1109     ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDCAPS), "Got unexpected hr %#x.\n", hr);
1110     if (FAILED(hr))
1111     {
1112         /* Testbot Windows NT VMs */
1113         skip("IDirect3DTexture::Load does not work, skipping color keying tests.\n");
1114         goto done;
1115     }
1116
1117     ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0xdeadbeef;
1118     hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1119     ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1120     ok(ckey.dwColorSpaceLowValue == 0xdeadbeef, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1121     ok(ckey.dwColorSpaceHighValue == 0xdeadbeef, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1122
1123     /* Source surface has a color key */
1124     ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
1125     hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
1126     ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1127     hr = IDirect3DTexture_Load(dst_tex, src_tex);
1128     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1129     hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1130     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1131     ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1132     ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1133
1134     /* Both surfaces have a color key: Dest ckey is overwritten */
1135     ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x000000ff;
1136     hr = IDirectDrawSurface_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1137     ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1138     hr = IDirect3DTexture_Load(dst_tex, src_tex);
1139     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1140     hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1141     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1142     ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1143     ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1144
1145     /* Only the destination has a color key: It is not deleted */
1146     hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, NULL);
1147     ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1148     hr = IDirectDrawSurface_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
1149     ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1150     hr = IDirect3DTexture_Load(dst_tex, src_tex);
1151     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1152     hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1153     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1154     ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1155     ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1156
1157 done:
1158     if (dst_tex) IDirect3DTexture_Release(dst_tex);
1159     if (src_tex) IDirect3DTexture_Release(src_tex);
1160     if (dst) IDirectDrawSurface_Release(dst);
1161     if (src) IDirectDrawSurface_Release(src);
1162     if (ddraw) IDirectDraw2_Release(ddraw);
1163 }
1164
1165 static ULONG get_refcount(IUnknown *test_iface)
1166 {
1167     IUnknown_AddRef(test_iface);
1168     return IUnknown_Release(test_iface);
1169 }
1170
1171 static void test_viewport_interfaces(void)
1172 {
1173     IDirectDraw2 *ddraw;
1174     IDirect3D2 *d3d;
1175     HRESULT hr;
1176     ULONG ref, old_d3d_ref;
1177     IDirect3DViewport *viewport;
1178     IDirect3DViewport2 *viewport2;
1179     IDirect3DViewport3 *viewport3;
1180     IDirectDrawGammaControl *gamma;
1181     IUnknown *unknown;
1182
1183     if (!(ddraw = create_ddraw()))
1184     {
1185         skip("Failed to create ddraw object, skipping test.\n");
1186         return;
1187     }
1188
1189     hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d);
1190     ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get d3d interface, hr %#x.\n", hr);
1191     if (FAILED(hr))
1192     {
1193         skip("Direct3D not available, skipping tests\n");
1194         IDirectDraw2_Release(ddraw);
1195         return;
1196     }
1197     old_d3d_ref = get_refcount((IUnknown *)d3d);
1198
1199     hr = IDirect3D2_CreateViewport(d3d, &viewport2, NULL);
1200     ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1201     ref = get_refcount((IUnknown *)viewport2);
1202     ok(ref == 1, "Initial IDirect3DViewport2 refcount is %u\n", ref);
1203     ref = get_refcount((IUnknown *)d3d);
1204     ok(ref == old_d3d_ref, "IDirect3D2 refcount is %u\n", ref);
1205
1206     gamma = (IDirectDrawGammaControl *)0xdeadbeef;
1207     hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IDirectDrawGammaControl, (void **)&gamma);
1208     ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
1209     ok(gamma == NULL, "Interface not set to NULL by failed QI call: %p\n", gamma);
1210     if (SUCCEEDED(hr)) IDirectDrawGammaControl_Release(gamma);
1211     /* NULL iid: Segfaults */
1212
1213     hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IDirect3DViewport, (void **)&viewport);
1214     ok(SUCCEEDED(hr), "Failed to QI IDirect3DViewport, hr %#x.\n", hr);
1215     if (viewport)
1216     {
1217         ref = get_refcount((IUnknown *)viewport);
1218         ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
1219         ref = get_refcount((IUnknown *)viewport2);
1220         ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
1221         IDirect3DViewport_Release(viewport);
1222         viewport = NULL;
1223     }
1224
1225     hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IDirect3DViewport3, (void **)&viewport3);
1226     ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to QI IDirect3DViewport3, hr %#x.\n", hr);
1227     if (viewport3)
1228     {
1229         ref = get_refcount((IUnknown *)viewport2);
1230         ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
1231         ref = get_refcount((IUnknown *)viewport3);
1232         ok(ref == 2, "IDirect3DViewport3 refcount is %u\n", ref);
1233         IDirect3DViewport3_Release(viewport3);
1234     }
1235
1236     hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IUnknown, (void **)&unknown);
1237     ok(SUCCEEDED(hr), "Failed to QI IUnknown, hr %#x.\n", hr);
1238     if (unknown)
1239     {
1240         ref = get_refcount((IUnknown *)viewport2);
1241         ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
1242         ref = get_refcount(unknown);
1243         ok(ref == 2, "IUnknown refcount is %u\n", ref);
1244         IUnknown_Release(unknown);
1245     }
1246
1247     IDirect3DViewport2_Release(viewport2);
1248     IDirect3D2_Release(d3d);
1249     IDirectDraw2_Release(ddraw);
1250 }
1251
1252 static void test_zenable(void)
1253 {
1254     static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1255     static D3DTLVERTEX tquad[] =
1256     {
1257         {{  0.0f}, {480.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1258         {{  0.0f}, {  0.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1259         {{640.0f}, {480.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1260         {{640.0f}, {  0.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1261     };
1262     D3DMATERIALHANDLE background_handle;
1263     IDirect3DMaterial2 *background;
1264     IDirect3DViewport2 *viewport;
1265     IDirect3DDevice2 *device;
1266     IDirectDrawSurface *rt;
1267     D3DMATERIAL material;
1268     IDirectDraw2 *ddraw;
1269     IDirect3D2 *d3d;
1270     D3DCOLOR color;
1271     HWND window;
1272     HRESULT hr;
1273     UINT x, y;
1274     UINT i, j;
1275
1276     window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1277             0, 0, 640, 480, 0, 0, 0, 0);
1278     if (!(ddraw = create_ddraw()))
1279     {
1280         skip("Failed to create ddraw object, skipping test.\n");
1281         DestroyWindow(window);
1282         return;
1283     }
1284     if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1285     {
1286         skip("Failed to create D3D device, skipping test.\n");
1287         IDirectDraw2_Release(ddraw);
1288         DestroyWindow(window);
1289         return;
1290     }
1291
1292     hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
1293     ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1294     hr = IDirect3D2_CreateMaterial(d3d, &background, NULL);
1295     ok(SUCCEEDED(hr), "Failed to create material, hr %#x.\n", hr);
1296
1297     viewport = create_viewport(device, 0, 0, 640, 480);
1298     hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1299     ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1300
1301     memset(&material, 0, sizeof(material));
1302     material.dwSize = sizeof(material);
1303     U1(U(material).diffuse).r = 1.0f;
1304     U2(U(material).diffuse).g = 0.0f;
1305     U3(U(material).diffuse).b = 0.0f;
1306     U4(U(material).diffuse).a = 1.0f;
1307     hr = IDirect3DMaterial2_SetMaterial(background, &material);
1308     ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
1309     hr = IDirect3DMaterial2_GetHandle(background, device, &background_handle);
1310     ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
1311     hr = IDirect3DViewport2_SetBackground(viewport, background_handle);
1312     ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
1313
1314     hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1315     ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
1316
1317     hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1318     ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1319     hr = IDirect3DDevice2_BeginScene(device);
1320     ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1321     hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, tquad, 4, 0);
1322     ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1323     hr = IDirect3DDevice2_EndScene(device);
1324     ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1325
1326     hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1327     ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1328     for (i = 0; i < 4; ++i)
1329     {
1330         for (j = 0; j < 4; ++j)
1331         {
1332             x = 80 * ((2 * j) + 1);
1333             y = 60 * ((2 * i) + 1);
1334             color = get_surface_color(rt, x, y);
1335             ok(compare_color(color, 0x0000ff00, 1),
1336                     "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1337         }
1338     }
1339     IDirectDrawSurface_Release(rt);
1340
1341     destroy_viewport(device, viewport);
1342     IDirect3DMaterial2_Release(background);
1343     IDirect3D2_Release(d3d);
1344     IDirect3DDevice2_Release(device);
1345     IDirectDraw2_Release(ddraw);
1346     DestroyWindow(window);
1347 }
1348
1349 static void test_ck_rgba(void)
1350 {
1351     static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1352     static D3DTLVERTEX tquad[] =
1353     {
1354         {{  0.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1355         {{  0.0f}, {  0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1356         {{640.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1357         {{640.0f}, {  0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1358         {{  0.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1359         {{  0.0f}, {  0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1360         {{640.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1361         {{640.0f}, {  0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1362     };
1363     static const struct
1364     {
1365         D3DCOLOR fill_color;
1366         BOOL color_key;
1367         BOOL blend;
1368         D3DCOLOR result1;
1369         D3DCOLOR result2;
1370     }
1371     tests[] =
1372     {
1373         {0xff00ff00, TRUE,  TRUE,  0x00ff0000, 0x000000ff},
1374         {0xff00ff00, TRUE,  FALSE, 0x00ff0000, 0x000000ff},
1375         {0xff00ff00, FALSE, TRUE,  0x0000ff00, 0x0000ff00},
1376         {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00},
1377         {0x7f00ff00, TRUE,  TRUE,  0x00807f00, 0x00807f00},
1378         {0x7f00ff00, TRUE,  FALSE, 0x0000ff00, 0x0000ff00},
1379         {0x7f00ff00, FALSE, TRUE,  0x00807f00, 0x00807f00},
1380         {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00},
1381     };
1382
1383     D3DMATERIALHANDLE background_handle;
1384     D3DTEXTUREHANDLE texture_handle;
1385     IDirect3DMaterial2 *background;
1386     IDirectDrawSurface *surface;
1387     IDirect3DViewport2 *viewport;
1388     IDirect3DTexture2 *texture;
1389     DDSURFACEDESC surface_desc;
1390     IDirect3DDevice2 *device;
1391     IDirectDrawSurface *rt;
1392     D3DMATERIAL material;
1393     IDirectDraw2 *ddraw;
1394     IDirect3D2 *d3d;
1395     D3DCOLOR color;
1396     HWND window;
1397     DDBLTFX fx;
1398     HRESULT hr;
1399     UINT i;
1400
1401     window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1402             0, 0, 640, 480, 0, 0, 0, 0);
1403     if (!(ddraw = create_ddraw()))
1404     {
1405         skip("Failed to create ddraw object, skipping test.\n");
1406         DestroyWindow(window);
1407         return;
1408     }
1409     if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1410     {
1411         skip("Failed to create D3D device, skipping test.\n");
1412         DestroyWindow(window);
1413         return;
1414     }
1415
1416     hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
1417     ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1418
1419     viewport = create_viewport(device, 0, 0, 640, 480);
1420     hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1421     ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1422
1423     hr = IDirect3D2_CreateMaterial(d3d, &background, NULL);
1424     ok(SUCCEEDED(hr), "Failed to create material, hr %#x.\n", hr);
1425     memset(&material, 0, sizeof(material));
1426     material.dwSize = sizeof(material);
1427     U1(U(material).diffuse).r = 1.0f;
1428     U2(U(material).diffuse).g = 0.0f;
1429     U3(U(material).diffuse).b = 0.0f;
1430     U4(U(material).diffuse).a = 1.0f;
1431     hr = IDirect3DMaterial2_SetMaterial(background, &material);
1432     ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
1433     hr = IDirect3DMaterial2_GetHandle(background, device, &background_handle);
1434     ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
1435     hr = IDirect3DViewport2_SetBackground(viewport, background_handle);
1436     ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
1437
1438     IDirect3D2_Release(d3d);
1439
1440     memset(&surface_desc, 0, sizeof(surface_desc));
1441     surface_desc.dwSize = sizeof(surface_desc);
1442     surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1443     surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1444     surface_desc.dwWidth = 256;
1445     surface_desc.dwHeight = 256;
1446     surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1447     surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1448     U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1449     U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1450     U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1451     U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1452     U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1453     surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1454     surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1455     hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1456     ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1457     hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
1458     ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1459     hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
1460     ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1461     IDirect3DTexture2_Release(texture);
1462
1463     hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1464     ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1465     hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1466     ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1467     hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1468     ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1469
1470     hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1471     ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1472
1473     for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
1474     {
1475         hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1476         ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1477         hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1478         ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1479
1480         memset(&fx, 0, sizeof(fx));
1481         fx.dwSize = sizeof(fx);
1482         U5(fx).dwFillColor = tests[i].fill_color;
1483         hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1484         ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1485
1486         hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
1487         ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1488         hr = IDirect3DDevice2_BeginScene(device);
1489         ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1490         hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[0], 4, 0);
1491         ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1492         hr = IDirect3DDevice2_EndScene(device);
1493         ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1494
1495         color = get_surface_color(rt, 320, 240);
1496         if (i == 2)
1497             todo_wine ok(compare_color(color, tests[i].result1, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1498                     tests[i].result1, i, color);
1499         else
1500             ok(compare_color(color, tests[i].result1, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1501                     tests[i].result1, i, color);
1502
1503         U5(fx).dwFillColor = 0xff0000ff;
1504         hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1505         ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1506
1507         hr = IDirect3DDevice2_BeginScene(device);
1508         ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1509         hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[4], 4, 0);
1510         ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1511         hr = IDirect3DDevice2_EndScene(device);
1512         ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1513
1514         /* This tests that fragments that are masked out by the color key are
1515          * discarded, instead of just fully transparent. */
1516         color = get_surface_color(rt, 320, 240);
1517         if (i == 2)
1518             todo_wine ok(compare_color(color, tests[i].result2, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1519                     tests[i].result2, i, color);
1520         else
1521             ok(compare_color(color, tests[i].result2, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1522                     tests[i].result2, i, color);
1523     }
1524
1525     IDirectDrawSurface_Release(rt);
1526     hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1527     ok(SUCCEEDED(hr), "Failed to unset texture, hr %#x.\n", hr);
1528     IDirectDrawSurface_Release(surface);
1529     destroy_viewport(device, viewport);
1530     IDirect3DMaterial2_Release(background);
1531     IDirect3DDevice2_Release(device);
1532     IDirectDraw2_Release(ddraw);
1533     DestroyWindow(window);
1534 }
1535
1536 struct qi_test
1537 {
1538     REFIID iid;
1539     REFIID refcount_iid;
1540     HRESULT hr;
1541 };
1542
1543 static void test_qi(const char *test_name, IUnknown *base_iface,
1544         REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
1545 {
1546     ULONG refcount, expected_refcount;
1547     IUnknown *iface1, *iface2;
1548     HRESULT hr;
1549     UINT i, j;
1550
1551     for (i = 0; i < entry_count; ++i)
1552     {
1553         hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
1554         ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
1555         if (SUCCEEDED(hr))
1556         {
1557             for (j = 0; j < entry_count; ++j)
1558             {
1559                 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
1560                 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
1561                 if (SUCCEEDED(hr))
1562                 {
1563                     expected_refcount = 0;
1564                     if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
1565                         ++expected_refcount;
1566                     if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
1567                         ++expected_refcount;
1568                     refcount = IUnknown_Release(iface2);
1569                     ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
1570                             refcount, test_name, i, j, expected_refcount);
1571                 }
1572             }
1573
1574             expected_refcount = 0;
1575             if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
1576                 ++expected_refcount;
1577             refcount = IUnknown_Release(iface1);
1578             ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
1579                     refcount, test_name, i, expected_refcount);
1580         }
1581     }
1582 }
1583
1584 static void test_surface_qi(void)
1585 {
1586     static const struct qi_test tests[] =
1587     {
1588         {&IID_IDirect3DTexture2,        &IID_IDirectDrawSurface,        S_OK         },
1589         {&IID_IDirect3DTexture,         &IID_IDirectDrawSurface,        S_OK         },
1590         {&IID_IDirectDrawGammaControl,  &IID_IDirectDrawGammaControl,   S_OK         },
1591         {&IID_IDirectDrawColorControl,  NULL,                           E_NOINTERFACE},
1592         {&IID_IDirectDrawSurface7,      &IID_IDirectDrawSurface7,       S_OK         },
1593         {&IID_IDirectDrawSurface4,      &IID_IDirectDrawSurface4,       S_OK         },
1594         {&IID_IDirectDrawSurface3,      &IID_IDirectDrawSurface3,       S_OK         },
1595         {&IID_IDirectDrawSurface2,      &IID_IDirectDrawSurface2,       S_OK         },
1596         {&IID_IDirectDrawSurface,       &IID_IDirectDrawSurface,        S_OK         },
1597         {&IID_IDirect3DDevice7,         NULL,                           E_INVALIDARG },
1598         {&IID_IDirect3DDevice3,         NULL,                           E_INVALIDARG },
1599         {&IID_IDirect3DDevice2,         NULL,                           E_INVALIDARG },
1600         {&IID_IDirect3DDevice,          NULL,                           E_INVALIDARG },
1601         {&IID_IDirect3D7,               NULL,                           E_INVALIDARG },
1602         {&IID_IDirect3D3,               NULL,                           E_INVALIDARG },
1603         {&IID_IDirect3D2,               NULL,                           E_INVALIDARG },
1604         {&IID_IDirect3D,                NULL,                           E_INVALIDARG },
1605         {&IID_IDirectDraw7,             NULL,                           E_INVALIDARG },
1606         {&IID_IDirectDraw4,             NULL,                           E_INVALIDARG },
1607         {&IID_IDirectDraw3,             NULL,                           E_INVALIDARG },
1608         {&IID_IDirectDraw2,             NULL,                           E_INVALIDARG },
1609         {&IID_IDirectDraw,              NULL,                           E_INVALIDARG },
1610         {&IID_IDirect3DLight,           NULL,                           E_INVALIDARG },
1611         {&IID_IDirect3DMaterial,        NULL,                           E_INVALIDARG },
1612         {&IID_IDirect3DMaterial2,       NULL,                           E_INVALIDARG },
1613         {&IID_IDirect3DMaterial3,       NULL,                           E_INVALIDARG },
1614         {&IID_IDirect3DExecuteBuffer,   NULL,                           E_INVALIDARG },
1615         {&IID_IDirect3DViewport,        NULL,                           E_INVALIDARG },
1616         {&IID_IDirect3DViewport2,       NULL,                           E_INVALIDARG },
1617         {&IID_IDirect3DViewport3,       NULL,                           E_INVALIDARG },
1618         {&IID_IDirect3DVertexBuffer,    NULL,                           E_INVALIDARG },
1619         {&IID_IDirect3DVertexBuffer7,   NULL,                           E_INVALIDARG },
1620         {&IID_IDirectDrawPalette,       NULL,                           E_INVALIDARG },
1621         {&IID_IDirectDrawClipper,       NULL,                           E_INVALIDARG },
1622         {&IID_IUnknown,                 &IID_IDirectDrawSurface,        S_OK         },
1623     };
1624
1625     IDirectDrawSurface *surface;
1626     DDSURFACEDESC surface_desc;
1627     IDirect3DDevice2 *device;
1628     IDirectDraw2 *ddraw;
1629     HWND window;
1630     HRESULT hr;
1631
1632     if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
1633     {
1634         win_skip("DirectDrawCreateEx not available, skipping test.\n");
1635         return;
1636     }
1637
1638     window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1639             0, 0, 640, 480, 0, 0, 0, 0);
1640     if (!(ddraw = create_ddraw()))
1641     {
1642         skip("Failed to create a ddraw object, skipping test.\n");
1643         return;
1644     }
1645     /* Try to create a D3D device to see if the ddraw implementation supports
1646      * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
1647      * doesn't support e.g. the IDirect3DTexture interfaces. */
1648     if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1649     {
1650         skip("Failed to create D3D device, skipping test.\n");
1651         DestroyWindow(window);
1652         return;
1653     }
1654     IDirect3DDevice_Release(device);
1655
1656     memset(&surface_desc, 0, sizeof(surface_desc));
1657     surface_desc.dwSize = sizeof(surface_desc);
1658     surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1659     surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1660     surface_desc.dwWidth = 512;
1661     surface_desc.dwHeight = 512;
1662     hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1663     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1664
1665     test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface, tests, sizeof(tests) / sizeof(*tests));
1666
1667     IDirectDrawSurface_Release(surface);
1668     IDirectDraw2_Release(ddraw);
1669     DestroyWindow(window);
1670 }
1671
1672 START_TEST(ddraw2)
1673 {
1674     test_coop_level_create_device_window();
1675     test_clipper_blt();
1676     test_coop_level_d3d_state();
1677     test_surface_interface_mismatch();
1678     test_coop_level_threaded();
1679     test_depth_blit();
1680     test_texture_load_ckey();
1681     test_viewport_interfaces();
1682     test_zenable();
1683     test_ck_rgba();
1684     test_surface_qi();
1685 }