wined3d: Ignore clears if count = 0 and rects != NULL.
[wine.git] / dlls / ddraw / tests / ddraw2.c
bloba3ecbfdf081909cd3e29fafba17aea7448213fcb
1 /*
2 * Copyright 2011-2012 Henri Verbeet for CodeWeavers
3 * Copyright 2012-2013 Stefan Dösinger for CodeWeavers
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.
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.
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
19 #define COBJMACROS
21 #include "wine/test.h"
22 #include "d3d.h"
24 struct create_window_thread_param
26 HWND window;
27 HANDLE window_created;
28 HANDLE destroy_window;
29 HANDLE thread;
32 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
34 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
35 c1 >>= 8; c2 >>= 8;
36 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
37 c1 >>= 8; c2 >>= 8;
38 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
39 c1 >>= 8; c2 >>= 8;
40 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
41 return TRUE;
44 static DWORD WINAPI create_window_thread_proc(void *param)
46 struct create_window_thread_param *p = param;
47 DWORD res;
48 BOOL ret;
50 p->window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
51 0, 0, 640, 480, 0, 0, 0, 0);
52 ret = SetEvent(p->window_created);
53 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
55 for (;;)
57 MSG msg;
59 while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
60 DispatchMessage(&msg);
61 res = WaitForSingleObject(p->destroy_window, 100);
62 if (res == WAIT_OBJECT_0)
63 break;
64 if (res != WAIT_TIMEOUT)
66 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
67 break;
71 DestroyWindow(p->window);
73 return 0;
76 static void create_window_thread(struct create_window_thread_param *p)
78 DWORD res, tid;
80 p->window_created = CreateEvent(NULL, FALSE, FALSE, NULL);
81 ok(!!p->window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
82 p->destroy_window = CreateEvent(NULL, FALSE, FALSE, NULL);
83 ok(!!p->destroy_window, "CreateEvent failed, last error %#x.\n", GetLastError());
84 p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
85 ok(!!p->thread, "Failed to create thread, last error %#x.\n", GetLastError());
86 res = WaitForSingleObject(p->window_created, INFINITE);
87 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
90 static void destroy_window_thread(struct create_window_thread_param *p)
92 SetEvent(p->destroy_window);
93 WaitForSingleObject(p->thread, INFINITE);
94 CloseHandle(p->destroy_window);
95 CloseHandle(p->window_created);
96 CloseHandle(p->thread);
99 static IDirectDrawSurface *get_depth_stencil(IDirect3DDevice2 *device)
101 IDirectDrawSurface *rt, *ret;
102 DDSCAPS caps = {DDSCAPS_ZBUFFER};
103 HRESULT hr;
105 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
106 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
107 hr = IDirectDrawSurface_GetAttachedSurface(rt, &caps, &ret);
108 ok(SUCCEEDED(hr) || hr == DDERR_NOTFOUND, "Failed to get the z buffer, hr %#x.\n", hr);
109 IDirectDrawSurface_Release(rt);
110 return ret;
113 static D3DCOLOR get_surface_color(IDirectDrawSurface *surface, UINT x, UINT y)
115 RECT rect = {x, y, x + 1, y + 1};
116 DDSURFACEDESC surface_desc;
117 D3DCOLOR color;
118 HRESULT hr;
120 memset(&surface_desc, 0, sizeof(surface_desc));
121 surface_desc.dwSize = sizeof(surface_desc);
123 hr = IDirectDrawSurface_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
124 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
125 if (FAILED(hr))
126 return 0xdeadbeef;
128 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
130 hr = IDirectDrawSurface_Unlock(surface, NULL);
131 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
133 return color;
136 static HRESULT CALLBACK enum_z_fmt(GUID *guid, char *description, char *name,
137 D3DDEVICEDESC *hal_desc, D3DDEVICEDESC *hel_desc, void *ctx)
139 DWORD *z_depth = ctx;
141 if (!IsEqualGUID(&IID_IDirect3DHALDevice, guid))
142 return D3DENUMRET_OK;
144 if (hal_desc->dwDeviceZBufferBitDepth & DDBD_32)
145 *z_depth = 32;
146 else if (hal_desc->dwDeviceZBufferBitDepth & DDBD_24)
147 *z_depth = 24;
148 else if (hal_desc->dwDeviceZBufferBitDepth & DDBD_16)
149 *z_depth = 16;
151 return DDENUMRET_OK;
154 static IDirectDraw2 *create_ddraw(void)
156 IDirectDraw2 *ddraw2;
157 IDirectDraw *ddraw1;
158 HRESULT hr;
160 if (FAILED(DirectDrawCreate(NULL, &ddraw1, NULL)))
161 return NULL;
163 hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw2, (void **)&ddraw2);
164 IDirectDraw_Release(ddraw1);
165 if (FAILED(hr))
166 return NULL;
168 return ddraw2;
171 static IDirect3DDevice2 *create_device(IDirectDraw2 *ddraw, HWND window, DWORD coop_level)
173 IDirectDrawSurface *surface, *ds;
174 IDirect3DDevice2 *device = NULL;
175 DDSURFACEDESC surface_desc;
176 DWORD z_depth = 0;
177 IDirect3D2 *d3d;
178 HRESULT hr;
180 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, coop_level);
181 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
183 memset(&surface_desc, 0, sizeof(surface_desc));
184 surface_desc.dwSize = sizeof(surface_desc);
185 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
186 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
187 surface_desc.dwWidth = 640;
188 surface_desc.dwHeight = 480;
190 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
191 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
193 if (coop_level & DDSCL_NORMAL)
195 IDirectDrawClipper *clipper;
197 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
198 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
199 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
200 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
201 hr = IDirectDrawSurface_SetClipper(surface, clipper);
202 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\n", hr);
203 IDirectDrawClipper_Release(clipper);
206 hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d);
207 if (FAILED(hr))
209 IDirectDrawSurface_Release(surface);
210 return NULL;
213 hr = IDirect3D2_EnumDevices(d3d, enum_z_fmt, &z_depth);
214 ok(SUCCEEDED(hr), "Failed to enumerate z-formats, hr %#x.\n", hr);
215 if (FAILED(hr) || !z_depth)
217 IDirect3D2_Release(d3d);
218 IDirectDrawSurface_Release(surface);
219 return NULL;
222 memset(&surface_desc, 0, sizeof(surface_desc));
223 surface_desc.dwSize = sizeof(surface_desc);
224 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
225 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
226 U2(surface_desc).dwZBufferBitDepth = z_depth;
227 surface_desc.dwWidth = 640;
228 surface_desc.dwHeight = 480;
229 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &ds, NULL);
230 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
231 if (FAILED(hr))
233 IDirect3D2_Release(d3d);
234 IDirectDrawSurface_Release(surface);
235 return NULL;
238 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
239 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
240 IDirectDrawSurface_Release(ds);
241 if (FAILED(hr))
243 IDirect3D2_Release(d3d);
244 IDirectDrawSurface_Release(surface);
245 return NULL;
248 hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device);
249 IDirect3D2_Release(d3d);
250 IDirectDrawSurface_Release(surface);
251 if (FAILED(hr))
252 return NULL;
254 return device;
257 static IDirect3DViewport2 *create_viewport(IDirect3DDevice2 *device, UINT x, UINT y, UINT w, UINT h)
259 IDirect3DViewport2 *viewport;
260 D3DVIEWPORT2 vp;
261 IDirect3D2 *d3d;
262 HRESULT hr;
264 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
265 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
266 hr = IDirect3D2_CreateViewport(d3d, &viewport, NULL);
267 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
268 hr = IDirect3DDevice2_AddViewport(device, viewport);
269 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
270 memset(&vp, 0, sizeof(vp));
271 vp.dwSize = sizeof(vp);
272 vp.dwX = x;
273 vp.dwY = y;
274 vp.dwWidth = w;
275 vp.dwHeight = h;
276 vp.dvClipX = -1.0f;
277 vp.dvClipY = 1.0f;
278 vp.dvClipWidth = 2.0f;
279 vp.dvClipHeight = 2.0f;
280 vp.dvMinZ = 0.0f;
281 vp.dvMaxZ = 1.0f;
282 hr = IDirect3DViewport2_SetViewport2(viewport, &vp);
283 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
284 IDirect3D2_Release(d3d);
286 return viewport;
289 static void viewport_set_background(IDirect3DDevice2 *device, IDirect3DViewport2 *viewport,
290 IDirect3DMaterial2 *material)
292 D3DMATERIALHANDLE material_handle;
293 HRESULT hr;
295 hr = IDirect3DMaterial2_GetHandle(material, device, &material_handle);
296 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
297 hr = IDirect3DViewport2_SetBackground(viewport, material_handle);
298 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
301 static void destroy_viewport(IDirect3DDevice2 *device, IDirect3DViewport2 *viewport)
303 HRESULT hr;
305 hr = IDirect3DDevice2_DeleteViewport(device, viewport);
306 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
307 IDirect3DViewport2_Release(viewport);
310 static IDirect3DMaterial2 *create_diffuse_material(IDirect3DDevice2 *device, float r, float g, float b, float a)
312 IDirect3DMaterial2 *material;
313 D3DMATERIAL mat;
314 IDirect3D2 *d3d;
315 HRESULT hr;
317 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
318 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
319 hr = IDirect3D2_CreateMaterial(d3d, &material, NULL);
320 ok(SUCCEEDED(hr), "Failed to create material, hr %#x.\n", hr);
321 memset(&mat, 0, sizeof(mat));
322 mat.dwSize = sizeof(mat);
323 U1(U(mat).diffuse).r = r;
324 U2(U(mat).diffuse).g = g;
325 U3(U(mat).diffuse).b = b;
326 U4(U(mat).diffuse).a = a;
327 hr = IDirect3DMaterial2_SetMaterial(material, &mat);
328 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
329 IDirect3D2_Release(d3d);
331 return material;
334 static void destroy_material(IDirect3DMaterial2 *material)
336 IDirect3DMaterial2_Release(material);
339 static const UINT *expect_messages;
341 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
343 if (expect_messages && message == *expect_messages)
344 ++expect_messages;
346 return DefWindowProcA(hwnd, message, wparam, lparam);
349 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
350 * interface. This prevents subsequent SetCooperativeLevel() calls on a
351 * different window from failing with DDERR_HWNDALREADYSET. */
352 static void fix_wndproc(HWND window, LONG_PTR proc)
354 IDirectDraw2 *ddraw;
355 HRESULT hr;
357 if (!(ddraw = create_ddraw()))
358 return;
360 SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
361 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
362 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
363 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
364 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
366 IDirectDraw2_Release(ddraw);
369 static HRESULT CALLBACK restore_callback(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
371 HRESULT hr = IDirectDrawSurface_Restore(surface);
372 ok(SUCCEEDED(hr), "Failed to restore surface, hr %#x.\n", hr);
373 IDirectDrawSurface_Release(surface);
375 return DDENUMRET_OK;
378 static HRESULT restore_surfaces(IDirectDraw2 *ddraw)
380 return IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
381 NULL, NULL, restore_callback);
384 static void test_coop_level_create_device_window(void)
386 HWND focus_window, device_window;
387 IDirectDraw2 *ddraw;
388 HRESULT hr;
390 focus_window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
391 0, 0, 640, 480, 0, 0, 0, 0);
392 if (!(ddraw = create_ddraw()))
394 skip("Failed to create a ddraw object, skipping test.\n");
395 DestroyWindow(focus_window);
396 return;
399 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
400 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
401 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
402 ok(!device_window, "Unexpected device window found.\n");
403 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
404 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
405 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
406 ok(!device_window, "Unexpected device window found.\n");
407 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
408 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
409 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
410 ok(!device_window, "Unexpected device window found.\n");
411 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
412 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
413 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
414 ok(!device_window, "Unexpected device window found.\n");
415 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
416 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
417 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
418 ok(!device_window, "Unexpected device window found.\n");
420 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
421 if (broken(hr == DDERR_INVALIDPARAMS))
423 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
424 IDirectDraw2_Release(ddraw);
425 DestroyWindow(focus_window);
426 return;
429 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
430 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
431 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
432 ok(!device_window, "Unexpected device window found.\n");
433 hr = IDirectDraw2_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
434 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
435 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
436 ok(!device_window, "Unexpected device window found.\n");
438 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
439 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
440 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
441 ok(!device_window, "Unexpected device window found.\n");
442 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
443 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
444 ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
445 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
446 ok(!!device_window, "Device window not found.\n");
448 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
449 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
450 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
451 ok(!device_window, "Unexpected device window found.\n");
452 hr = IDirectDraw2_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
453 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
454 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
455 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
456 ok(!!device_window, "Device window not found.\n");
458 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
459 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
460 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
461 ok(!device_window, "Unexpected device window found.\n");
462 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
463 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
464 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
465 ok(!device_window, "Unexpected device window found.\n");
466 hr = IDirectDraw2_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
467 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
468 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
469 ok(!device_window, "Unexpected device window found.\n");
470 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
471 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
472 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
473 ok(!!device_window, "Device window not found.\n");
475 IDirectDraw2_Release(ddraw);
476 DestroyWindow(focus_window);
479 static void test_clipper_blt(void)
481 IDirectDrawSurface *src_surface, *dst_surface;
482 RECT client_rect, src_rect;
483 IDirectDrawClipper *clipper;
484 DDSURFACEDESC surface_desc;
485 unsigned int i, j, x, y;
486 IDirectDraw2 *ddraw;
487 RGNDATA *rgn_data;
488 D3DCOLOR color;
489 HRGN r1, r2;
490 HWND window;
491 DDBLTFX fx;
492 HRESULT hr;
493 DWORD *ptr;
494 DWORD ret;
496 static const DWORD src_data[] =
498 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
499 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
500 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
502 static const D3DCOLOR expected1[] =
504 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
505 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
506 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
507 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
509 static const D3DCOLOR expected2[] =
511 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
512 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
513 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
514 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
517 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
518 10, 10, 640, 480, 0, 0, 0, 0);
519 ShowWindow(window, SW_SHOW);
520 if (!(ddraw = create_ddraw()))
522 skip("Failed to create a ddraw object, skipping test.\n");
523 DestroyWindow(window);
524 return;
527 ret = GetClientRect(window, &client_rect);
528 ok(ret, "Failed to get client rect.\n");
529 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
530 ok(ret, "Failed to map client rect.\n");
532 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
533 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
535 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
536 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
537 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
538 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
539 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
540 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
541 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
542 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
543 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
544 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
545 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
546 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
547 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
548 ok(rgn_data->rdh.nCount >= 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
549 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
550 "Got unexpected bounding rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
551 rgn_data->rdh.rcBound.left, rgn_data->rdh.rcBound.top,
552 rgn_data->rdh.rcBound.right, rgn_data->rdh.rcBound.bottom,
553 client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
554 HeapFree(GetProcessHeap(), 0, rgn_data);
556 r1 = CreateRectRgn(0, 0, 320, 240);
557 ok(!!r1, "Failed to create region.\n");
558 r2 = CreateRectRgn(320, 240, 640, 480);
559 ok(!!r2, "Failed to create region.\n");
560 CombineRgn(r1, r1, r2, RGN_OR);
561 ret = GetRegionData(r1, 0, NULL);
562 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
563 ret = GetRegionData(r1, ret, rgn_data);
564 ok(!!ret, "Failed to get region data.\n");
566 DeleteObject(r2);
567 DeleteObject(r1);
569 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
570 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
571 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
572 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
573 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
574 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
576 HeapFree(GetProcessHeap(), 0, rgn_data);
578 memset(&surface_desc, 0, sizeof(surface_desc));
579 surface_desc.dwSize = sizeof(surface_desc);
580 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
581 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
582 surface_desc.dwWidth = 640;
583 surface_desc.dwHeight = 480;
584 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
585 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
586 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
587 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
588 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
589 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
591 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
592 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
593 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
594 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
596 memset(&fx, 0, sizeof(fx));
597 fx.dwSize = sizeof(fx);
598 hr = IDirectDrawSurface_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
599 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
600 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
601 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
603 hr = IDirectDrawSurface_Lock(src_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
604 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
605 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
606 ptr = surface_desc.lpSurface;
607 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
608 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
609 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
610 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
611 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
613 hr = IDirectDrawSurface_SetClipper(dst_surface, clipper);
614 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
616 SetRect(&src_rect, 1, 1, 5, 2);
617 hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
618 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
619 for (i = 0; i < 4; ++i)
621 for (j = 0; j < 4; ++j)
623 x = 80 * ((2 * j) + 1);
624 y = 60 * ((2 * i) + 1);
625 color = get_surface_color(dst_surface, x, y);
626 ok(compare_color(color, expected1[i * 4 + j], 1),
627 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
631 U5(fx).dwFillColor = 0xff0000ff;
632 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
633 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
634 for (i = 0; i < 4; ++i)
636 for (j = 0; j < 4; ++j)
638 x = 80 * ((2 * j) + 1);
639 y = 60 * ((2 * i) + 1);
640 color = get_surface_color(dst_surface, x, y);
641 ok(compare_color(color, expected2[i * 4 + j], 1),
642 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
646 hr = IDirectDrawSurface_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
647 ok(hr == DDERR_BLTFASTCANTCLIP || broken(hr == E_NOTIMPL /* NT4 */), "Got unexpected hr %#x.\n", hr);
649 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
650 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
651 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
652 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
653 DestroyWindow(window);
654 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
655 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
656 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
657 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
658 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
659 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
660 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
661 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
662 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
663 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
664 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
665 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
667 IDirectDrawSurface_Release(dst_surface);
668 IDirectDrawSurface_Release(src_surface);
669 IDirectDrawClipper_Release(clipper);
670 IDirectDraw2_Release(ddraw);
673 static void test_coop_level_d3d_state(void)
675 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
676 IDirectDrawSurface *rt, *surface;
677 IDirect3DMaterial2 *background;
678 IDirect3DViewport2 *viewport;
679 IDirect3DDevice2 *device;
680 D3DMATERIAL material;
681 IDirectDraw2 *ddraw;
682 D3DCOLOR color;
683 DWORD value;
684 HWND window;
685 HRESULT hr;
687 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
688 0, 0, 640, 480, 0, 0, 0, 0);
689 if (!(ddraw = create_ddraw()))
691 skip("Failed to create ddraw object, skipping test.\n");
692 DestroyWindow(window);
693 return;
695 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
697 skip("Failed to create D3D device, skipping test.\n");
698 IDirectDraw2_Release(ddraw);
699 DestroyWindow(window);
700 return;
703 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
704 viewport = create_viewport(device, 0, 0, 640, 480);
705 viewport_set_background(device, viewport, background);
707 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
708 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
709 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
710 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
711 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
712 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
713 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
714 ok(!value, "Got unexpected alpha blend enable state %#x.\n", value);
715 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
716 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
717 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
718 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
719 color = get_surface_color(rt, 320, 240);
720 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
722 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
723 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
724 hr = IDirectDrawSurface_IsLost(rt);
725 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
726 hr = restore_surfaces(ddraw);
727 ok(SUCCEEDED(hr), "Failed to restore surfaces, hr %#x.\n", hr);
729 memset(&material, 0, sizeof(material));
730 material.dwSize = sizeof(material);
731 U1(U(material).diffuse).r = 0.0f;
732 U2(U(material).diffuse).g = 1.0f;
733 U3(U(material).diffuse).b = 0.0f;
734 U4(U(material).diffuse).a = 1.0f;
735 hr = IDirect3DMaterial2_SetMaterial(background, &material);
736 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
738 hr = IDirect3DDevice2_GetRenderTarget(device, &surface);
739 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
740 ok(surface == rt, "Got unexpected surface %p.\n", surface);
741 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
742 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
743 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
744 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
745 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
746 ok(!!value, "Got unexpected alpha blend enable state %#x.\n", value);
747 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
748 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
749 color = get_surface_color(rt, 320, 240);
750 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
752 destroy_viewport(device, viewport);
753 destroy_material(background);
754 IDirectDrawSurface_Release(surface);
755 IDirectDrawSurface_Release(rt);
756 IDirect3DDevice2_Release(device);
757 IDirectDraw2_Release(ddraw);
758 DestroyWindow(window);
761 static void test_surface_interface_mismatch(void)
763 IDirectDraw2 *ddraw = NULL;
764 IDirect3D2 *d3d = NULL;
765 IDirectDrawSurface *surface = NULL, *ds;
766 IDirectDrawSurface3 *surface3 = NULL;
767 IDirect3DDevice2 *device = NULL;
768 IDirect3DViewport2 *viewport = NULL;
769 IDirect3DMaterial2 *background = NULL;
770 DDSURFACEDESC surface_desc;
771 DWORD z_depth = 0;
772 ULONG refcount;
773 HRESULT hr;
774 D3DCOLOR color;
775 HWND window;
776 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
778 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
779 0, 0, 640, 480, 0, 0, 0, 0);
781 if (!(ddraw = create_ddraw()))
783 skip("Failed to create a ddraw object, skipping test.\n");
784 goto cleanup;
787 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
788 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
790 memset(&surface_desc, 0, sizeof(surface_desc));
791 surface_desc.dwSize = sizeof(surface_desc);
792 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
793 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
794 surface_desc.dwWidth = 640;
795 surface_desc.dwHeight = 480;
797 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
798 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
800 hr = IDirectDrawSurface2_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
801 if (FAILED(hr))
803 skip("Failed to get the IDirectDrawSurface3 interface, skipping test.\n");
804 goto cleanup;
807 hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d);
808 if (FAILED(hr))
810 skip("Failed to get the IDirect3D2 interface, skipping test.\n");
811 goto cleanup;
814 hr = IDirect3D2_EnumDevices(d3d, enum_z_fmt, &z_depth);
815 if (FAILED(hr) || !z_depth)
817 skip("No depth buffer formats available, skipping test.\n");
818 goto cleanup;
821 memset(&surface_desc, 0, sizeof(surface_desc));
822 surface_desc.dwSize = sizeof(surface_desc);
823 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
824 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
825 U2(surface_desc).dwZBufferBitDepth = z_depth;
826 surface_desc.dwWidth = 640;
827 surface_desc.dwHeight = 480;
828 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &ds, NULL);
829 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
830 if (FAILED(hr))
831 goto cleanup;
833 /* Using a different surface interface version still works */
834 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
835 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
836 refcount = IDirectDrawSurface_Release(ds);
837 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
838 if (FAILED(hr))
839 goto cleanup;
841 /* Here too */
842 hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, (IDirectDrawSurface *)surface3, &device);
843 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
844 if (FAILED(hr))
845 goto cleanup;
847 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
848 viewport = create_viewport(device, 0, 0, 640, 480);
849 viewport_set_background(device, viewport, background);
851 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
852 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
853 color = get_surface_color(surface, 320, 240);
854 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
856 cleanup:
857 if (viewport)
858 destroy_viewport(device, viewport);
859 if (background)
860 destroy_material(background);
861 if (surface3) IDirectDrawSurface3_Release(surface3);
862 if (surface) IDirectDrawSurface_Release(surface);
863 if (device) IDirect3DDevice2_Release(device);
864 if (d3d) IDirect3D2_Release(d3d);
865 if (ddraw) IDirectDraw2_Release(ddraw);
866 DestroyWindow(window);
869 static void test_coop_level_threaded(void)
871 struct create_window_thread_param p;
872 IDirectDraw2 *ddraw;
873 HRESULT hr;
875 if (!(ddraw = create_ddraw()))
877 skip("Failed to create a ddraw object, skipping test.\n");
878 return;
880 create_window_thread(&p);
882 hr = IDirectDraw2_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
883 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
885 IDirectDraw2_Release(ddraw);
886 destroy_window_thread(&p);
889 static void test_depth_blit(void)
891 static D3DLVERTEX quad1[] =
893 {{-1.0}, { 1.0}, {0.50f}, 0, {0xff00ff00}},
894 {{ 1.0}, { 1.0}, {0.50f}, 0, {0xff00ff00}},
895 {{-1.0}, {-1.0}, {0.50f}, 0, {0xff00ff00}},
896 {{ 1.0}, {-1.0}, {0.50f}, 0, {0xff00ff00}},
898 static const D3DCOLOR expected_colors[4][4] =
900 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
901 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
902 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
903 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
905 static const BOOL todo[4][4] =
907 {FALSE, FALSE, TRUE, TRUE},
908 {FALSE, FALSE, TRUE, TRUE},
909 {TRUE, TRUE, TRUE, TRUE},
910 {TRUE, TRUE, TRUE, TRUE},
912 DDSURFACEDESC ddsd_new, ddsd_existing;
914 IDirect3DDevice2 *device;
915 IDirectDrawSurface *ds1, *ds2, *ds3, *rt;
916 IDirect3DViewport2 *viewport;
917 RECT src_rect, dst_rect;
918 unsigned int i, j;
919 D3DCOLOR color;
920 HRESULT hr;
921 IDirectDraw2 *ddraw;
922 DDBLTFX fx;
923 HWND window;
924 D3DRECT d3drect;
925 IDirect3DMaterial2 *background;
927 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
928 0, 0, 640, 480, 0, 0, 0, 0);
929 if (!(ddraw = create_ddraw()))
931 skip("Failed to create ddraw object, skipping test.\n");
932 DestroyWindow(window);
933 return;
935 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
937 skip("Failed to create D3D device, skipping test.\n");
938 IDirectDraw2_Release(ddraw);
939 DestroyWindow(window);
940 return;
943 ds1 = get_depth_stencil(device);
945 memset(&ddsd_new, 0, sizeof(ddsd_new));
946 ddsd_new.dwSize = sizeof(ddsd_new);
947 memset(&ddsd_existing, 0, sizeof(ddsd_existing));
948 ddsd_existing.dwSize = sizeof(ddsd_existing);
949 hr = IDirectDrawSurface_GetSurfaceDesc(ds1, &ddsd_existing);
950 ddsd_new.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
951 ddsd_new.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
952 ddsd_new.dwWidth = ddsd_existing.dwWidth;
953 ddsd_new.dwHeight = ddsd_existing.dwHeight;
954 ddsd_new.ddpfPixelFormat = ddsd_existing.ddpfPixelFormat;
955 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd_new, &ds2, NULL);
956 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
957 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd_new, &ds3, NULL);
958 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
960 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
961 viewport = create_viewport(device, 0, 0, ddsd_existing.dwWidth, ddsd_existing.dwHeight);
962 viewport_set_background(device, viewport, background);
963 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
964 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
966 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
967 ok(SUCCEEDED(hr), "Failed to enable z testing, hr %#x.\n", hr);
968 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
969 ok(SUCCEEDED(hr), "Failed to set the z function, hr %#x.\n", hr);
971 U1(d3drect).x1 = U2(d3drect).y1 = 0;
972 U3(d3drect).x2 = ddsd_existing.dwWidth; U4(d3drect).y2 = ddsd_existing.dwHeight;
973 hr = IDirect3DViewport2_Clear(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER);
974 ok(SUCCEEDED(hr), "Failed to clear the z buffer, hr %#x.\n", hr);
976 /* Partial blit. */
977 SetRect(&src_rect, 0, 0, 320, 240);
978 SetRect(&dst_rect, 0, 0, 320, 240);
979 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
980 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
981 /* Different locations. */
982 SetRect(&src_rect, 0, 0, 320, 240);
983 SetRect(&dst_rect, 320, 240, 640, 480);
984 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
985 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
986 /* Streched. */
987 SetRect(&src_rect, 0, 0, 320, 240);
988 SetRect(&dst_rect, 0, 0, 640, 480);
989 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
990 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
991 /* Flipped. */
992 SetRect(&src_rect, 0, 480, 640, 0);
993 SetRect(&dst_rect, 0, 0, 640, 480);
994 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
995 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
996 SetRect(&src_rect, 0, 0, 640, 480);
997 SetRect(&dst_rect, 0, 480, 640, 0);
998 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
999 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1000 /* Full, explicit. */
1001 SetRect(&src_rect, 0, 0, 640, 480);
1002 SetRect(&dst_rect, 0, 0, 640, 480);
1003 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1004 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1005 /* Depth -> color blit: Succeeds on Win7 + Radeon HD 5700, fails on WinXP + Radeon X1600 */
1007 /* Depth blit inside a BeginScene / EndScene pair */
1008 hr = IDirect3DDevice2_BeginScene(device);
1009 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
1010 /* From the current depth stencil */
1011 hr = IDirectDrawSurface_Blt(ds2, NULL, ds1, NULL, DDBLT_WAIT, NULL);
1012 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1013 /* To the current depth stencil */
1014 hr = IDirectDrawSurface_Blt(ds1, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1015 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1016 /* Between unbound surfaces */
1017 hr = IDirectDrawSurface_Blt(ds3, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1018 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1019 hr = IDirect3DDevice2_EndScene(device);
1020 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1022 /* Avoid changing the depth stencil, it doesn't work properly on Windows.
1023 * Instead use DDBLT_DEPTHFILL to clear the depth stencil. Unfortunately
1024 * drivers disagree on the meaning of dwFillDepth. Only 0 seems to produce
1025 * a reliable result(z = 0.0) */
1026 memset(&fx, 0, sizeof(fx));
1027 fx.dwSize = sizeof(fx);
1028 U5(fx).dwFillDepth = 0;
1029 hr = IDirectDrawSurface_Blt(ds2, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
1030 ok(SUCCEEDED(hr), "Failed to clear the source z buffer, hr %#x.\n", hr);
1032 /* This clears the Z buffer with 1.0 */
1033 hr = IDirect3DViewport2_Clear(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET);
1034 ok(SUCCEEDED(hr), "Failed to clear the color and z buffers, hr %#x.\n", hr);
1036 SetRect(&dst_rect, 0, 0, 320, 240);
1037 hr = IDirectDrawSurface_Blt(ds1, &dst_rect, ds2, NULL, DDBLT_WAIT, NULL);
1038 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1039 IDirectDrawSurface_Release(ds3);
1040 IDirectDrawSurface_Release(ds2);
1041 IDirectDrawSurface_Release(ds1);
1043 hr = IDirect3DDevice2_BeginScene(device);
1044 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
1045 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad1, 4, 0);
1046 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1047 hr = IDirect3DDevice2_EndScene(device);
1048 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1050 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1051 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1052 for (i = 0; i < 4; ++i)
1054 for (j = 0; j < 4; ++j)
1056 unsigned int x = 80 * ((2 * j) + 1);
1057 unsigned int y = 60 * ((2 * i) + 1);
1058 color = get_surface_color(rt, x, y);
1059 if (todo[i][j])
1060 todo_wine ok(compare_color(color, expected_colors[i][j], 1),
1061 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
1062 else
1063 ok(compare_color(color, expected_colors[i][j], 1),
1064 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
1067 IDirectDrawSurface_Release(rt);
1069 destroy_viewport(device, viewport);
1070 destroy_material(background);
1071 IDirect3DDevice2_Release(device);
1072 IDirectDraw2_Release(ddraw);
1073 DestroyWindow(window);
1076 static void test_texture_load_ckey(void)
1078 IDirectDraw2 *ddraw = NULL;
1079 IDirectDrawSurface *src = NULL;
1080 IDirectDrawSurface *dst = NULL;
1081 IDirect3DTexture *src_tex = NULL;
1082 IDirect3DTexture *dst_tex = NULL;
1083 DDSURFACEDESC ddsd;
1084 HRESULT hr;
1085 DDCOLORKEY ckey;
1087 if (!(ddraw = create_ddraw()))
1089 skip("Failed to create ddraw object, skipping test.\n");
1090 return;
1092 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
1093 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1095 memset(&ddsd, 0, sizeof(ddsd));
1096 ddsd.dwSize = sizeof(ddsd);
1097 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
1098 ddsd.dwHeight = 128;
1099 ddsd.dwWidth = 128;
1100 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
1101 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &src, NULL);
1102 ok(SUCCEEDED(hr), "Failed to create source texture, hr %#x.\n", hr);
1103 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1104 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &dst, NULL);
1105 ok(SUCCEEDED(hr), "Failed to create destination texture, hr %#x.\n", hr);
1107 hr = IDirectDrawSurface_QueryInterface(src, &IID_IDirect3DTexture, (void **)&src_tex);
1108 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get Direct3DTexture interface, hr %#x.\n", hr);
1109 if (FAILED(hr))
1111 /* 64 bit ddraw does not support d3d */
1112 skip("Could not get Direct3DTexture interface, skipping texture::Load color keying tests.\n");
1113 goto done;
1115 hr = IDirectDrawSurface_QueryInterface(dst, &IID_IDirect3DTexture, (void **)&dst_tex);
1116 ok(SUCCEEDED(hr), "Failed to get Direct3DTexture interface, hr %#x.\n", hr);
1118 /* No surface has a color key */
1119 hr = IDirect3DTexture_Load(dst_tex, src_tex);
1120 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDCAPS), "Got unexpected hr %#x.\n", hr);
1121 if (FAILED(hr))
1123 /* Testbot Windows NT VMs */
1124 skip("IDirect3DTexture::Load does not work, skipping color keying tests.\n");
1125 goto done;
1128 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0xdeadbeef;
1129 hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1130 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1131 ok(ckey.dwColorSpaceLowValue == 0xdeadbeef, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1132 ok(ckey.dwColorSpaceHighValue == 0xdeadbeef, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1134 /* Source surface has a color key */
1135 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
1136 hr = IDirectDrawSurface_SetColorKey(src, 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);
1145 /* Both surfaces have a color key: Dest ckey is overwritten */
1146 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x000000ff;
1147 hr = IDirectDrawSurface_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1148 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1149 hr = IDirect3DTexture_Load(dst_tex, src_tex);
1150 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1151 hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1152 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1153 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1154 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1156 /* Only the destination has a color key: It is not deleted */
1157 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, NULL);
1158 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1159 hr = IDirectDrawSurface_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
1160 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1161 hr = IDirect3DTexture_Load(dst_tex, src_tex);
1162 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1163 hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1164 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1165 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1166 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1168 done:
1169 if (dst_tex) IDirect3DTexture_Release(dst_tex);
1170 if (src_tex) IDirect3DTexture_Release(src_tex);
1171 if (dst) IDirectDrawSurface_Release(dst);
1172 if (src) IDirectDrawSurface_Release(src);
1173 if (ddraw) IDirectDraw2_Release(ddraw);
1176 static ULONG get_refcount(IUnknown *test_iface)
1178 IUnknown_AddRef(test_iface);
1179 return IUnknown_Release(test_iface);
1182 static void test_viewport_interfaces(void)
1184 IDirectDraw2 *ddraw;
1185 IDirect3D2 *d3d;
1186 HRESULT hr;
1187 ULONG ref, old_d3d_ref;
1188 IDirect3DViewport *viewport;
1189 IDirect3DViewport2 *viewport2;
1190 IDirect3DViewport3 *viewport3;
1191 IDirectDrawGammaControl *gamma;
1192 IUnknown *unknown;
1194 if (!(ddraw = create_ddraw()))
1196 skip("Failed to create ddraw object, skipping test.\n");
1197 return;
1200 hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d);
1201 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get d3d interface, hr %#x.\n", hr);
1202 if (FAILED(hr))
1204 skip("Direct3D not available, skipping tests\n");
1205 IDirectDraw2_Release(ddraw);
1206 return;
1208 old_d3d_ref = get_refcount((IUnknown *)d3d);
1210 hr = IDirect3D2_CreateViewport(d3d, &viewport2, NULL);
1211 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1212 ref = get_refcount((IUnknown *)viewport2);
1213 ok(ref == 1, "Initial IDirect3DViewport2 refcount is %u\n", ref);
1214 ref = get_refcount((IUnknown *)d3d);
1215 ok(ref == old_d3d_ref, "IDirect3D2 refcount is %u\n", ref);
1217 gamma = (IDirectDrawGammaControl *)0xdeadbeef;
1218 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IDirectDrawGammaControl, (void **)&gamma);
1219 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
1220 ok(gamma == NULL, "Interface not set to NULL by failed QI call: %p\n", gamma);
1221 if (SUCCEEDED(hr)) IDirectDrawGammaControl_Release(gamma);
1222 /* NULL iid: Segfaults */
1224 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IDirect3DViewport, (void **)&viewport);
1225 ok(SUCCEEDED(hr), "Failed to QI IDirect3DViewport, hr %#x.\n", hr);
1226 if (viewport)
1228 ref = get_refcount((IUnknown *)viewport);
1229 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
1230 ref = get_refcount((IUnknown *)viewport2);
1231 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
1232 IDirect3DViewport_Release(viewport);
1233 viewport = NULL;
1236 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IDirect3DViewport3, (void **)&viewport3);
1237 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to QI IDirect3DViewport3, hr %#x.\n", hr);
1238 if (viewport3)
1240 ref = get_refcount((IUnknown *)viewport2);
1241 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
1242 ref = get_refcount((IUnknown *)viewport3);
1243 ok(ref == 2, "IDirect3DViewport3 refcount is %u\n", ref);
1244 IDirect3DViewport3_Release(viewport3);
1247 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IUnknown, (void **)&unknown);
1248 ok(SUCCEEDED(hr), "Failed to QI IUnknown, hr %#x.\n", hr);
1249 if (unknown)
1251 ref = get_refcount((IUnknown *)viewport2);
1252 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
1253 ref = get_refcount(unknown);
1254 ok(ref == 2, "IUnknown refcount is %u\n", ref);
1255 IUnknown_Release(unknown);
1258 IDirect3DViewport2_Release(viewport2);
1259 IDirect3D2_Release(d3d);
1260 IDirectDraw2_Release(ddraw);
1263 static void test_zenable(void)
1265 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1266 static D3DTLVERTEX tquad[] =
1268 {{ 0.0f}, {480.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1269 {{ 0.0f}, { 0.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1270 {{640.0f}, {480.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1271 {{640.0f}, { 0.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1273 IDirect3DMaterial2 *background;
1274 IDirect3DViewport2 *viewport;
1275 IDirect3DDevice2 *device;
1276 IDirectDrawSurface *rt;
1277 IDirectDraw2 *ddraw;
1278 D3DCOLOR color;
1279 HWND window;
1280 HRESULT hr;
1281 UINT x, y;
1282 UINT i, j;
1284 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1285 0, 0, 640, 480, 0, 0, 0, 0);
1286 if (!(ddraw = create_ddraw()))
1288 skip("Failed to create ddraw object, skipping test.\n");
1289 DestroyWindow(window);
1290 return;
1292 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1294 skip("Failed to create D3D device, skipping test.\n");
1295 IDirectDraw2_Release(ddraw);
1296 DestroyWindow(window);
1297 return;
1300 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1301 viewport = create_viewport(device, 0, 0, 640, 480);
1302 viewport_set_background(device, viewport, background);
1303 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1304 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1306 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1307 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
1309 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1310 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1311 hr = IDirect3DDevice2_BeginScene(device);
1312 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1313 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, tquad, 4, 0);
1314 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1315 hr = IDirect3DDevice2_EndScene(device);
1316 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1318 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1319 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1320 for (i = 0; i < 4; ++i)
1322 for (j = 0; j < 4; ++j)
1324 x = 80 * ((2 * j) + 1);
1325 y = 60 * ((2 * i) + 1);
1326 color = get_surface_color(rt, x, y);
1327 ok(compare_color(color, 0x0000ff00, 1),
1328 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1331 IDirectDrawSurface_Release(rt);
1333 destroy_viewport(device, viewport);
1334 destroy_material(background);
1335 IDirect3DDevice2_Release(device);
1336 IDirectDraw2_Release(ddraw);
1337 DestroyWindow(window);
1340 static void test_ck_rgba(void)
1342 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1343 static D3DTLVERTEX tquad[] =
1345 {{ 0.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1346 {{ 0.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1347 {{640.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1348 {{640.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1349 {{ 0.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1350 {{ 0.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1351 {{640.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1352 {{640.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1354 static const struct
1356 D3DCOLOR fill_color;
1357 BOOL color_key;
1358 BOOL blend;
1359 D3DCOLOR result1;
1360 D3DCOLOR result2;
1362 tests[] =
1364 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x000000ff},
1365 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x000000ff},
1366 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00},
1367 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00},
1368 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00807f00},
1369 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x0000ff00},
1370 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00},
1371 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00},
1374 D3DTEXTUREHANDLE texture_handle;
1375 IDirect3DMaterial2 *background;
1376 IDirectDrawSurface *surface;
1377 IDirect3DViewport2 *viewport;
1378 IDirect3DTexture2 *texture;
1379 DDSURFACEDESC surface_desc;
1380 IDirect3DDevice2 *device;
1381 IDirectDrawSurface *rt;
1382 IDirectDraw2 *ddraw;
1383 D3DCOLOR color;
1384 HWND window;
1385 DDBLTFX fx;
1386 HRESULT hr;
1387 UINT i;
1389 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1390 0, 0, 640, 480, 0, 0, 0, 0);
1391 if (!(ddraw = create_ddraw()))
1393 skip("Failed to create ddraw object, skipping test.\n");
1394 DestroyWindow(window);
1395 return;
1397 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1399 skip("Failed to create D3D device, skipping test.\n");
1400 IDirectDraw2_Release(ddraw);
1401 DestroyWindow(window);
1402 return;
1405 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1406 viewport = create_viewport(device, 0, 0, 640, 480);
1407 viewport_set_background(device, viewport, background);
1408 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1409 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1411 memset(&surface_desc, 0, sizeof(surface_desc));
1412 surface_desc.dwSize = sizeof(surface_desc);
1413 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1414 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1415 surface_desc.dwWidth = 256;
1416 surface_desc.dwHeight = 256;
1417 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1418 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1419 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1420 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1421 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1422 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1423 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1424 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1425 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1426 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1427 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1428 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
1429 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1430 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
1431 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1432 IDirect3DTexture2_Release(texture);
1434 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1435 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1436 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1437 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1438 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1439 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1441 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1442 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1444 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
1446 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1447 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1448 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1449 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1451 memset(&fx, 0, sizeof(fx));
1452 fx.dwSize = sizeof(fx);
1453 U5(fx).dwFillColor = tests[i].fill_color;
1454 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1455 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1457 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
1458 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1459 hr = IDirect3DDevice2_BeginScene(device);
1460 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1461 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[0], 4, 0);
1462 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1463 hr = IDirect3DDevice2_EndScene(device);
1464 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1466 color = get_surface_color(rt, 320, 240);
1467 if (i == 2)
1468 todo_wine ok(compare_color(color, tests[i].result1, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1469 tests[i].result1, i, color);
1470 else
1471 ok(compare_color(color, tests[i].result1, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1472 tests[i].result1, i, color);
1474 U5(fx).dwFillColor = 0xff0000ff;
1475 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1476 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1478 hr = IDirect3DDevice2_BeginScene(device);
1479 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1480 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[4], 4, 0);
1481 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1482 hr = IDirect3DDevice2_EndScene(device);
1483 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1485 /* This tests that fragments that are masked out by the color key are
1486 * discarded, instead of just fully transparent. */
1487 color = get_surface_color(rt, 320, 240);
1488 if (i == 2)
1489 todo_wine ok(compare_color(color, tests[i].result2, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1490 tests[i].result2, i, color);
1491 else
1492 ok(compare_color(color, tests[i].result2, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1493 tests[i].result2, i, color);
1496 IDirectDrawSurface_Release(rt);
1497 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1498 ok(SUCCEEDED(hr), "Failed to unset texture, hr %#x.\n", hr);
1499 IDirectDrawSurface_Release(surface);
1500 destroy_viewport(device, viewport);
1501 destroy_material(background);
1502 IDirect3DDevice2_Release(device);
1503 IDirectDraw2_Release(ddraw);
1504 DestroyWindow(window);
1507 static void test_ck_default(void)
1509 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1510 static D3DTLVERTEX tquad[] =
1512 {{ 0.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1513 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1514 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1515 {{640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1517 IDirectDrawSurface *surface, *rt;
1518 D3DTEXTUREHANDLE texture_handle;
1519 IDirect3DMaterial2 *background;
1520 IDirect3DViewport2 *viewport;
1521 DDSURFACEDESC surface_desc;
1522 IDirect3DTexture2 *texture;
1523 IDirect3DDevice2 *device;
1524 IDirectDraw2 *ddraw;
1525 D3DCOLOR color;
1526 DWORD value;
1527 HWND window;
1528 DDBLTFX fx;
1529 HRESULT hr;
1531 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1532 0, 0, 640, 480, 0, 0, 0, 0);
1534 if (!(ddraw = create_ddraw()))
1536 skip("Failed to create ddraw object, skipping test.\n");
1537 DestroyWindow(window);
1538 return;
1540 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1542 skip("Failed to create D3D device, skipping test.\n");
1543 IDirectDraw2_Release(ddraw);
1544 DestroyWindow(window);
1545 return;
1548 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1549 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1551 background = create_diffuse_material(device, 0.0, 1.0f, 0.0f, 1.0f);
1552 viewport = create_viewport(device, 0, 0, 640, 480);
1553 viewport_set_background(device, viewport, background);
1554 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1555 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1557 memset(&surface_desc, 0, sizeof(surface_desc));
1558 surface_desc.dwSize = sizeof(surface_desc);
1559 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1560 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1561 surface_desc.dwWidth = 256;
1562 surface_desc.dwHeight = 256;
1563 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1564 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
1565 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1566 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1567 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1568 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1569 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
1570 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
1571 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1572 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1573 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
1574 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1575 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
1576 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1577 IDirect3DTexture_Release(texture);
1579 memset(&fx, 0, sizeof(fx));
1580 fx.dwSize = sizeof(fx);
1581 U5(fx).dwFillColor = 0x000000ff;
1582 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1583 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
1585 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1586 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1587 hr = IDirect3DDevice2_BeginScene(device);
1588 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1589 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1590 ok(SUCCEEDED(hr), "Failed to set texture handle, hr %#x.\n", hr);
1591 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1592 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1593 ok(!value, "Got unexpected color keying state %#x.\n", value);
1594 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[0], 4, 0);
1595 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1596 hr = IDirect3DDevice2_EndScene(device);
1597 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1598 color = get_surface_color(rt, 320, 240);
1599 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1601 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1602 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1603 hr = IDirect3DDevice2_BeginScene(device);
1604 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1605 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
1606 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1607 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[0], 4, 0);
1608 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1609 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1610 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1611 ok(!!value, "Got unexpected color keying state %#x.\n", value);
1612 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1613 ok(SUCCEEDED(hr), "Failed to set texture handle, hr %#x.\n", hr);
1614 hr = IDirect3DDevice2_EndScene(device);
1615 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1616 color = get_surface_color(rt, 320, 240);
1617 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1619 IDirectDrawSurface_Release(surface);
1620 destroy_viewport(device, viewport);
1621 destroy_material(background);
1622 IDirectDrawSurface_Release(rt);
1623 IDirect3DDevice2_Release(device);
1624 IDirectDraw2_Release(ddraw);
1625 DestroyWindow(window);
1628 struct qi_test
1630 REFIID iid;
1631 REFIID refcount_iid;
1632 HRESULT hr;
1635 static void test_qi(const char *test_name, IUnknown *base_iface,
1636 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
1638 ULONG refcount, expected_refcount;
1639 IUnknown *iface1, *iface2;
1640 HRESULT hr;
1641 UINT i, j;
1643 for (i = 0; i < entry_count; ++i)
1645 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
1646 ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
1647 if (SUCCEEDED(hr))
1649 for (j = 0; j < entry_count; ++j)
1651 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
1652 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
1653 if (SUCCEEDED(hr))
1655 expected_refcount = 0;
1656 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
1657 ++expected_refcount;
1658 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
1659 ++expected_refcount;
1660 refcount = IUnknown_Release(iface2);
1661 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
1662 refcount, test_name, i, j, expected_refcount);
1666 expected_refcount = 0;
1667 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
1668 ++expected_refcount;
1669 refcount = IUnknown_Release(iface1);
1670 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
1671 refcount, test_name, i, expected_refcount);
1676 static void test_surface_qi(void)
1678 static const struct qi_test tests[] =
1680 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface, S_OK },
1681 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface, S_OK },
1682 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
1683 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1684 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
1685 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
1686 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
1687 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
1688 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
1689 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
1690 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
1691 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
1692 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
1693 {&IID_IDirect3D7, NULL, E_INVALIDARG },
1694 {&IID_IDirect3D3, NULL, E_INVALIDARG },
1695 {&IID_IDirect3D2, NULL, E_INVALIDARG },
1696 {&IID_IDirect3D, NULL, E_INVALIDARG },
1697 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
1698 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
1699 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
1700 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
1701 {&IID_IDirectDraw, NULL, E_INVALIDARG },
1702 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
1703 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
1704 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
1705 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
1706 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
1707 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
1708 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
1709 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
1710 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
1711 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
1712 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
1713 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
1714 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
1717 IDirectDrawSurface *surface;
1718 DDSURFACEDESC surface_desc;
1719 IDirect3DDevice2 *device;
1720 IDirectDraw2 *ddraw;
1721 HWND window;
1722 HRESULT hr;
1724 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
1726 win_skip("DirectDrawCreateEx not available, skipping test.\n");
1727 return;
1730 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1731 0, 0, 640, 480, 0, 0, 0, 0);
1732 if (!(ddraw = create_ddraw()))
1734 skip("Failed to create a ddraw object, skipping test.\n");
1735 DestroyWindow(window);
1736 return;
1738 /* Try to create a D3D device to see if the ddraw implementation supports
1739 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
1740 * doesn't support e.g. the IDirect3DTexture interfaces. */
1741 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1743 skip("Failed to create D3D device, skipping test.\n");
1744 IDirectDraw2_Release(ddraw);
1745 DestroyWindow(window);
1746 return;
1748 IDirect3DDevice_Release(device);
1750 memset(&surface_desc, 0, sizeof(surface_desc));
1751 surface_desc.dwSize = sizeof(surface_desc);
1752 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1753 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1754 surface_desc.dwWidth = 512;
1755 surface_desc.dwHeight = 512;
1756 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1757 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1759 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface, tests, sizeof(tests) / sizeof(*tests));
1761 IDirectDrawSurface_Release(surface);
1762 IDirectDraw2_Release(ddraw);
1763 DestroyWindow(window);
1766 static void test_device_qi(void)
1768 static const struct qi_test tests[] =
1770 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
1771 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
1772 {&IID_IDirectDrawGammaControl, NULL, E_NOINTERFACE},
1773 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1774 {&IID_IDirectDrawSurface7, NULL, E_NOINTERFACE},
1775 {&IID_IDirectDrawSurface4, NULL, E_NOINTERFACE},
1776 {&IID_IDirectDrawSurface3, NULL, E_NOINTERFACE},
1777 {&IID_IDirectDrawSurface2, NULL, E_NOINTERFACE},
1778 {&IID_IDirectDrawSurface, NULL, E_NOINTERFACE},
1779 {&IID_IDirect3DDevice7, NULL, E_NOINTERFACE},
1780 {&IID_IDirect3DDevice3, NULL, E_NOINTERFACE},
1781 {&IID_IDirect3DDevice2, &IID_IDirect3DDevice2, S_OK },
1782 {&IID_IDirect3DDevice, &IID_IDirect3DDevice2, S_OK },
1783 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
1784 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
1785 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
1786 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
1787 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
1788 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
1789 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
1790 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
1791 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
1792 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
1793 {&IID_IDirect3D, NULL, E_NOINTERFACE},
1794 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
1795 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
1796 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
1797 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
1798 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
1799 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
1800 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
1801 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
1802 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
1803 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
1804 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
1805 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
1806 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
1807 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
1808 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
1809 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
1810 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
1811 {&IID_IUnknown, &IID_IDirect3DDevice2, S_OK },
1814 IDirect3DDevice2 *device;
1815 IDirectDraw2 *ddraw;
1816 HWND window;
1818 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1819 0, 0, 640, 480, 0, 0, 0, 0);
1820 if (!(ddraw = create_ddraw()))
1822 skip("Failed to create ddraw object, skipping test.\n");
1823 DestroyWindow(window);
1824 return;
1826 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1828 skip("Failed to create D3D device, skipping test.\n");
1829 IDirectDraw2_Release(ddraw);
1830 DestroyWindow(window);
1831 return;
1834 test_qi("device_qi", (IUnknown *)device, &IID_IDirect3DDevice2, tests, sizeof(tests) / sizeof(*tests));
1836 IDirect3DDevice2_Release(device);
1837 IDirectDraw2_Release(ddraw);
1838 DestroyWindow(window);
1841 static void test_wndproc(void)
1843 LONG_PTR proc, ddraw_proc;
1844 IDirectDraw2 *ddraw;
1845 WNDCLASSA wc = {0};
1846 HWND window;
1847 HRESULT hr;
1848 ULONG ref;
1850 static const UINT messages[] =
1852 WM_WINDOWPOSCHANGING,
1853 WM_MOVE,
1854 WM_SIZE,
1855 WM_WINDOWPOSCHANGING,
1856 WM_ACTIVATE,
1857 WM_SETFOCUS,
1861 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
1862 if (!(ddraw = create_ddraw()))
1864 skip("Failed to create IDirectDraw2 object, skipping tests.\n");
1865 return;
1868 wc.lpfnWndProc = test_proc;
1869 wc.lpszClassName = "ddraw_test_wndproc_wc";
1870 ok(RegisterClassA(&wc), "Failed to register window class.\n");
1872 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
1873 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
1875 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1876 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1877 (LONG_PTR)test_proc, proc);
1878 expect_messages = messages;
1879 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1880 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1881 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
1882 expect_messages = NULL;
1883 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1884 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1885 (LONG_PTR)test_proc, proc);
1886 ref = IDirectDraw2_Release(ddraw);
1887 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1888 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1889 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1890 (LONG_PTR)test_proc, proc);
1892 /* DDSCL_NORMAL doesn't. */
1893 ddraw = create_ddraw();
1894 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1895 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1896 (LONG_PTR)test_proc, proc);
1897 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
1898 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1899 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1900 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1901 (LONG_PTR)test_proc, proc);
1902 ref = IDirectDraw2_Release(ddraw);
1903 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1904 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1905 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1906 (LONG_PTR)test_proc, proc);
1908 /* The original window proc is only restored by ddraw if the current
1909 * window proc matches the one ddraw set. This also affects switching
1910 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
1911 ddraw = create_ddraw();
1912 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1913 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1914 (LONG_PTR)test_proc, proc);
1915 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1916 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1917 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1918 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1919 (LONG_PTR)test_proc, proc);
1920 ddraw_proc = proc;
1921 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1922 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1923 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1924 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1925 (LONG_PTR)test_proc, proc);
1926 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1927 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1928 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
1929 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1930 (LONG_PTR)test_proc, proc);
1931 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1932 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1933 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1934 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
1935 (LONG_PTR)DefWindowProcA, proc);
1936 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1937 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1938 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc);
1939 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
1940 (LONG_PTR)DefWindowProcA, proc);
1941 ref = IDirectDraw2_Release(ddraw);
1942 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1943 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1944 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1945 (LONG_PTR)test_proc, proc);
1947 ddraw = create_ddraw();
1948 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1949 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1950 (LONG_PTR)test_proc, proc);
1951 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1952 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1953 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
1954 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1955 (LONG_PTR)test_proc, proc);
1956 ref = IDirectDraw2_Release(ddraw);
1957 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1958 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1959 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
1960 (LONG_PTR)DefWindowProcA, proc);
1962 fix_wndproc(window, (LONG_PTR)test_proc);
1963 expect_messages = NULL;
1964 DestroyWindow(window);
1965 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
1968 static void test_window_style(void)
1970 LONG style, exstyle, tmp;
1971 RECT fullscreen_rect, r;
1972 IDirectDraw2 *ddraw;
1973 HWND window;
1974 HRESULT hr;
1975 ULONG ref;
1977 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1978 0, 0, 100, 100, 0, 0, 0, 0);
1979 if (!(ddraw = create_ddraw()))
1981 skip("Failed to create a ddraw object, skipping test.\n");
1982 DestroyWindow(window);
1983 return;
1986 style = GetWindowLongA(window, GWL_STYLE);
1987 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
1988 SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
1990 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1991 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1993 tmp = GetWindowLongA(window, GWL_STYLE);
1994 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
1995 tmp = GetWindowLongA(window, GWL_EXSTYLE);
1996 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
1998 GetWindowRect(window, &r);
1999 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2000 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2001 r.left, r.top, r.right, r.bottom);
2002 GetClientRect(window, &r);
2003 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2005 ref = IDirectDraw2_Release(ddraw);
2006 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2008 DestroyWindow(window);
2011 static void test_redundant_mode_set(void)
2013 DDSURFACEDESC surface_desc = {0};
2014 IDirectDraw2 *ddraw;
2015 HWND window;
2016 HRESULT hr;
2017 RECT r, s;
2018 ULONG ref;
2020 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2021 0, 0, 100, 100, 0, 0, 0, 0);
2022 if (!(ddraw = create_ddraw()))
2024 skip("Failed to create a ddraw object, skipping test.\n");
2025 DestroyWindow(window);
2026 return;
2029 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2030 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2032 surface_desc.dwSize = sizeof(surface_desc);
2033 hr = IDirectDraw2_GetDisplayMode(ddraw, &surface_desc);
2034 ok(SUCCEEDED(hr), "GetDipslayMode failed, hr %#x.\n", hr);
2036 hr = IDirectDraw2_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2037 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount, 0, 0);
2038 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2040 GetWindowRect(window, &r);
2041 r.right /= 2;
2042 r.bottom /= 2;
2043 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
2044 GetWindowRect(window, &s);
2045 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2046 r.left, r.top, r.right, r.bottom,
2047 s.left, s.top, s.right, s.bottom);
2049 hr = IDirectDraw2_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2050 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount, 0, 0);
2051 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2053 GetWindowRect(window, &s);
2054 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2055 r.left, r.top, r.right, r.bottom,
2056 s.left, s.top, s.right, s.bottom);
2058 ref = IDirectDraw2_Release(ddraw);
2059 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2061 DestroyWindow(window);
2064 static SIZE screen_size;
2066 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2068 if (message == WM_SIZE)
2070 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2071 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2074 return test_proc(hwnd, message, wparam, lparam);
2077 static void test_coop_level_mode_set(void)
2079 IDirectDrawSurface *primary;
2080 RECT fullscreen_rect, r, s;
2081 IDirectDraw2 *ddraw;
2082 DDSURFACEDESC ddsd;
2083 WNDCLASSA wc = {0};
2084 HWND window;
2085 HRESULT hr;
2086 ULONG ref;
2088 static const UINT exclusive_messages[] =
2090 WM_WINDOWPOSCHANGING,
2091 WM_WINDOWPOSCHANGED,
2092 WM_SIZE,
2093 WM_DISPLAYCHANGE,
2097 static const UINT normal_messages[] =
2099 WM_DISPLAYCHANGE,
2103 if (!(ddraw = create_ddraw()))
2105 skip("Failed to create a ddraw object, skipping test.\n");
2106 return;
2109 wc.lpfnWndProc = mode_set_proc;
2110 wc.lpszClassName = "ddraw_test_wndproc_wc";
2111 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2113 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
2114 0, 0, 100, 100, 0, 0, 0, 0);
2116 SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2117 SetRect(&s, 0, 0, 640, 480);
2119 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2120 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2122 GetWindowRect(window, &r);
2123 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2124 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2125 r.left, r.top, r.right, r.bottom);
2127 memset(&ddsd, 0, sizeof(ddsd));
2128 ddsd.dwSize = sizeof(ddsd);
2129 ddsd.dwFlags = DDSD_CAPS;
2130 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2132 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2133 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2134 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2135 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2136 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2137 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2138 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2139 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2141 GetWindowRect(window, &r);
2142 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2143 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2144 r.left, r.top, r.right, r.bottom);
2146 expect_messages = exclusive_messages;
2147 screen_size.cx = 0;
2148 screen_size.cy = 0;
2150 hr = IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 32, 0, 0);
2151 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2153 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2154 expect_messages = NULL;
2155 ok(screen_size.cx == s.right && screen_size.cy == s.bottom,
2156 "Expected screen size %ux%u, got %ux%u.\n",
2157 s.right, s.bottom, screen_size.cx, screen_size.cy);
2159 GetWindowRect(window, &r);
2160 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2161 s.left, s.top, s.right, s.bottom,
2162 r.left, r.top, r.right, r.bottom);
2164 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2165 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2166 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2167 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2168 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2169 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2170 IDirectDrawSurface_Release(primary);
2172 memset(&ddsd, 0, sizeof(ddsd));
2173 ddsd.dwSize = sizeof(ddsd);
2174 ddsd.dwFlags = DDSD_CAPS;
2175 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2177 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2178 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2179 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2180 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2181 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2182 s.right - s.left, ddsd.dwWidth);
2183 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2184 s.bottom - s.top, ddsd.dwHeight);
2186 GetWindowRect(window, &r);
2187 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2188 s.left, s.top, s.right, s.bottom,
2189 r.left, r.top, r.right, r.bottom);
2191 expect_messages = exclusive_messages;
2192 screen_size.cx = 0;
2193 screen_size.cy = 0;
2195 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2196 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2198 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2199 expect_messages = NULL;
2200 ok(screen_size.cx == fullscreen_rect.right && screen_size.cy == fullscreen_rect.bottom,
2201 "Expected screen size %ux%u, got %ux%u.\n",
2202 fullscreen_rect.right, fullscreen_rect.bottom, screen_size.cx, screen_size.cy);
2204 GetWindowRect(window, &r);
2205 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2206 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2207 r.left, r.top, r.right, r.bottom);
2209 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2210 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2211 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2212 s.right - s.left, ddsd.dwWidth);
2213 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2214 s.bottom - s.top, ddsd.dwHeight);
2215 IDirectDrawSurface_Release(primary);
2217 memset(&ddsd, 0, sizeof(ddsd));
2218 ddsd.dwSize = sizeof(ddsd);
2219 ddsd.dwFlags = DDSD_CAPS;
2220 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2222 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2223 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2224 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2225 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2226 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2227 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2228 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2229 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2231 GetWindowRect(window, &r);
2232 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2233 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2234 r.left, r.top, r.right, r.bottom);
2236 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2237 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2239 GetWindowRect(window, &r);
2240 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2241 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2242 r.left, r.top, r.right, r.bottom);
2244 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2245 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2246 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2247 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2248 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2249 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2250 IDirectDrawSurface_Release(primary);
2252 memset(&ddsd, 0, sizeof(ddsd));
2253 ddsd.dwSize = sizeof(ddsd);
2254 ddsd.dwFlags = DDSD_CAPS;
2255 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2257 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2258 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2259 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2260 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2261 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2262 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2263 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2264 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2266 GetWindowRect(window, &r);
2267 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2268 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2269 r.left, r.top, r.right, r.bottom);
2271 expect_messages = normal_messages;
2272 screen_size.cx = 0;
2273 screen_size.cy = 0;
2275 hr = IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 32, 0, 0);
2276 ok(SUCCEEDED(hr) || broken(hr == DDERR_NOEXCLUSIVEMODE) /* NT4 testbot */,
2277 "SetDipslayMode failed, hr %#x.\n", hr);
2278 if (hr == DDERR_NOEXCLUSIVEMODE)
2280 win_skip("Broken SetDisplayMode(), skipping remaining tests.\n");
2281 IDirectDrawSurface_Release(primary);
2282 IDirectDraw2_Release(ddraw);
2283 goto done;
2286 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2287 expect_messages = NULL;
2288 ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2290 GetWindowRect(window, &r);
2291 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2292 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2293 r.left, r.top, r.right, r.bottom);
2295 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2296 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2297 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2298 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2299 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2300 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2301 IDirectDrawSurface_Release(primary);
2303 memset(&ddsd, 0, sizeof(ddsd));
2304 ddsd.dwSize = sizeof(ddsd);
2305 ddsd.dwFlags = DDSD_CAPS;
2306 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2308 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2309 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2310 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2311 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2312 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2313 s.right - s.left, ddsd.dwWidth);
2314 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2315 s.bottom - s.top, ddsd.dwHeight);
2317 GetWindowRect(window, &r);
2318 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2319 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2320 r.left, r.top, r.right, r.bottom);
2322 expect_messages = normal_messages;
2323 screen_size.cx = 0;
2324 screen_size.cy = 0;
2326 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2327 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2329 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2330 expect_messages = NULL;
2331 ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2333 GetWindowRect(window, &r);
2334 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2335 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2336 r.left, r.top, r.right, r.bottom);
2338 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2339 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2340 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2341 s.right - s.left, ddsd.dwWidth);
2342 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2343 s.bottom - s.top, ddsd.dwHeight);
2344 IDirectDrawSurface_Release(primary);
2346 memset(&ddsd, 0, sizeof(ddsd));
2347 ddsd.dwSize = sizeof(ddsd);
2348 ddsd.dwFlags = DDSD_CAPS;
2349 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2351 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2352 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2353 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2354 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2355 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2356 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2357 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2358 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2360 GetWindowRect(window, &r);
2361 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2362 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2363 r.left, r.top, r.right, r.bottom);
2365 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
2366 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
2367 * not DDSCL_FULLSCREEN. */
2368 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2369 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2371 GetWindowRect(window, &r);
2372 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2373 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2374 r.left, r.top, r.right, r.bottom);
2376 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2377 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2378 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2379 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2380 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2381 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2382 IDirectDrawSurface_Release(primary);
2384 memset(&ddsd, 0, sizeof(ddsd));
2385 ddsd.dwSize = sizeof(ddsd);
2386 ddsd.dwFlags = DDSD_CAPS;
2387 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2389 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2390 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2391 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2392 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2393 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2394 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2395 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2396 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2398 GetWindowRect(window, &r);
2399 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2400 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2401 r.left, r.top, r.right, r.bottom);
2403 expect_messages = normal_messages;
2404 screen_size.cx = 0;
2405 screen_size.cy = 0;
2407 hr = IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 32, 0, 0);
2408 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2410 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2411 expect_messages = NULL;
2412 ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2414 GetWindowRect(window, &r);
2415 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2416 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2417 r.left, r.top, r.right, r.bottom);
2419 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2420 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2421 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2422 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2423 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2424 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2425 IDirectDrawSurface_Release(primary);
2427 memset(&ddsd, 0, sizeof(ddsd));
2428 ddsd.dwSize = sizeof(ddsd);
2429 ddsd.dwFlags = DDSD_CAPS;
2430 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2432 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2433 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2434 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2435 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2436 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2437 s.right - s.left, ddsd.dwWidth);
2438 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2439 s.bottom - s.top, ddsd.dwHeight);
2441 GetWindowRect(window, &r);
2442 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2443 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2444 r.left, r.top, r.right, r.bottom);
2446 expect_messages = normal_messages;
2447 screen_size.cx = 0;
2448 screen_size.cy = 0;
2450 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2451 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2453 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2454 expect_messages = NULL;
2455 ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2457 GetWindowRect(window, &r);
2458 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2459 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2460 r.left, r.top, r.right, r.bottom);
2462 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2463 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2464 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2465 s.right - s.left, ddsd.dwWidth);
2466 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2467 s.bottom - s.top, ddsd.dwHeight);
2468 IDirectDrawSurface_Release(primary);
2470 memset(&ddsd, 0, sizeof(ddsd));
2471 ddsd.dwSize = sizeof(ddsd);
2472 ddsd.dwFlags = DDSD_CAPS;
2473 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2475 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2476 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2477 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2478 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2479 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2480 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2481 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2482 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2483 IDirectDrawSurface_Release(primary);
2485 GetWindowRect(window, &r);
2486 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2487 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2488 r.left, r.top, r.right, r.bottom);
2490 ref = IDirectDraw2_Release(ddraw);
2491 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2493 GetWindowRect(window, &r);
2494 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2495 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2496 r.left, r.top, r.right, r.bottom);
2498 done:
2499 expect_messages = NULL;
2500 DestroyWindow(window);
2501 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2504 static void test_coop_level_mode_set_multi(void)
2506 IDirectDraw2 *ddraw1, *ddraw2;
2507 UINT orig_w, orig_h, w, h;
2508 HWND window;
2509 HRESULT hr;
2510 ULONG ref;
2512 if (!(ddraw1 = create_ddraw()))
2514 skip("Failed to create a ddraw object, skipping test.\n");
2515 return;
2518 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2519 0, 0, 100, 100, 0, 0, 0, 0);
2521 orig_w = GetSystemMetrics(SM_CXSCREEN);
2522 orig_h = GetSystemMetrics(SM_CYSCREEN);
2524 /* With just a single ddraw object, the display mode is restored on
2525 * release. */
2526 hr = IDirectDraw2_SetDisplayMode(ddraw1, 800, 600, 32, 0, 0);
2527 ok(SUCCEEDED(hr) || broken(hr == DDERR_NOEXCLUSIVEMODE) /* NT4 testbot */,
2528 "SetDipslayMode failed, hr %#x.\n", hr);
2529 if (hr == DDERR_NOEXCLUSIVEMODE)
2531 win_skip("Broken SetDisplayMode(), skipping test.\n");
2532 IDirectDraw2_Release(ddraw1);
2533 DestroyWindow(window);
2534 return;
2536 w = GetSystemMetrics(SM_CXSCREEN);
2537 ok(w == 800, "Got unexpected screen width %u.\n", w);
2538 h = GetSystemMetrics(SM_CYSCREEN);
2539 ok(h == 600, "Got unexpected screen height %u.\n", h);
2541 ref = IDirectDraw2_Release(ddraw1);
2542 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2543 w = GetSystemMetrics(SM_CXSCREEN);
2544 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2545 h = GetSystemMetrics(SM_CYSCREEN);
2546 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2548 /* When there are multiple ddraw objects, the display mode is restored to
2549 * the initial mode, before the first SetDisplayMode() call. */
2550 ddraw1 = create_ddraw();
2551 hr = IDirectDraw2_SetDisplayMode(ddraw1, 800, 600, 32, 0, 0);
2552 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2553 w = GetSystemMetrics(SM_CXSCREEN);
2554 ok(w == 800, "Got unexpected screen width %u.\n", w);
2555 h = GetSystemMetrics(SM_CYSCREEN);
2556 ok(h == 600, "Got unexpected screen height %u.\n", h);
2558 ddraw2 = create_ddraw();
2559 hr = IDirectDraw2_SetDisplayMode(ddraw2, 640, 480, 32, 0, 0);
2560 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2561 w = GetSystemMetrics(SM_CXSCREEN);
2562 ok(w == 640, "Got unexpected screen width %u.\n", w);
2563 h = GetSystemMetrics(SM_CYSCREEN);
2564 ok(h == 480, "Got unexpected screen height %u.\n", h);
2566 ref = IDirectDraw2_Release(ddraw2);
2567 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2568 w = GetSystemMetrics(SM_CXSCREEN);
2569 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2570 h = GetSystemMetrics(SM_CYSCREEN);
2571 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2573 ref = IDirectDraw2_Release(ddraw1);
2574 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2575 w = GetSystemMetrics(SM_CXSCREEN);
2576 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2577 h = GetSystemMetrics(SM_CYSCREEN);
2578 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2580 /* Regardless of release ordering. */
2581 ddraw1 = create_ddraw();
2582 hr = IDirectDraw2_SetDisplayMode(ddraw1, 800, 600, 32, 0, 0);
2583 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2584 w = GetSystemMetrics(SM_CXSCREEN);
2585 ok(w == 800, "Got unexpected screen width %u.\n", w);
2586 h = GetSystemMetrics(SM_CYSCREEN);
2587 ok(h == 600, "Got unexpected screen height %u.\n", h);
2589 ddraw2 = create_ddraw();
2590 hr = IDirectDraw2_SetDisplayMode(ddraw2, 640, 480, 32, 0, 0);
2591 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2592 w = GetSystemMetrics(SM_CXSCREEN);
2593 ok(w == 640, "Got unexpected screen width %u.\n", w);
2594 h = GetSystemMetrics(SM_CYSCREEN);
2595 ok(h == 480, "Got unexpected screen height %u.\n", h);
2597 ref = IDirectDraw2_Release(ddraw1);
2598 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2599 w = GetSystemMetrics(SM_CXSCREEN);
2600 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2601 h = GetSystemMetrics(SM_CYSCREEN);
2602 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2604 ref = IDirectDraw2_Release(ddraw2);
2605 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2606 w = GetSystemMetrics(SM_CXSCREEN);
2607 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2608 h = GetSystemMetrics(SM_CYSCREEN);
2609 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2611 /* But only for ddraw objects that called SetDisplayMode(). */
2612 ddraw1 = create_ddraw();
2613 ddraw2 = create_ddraw();
2614 hr = IDirectDraw2_SetDisplayMode(ddraw2, 640, 480, 32, 0, 0);
2615 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2616 w = GetSystemMetrics(SM_CXSCREEN);
2617 ok(w == 640, "Got unexpected screen width %u.\n", w);
2618 h = GetSystemMetrics(SM_CYSCREEN);
2619 ok(h == 480, "Got unexpected screen height %u.\n", h);
2621 ref = IDirectDraw2_Release(ddraw1);
2622 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2623 w = GetSystemMetrics(SM_CXSCREEN);
2624 ok(w == 640, "Got unexpected screen width %u.\n", w);
2625 h = GetSystemMetrics(SM_CYSCREEN);
2626 ok(h == 480, "Got unexpected screen height %u.\n", h);
2628 ref = IDirectDraw2_Release(ddraw2);
2629 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2630 w = GetSystemMetrics(SM_CXSCREEN);
2631 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2632 h = GetSystemMetrics(SM_CYSCREEN);
2633 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2635 /* If there's a ddraw object that's currently in exclusive mode, it blocks
2636 * restoring the display mode. */
2637 ddraw1 = create_ddraw();
2638 hr = IDirectDraw2_SetDisplayMode(ddraw1, 800, 600, 32, 0, 0);
2639 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2640 w = GetSystemMetrics(SM_CXSCREEN);
2641 ok(w == 800, "Got unexpected screen width %u.\n", w);
2642 h = GetSystemMetrics(SM_CYSCREEN);
2643 ok(h == 600, "Got unexpected screen height %u.\n", h);
2645 ddraw2 = create_ddraw();
2646 hr = IDirectDraw2_SetDisplayMode(ddraw2, 640, 480, 32, 0, 0);
2647 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2648 w = GetSystemMetrics(SM_CXSCREEN);
2649 ok(w == 640, "Got unexpected screen width %u.\n", w);
2650 h = GetSystemMetrics(SM_CYSCREEN);
2651 ok(h == 480, "Got unexpected screen height %u.\n", h);
2653 hr = IDirectDraw2_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2654 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2656 ref = IDirectDraw2_Release(ddraw1);
2657 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2658 w = GetSystemMetrics(SM_CXSCREEN);
2659 ok(w == 640, "Got unexpected screen width %u.\n", w);
2660 h = GetSystemMetrics(SM_CYSCREEN);
2661 ok(h == 480, "Got unexpected screen height %u.\n", h);
2663 ref = IDirectDraw2_Release(ddraw2);
2664 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2665 w = GetSystemMetrics(SM_CXSCREEN);
2666 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2667 h = GetSystemMetrics(SM_CYSCREEN);
2668 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2670 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
2671 ddraw1 = create_ddraw();
2672 hr = IDirectDraw2_SetDisplayMode(ddraw1, 800, 600, 32, 0, 0);
2673 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2674 w = GetSystemMetrics(SM_CXSCREEN);
2675 ok(w == 800, "Got unexpected screen width %u.\n", w);
2676 h = GetSystemMetrics(SM_CYSCREEN);
2677 ok(h == 600, "Got unexpected screen height %u.\n", h);
2679 hr = IDirectDraw2_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2680 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2682 ddraw2 = create_ddraw();
2683 hr = IDirectDraw2_SetDisplayMode(ddraw2, 640, 480, 32, 0, 0);
2684 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
2686 ref = IDirectDraw2_Release(ddraw1);
2687 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2688 w = GetSystemMetrics(SM_CXSCREEN);
2689 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2690 h = GetSystemMetrics(SM_CYSCREEN);
2691 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2693 ref = IDirectDraw2_Release(ddraw2);
2694 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2695 w = GetSystemMetrics(SM_CXSCREEN);
2696 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2697 h = GetSystemMetrics(SM_CYSCREEN);
2698 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2700 DestroyWindow(window);
2703 static void test_initialize(void)
2705 IDirectDraw2 *ddraw;
2706 HRESULT hr;
2708 if (!(ddraw = create_ddraw()))
2710 skip("Failed to create a ddraw object, skipping test.\n");
2711 return;
2714 hr = IDirectDraw2_Initialize(ddraw, NULL);
2715 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
2716 IDirectDraw2_Release(ddraw);
2718 CoInitialize(NULL);
2719 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw2, (void **)&ddraw);
2720 ok(SUCCEEDED(hr), "Failed to create IDirectDraw2 instance, hr %#x.\n", hr);
2721 hr = IDirectDraw2_Initialize(ddraw, NULL);
2722 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
2723 hr = IDirectDraw2_Initialize(ddraw, NULL);
2724 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
2725 IDirectDraw2_Release(ddraw);
2726 CoUninitialize();
2729 static void test_coop_level_surf_create(void)
2731 IDirectDrawSurface *surface;
2732 IDirectDraw2 *ddraw;
2733 DDSURFACEDESC ddsd;
2734 HRESULT hr;
2736 if (!(ddraw = create_ddraw()))
2738 skip("Failed to create a ddraw object, skipping test.\n");
2739 return;
2742 memset(&ddsd, 0, sizeof(ddsd));
2743 ddsd.dwSize = sizeof(ddsd);
2744 ddsd.dwFlags = DDSD_CAPS;
2745 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2746 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
2747 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
2749 IDirectDraw2_Release(ddraw);
2752 static void test_coop_level_multi_window(void)
2754 HWND window1, window2;
2755 IDirectDraw2 *ddraw;
2756 HRESULT hr;
2758 window1 = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
2759 0, 0, 640, 480, 0, 0, 0, 0);
2760 window2 = CreateWindowA("static", "ddraw_test2", WS_OVERLAPPEDWINDOW,
2761 0, 0, 640, 480, 0, 0, 0, 0);
2762 if (!(ddraw = create_ddraw()))
2764 skip("Failed to create a ddraw object, skipping test.\n");
2765 DestroyWindow(window2);
2766 DestroyWindow(window1);
2767 return;
2770 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
2771 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2772 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
2773 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2774 ok(IsWindow(window1), "Window 1 was destroyed.\n");
2775 ok(IsWindow(window2), "Window 2 was destroyed.\n");
2777 IDirectDraw2_Release(ddraw);
2778 DestroyWindow(window2);
2779 DestroyWindow(window1);
2782 static void test_clear_rect_count(void)
2784 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
2785 IDirect3DMaterial2 *white, *red, *green, *blue;
2786 IDirect3DViewport2 *viewport;
2787 IDirect3DDevice2 *device;
2788 IDirectDrawSurface *rt;
2789 IDirectDraw2 *ddraw;
2790 D3DCOLOR color;
2791 HWND window;
2792 HRESULT hr;
2794 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2795 0, 0, 640, 480, 0, 0, 0, 0);
2796 if (!(ddraw = create_ddraw()))
2798 skip("Failed to create ddraw object, skipping test.\n");
2799 DestroyWindow(window);
2800 return;
2802 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
2804 skip("Failed to create D3D device, skipping test.\n");
2805 IDirectDraw2_Release(ddraw);
2806 DestroyWindow(window);
2807 return;
2810 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
2811 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
2813 white = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
2814 red = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
2815 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
2816 blue = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
2818 viewport = create_viewport(device, 0, 0, 640, 480);
2819 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
2820 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
2822 viewport_set_background(device, viewport, white);
2823 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
2824 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2825 viewport_set_background(device, viewport, red);
2826 hr = IDirect3DViewport2_Clear(viewport, 0, &clear_rect, D3DCLEAR_TARGET);
2827 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2828 viewport_set_background(device, viewport, green);
2829 hr = IDirect3DViewport2_Clear(viewport, 0, NULL, D3DCLEAR_TARGET);
2830 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2831 viewport_set_background(device, viewport, blue);
2832 hr = IDirect3DViewport2_Clear(viewport, 0, &clear_rect, D3DCLEAR_TARGET);
2833 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2835 color = get_surface_color(rt, 320, 240);
2836 ok(compare_color(color, 0x00ffffff, 1), "Got unexpected color 0x%08x.\n", color);
2838 IDirectDrawSurface_Release(rt);
2839 destroy_viewport(device, viewport);
2840 destroy_material(white);
2841 destroy_material(red);
2842 destroy_material(green);
2843 destroy_material(blue);
2844 IDirect3DDevice2_Release(device);
2845 IDirectDraw2_Release(ddraw);
2846 DestroyWindow(window);
2849 START_TEST(ddraw2)
2851 test_coop_level_create_device_window();
2852 test_clipper_blt();
2853 test_coop_level_d3d_state();
2854 test_surface_interface_mismatch();
2855 test_coop_level_threaded();
2856 test_depth_blit();
2857 test_texture_load_ckey();
2858 test_viewport_interfaces();
2859 test_zenable();
2860 test_ck_rgba();
2861 test_ck_default();
2862 test_surface_qi();
2863 test_device_qi();
2864 test_wndproc();
2865 test_window_style();
2866 test_redundant_mode_set();
2867 test_coop_level_mode_set();
2868 test_coop_level_mode_set_multi();
2869 test_initialize();
2870 test_coop_level_surf_create();
2871 test_coop_level_multi_window();
2872 test_clear_rect_count();