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
21 #include "wine/test.h"
24 struct create_window_thread_param
27 HANDLE window_created;
28 HANDLE destroy_window;
32 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
34 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
36 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
38 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
40 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
44 static DWORD WINAPI create_window_thread_proc(void *param)
46 struct create_window_thread_param *p = param;
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());
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)
64 if (res != WAIT_TIMEOUT)
66 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
71 DestroyWindow(p->window);
76 static void create_window_thread(struct create_window_thread_param *p)
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};
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);
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;
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);
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);
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)
146 else if (hal_desc->dwDeviceZBufferBitDepth & DDBD_24)
148 else if (hal_desc->dwDeviceZBufferBitDepth & DDBD_16)
154 static IDirectDraw2 *create_ddraw(void)
156 IDirectDraw2 *ddraw2;
160 if (FAILED(DirectDrawCreate(NULL, &ddraw1, NULL)))
163 hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw2, (void **)&ddraw2);
164 IDirectDraw_Release(ddraw1);
171 static IDirect3DDevice2 *create_device(IDirectDraw2 *ddraw, HWND window, DWORD coop_level)
173 IDirectDrawSurface *surface, *ds;
174 IDirect3DDevice2 *device = NULL;
175 DDSURFACEDESC surface_desc;
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);
209 IDirectDrawSurface_Release(surface);
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);
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);
233 IDirect3D2_Release(d3d);
234 IDirectDrawSurface_Release(surface);
238 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
239 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
240 IDirectDrawSurface_Release(ds);
243 IDirect3D2_Release(d3d);
244 IDirectDrawSurface_Release(surface);
248 hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device);
249 IDirect3D2_Release(d3d);
250 IDirectDrawSurface_Release(surface);
257 static IDirect3DViewport2 *create_viewport(IDirect3DDevice2 *device, UINT x, UINT y, UINT w, UINT h)
259 IDirect3DViewport2 *viewport;
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);
278 vp.dvClipWidth = 2.0f;
279 vp.dvClipHeight = 2.0f;
282 hr = IDirect3DViewport2_SetViewport2(viewport, &vp);
283 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
284 IDirect3D2_Release(d3d);
289 static void viewport_set_background(IDirect3DDevice2 *device, IDirect3DViewport2 *viewport,
290 IDirect3DMaterial2 *material)
292 D3DMATERIALHANDLE material_handle;
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)
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;
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);
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)
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)
357 if (!(ddraw = create_ddraw()))
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);
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;
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);
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);
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;
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);
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");
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;
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);
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);
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;
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");
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);
803 skip("Failed to get the IDirectDrawSurface3 interface, skipping test.\n");
807 hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d);
810 skip("Failed to get the IDirect3D2 interface, skipping test.\n");
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");
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);
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);
842 hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, (IDirectDrawSurface *)surface3, &device);
843 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
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);
858 destroy_viewport(device, viewport);
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;
875 if (!(ddraw = create_ddraw()))
877 skip("Failed to create a ddraw object, skipping test.\n");
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;
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);
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);
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);
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);
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);
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);
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);
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;
1087 if (!(ddraw = create_ddraw()))
1089 skip("Failed to create ddraw object, skipping test.\n");
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;
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);
1111 /* 64 bit ddraw does not support d3d */
1112 skip("Could not get Direct3DTexture interface, skipping texture::Load color keying tests.\n");
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);
1123 /* Testbot Windows NT VMs */
1124 skip("IDirect3DTexture::Load does not work, skipping color keying tests.\n");
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);
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(void)
1184 IDirectDraw2 *ddraw;
1187 ULONG ref, old_d3d_ref;
1188 IDirect3DViewport *viewport;
1189 IDirect3DViewport2 *viewport2, *another_vp, *test_vp;
1190 IDirect3DViewport3 *viewport3;
1191 IDirectDrawGammaControl *gamma;
1193 IDirect3DDevice2 *device;
1196 if (!(ddraw = create_ddraw()))
1198 skip("Failed to create ddraw object, skipping test.\n");
1201 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1202 0, 0, 640, 480, 0, 0, 0, 0);
1203 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1205 skip("Failed to create D3D device, skipping test.\n");
1206 IDirectDraw_Release(ddraw);
1207 DestroyWindow(window);
1211 hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d);
1212 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get d3d interface, hr %#x.\n", hr);
1215 skip("Direct3D not available, skipping tests\n");
1216 IDirectDraw2_Release(ddraw);
1219 old_d3d_ref = get_refcount((IUnknown *)d3d);
1221 hr = IDirect3D2_CreateViewport(d3d, &viewport2, NULL);
1222 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1223 ref = get_refcount((IUnknown *)viewport2);
1224 ok(ref == 1, "Initial IDirect3DViewport2 refcount is %u\n", ref);
1225 ref = get_refcount((IUnknown *)d3d);
1226 ok(ref == old_d3d_ref, "IDirect3D2 refcount is %u\n", ref);
1228 gamma = (IDirectDrawGammaControl *)0xdeadbeef;
1229 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IDirectDrawGammaControl, (void **)&gamma);
1230 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
1231 ok(gamma == NULL, "Interface not set to NULL by failed QI call: %p\n", gamma);
1232 if (SUCCEEDED(hr)) IDirectDrawGammaControl_Release(gamma);
1233 /* NULL iid: Segfaults */
1235 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IDirect3DViewport, (void **)&viewport);
1236 ok(SUCCEEDED(hr), "Failed to QI IDirect3DViewport, hr %#x.\n", hr);
1239 ref = get_refcount((IUnknown *)viewport);
1240 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
1241 ref = get_refcount((IUnknown *)viewport2);
1242 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
1243 IDirect3DViewport_Release(viewport);
1247 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IDirect3DViewport3, (void **)&viewport3);
1248 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to QI IDirect3DViewport3, hr %#x.\n", hr);
1251 ref = get_refcount((IUnknown *)viewport2);
1252 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
1253 ref = get_refcount((IUnknown *)viewport3);
1254 ok(ref == 2, "IDirect3DViewport3 refcount is %u\n", ref);
1255 IDirect3DViewport3_Release(viewport3);
1258 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IUnknown, (void **)&unknown);
1259 ok(SUCCEEDED(hr), "Failed to QI IUnknown, hr %#x.\n", hr);
1262 ref = get_refcount((IUnknown *)viewport2);
1263 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
1264 ref = get_refcount(unknown);
1265 ok(ref == 2, "IUnknown refcount is %u\n", ref);
1266 IUnknown_Release(unknown);
1269 /* AddViewport(NULL): Segfault */
1270 hr = IDirect3DDevice2_DeleteViewport(device, NULL);
1271 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1272 hr = IDirect3DDevice2_GetCurrentViewport(device, NULL);
1273 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1275 hr = IDirect3D2_CreateViewport(d3d, &another_vp, NULL);
1276 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1278 /* Setting a viewport not in the viewport list fails */
1279 hr = IDirect3DDevice2_SetCurrentViewport(device, another_vp);
1280 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1282 hr = IDirect3DDevice2_AddViewport(device, viewport2);
1283 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1284 ref = get_refcount((IUnknown *) viewport2);
1285 ok(ref == 2, "viewport2 refcount is %d\n", ref);
1286 hr = IDirect3DDevice2_AddViewport(device, another_vp);
1287 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1288 ref = get_refcount((IUnknown *) another_vp);
1289 ok(ref == 2, "another_vp refcount is %d\n", ref);
1291 test_vp = (IDirect3DViewport2 *) 0xbaadc0de;
1292 hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
1293 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1294 ok(test_vp == (IDirect3DViewport2 *) 0xbaadc0de, "Got unexpected pointer %p\n", test_vp);
1296 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport2);
1297 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1298 ref = get_refcount((IUnknown *) viewport2);
1299 ok(ref == 3, "viewport2 refcount is %d\n", ref);
1300 ref = get_refcount((IUnknown *) device);
1301 ok(ref == 1, "device refcount is %d\n", ref);
1304 hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
1305 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1306 ok(test_vp == viewport2, "Got unexpected viewport %p\n", test_vp);
1307 ref = get_refcount((IUnknown *) viewport2);
1308 ok(ref == 4, "viewport2 refcount is %d\n", ref);
1309 if(test_vp) IDirect3DViewport2_Release(test_vp);
1311 /* GetCurrentViewport with a viewport set and NULL input param: Segfault */
1313 /* Cannot set the viewport to NULL */
1314 hr = IDirect3DDevice2_SetCurrentViewport(device, NULL);
1315 ok(hr == DDERR_INVALIDPARAMS, "Failed to set viewport to NULL, hr %#x.\n", hr);
1317 hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
1318 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1319 ok(test_vp == viewport2, "Got unexpected viewport %p\n", test_vp);
1320 if(test_vp) IDirect3DViewport2_Release(test_vp);
1322 /* SetCurrentViewport properly releases the old viewport's reference */
1323 hr = IDirect3DDevice2_SetCurrentViewport(device, another_vp);
1324 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1325 ref = get_refcount((IUnknown *) viewport2);
1326 ok(ref == 2, "viewport2 refcount is %d\n", ref);
1327 ref = get_refcount((IUnknown *) another_vp);
1328 ok(ref == 3, "another_vp refcount is %d\n", ref);
1330 /* Deleting the viewport removes the reference added by AddViewport, but not
1331 * the one added by SetCurrentViewport. */
1332 hr = IDirect3DDevice2_DeleteViewport(device, another_vp);
1333 ok(SUCCEEDED(hr), "Failed to delete viewport from device, hr %#x.\n", hr);
1334 ref = get_refcount((IUnknown *) another_vp);
1335 todo_wine ok(ref == 2, "IDirect3DViewport2 refcount is %d\n", ref);
1337 /* GetCurrentViewport fails though */
1339 hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
1340 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1341 ok(test_vp == NULL, "Got unexpected viewport %p\n", test_vp);
1342 if(test_vp) IDirect3DViewport2_Release(test_vp);
1344 /* Setting a different viewport does not free the leaked reference. How
1345 * do I get rid of it? Leak the viewport for now. */
1346 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport2);
1347 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1348 ref = get_refcount((IUnknown *) viewport2);
1349 ok(ref == 3, "viewport2 refcount is %d\n", ref);
1350 ref = get_refcount((IUnknown *) another_vp);
1351 todo_wine ok(ref == 2, "another_vp refcount is %d\n", ref);
1353 /* Destroying the device removes the viewport, but does not free the reference
1354 * added by SetCurrentViewport. */
1355 IDirect3DDevice2_Release(device);
1356 ref = get_refcount((IUnknown *) viewport2);
1357 todo_wine ok(ref == 2, "viewport2 refcount is %d\n", ref);
1359 IDirect3DViewport2_Release(another_vp);
1360 IDirect3DViewport2_Release(viewport2);
1361 IDirect3D2_Release(d3d);
1362 DestroyWindow(window);
1363 IDirectDraw2_Release(ddraw);
1366 static void test_zenable(void)
1368 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1369 static D3DTLVERTEX tquad[] =
1371 {{ 0.0f}, {480.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1372 {{ 0.0f}, { 0.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1373 {{640.0f}, {480.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1374 {{640.0f}, { 0.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1376 IDirect3DMaterial2 *background;
1377 IDirect3DViewport2 *viewport;
1378 IDirect3DDevice2 *device;
1379 IDirectDrawSurface *rt;
1380 IDirectDraw2 *ddraw;
1387 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1388 0, 0, 640, 480, 0, 0, 0, 0);
1389 if (!(ddraw = create_ddraw()))
1391 skip("Failed to create ddraw object, skipping test.\n");
1392 DestroyWindow(window);
1395 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1397 skip("Failed to create D3D device, skipping test.\n");
1398 IDirectDraw2_Release(ddraw);
1399 DestroyWindow(window);
1403 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1404 viewport = create_viewport(device, 0, 0, 640, 480);
1405 viewport_set_background(device, viewport, background);
1406 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1407 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1409 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1410 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
1412 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1413 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1414 hr = IDirect3DDevice2_BeginScene(device);
1415 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1416 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, tquad, 4, 0);
1417 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1418 hr = IDirect3DDevice2_EndScene(device);
1419 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1421 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1422 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1423 for (i = 0; i < 4; ++i)
1425 for (j = 0; j < 4; ++j)
1427 x = 80 * ((2 * j) + 1);
1428 y = 60 * ((2 * i) + 1);
1429 color = get_surface_color(rt, x, y);
1430 ok(compare_color(color, 0x0000ff00, 1),
1431 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1434 IDirectDrawSurface_Release(rt);
1436 destroy_viewport(device, viewport);
1437 destroy_material(background);
1438 IDirect3DDevice2_Release(device);
1439 IDirectDraw2_Release(ddraw);
1440 DestroyWindow(window);
1443 static void test_ck_rgba(void)
1445 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1446 static D3DTLVERTEX tquad[] =
1448 {{ 0.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1449 {{ 0.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1450 {{640.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1451 {{640.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1452 {{ 0.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1453 {{ 0.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1454 {{640.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1455 {{640.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1459 D3DCOLOR fill_color;
1467 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x000000ff},
1468 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x000000ff},
1469 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00},
1470 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00},
1471 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00807f00},
1472 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x0000ff00},
1473 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00},
1474 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00},
1477 D3DTEXTUREHANDLE texture_handle;
1478 IDirect3DMaterial2 *background;
1479 IDirectDrawSurface *surface;
1480 IDirect3DViewport2 *viewport;
1481 IDirect3DTexture2 *texture;
1482 DDSURFACEDESC surface_desc;
1483 IDirect3DDevice2 *device;
1484 IDirectDrawSurface *rt;
1485 IDirectDraw2 *ddraw;
1492 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1493 0, 0, 640, 480, 0, 0, 0, 0);
1494 if (!(ddraw = create_ddraw()))
1496 skip("Failed to create ddraw object, skipping test.\n");
1497 DestroyWindow(window);
1500 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1502 skip("Failed to create D3D device, skipping test.\n");
1503 IDirectDraw2_Release(ddraw);
1504 DestroyWindow(window);
1508 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1509 viewport = create_viewport(device, 0, 0, 640, 480);
1510 viewport_set_background(device, viewport, background);
1511 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1512 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1514 memset(&surface_desc, 0, sizeof(surface_desc));
1515 surface_desc.dwSize = sizeof(surface_desc);
1516 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1517 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1518 surface_desc.dwWidth = 256;
1519 surface_desc.dwHeight = 256;
1520 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1521 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1522 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1523 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1524 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1525 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1526 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1527 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1528 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1529 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1530 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1531 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
1532 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1533 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
1534 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1535 IDirect3DTexture2_Release(texture);
1537 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1538 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1539 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1540 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1541 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1542 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1544 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1545 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1547 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
1549 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1550 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1551 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1552 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1554 memset(&fx, 0, sizeof(fx));
1555 fx.dwSize = sizeof(fx);
1556 U5(fx).dwFillColor = tests[i].fill_color;
1557 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1558 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1560 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
1561 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1562 hr = IDirect3DDevice2_BeginScene(device);
1563 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1564 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[0], 4, 0);
1565 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1566 hr = IDirect3DDevice2_EndScene(device);
1567 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1569 color = get_surface_color(rt, 320, 240);
1571 todo_wine ok(compare_color(color, tests[i].result1, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1572 tests[i].result1, i, color);
1574 ok(compare_color(color, tests[i].result1, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1575 tests[i].result1, i, color);
1577 U5(fx).dwFillColor = 0xff0000ff;
1578 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1579 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1581 hr = IDirect3DDevice2_BeginScene(device);
1582 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1583 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[4], 4, 0);
1584 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1585 hr = IDirect3DDevice2_EndScene(device);
1586 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1588 /* This tests that fragments that are masked out by the color key are
1589 * discarded, instead of just fully transparent. */
1590 color = get_surface_color(rt, 320, 240);
1592 todo_wine ok(compare_color(color, tests[i].result2, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1593 tests[i].result2, i, color);
1595 ok(compare_color(color, tests[i].result2, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1596 tests[i].result2, i, color);
1599 IDirectDrawSurface_Release(rt);
1600 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1601 ok(SUCCEEDED(hr), "Failed to unset texture, hr %#x.\n", hr);
1602 IDirectDrawSurface_Release(surface);
1603 destroy_viewport(device, viewport);
1604 destroy_material(background);
1605 IDirect3DDevice2_Release(device);
1606 IDirectDraw2_Release(ddraw);
1607 DestroyWindow(window);
1610 static void test_ck_default(void)
1612 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1613 static D3DTLVERTEX tquad[] =
1615 {{ 0.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1616 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1617 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1618 {{640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1620 IDirectDrawSurface *surface, *rt;
1621 D3DTEXTUREHANDLE texture_handle;
1622 IDirect3DMaterial2 *background;
1623 IDirect3DViewport2 *viewport;
1624 DDSURFACEDESC surface_desc;
1625 IDirect3DTexture2 *texture;
1626 IDirect3DDevice2 *device;
1627 IDirectDraw2 *ddraw;
1634 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1635 0, 0, 640, 480, 0, 0, 0, 0);
1637 if (!(ddraw = create_ddraw()))
1639 skip("Failed to create ddraw object, skipping test.\n");
1640 DestroyWindow(window);
1643 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1645 skip("Failed to create D3D device, skipping test.\n");
1646 IDirectDraw2_Release(ddraw);
1647 DestroyWindow(window);
1651 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1652 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1654 background = create_diffuse_material(device, 0.0, 1.0f, 0.0f, 1.0f);
1655 viewport = create_viewport(device, 0, 0, 640, 480);
1656 viewport_set_background(device, viewport, background);
1657 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1658 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1660 memset(&surface_desc, 0, sizeof(surface_desc));
1661 surface_desc.dwSize = sizeof(surface_desc);
1662 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1663 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1664 surface_desc.dwWidth = 256;
1665 surface_desc.dwHeight = 256;
1666 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1667 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
1668 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1669 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1670 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1671 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1672 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
1673 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
1674 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1675 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1676 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
1677 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1678 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
1679 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1680 IDirect3DTexture_Release(texture);
1682 memset(&fx, 0, sizeof(fx));
1683 fx.dwSize = sizeof(fx);
1684 U5(fx).dwFillColor = 0x000000ff;
1685 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1686 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
1688 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1689 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1690 hr = IDirect3DDevice2_BeginScene(device);
1691 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1692 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1693 ok(SUCCEEDED(hr), "Failed to set texture handle, hr %#x.\n", hr);
1694 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1695 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1696 ok(!value, "Got unexpected color keying state %#x.\n", value);
1697 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[0], 4, 0);
1698 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1699 hr = IDirect3DDevice2_EndScene(device);
1700 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1701 color = get_surface_color(rt, 320, 240);
1702 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1704 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1705 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1706 hr = IDirect3DDevice2_BeginScene(device);
1707 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1708 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
1709 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1710 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[0], 4, 0);
1711 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1712 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1713 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1714 ok(!!value, "Got unexpected color keying state %#x.\n", value);
1715 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1716 ok(SUCCEEDED(hr), "Failed to set texture handle, hr %#x.\n", hr);
1717 hr = IDirect3DDevice2_EndScene(device);
1718 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1719 color = get_surface_color(rt, 320, 240);
1720 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1722 IDirectDrawSurface_Release(surface);
1723 destroy_viewport(device, viewport);
1724 destroy_material(background);
1725 IDirectDrawSurface_Release(rt);
1726 IDirect3DDevice2_Release(device);
1727 IDirectDraw2_Release(ddraw);
1728 DestroyWindow(window);
1734 REFIID refcount_iid;
1738 static void test_qi(const char *test_name, IUnknown *base_iface,
1739 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
1741 ULONG refcount, expected_refcount;
1742 IUnknown *iface1, *iface2;
1746 for (i = 0; i < entry_count; ++i)
1748 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
1749 ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
1752 for (j = 0; j < entry_count; ++j)
1754 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
1755 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
1758 expected_refcount = 0;
1759 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
1760 ++expected_refcount;
1761 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
1762 ++expected_refcount;
1763 refcount = IUnknown_Release(iface2);
1764 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
1765 refcount, test_name, i, j, expected_refcount);
1769 expected_refcount = 0;
1770 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
1771 ++expected_refcount;
1772 refcount = IUnknown_Release(iface1);
1773 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
1774 refcount, test_name, i, expected_refcount);
1779 static void test_surface_qi(void)
1781 static const struct qi_test tests[] =
1783 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface, S_OK },
1784 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface, S_OK },
1785 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
1786 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1787 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
1788 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
1789 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
1790 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
1791 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
1792 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
1793 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
1794 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
1795 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
1796 {&IID_IDirect3D7, NULL, E_INVALIDARG },
1797 {&IID_IDirect3D3, NULL, E_INVALIDARG },
1798 {&IID_IDirect3D2, NULL, E_INVALIDARG },
1799 {&IID_IDirect3D, NULL, E_INVALIDARG },
1800 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
1801 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
1802 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
1803 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
1804 {&IID_IDirectDraw, NULL, E_INVALIDARG },
1805 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
1806 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
1807 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
1808 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
1809 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
1810 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
1811 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
1812 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
1813 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
1814 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
1815 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
1816 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
1817 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
1820 IDirectDrawSurface *surface;
1821 DDSURFACEDESC surface_desc;
1822 IDirect3DDevice2 *device;
1823 IDirectDraw2 *ddraw;
1827 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
1829 win_skip("DirectDrawCreateEx not available, skipping test.\n");
1833 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1834 0, 0, 640, 480, 0, 0, 0, 0);
1835 if (!(ddraw = create_ddraw()))
1837 skip("Failed to create a ddraw object, skipping test.\n");
1838 DestroyWindow(window);
1841 /* Try to create a D3D device to see if the ddraw implementation supports
1842 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
1843 * doesn't support e.g. the IDirect3DTexture interfaces. */
1844 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1846 skip("Failed to create D3D device, skipping test.\n");
1847 IDirectDraw2_Release(ddraw);
1848 DestroyWindow(window);
1851 IDirect3DDevice_Release(device);
1853 memset(&surface_desc, 0, sizeof(surface_desc));
1854 surface_desc.dwSize = sizeof(surface_desc);
1855 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1856 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1857 surface_desc.dwWidth = 512;
1858 surface_desc.dwHeight = 512;
1859 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1860 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1862 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface, tests, sizeof(tests) / sizeof(*tests));
1864 IDirectDrawSurface_Release(surface);
1865 IDirectDraw2_Release(ddraw);
1866 DestroyWindow(window);
1869 static void test_device_qi(void)
1871 static const struct qi_test tests[] =
1873 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
1874 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
1875 {&IID_IDirectDrawGammaControl, NULL, E_NOINTERFACE},
1876 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1877 {&IID_IDirectDrawSurface7, NULL, E_NOINTERFACE},
1878 {&IID_IDirectDrawSurface4, NULL, E_NOINTERFACE},
1879 {&IID_IDirectDrawSurface3, NULL, E_NOINTERFACE},
1880 {&IID_IDirectDrawSurface2, NULL, E_NOINTERFACE},
1881 {&IID_IDirectDrawSurface, NULL, E_NOINTERFACE},
1882 {&IID_IDirect3DDevice7, NULL, E_NOINTERFACE},
1883 {&IID_IDirect3DDevice3, NULL, E_NOINTERFACE},
1884 {&IID_IDirect3DDevice2, &IID_IDirect3DDevice2, S_OK },
1885 {&IID_IDirect3DDevice, &IID_IDirect3DDevice2, S_OK },
1886 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
1887 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
1888 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
1889 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
1890 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
1891 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
1892 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
1893 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
1894 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
1895 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
1896 {&IID_IDirect3D, NULL, E_NOINTERFACE},
1897 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
1898 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
1899 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
1900 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
1901 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
1902 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
1903 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
1904 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
1905 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
1906 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
1907 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
1908 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
1909 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
1910 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
1911 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
1912 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
1913 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
1914 {&IID_IUnknown, &IID_IDirect3DDevice2, S_OK },
1917 IDirect3DDevice2 *device;
1918 IDirectDraw2 *ddraw;
1921 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1922 0, 0, 640, 480, 0, 0, 0, 0);
1923 if (!(ddraw = create_ddraw()))
1925 skip("Failed to create ddraw object, skipping test.\n");
1926 DestroyWindow(window);
1929 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1931 skip("Failed to create D3D device, skipping test.\n");
1932 IDirectDraw2_Release(ddraw);
1933 DestroyWindow(window);
1937 test_qi("device_qi", (IUnknown *)device, &IID_IDirect3DDevice2, tests, sizeof(tests) / sizeof(*tests));
1939 IDirect3DDevice2_Release(device);
1940 IDirectDraw2_Release(ddraw);
1941 DestroyWindow(window);
1944 static void test_wndproc(void)
1946 LONG_PTR proc, ddraw_proc;
1947 IDirectDraw2 *ddraw;
1953 static const UINT messages[] =
1955 WM_WINDOWPOSCHANGING,
1958 WM_WINDOWPOSCHANGING,
1964 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
1965 if (!(ddraw = create_ddraw()))
1967 skip("Failed to create IDirectDraw2 object, skipping tests.\n");
1971 wc.lpfnWndProc = test_proc;
1972 wc.lpszClassName = "ddraw_test_wndproc_wc";
1973 ok(RegisterClassA(&wc), "Failed to register window class.\n");
1975 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
1976 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
1978 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1979 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1980 (LONG_PTR)test_proc, proc);
1981 expect_messages = messages;
1982 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1983 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1984 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
1985 expect_messages = NULL;
1986 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1987 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1988 (LONG_PTR)test_proc, proc);
1989 ref = IDirectDraw2_Release(ddraw);
1990 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1991 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1992 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1993 (LONG_PTR)test_proc, proc);
1995 /* DDSCL_NORMAL doesn't. */
1996 ddraw = create_ddraw();
1997 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1998 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1999 (LONG_PTR)test_proc, proc);
2000 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2001 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2002 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2003 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2004 (LONG_PTR)test_proc, proc);
2005 ref = IDirectDraw2_Release(ddraw);
2006 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2007 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2008 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2009 (LONG_PTR)test_proc, proc);
2011 /* The original window proc is only restored by ddraw if the current
2012 * window proc matches the one ddraw set. This also affects switching
2013 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
2014 ddraw = create_ddraw();
2015 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2016 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2017 (LONG_PTR)test_proc, proc);
2018 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2019 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2020 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2021 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2022 (LONG_PTR)test_proc, proc);
2024 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2025 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2026 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2027 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2028 (LONG_PTR)test_proc, proc);
2029 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2030 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2031 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2032 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2033 (LONG_PTR)test_proc, proc);
2034 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2035 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2036 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2037 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2038 (LONG_PTR)DefWindowProcA, proc);
2039 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2040 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2041 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc);
2042 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2043 (LONG_PTR)DefWindowProcA, proc);
2044 ref = IDirectDraw2_Release(ddraw);
2045 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2046 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2047 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2048 (LONG_PTR)test_proc, proc);
2050 ddraw = create_ddraw();
2051 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2052 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2053 (LONG_PTR)test_proc, proc);
2054 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2055 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2056 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2057 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2058 (LONG_PTR)test_proc, proc);
2059 ref = IDirectDraw2_Release(ddraw);
2060 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2061 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2062 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2063 (LONG_PTR)DefWindowProcA, proc);
2065 fix_wndproc(window, (LONG_PTR)test_proc);
2066 expect_messages = NULL;
2067 DestroyWindow(window);
2068 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2071 static void test_window_style(void)
2073 LONG style, exstyle, tmp;
2074 RECT fullscreen_rect, r;
2075 IDirectDraw2 *ddraw;
2080 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2081 0, 0, 100, 100, 0, 0, 0, 0);
2082 if (!(ddraw = create_ddraw()))
2084 skip("Failed to create a ddraw object, skipping test.\n");
2085 DestroyWindow(window);
2089 style = GetWindowLongA(window, GWL_STYLE);
2090 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
2091 SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2093 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2094 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2096 tmp = GetWindowLongA(window, GWL_STYLE);
2097 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2098 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2099 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2101 GetWindowRect(window, &r);
2102 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2103 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2104 r.left, r.top, r.right, r.bottom);
2105 GetClientRect(window, &r);
2106 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2108 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2109 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2111 tmp = GetWindowLongA(window, GWL_STYLE);
2112 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2113 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2114 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2116 ref = IDirectDraw2_Release(ddraw);
2117 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2119 DestroyWindow(window);
2122 static void test_redundant_mode_set(void)
2124 DDSURFACEDESC surface_desc = {0};
2125 IDirectDraw2 *ddraw;
2131 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2132 0, 0, 100, 100, 0, 0, 0, 0);
2133 if (!(ddraw = create_ddraw()))
2135 skip("Failed to create a ddraw object, skipping test.\n");
2136 DestroyWindow(window);
2140 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2141 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2143 surface_desc.dwSize = sizeof(surface_desc);
2144 hr = IDirectDraw2_GetDisplayMode(ddraw, &surface_desc);
2145 ok(SUCCEEDED(hr), "GetDipslayMode failed, hr %#x.\n", hr);
2147 hr = IDirectDraw2_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2148 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount, 0, 0);
2149 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2151 GetWindowRect(window, &r);
2154 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
2155 GetWindowRect(window, &s);
2156 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2157 r.left, r.top, r.right, r.bottom,
2158 s.left, s.top, s.right, s.bottom);
2160 hr = IDirectDraw2_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2161 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount, 0, 0);
2162 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2164 GetWindowRect(window, &s);
2165 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2166 r.left, r.top, r.right, r.bottom,
2167 s.left, s.top, s.right, s.bottom);
2169 ref = IDirectDraw2_Release(ddraw);
2170 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2172 DestroyWindow(window);
2175 static SIZE screen_size;
2177 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2179 if (message == WM_SIZE)
2181 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2182 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2185 return test_proc(hwnd, message, wparam, lparam);
2188 static void test_coop_level_mode_set(void)
2190 IDirectDrawSurface *primary;
2191 RECT fullscreen_rect, r, s;
2192 IDirectDraw2 *ddraw;
2199 static const UINT exclusive_messages[] =
2201 WM_WINDOWPOSCHANGING,
2202 WM_WINDOWPOSCHANGED,
2208 static const UINT normal_messages[] =
2214 if (!(ddraw = create_ddraw()))
2216 skip("Failed to create a ddraw object, skipping test.\n");
2220 wc.lpfnWndProc = mode_set_proc;
2221 wc.lpszClassName = "ddraw_test_wndproc_wc";
2222 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2224 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
2225 0, 0, 100, 100, 0, 0, 0, 0);
2227 SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2228 SetRect(&s, 0, 0, 640, 480);
2230 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2231 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2233 GetWindowRect(window, &r);
2234 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2235 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2236 r.left, r.top, r.right, r.bottom);
2238 memset(&ddsd, 0, sizeof(ddsd));
2239 ddsd.dwSize = sizeof(ddsd);
2240 ddsd.dwFlags = DDSD_CAPS;
2241 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2243 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2244 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2245 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2246 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2247 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2248 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2249 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2250 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2252 GetWindowRect(window, &r);
2253 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2254 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2255 r.left, r.top, r.right, r.bottom);
2257 expect_messages = exclusive_messages;
2261 hr = IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 32, 0, 0);
2262 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2264 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2265 expect_messages = NULL;
2266 ok(screen_size.cx == s.right && screen_size.cy == s.bottom,
2267 "Expected screen size %ux%u, got %ux%u.\n",
2268 s.right, s.bottom, screen_size.cx, screen_size.cy);
2270 GetWindowRect(window, &r);
2271 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2272 s.left, s.top, s.right, s.bottom,
2273 r.left, r.top, r.right, r.bottom);
2275 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2276 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2277 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2278 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2279 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2280 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2281 IDirectDrawSurface_Release(primary);
2283 memset(&ddsd, 0, sizeof(ddsd));
2284 ddsd.dwSize = sizeof(ddsd);
2285 ddsd.dwFlags = DDSD_CAPS;
2286 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2288 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2289 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2290 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2291 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2292 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2293 s.right - s.left, ddsd.dwWidth);
2294 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2295 s.bottom - s.top, ddsd.dwHeight);
2297 GetWindowRect(window, &r);
2298 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2299 s.left, s.top, s.right, s.bottom,
2300 r.left, r.top, r.right, r.bottom);
2302 expect_messages = exclusive_messages;
2306 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2307 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2309 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2310 expect_messages = NULL;
2311 ok(screen_size.cx == fullscreen_rect.right && screen_size.cy == fullscreen_rect.bottom,
2312 "Expected screen size %ux%u, got %ux%u.\n",
2313 fullscreen_rect.right, fullscreen_rect.bottom, screen_size.cx, screen_size.cy);
2315 GetWindowRect(window, &r);
2316 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2317 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2318 r.left, r.top, r.right, r.bottom);
2320 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2321 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2322 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2323 s.right - s.left, ddsd.dwWidth);
2324 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2325 s.bottom - s.top, ddsd.dwHeight);
2326 IDirectDrawSurface_Release(primary);
2328 memset(&ddsd, 0, sizeof(ddsd));
2329 ddsd.dwSize = sizeof(ddsd);
2330 ddsd.dwFlags = DDSD_CAPS;
2331 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2333 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2334 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2335 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2336 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2337 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2338 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2339 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2340 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2342 GetWindowRect(window, &r);
2343 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2344 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2345 r.left, r.top, r.right, r.bottom);
2347 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2348 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2350 GetWindowRect(window, &r);
2351 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2352 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2353 r.left, r.top, r.right, r.bottom);
2355 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2356 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2357 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2358 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2359 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2360 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2361 IDirectDrawSurface_Release(primary);
2363 memset(&ddsd, 0, sizeof(ddsd));
2364 ddsd.dwSize = sizeof(ddsd);
2365 ddsd.dwFlags = DDSD_CAPS;
2366 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2368 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2369 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2370 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2371 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2372 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2373 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2374 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2375 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2377 GetWindowRect(window, &r);
2378 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2379 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2380 r.left, r.top, r.right, r.bottom);
2382 expect_messages = normal_messages;
2386 hr = IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 32, 0, 0);
2387 ok(SUCCEEDED(hr) || broken(hr == DDERR_NOEXCLUSIVEMODE) /* NT4 testbot */,
2388 "SetDipslayMode failed, hr %#x.\n", hr);
2389 if (hr == DDERR_NOEXCLUSIVEMODE)
2391 win_skip("Broken SetDisplayMode(), skipping remaining tests.\n");
2392 IDirectDrawSurface_Release(primary);
2393 IDirectDraw2_Release(ddraw);
2397 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2398 expect_messages = NULL;
2399 ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2401 GetWindowRect(window, &r);
2402 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2403 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2404 r.left, r.top, r.right, r.bottom);
2406 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2407 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2408 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2409 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2410 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2411 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2412 IDirectDrawSurface_Release(primary);
2414 memset(&ddsd, 0, sizeof(ddsd));
2415 ddsd.dwSize = sizeof(ddsd);
2416 ddsd.dwFlags = DDSD_CAPS;
2417 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2419 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2420 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2421 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2422 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2423 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2424 s.right - s.left, ddsd.dwWidth);
2425 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2426 s.bottom - s.top, ddsd.dwHeight);
2428 GetWindowRect(window, &r);
2429 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2430 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2431 r.left, r.top, r.right, r.bottom);
2433 expect_messages = normal_messages;
2437 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2438 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2440 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2441 expect_messages = NULL;
2442 ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2444 GetWindowRect(window, &r);
2445 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2446 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2447 r.left, r.top, r.right, r.bottom);
2449 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2450 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2451 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2452 s.right - s.left, ddsd.dwWidth);
2453 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2454 s.bottom - s.top, ddsd.dwHeight);
2455 IDirectDrawSurface_Release(primary);
2457 memset(&ddsd, 0, sizeof(ddsd));
2458 ddsd.dwSize = sizeof(ddsd);
2459 ddsd.dwFlags = DDSD_CAPS;
2460 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2462 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2463 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2464 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2465 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2466 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2467 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2468 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2469 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2471 GetWindowRect(window, &r);
2472 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2473 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2474 r.left, r.top, r.right, r.bottom);
2476 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
2477 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
2478 * not DDSCL_FULLSCREEN. */
2479 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2480 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2482 GetWindowRect(window, &r);
2483 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2484 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2485 r.left, r.top, r.right, r.bottom);
2487 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2488 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2489 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2490 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2491 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2492 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2493 IDirectDrawSurface_Release(primary);
2495 memset(&ddsd, 0, sizeof(ddsd));
2496 ddsd.dwSize = sizeof(ddsd);
2497 ddsd.dwFlags = DDSD_CAPS;
2498 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2500 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2501 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2502 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2503 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2504 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2505 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2506 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2507 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2509 GetWindowRect(window, &r);
2510 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2511 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2512 r.left, r.top, r.right, r.bottom);
2514 expect_messages = normal_messages;
2518 hr = IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 32, 0, 0);
2519 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2521 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2522 expect_messages = NULL;
2523 ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2525 GetWindowRect(window, &r);
2526 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2527 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2528 r.left, r.top, r.right, r.bottom);
2530 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2531 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2532 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2533 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2534 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2535 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2536 IDirectDrawSurface_Release(primary);
2538 memset(&ddsd, 0, sizeof(ddsd));
2539 ddsd.dwSize = sizeof(ddsd);
2540 ddsd.dwFlags = DDSD_CAPS;
2541 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2543 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2544 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2545 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2546 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2547 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2548 s.right - s.left, ddsd.dwWidth);
2549 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2550 s.bottom - s.top, ddsd.dwHeight);
2552 GetWindowRect(window, &r);
2553 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2554 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2555 r.left, r.top, r.right, r.bottom);
2557 expect_messages = normal_messages;
2561 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2562 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2564 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2565 expect_messages = NULL;
2566 ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2568 GetWindowRect(window, &r);
2569 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2570 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2571 r.left, r.top, r.right, r.bottom);
2573 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2574 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2575 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2576 s.right - s.left, ddsd.dwWidth);
2577 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2578 s.bottom - s.top, ddsd.dwHeight);
2579 IDirectDrawSurface_Release(primary);
2581 memset(&ddsd, 0, sizeof(ddsd));
2582 ddsd.dwSize = sizeof(ddsd);
2583 ddsd.dwFlags = DDSD_CAPS;
2584 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2586 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2587 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2588 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2589 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2590 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2591 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2592 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2593 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2594 IDirectDrawSurface_Release(primary);
2596 GetWindowRect(window, &r);
2597 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2598 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2599 r.left, r.top, r.right, r.bottom);
2601 ref = IDirectDraw2_Release(ddraw);
2602 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2604 GetWindowRect(window, &r);
2605 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2606 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2607 r.left, r.top, r.right, r.bottom);
2610 expect_messages = NULL;
2611 DestroyWindow(window);
2612 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2615 static void test_coop_level_mode_set_multi(void)
2617 IDirectDraw2 *ddraw1, *ddraw2;
2618 UINT orig_w, orig_h, w, h;
2623 if (!(ddraw1 = create_ddraw()))
2625 skip("Failed to create a ddraw object, skipping test.\n");
2629 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2630 0, 0, 100, 100, 0, 0, 0, 0);
2632 orig_w = GetSystemMetrics(SM_CXSCREEN);
2633 orig_h = GetSystemMetrics(SM_CYSCREEN);
2635 /* With just a single ddraw object, the display mode is restored on
2637 hr = IDirectDraw2_SetDisplayMode(ddraw1, 800, 600, 32, 0, 0);
2638 ok(SUCCEEDED(hr) || broken(hr == DDERR_NOEXCLUSIVEMODE) /* NT4 testbot */,
2639 "SetDipslayMode failed, hr %#x.\n", hr);
2640 if (hr == DDERR_NOEXCLUSIVEMODE)
2642 win_skip("Broken SetDisplayMode(), skipping test.\n");
2643 IDirectDraw2_Release(ddraw1);
2644 DestroyWindow(window);
2647 w = GetSystemMetrics(SM_CXSCREEN);
2648 ok(w == 800, "Got unexpected screen width %u.\n", w);
2649 h = GetSystemMetrics(SM_CYSCREEN);
2650 ok(h == 600, "Got unexpected screen height %u.\n", h);
2652 ref = IDirectDraw2_Release(ddraw1);
2653 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2654 w = GetSystemMetrics(SM_CXSCREEN);
2655 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2656 h = GetSystemMetrics(SM_CYSCREEN);
2657 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2659 /* When there are multiple ddraw objects, the display mode is restored to
2660 * the initial mode, before the first SetDisplayMode() call. */
2661 ddraw1 = create_ddraw();
2662 hr = IDirectDraw2_SetDisplayMode(ddraw1, 800, 600, 32, 0, 0);
2663 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2664 w = GetSystemMetrics(SM_CXSCREEN);
2665 ok(w == 800, "Got unexpected screen width %u.\n", w);
2666 h = GetSystemMetrics(SM_CYSCREEN);
2667 ok(h == 600, "Got unexpected screen height %u.\n", h);
2669 ddraw2 = create_ddraw();
2670 hr = IDirectDraw2_SetDisplayMode(ddraw2, 640, 480, 32, 0, 0);
2671 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2672 w = GetSystemMetrics(SM_CXSCREEN);
2673 ok(w == 640, "Got unexpected screen width %u.\n", w);
2674 h = GetSystemMetrics(SM_CYSCREEN);
2675 ok(h == 480, "Got unexpected screen height %u.\n", h);
2677 ref = IDirectDraw2_Release(ddraw2);
2678 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2679 w = GetSystemMetrics(SM_CXSCREEN);
2680 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2681 h = GetSystemMetrics(SM_CYSCREEN);
2682 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2684 ref = IDirectDraw2_Release(ddraw1);
2685 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2686 w = GetSystemMetrics(SM_CXSCREEN);
2687 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2688 h = GetSystemMetrics(SM_CYSCREEN);
2689 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2691 /* Regardless of release ordering. */
2692 ddraw1 = create_ddraw();
2693 hr = IDirectDraw2_SetDisplayMode(ddraw1, 800, 600, 32, 0, 0);
2694 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2695 w = GetSystemMetrics(SM_CXSCREEN);
2696 ok(w == 800, "Got unexpected screen width %u.\n", w);
2697 h = GetSystemMetrics(SM_CYSCREEN);
2698 ok(h == 600, "Got unexpected screen height %u.\n", h);
2700 ddraw2 = create_ddraw();
2701 hr = IDirectDraw2_SetDisplayMode(ddraw2, 640, 480, 32, 0, 0);
2702 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2703 w = GetSystemMetrics(SM_CXSCREEN);
2704 ok(w == 640, "Got unexpected screen width %u.\n", w);
2705 h = GetSystemMetrics(SM_CYSCREEN);
2706 ok(h == 480, "Got unexpected screen height %u.\n", h);
2708 ref = IDirectDraw2_Release(ddraw1);
2709 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2710 w = GetSystemMetrics(SM_CXSCREEN);
2711 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2712 h = GetSystemMetrics(SM_CYSCREEN);
2713 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2715 ref = IDirectDraw2_Release(ddraw2);
2716 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2717 w = GetSystemMetrics(SM_CXSCREEN);
2718 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2719 h = GetSystemMetrics(SM_CYSCREEN);
2720 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2722 /* But only for ddraw objects that called SetDisplayMode(). */
2723 ddraw1 = create_ddraw();
2724 ddraw2 = create_ddraw();
2725 hr = IDirectDraw2_SetDisplayMode(ddraw2, 640, 480, 32, 0, 0);
2726 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2727 w = GetSystemMetrics(SM_CXSCREEN);
2728 ok(w == 640, "Got unexpected screen width %u.\n", w);
2729 h = GetSystemMetrics(SM_CYSCREEN);
2730 ok(h == 480, "Got unexpected screen height %u.\n", h);
2732 ref = IDirectDraw2_Release(ddraw1);
2733 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2734 w = GetSystemMetrics(SM_CXSCREEN);
2735 ok(w == 640, "Got unexpected screen width %u.\n", w);
2736 h = GetSystemMetrics(SM_CYSCREEN);
2737 ok(h == 480, "Got unexpected screen height %u.\n", h);
2739 ref = IDirectDraw2_Release(ddraw2);
2740 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2741 w = GetSystemMetrics(SM_CXSCREEN);
2742 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2743 h = GetSystemMetrics(SM_CYSCREEN);
2744 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2746 /* If there's a ddraw object that's currently in exclusive mode, it blocks
2747 * restoring the display mode. */
2748 ddraw1 = create_ddraw();
2749 hr = IDirectDraw2_SetDisplayMode(ddraw1, 800, 600, 32, 0, 0);
2750 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2751 w = GetSystemMetrics(SM_CXSCREEN);
2752 ok(w == 800, "Got unexpected screen width %u.\n", w);
2753 h = GetSystemMetrics(SM_CYSCREEN);
2754 ok(h == 600, "Got unexpected screen height %u.\n", h);
2756 ddraw2 = create_ddraw();
2757 hr = IDirectDraw2_SetDisplayMode(ddraw2, 640, 480, 32, 0, 0);
2758 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2759 w = GetSystemMetrics(SM_CXSCREEN);
2760 ok(w == 640, "Got unexpected screen width %u.\n", w);
2761 h = GetSystemMetrics(SM_CYSCREEN);
2762 ok(h == 480, "Got unexpected screen height %u.\n", h);
2764 hr = IDirectDraw2_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2765 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2767 ref = IDirectDraw2_Release(ddraw1);
2768 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2769 w = GetSystemMetrics(SM_CXSCREEN);
2770 ok(w == 640, "Got unexpected screen width %u.\n", w);
2771 h = GetSystemMetrics(SM_CYSCREEN);
2772 ok(h == 480, "Got unexpected screen height %u.\n", h);
2774 ref = IDirectDraw2_Release(ddraw2);
2775 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2776 w = GetSystemMetrics(SM_CXSCREEN);
2777 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2778 h = GetSystemMetrics(SM_CYSCREEN);
2779 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2781 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
2782 ddraw1 = create_ddraw();
2783 hr = IDirectDraw2_SetDisplayMode(ddraw1, 800, 600, 32, 0, 0);
2784 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2785 w = GetSystemMetrics(SM_CXSCREEN);
2786 ok(w == 800, "Got unexpected screen width %u.\n", w);
2787 h = GetSystemMetrics(SM_CYSCREEN);
2788 ok(h == 600, "Got unexpected screen height %u.\n", h);
2790 hr = IDirectDraw2_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2791 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2793 ddraw2 = create_ddraw();
2794 hr = IDirectDraw2_SetDisplayMode(ddraw2, 640, 480, 32, 0, 0);
2795 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
2797 ref = IDirectDraw2_Release(ddraw1);
2798 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2799 w = GetSystemMetrics(SM_CXSCREEN);
2800 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2801 h = GetSystemMetrics(SM_CYSCREEN);
2802 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2804 ref = IDirectDraw2_Release(ddraw2);
2805 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2806 w = GetSystemMetrics(SM_CXSCREEN);
2807 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2808 h = GetSystemMetrics(SM_CYSCREEN);
2809 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2811 DestroyWindow(window);
2814 static void test_initialize(void)
2816 IDirectDraw2 *ddraw;
2819 if (!(ddraw = create_ddraw()))
2821 skip("Failed to create a ddraw object, skipping test.\n");
2825 hr = IDirectDraw2_Initialize(ddraw, NULL);
2826 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
2827 IDirectDraw2_Release(ddraw);
2830 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw2, (void **)&ddraw);
2831 ok(SUCCEEDED(hr), "Failed to create IDirectDraw2 instance, hr %#x.\n", hr);
2832 hr = IDirectDraw2_Initialize(ddraw, NULL);
2833 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
2834 hr = IDirectDraw2_Initialize(ddraw, NULL);
2835 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
2836 IDirectDraw2_Release(ddraw);
2840 static void test_coop_level_surf_create(void)
2842 IDirectDrawSurface *surface;
2843 IDirectDraw2 *ddraw;
2847 if (!(ddraw = create_ddraw()))
2849 skip("Failed to create a ddraw object, skipping test.\n");
2853 memset(&ddsd, 0, sizeof(ddsd));
2854 ddsd.dwSize = sizeof(ddsd);
2855 ddsd.dwFlags = DDSD_CAPS;
2856 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2857 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
2858 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
2860 IDirectDraw2_Release(ddraw);
2863 static void test_coop_level_multi_window(void)
2865 HWND window1, window2;
2866 IDirectDraw2 *ddraw;
2869 window1 = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
2870 0, 0, 640, 480, 0, 0, 0, 0);
2871 window2 = CreateWindowA("static", "ddraw_test2", WS_OVERLAPPEDWINDOW,
2872 0, 0, 640, 480, 0, 0, 0, 0);
2873 if (!(ddraw = create_ddraw()))
2875 skip("Failed to create a ddraw object, skipping test.\n");
2876 DestroyWindow(window2);
2877 DestroyWindow(window1);
2881 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
2882 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2883 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
2884 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2885 ok(IsWindow(window1), "Window 1 was destroyed.\n");
2886 ok(IsWindow(window2), "Window 2 was destroyed.\n");
2888 IDirectDraw2_Release(ddraw);
2889 DestroyWindow(window2);
2890 DestroyWindow(window1);
2893 static void test_clear_rect_count(void)
2895 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
2896 IDirect3DMaterial2 *white, *red, *green, *blue;
2897 IDirect3DViewport2 *viewport;
2898 IDirect3DDevice2 *device;
2899 IDirectDrawSurface *rt;
2900 IDirectDraw2 *ddraw;
2905 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2906 0, 0, 640, 480, 0, 0, 0, 0);
2907 if (!(ddraw = create_ddraw()))
2909 skip("Failed to create ddraw object, skipping test.\n");
2910 DestroyWindow(window);
2913 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
2915 skip("Failed to create D3D device, skipping test.\n");
2916 IDirectDraw2_Release(ddraw);
2917 DestroyWindow(window);
2921 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
2922 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
2924 white = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
2925 red = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
2926 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
2927 blue = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
2929 viewport = create_viewport(device, 0, 0, 640, 480);
2930 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
2931 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
2933 viewport_set_background(device, viewport, white);
2934 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
2935 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2936 viewport_set_background(device, viewport, red);
2937 hr = IDirect3DViewport2_Clear(viewport, 0, &clear_rect, D3DCLEAR_TARGET);
2938 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2939 viewport_set_background(device, viewport, green);
2940 hr = IDirect3DViewport2_Clear(viewport, 0, NULL, D3DCLEAR_TARGET);
2941 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2942 viewport_set_background(device, viewport, blue);
2943 hr = IDirect3DViewport2_Clear(viewport, 0, &clear_rect, D3DCLEAR_TARGET);
2944 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2946 color = get_surface_color(rt, 320, 240);
2947 ok(compare_color(color, 0x00ffffff, 1), "Got unexpected color 0x%08x.\n", color);
2949 IDirectDrawSurface_Release(rt);
2950 destroy_viewport(device, viewport);
2951 destroy_material(white);
2952 destroy_material(red);
2953 destroy_material(green);
2954 destroy_material(blue);
2955 IDirect3DDevice2_Release(device);
2956 IDirectDraw2_Release(ddraw);
2957 DestroyWindow(window);
2962 test_coop_level_create_device_window();
2964 test_coop_level_d3d_state();
2965 test_surface_interface_mismatch();
2966 test_coop_level_threaded();
2968 test_texture_load_ckey();
2976 test_window_style();
2977 test_redundant_mode_set();
2978 test_coop_level_mode_set();
2979 test_coop_level_mode_set_multi();
2981 test_coop_level_surf_create();
2982 test_coop_level_multi_window();
2983 test_clear_rect_count();