ddraw/tests: Test that DirectDraw doesn't modify the pixel format of the window it...
[wine/multimedia.git] / dlls / ddraw / tests / ddraw2.c
blobea8939894a6a2bb500526afa45413b913ed6792b
1 /*
2 * Copyright 2011-2012 Henri Verbeet for CodeWeavers
3 * Copyright 2012-2014 Stefan Dösinger for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define COBJMACROS
21 #include "wine/test.h"
22 #include "d3d.h"
24 struct create_window_thread_param
26 HWND window;
27 HANDLE window_created;
28 HANDLE destroy_window;
29 HANDLE thread;
32 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
34 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
35 c1 >>= 8; c2 >>= 8;
36 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
37 c1 >>= 8; c2 >>= 8;
38 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
39 c1 >>= 8; c2 >>= 8;
40 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
41 return TRUE;
44 static DWORD WINAPI create_window_thread_proc(void *param)
46 struct create_window_thread_param *p = param;
47 DWORD res;
48 BOOL ret;
50 p->window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
51 0, 0, 640, 480, 0, 0, 0, 0);
52 ret = SetEvent(p->window_created);
53 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
55 for (;;)
57 MSG msg;
59 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
60 DispatchMessageA(&msg);
61 res = WaitForSingleObject(p->destroy_window, 100);
62 if (res == WAIT_OBJECT_0)
63 break;
64 if (res != WAIT_TIMEOUT)
66 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
67 break;
71 DestroyWindow(p->window);
73 return 0;
76 static void create_window_thread(struct create_window_thread_param *p)
78 DWORD res, tid;
80 p->window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
81 ok(!!p->window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
82 p->destroy_window = CreateEventA(NULL, FALSE, FALSE, NULL);
83 ok(!!p->destroy_window, "CreateEvent failed, last error %#x.\n", GetLastError());
84 p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
85 ok(!!p->thread, "Failed to create thread, last error %#x.\n", GetLastError());
86 res = WaitForSingleObject(p->window_created, INFINITE);
87 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
90 static void destroy_window_thread(struct create_window_thread_param *p)
92 SetEvent(p->destroy_window);
93 WaitForSingleObject(p->thread, INFINITE);
94 CloseHandle(p->destroy_window);
95 CloseHandle(p->window_created);
96 CloseHandle(p->thread);
99 static IDirectDrawSurface *get_depth_stencil(IDirect3DDevice2 *device)
101 IDirectDrawSurface *rt, *ret;
102 DDSCAPS caps = {DDSCAPS_ZBUFFER};
103 HRESULT hr;
105 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
106 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
107 hr = IDirectDrawSurface_GetAttachedSurface(rt, &caps, &ret);
108 ok(SUCCEEDED(hr) || hr == DDERR_NOTFOUND, "Failed to get the z buffer, hr %#x.\n", hr);
109 IDirectDrawSurface_Release(rt);
110 return ret;
113 static D3DCOLOR get_surface_color(IDirectDrawSurface *surface, UINT x, UINT y)
115 RECT rect = {x, y, x + 1, y + 1};
116 DDSURFACEDESC surface_desc;
117 D3DCOLOR color;
118 HRESULT hr;
120 memset(&surface_desc, 0, sizeof(surface_desc));
121 surface_desc.dwSize = sizeof(surface_desc);
123 hr = IDirectDrawSurface_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
124 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
125 if (FAILED(hr))
126 return 0xdeadbeef;
128 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
130 hr = IDirectDrawSurface_Unlock(surface, NULL);
131 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
133 return color;
136 static HRESULT CALLBACK enum_z_fmt(GUID *guid, char *description, char *name,
137 D3DDEVICEDESC *hal_desc, D3DDEVICEDESC *hel_desc, void *ctx)
139 DWORD *z_depth = ctx;
141 if (!IsEqualGUID(&IID_IDirect3DHALDevice, guid))
142 return D3DENUMRET_OK;
144 if (hal_desc->dwDeviceZBufferBitDepth & DDBD_32)
145 *z_depth = 32;
146 else if (hal_desc->dwDeviceZBufferBitDepth & DDBD_24)
147 *z_depth = 24;
148 else if (hal_desc->dwDeviceZBufferBitDepth & DDBD_16)
149 *z_depth = 16;
151 return DDENUMRET_OK;
154 static IDirectDraw2 *create_ddraw(void)
156 IDirectDraw2 *ddraw2;
157 IDirectDraw *ddraw1;
158 HRESULT hr;
160 if (FAILED(DirectDrawCreate(NULL, &ddraw1, NULL)))
161 return NULL;
163 hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw2, (void **)&ddraw2);
164 IDirectDraw_Release(ddraw1);
165 if (FAILED(hr))
166 return NULL;
168 return ddraw2;
171 static IDirect3DDevice2 *create_device(IDirectDraw2 *ddraw, HWND window, DWORD coop_level)
173 IDirectDrawSurface *surface, *ds;
174 IDirect3DDevice2 *device = NULL;
175 DDSURFACEDESC surface_desc;
176 DWORD z_depth = 0;
177 IDirect3D2 *d3d;
178 HRESULT hr;
180 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, coop_level);
181 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
183 memset(&surface_desc, 0, sizeof(surface_desc));
184 surface_desc.dwSize = sizeof(surface_desc);
185 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
186 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
187 surface_desc.dwWidth = 640;
188 surface_desc.dwHeight = 480;
190 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
191 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
193 if (coop_level & DDSCL_NORMAL)
195 IDirectDrawClipper *clipper;
197 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
198 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
199 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
200 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
201 hr = IDirectDrawSurface_SetClipper(surface, clipper);
202 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\n", hr);
203 IDirectDrawClipper_Release(clipper);
206 hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d);
207 if (FAILED(hr))
209 IDirectDrawSurface_Release(surface);
210 return NULL;
213 hr = IDirect3D2_EnumDevices(d3d, enum_z_fmt, &z_depth);
214 ok(SUCCEEDED(hr), "Failed to enumerate z-formats, hr %#x.\n", hr);
215 if (FAILED(hr) || !z_depth)
217 IDirect3D2_Release(d3d);
218 IDirectDrawSurface_Release(surface);
219 return NULL;
222 memset(&surface_desc, 0, sizeof(surface_desc));
223 surface_desc.dwSize = sizeof(surface_desc);
224 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
225 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
226 U2(surface_desc).dwZBufferBitDepth = z_depth;
227 surface_desc.dwWidth = 640;
228 surface_desc.dwHeight = 480;
229 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &ds, NULL);
230 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
231 if (FAILED(hr))
233 IDirect3D2_Release(d3d);
234 IDirectDrawSurface_Release(surface);
235 return NULL;
238 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
239 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
240 IDirectDrawSurface_Release(ds);
241 if (FAILED(hr))
243 IDirect3D2_Release(d3d);
244 IDirectDrawSurface_Release(surface);
245 return NULL;
248 hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device);
249 IDirect3D2_Release(d3d);
250 IDirectDrawSurface_Release(surface);
251 if (FAILED(hr))
252 return NULL;
254 return device;
257 static IDirect3DViewport2 *create_viewport(IDirect3DDevice2 *device, UINT x, UINT y, UINT w, UINT h)
259 IDirect3DViewport2 *viewport;
260 D3DVIEWPORT2 vp;
261 IDirect3D2 *d3d;
262 HRESULT hr;
264 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
265 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
266 hr = IDirect3D2_CreateViewport(d3d, &viewport, NULL);
267 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
268 hr = IDirect3DDevice2_AddViewport(device, viewport);
269 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
270 memset(&vp, 0, sizeof(vp));
271 vp.dwSize = sizeof(vp);
272 vp.dwX = x;
273 vp.dwY = y;
274 vp.dwWidth = w;
275 vp.dwHeight = h;
276 vp.dvClipX = -1.0f;
277 vp.dvClipY = 1.0f;
278 vp.dvClipWidth = 2.0f;
279 vp.dvClipHeight = 2.0f;
280 vp.dvMinZ = 0.0f;
281 vp.dvMaxZ = 1.0f;
282 hr = IDirect3DViewport2_SetViewport2(viewport, &vp);
283 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
284 IDirect3D2_Release(d3d);
286 return viewport;
289 static void viewport_set_background(IDirect3DDevice2 *device, IDirect3DViewport2 *viewport,
290 IDirect3DMaterial2 *material)
292 D3DMATERIALHANDLE material_handle;
293 HRESULT hr;
295 hr = IDirect3DMaterial2_GetHandle(material, device, &material_handle);
296 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
297 hr = IDirect3DViewport2_SetBackground(viewport, material_handle);
298 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
301 static void destroy_viewport(IDirect3DDevice2 *device, IDirect3DViewport2 *viewport)
303 HRESULT hr;
305 hr = IDirect3DDevice2_DeleteViewport(device, viewport);
306 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
307 IDirect3DViewport2_Release(viewport);
310 static IDirect3DMaterial2 *create_diffuse_material(IDirect3DDevice2 *device, float r, float g, float b, float a)
312 IDirect3DMaterial2 *material;
313 D3DMATERIAL mat;
314 IDirect3D2 *d3d;
315 HRESULT hr;
317 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
318 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
319 hr = IDirect3D2_CreateMaterial(d3d, &material, NULL);
320 ok(SUCCEEDED(hr), "Failed to create material, hr %#x.\n", hr);
321 memset(&mat, 0, sizeof(mat));
322 mat.dwSize = sizeof(mat);
323 U1(U(mat).diffuse).r = r;
324 U2(U(mat).diffuse).g = g;
325 U3(U(mat).diffuse).b = b;
326 U4(U(mat).diffuse).a = a;
327 hr = IDirect3DMaterial2_SetMaterial(material, &mat);
328 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
329 IDirect3D2_Release(d3d);
331 return material;
334 static void destroy_material(IDirect3DMaterial2 *material)
336 IDirect3DMaterial2_Release(material);
339 static const UINT *expect_messages;
341 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
343 if (expect_messages && message == *expect_messages)
344 ++expect_messages;
346 return DefWindowProcA(hwnd, message, wparam, lparam);
349 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
350 * interface. This prevents subsequent SetCooperativeLevel() calls on a
351 * different window from failing with DDERR_HWNDALREADYSET. */
352 static void fix_wndproc(HWND window, LONG_PTR proc)
354 IDirectDraw2 *ddraw;
355 HRESULT hr;
357 if (!(ddraw = create_ddraw()))
358 return;
360 SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
361 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
362 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
363 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
364 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
366 IDirectDraw2_Release(ddraw);
369 static HRESULT CALLBACK restore_callback(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
371 HRESULT hr = IDirectDrawSurface_Restore(surface);
372 ok(SUCCEEDED(hr), "Failed to restore surface, hr %#x.\n", hr);
373 IDirectDrawSurface_Release(surface);
375 return DDENUMRET_OK;
378 static HRESULT restore_surfaces(IDirectDraw2 *ddraw)
380 return IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
381 NULL, NULL, restore_callback);
384 static void test_coop_level_create_device_window(void)
386 HWND focus_window, device_window;
387 IDirectDraw2 *ddraw;
388 HRESULT hr;
390 focus_window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
391 0, 0, 640, 480, 0, 0, 0, 0);
392 if (!(ddraw = create_ddraw()))
394 skip("Failed to create a ddraw object, skipping test.\n");
395 DestroyWindow(focus_window);
396 return;
399 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
400 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
401 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
402 ok(!device_window, "Unexpected device window found.\n");
403 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
404 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
405 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
406 ok(!device_window, "Unexpected device window found.\n");
407 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
408 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
409 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
410 ok(!device_window, "Unexpected device window found.\n");
411 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
412 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
413 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
414 ok(!device_window, "Unexpected device window found.\n");
415 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
416 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
417 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
418 ok(!device_window, "Unexpected device window found.\n");
420 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
421 if (broken(hr == DDERR_INVALIDPARAMS))
423 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
424 IDirectDraw2_Release(ddraw);
425 DestroyWindow(focus_window);
426 return;
429 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
430 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
431 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
432 ok(!device_window, "Unexpected device window found.\n");
433 hr = IDirectDraw2_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
434 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
435 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
436 ok(!device_window, "Unexpected device window found.\n");
438 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
439 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
440 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
441 ok(!device_window, "Unexpected device window found.\n");
442 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
443 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
444 ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
445 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
446 ok(!!device_window, "Device window not found.\n");
448 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
449 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
450 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
451 ok(!device_window, "Unexpected device window found.\n");
452 hr = IDirectDraw2_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
453 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
454 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
455 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
456 ok(!!device_window, "Device window not found.\n");
458 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
459 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
460 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
461 ok(!device_window, "Unexpected device window found.\n");
462 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
463 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
464 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
465 ok(!device_window, "Unexpected device window found.\n");
466 hr = IDirectDraw2_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
467 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
468 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
469 ok(!device_window, "Unexpected device window found.\n");
470 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
471 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
472 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
473 ok(!!device_window, "Device window not found.\n");
475 IDirectDraw2_Release(ddraw);
476 DestroyWindow(focus_window);
479 static void test_clipper_blt(void)
481 IDirectDrawSurface *src_surface, *dst_surface;
482 RECT client_rect, src_rect;
483 IDirectDrawClipper *clipper;
484 DDSURFACEDESC surface_desc;
485 unsigned int i, j, x, y;
486 IDirectDraw2 *ddraw;
487 RGNDATA *rgn_data;
488 D3DCOLOR color;
489 HRGN r1, r2;
490 HWND window;
491 DDBLTFX fx;
492 HRESULT hr;
493 DWORD *ptr;
494 DWORD ret;
496 static const DWORD src_data[] =
498 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
499 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
500 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
502 static const D3DCOLOR expected1[] =
504 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
505 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
506 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
507 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
509 static const D3DCOLOR expected2[] =
511 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
512 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
513 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
514 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
517 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
518 10, 10, 640, 480, 0, 0, 0, 0);
519 ShowWindow(window, SW_SHOW);
520 if (!(ddraw = create_ddraw()))
522 skip("Failed to create a ddraw object, skipping test.\n");
523 DestroyWindow(window);
524 return;
527 ret = GetClientRect(window, &client_rect);
528 ok(ret, "Failed to get client rect.\n");
529 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
530 ok(ret, "Failed to map client rect.\n");
532 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
533 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
535 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
536 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
537 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
538 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
539 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
540 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
541 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
542 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
543 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
544 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
545 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
546 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
547 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
548 ok(rgn_data->rdh.nCount >= 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
549 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
550 "Got unexpected bounding rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
551 rgn_data->rdh.rcBound.left, rgn_data->rdh.rcBound.top,
552 rgn_data->rdh.rcBound.right, rgn_data->rdh.rcBound.bottom,
553 client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
554 HeapFree(GetProcessHeap(), 0, rgn_data);
556 r1 = CreateRectRgn(0, 0, 320, 240);
557 ok(!!r1, "Failed to create region.\n");
558 r2 = CreateRectRgn(320, 240, 640, 480);
559 ok(!!r2, "Failed to create region.\n");
560 CombineRgn(r1, r1, r2, RGN_OR);
561 ret = GetRegionData(r1, 0, NULL);
562 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
563 ret = GetRegionData(r1, ret, rgn_data);
564 ok(!!ret, "Failed to get region data.\n");
566 DeleteObject(r2);
567 DeleteObject(r1);
569 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
570 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
571 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
572 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
573 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
574 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
576 HeapFree(GetProcessHeap(), 0, rgn_data);
578 memset(&surface_desc, 0, sizeof(surface_desc));
579 surface_desc.dwSize = sizeof(surface_desc);
580 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
581 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
582 surface_desc.dwWidth = 640;
583 surface_desc.dwHeight = 480;
584 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
585 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
586 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
587 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
588 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
589 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
591 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
592 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
593 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
594 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
596 memset(&fx, 0, sizeof(fx));
597 fx.dwSize = sizeof(fx);
598 hr = IDirectDrawSurface_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
599 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
600 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
601 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
603 hr = IDirectDrawSurface_Lock(src_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
604 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
605 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
606 ptr = surface_desc.lpSurface;
607 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
608 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
609 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
610 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
611 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
613 hr = IDirectDrawSurface_SetClipper(dst_surface, clipper);
614 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
616 SetRect(&src_rect, 1, 1, 5, 2);
617 hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
618 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
619 for (i = 0; i < 4; ++i)
621 for (j = 0; j < 4; ++j)
623 x = 80 * ((2 * j) + 1);
624 y = 60 * ((2 * i) + 1);
625 color = get_surface_color(dst_surface, x, y);
626 ok(compare_color(color, expected1[i * 4 + j], 1),
627 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
631 U5(fx).dwFillColor = 0xff0000ff;
632 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
633 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
634 for (i = 0; i < 4; ++i)
636 for (j = 0; j < 4; ++j)
638 x = 80 * ((2 * j) + 1);
639 y = 60 * ((2 * i) + 1);
640 color = get_surface_color(dst_surface, x, y);
641 ok(compare_color(color, expected2[i * 4 + j], 1),
642 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
646 hr = IDirectDrawSurface_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
647 ok(hr == DDERR_BLTFASTCANTCLIP || broken(hr == E_NOTIMPL /* NT4 */), "Got unexpected hr %#x.\n", hr);
649 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
650 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
651 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
652 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
653 DestroyWindow(window);
654 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
655 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
656 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
657 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
658 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
659 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
660 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
661 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
662 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
663 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
664 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
665 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
667 IDirectDrawSurface_Release(dst_surface);
668 IDirectDrawSurface_Release(src_surface);
669 IDirectDrawClipper_Release(clipper);
670 IDirectDraw2_Release(ddraw);
673 static void test_coop_level_d3d_state(void)
675 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
676 IDirectDrawSurface *rt, *surface;
677 IDirect3DMaterial2 *background;
678 IDirect3DViewport2 *viewport;
679 IDirect3DDevice2 *device;
680 D3DMATERIAL material;
681 IDirectDraw2 *ddraw;
682 D3DCOLOR color;
683 DWORD value;
684 HWND window;
685 HRESULT hr;
687 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
688 0, 0, 640, 480, 0, 0, 0, 0);
689 if (!(ddraw = create_ddraw()))
691 skip("Failed to create a ddraw object, skipping test.\n");
692 DestroyWindow(window);
693 return;
695 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
697 skip("Failed to create a 3D device, skipping test.\n");
698 IDirectDraw2_Release(ddraw);
699 DestroyWindow(window);
700 return;
703 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
704 viewport = create_viewport(device, 0, 0, 640, 480);
705 viewport_set_background(device, viewport, background);
707 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
708 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
709 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
710 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
711 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
712 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
713 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
714 ok(!value, "Got unexpected alpha blend enable state %#x.\n", value);
715 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
716 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
717 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
718 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
719 color = get_surface_color(rt, 320, 240);
720 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
722 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
723 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
724 hr = IDirectDrawSurface_IsLost(rt);
725 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
726 hr = restore_surfaces(ddraw);
727 ok(SUCCEEDED(hr), "Failed to restore surfaces, hr %#x.\n", hr);
729 memset(&material, 0, sizeof(material));
730 material.dwSize = sizeof(material);
731 U1(U(material).diffuse).r = 0.0f;
732 U2(U(material).diffuse).g = 1.0f;
733 U3(U(material).diffuse).b = 0.0f;
734 U4(U(material).diffuse).a = 1.0f;
735 hr = IDirect3DMaterial2_SetMaterial(background, &material);
736 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
738 hr = IDirect3DDevice2_GetRenderTarget(device, &surface);
739 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
740 ok(surface == rt, "Got unexpected surface %p.\n", surface);
741 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
742 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
743 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
744 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
745 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
746 ok(!!value, "Got unexpected alpha blend enable state %#x.\n", value);
747 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
748 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
749 color = get_surface_color(rt, 320, 240);
750 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
752 destroy_viewport(device, viewport);
753 destroy_material(background);
754 IDirectDrawSurface_Release(surface);
755 IDirectDrawSurface_Release(rt);
756 IDirect3DDevice2_Release(device);
757 IDirectDraw2_Release(ddraw);
758 DestroyWindow(window);
761 static void test_surface_interface_mismatch(void)
763 IDirectDraw2 *ddraw = NULL;
764 IDirect3D2 *d3d = NULL;
765 IDirectDrawSurface *surface = NULL, *ds;
766 IDirectDrawSurface3 *surface3 = NULL;
767 IDirect3DDevice2 *device = NULL;
768 IDirect3DViewport2 *viewport = NULL;
769 IDirect3DMaterial2 *background = NULL;
770 DDSURFACEDESC surface_desc;
771 DWORD z_depth = 0;
772 ULONG refcount;
773 HRESULT hr;
774 D3DCOLOR color;
775 HWND window;
776 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
778 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
779 0, 0, 640, 480, 0, 0, 0, 0);
781 if (!(ddraw = create_ddraw()))
783 skip("Failed to create a ddraw object, skipping test.\n");
784 goto cleanup;
787 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
788 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
790 memset(&surface_desc, 0, sizeof(surface_desc));
791 surface_desc.dwSize = sizeof(surface_desc);
792 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
793 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
794 surface_desc.dwWidth = 640;
795 surface_desc.dwHeight = 480;
797 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
798 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
800 hr = IDirectDrawSurface2_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
801 if (FAILED(hr))
803 skip("Failed to get the IDirectDrawSurface3 interface, skipping test.\n");
804 goto cleanup;
807 if (FAILED(hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d)))
809 skip("D3D interface is not available, skipping test.\n");
810 goto cleanup;
813 hr = IDirect3D2_EnumDevices(d3d, enum_z_fmt, &z_depth);
814 if (FAILED(hr) || !z_depth)
816 skip("No depth buffer formats available, skipping test.\n");
817 goto cleanup;
820 memset(&surface_desc, 0, sizeof(surface_desc));
821 surface_desc.dwSize = sizeof(surface_desc);
822 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
823 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
824 U2(surface_desc).dwZBufferBitDepth = z_depth;
825 surface_desc.dwWidth = 640;
826 surface_desc.dwHeight = 480;
827 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &ds, NULL);
828 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
829 if (FAILED(hr))
830 goto cleanup;
832 /* Using a different surface interface version still works */
833 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
834 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
835 refcount = IDirectDrawSurface_Release(ds);
836 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
837 if (FAILED(hr))
838 goto cleanup;
840 /* Here too */
841 hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, (IDirectDrawSurface *)surface3, &device);
842 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
843 if (FAILED(hr))
844 goto cleanup;
846 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
847 viewport = create_viewport(device, 0, 0, 640, 480);
848 viewport_set_background(device, viewport, background);
850 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
851 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
852 color = get_surface_color(surface, 320, 240);
853 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
855 cleanup:
856 if (viewport)
857 destroy_viewport(device, viewport);
858 if (background)
859 destroy_material(background);
860 if (surface3) IDirectDrawSurface3_Release(surface3);
861 if (surface) IDirectDrawSurface_Release(surface);
862 if (device) IDirect3DDevice2_Release(device);
863 if (d3d) IDirect3D2_Release(d3d);
864 if (ddraw) IDirectDraw2_Release(ddraw);
865 DestroyWindow(window);
868 static void test_coop_level_threaded(void)
870 struct create_window_thread_param p;
871 IDirectDraw2 *ddraw;
872 HRESULT hr;
874 if (!(ddraw = create_ddraw()))
876 skip("Failed to create a ddraw object, skipping test.\n");
877 return;
879 create_window_thread(&p);
881 hr = IDirectDraw2_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
882 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
884 IDirectDraw2_Release(ddraw);
885 destroy_window_thread(&p);
888 static void test_depth_blit(void)
890 static D3DLVERTEX quad1[] =
892 {{-1.0}, { 1.0}, {0.50f}, 0, {0xff00ff00}},
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}},
897 static const D3DCOLOR expected_colors[4][4] =
899 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
900 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
901 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
902 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
904 DDSURFACEDESC ddsd_new, ddsd_existing;
906 IDirect3DDevice2 *device;
907 IDirectDrawSurface *ds1, *ds2, *ds3, *rt;
908 IDirect3DViewport2 *viewport;
909 RECT src_rect, dst_rect;
910 unsigned int i, j;
911 D3DCOLOR color;
912 HRESULT hr;
913 IDirectDraw2 *ddraw;
914 DDBLTFX fx;
915 HWND window;
916 D3DRECT d3drect;
917 IDirect3DMaterial2 *background;
919 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
920 0, 0, 640, 480, 0, 0, 0, 0);
921 if (!(ddraw = create_ddraw()))
923 skip("Failed to create a ddraw object, skipping test.\n");
924 DestroyWindow(window);
925 return;
927 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
929 skip("Failed to create a 3D device, skipping test.\n");
930 IDirectDraw2_Release(ddraw);
931 DestroyWindow(window);
932 return;
935 ds1 = get_depth_stencil(device);
937 memset(&ddsd_new, 0, sizeof(ddsd_new));
938 ddsd_new.dwSize = sizeof(ddsd_new);
939 memset(&ddsd_existing, 0, sizeof(ddsd_existing));
940 ddsd_existing.dwSize = sizeof(ddsd_existing);
941 hr = IDirectDrawSurface_GetSurfaceDesc(ds1, &ddsd_existing);
942 ddsd_new.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
943 ddsd_new.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
944 ddsd_new.dwWidth = ddsd_existing.dwWidth;
945 ddsd_new.dwHeight = ddsd_existing.dwHeight;
946 ddsd_new.ddpfPixelFormat = ddsd_existing.ddpfPixelFormat;
947 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd_new, &ds2, NULL);
948 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
949 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd_new, &ds3, NULL);
950 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
952 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
953 viewport = create_viewport(device, 0, 0, ddsd_existing.dwWidth, ddsd_existing.dwHeight);
954 viewport_set_background(device, viewport, background);
955 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
956 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
958 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
959 ok(SUCCEEDED(hr), "Failed to enable z testing, hr %#x.\n", hr);
960 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
961 ok(SUCCEEDED(hr), "Failed to set the z function, hr %#x.\n", hr);
963 U1(d3drect).x1 = U2(d3drect).y1 = 0;
964 U3(d3drect).x2 = ddsd_existing.dwWidth; U4(d3drect).y2 = ddsd_existing.dwHeight;
965 hr = IDirect3DViewport2_Clear(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER);
966 ok(SUCCEEDED(hr), "Failed to clear the z buffer, hr %#x.\n", hr);
968 /* Partial blit. */
969 SetRect(&src_rect, 0, 0, 320, 240);
970 SetRect(&dst_rect, 0, 0, 320, 240);
971 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
972 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
973 /* Different locations. */
974 SetRect(&src_rect, 0, 0, 320, 240);
975 SetRect(&dst_rect, 320, 240, 640, 480);
976 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
977 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
978 /* Streched. */
979 SetRect(&src_rect, 0, 0, 320, 240);
980 SetRect(&dst_rect, 0, 0, 640, 480);
981 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
982 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
983 /* Flipped. */
984 SetRect(&src_rect, 0, 480, 640, 0);
985 SetRect(&dst_rect, 0, 0, 640, 480);
986 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
987 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
988 SetRect(&src_rect, 0, 0, 640, 480);
989 SetRect(&dst_rect, 0, 480, 640, 0);
990 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
991 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
992 /* Full, explicit. */
993 SetRect(&src_rect, 0, 0, 640, 480);
994 SetRect(&dst_rect, 0, 0, 640, 480);
995 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
996 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
997 /* Depth -> color blit: Succeeds on Win7 + Radeon HD 5700, fails on WinXP + Radeon X1600 */
999 /* Depth blit inside a BeginScene / EndScene pair */
1000 hr = IDirect3DDevice2_BeginScene(device);
1001 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
1002 /* From the current depth stencil */
1003 hr = IDirectDrawSurface_Blt(ds2, NULL, ds1, NULL, DDBLT_WAIT, NULL);
1004 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1005 /* To the current depth stencil */
1006 hr = IDirectDrawSurface_Blt(ds1, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1007 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1008 /* Between unbound surfaces */
1009 hr = IDirectDrawSurface_Blt(ds3, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1010 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1011 hr = IDirect3DDevice2_EndScene(device);
1012 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1014 /* Avoid changing the depth stencil, it doesn't work properly on Windows.
1015 * Instead use DDBLT_DEPTHFILL to clear the depth stencil. Unfortunately
1016 * drivers disagree on the meaning of dwFillDepth. Only 0 seems to produce
1017 * a reliable result(z = 0.0) */
1018 memset(&fx, 0, sizeof(fx));
1019 fx.dwSize = sizeof(fx);
1020 U5(fx).dwFillDepth = 0;
1021 hr = IDirectDrawSurface_Blt(ds2, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
1022 ok(SUCCEEDED(hr), "Failed to clear the source z buffer, hr %#x.\n", hr);
1024 /* This clears the Z buffer with 1.0 */
1025 hr = IDirect3DViewport2_Clear(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET);
1026 ok(SUCCEEDED(hr), "Failed to clear the color and z buffers, hr %#x.\n", hr);
1028 SetRect(&dst_rect, 0, 0, 320, 240);
1029 hr = IDirectDrawSurface_Blt(ds1, &dst_rect, ds2, NULL, DDBLT_WAIT, NULL);
1030 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1031 IDirectDrawSurface_Release(ds3);
1032 IDirectDrawSurface_Release(ds2);
1033 IDirectDrawSurface_Release(ds1);
1035 hr = IDirect3DDevice2_BeginScene(device);
1036 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
1037 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad1, 4, 0);
1038 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1039 hr = IDirect3DDevice2_EndScene(device);
1040 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1042 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1043 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1044 for (i = 0; i < 4; ++i)
1046 for (j = 0; j < 4; ++j)
1048 unsigned int x = 80 * ((2 * j) + 1);
1049 unsigned int y = 60 * ((2 * i) + 1);
1050 color = get_surface_color(rt, x, y);
1051 ok(compare_color(color, expected_colors[i][j], 1),
1052 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
1055 IDirectDrawSurface_Release(rt);
1057 destroy_viewport(device, viewport);
1058 destroy_material(background);
1059 IDirect3DDevice2_Release(device);
1060 IDirectDraw2_Release(ddraw);
1061 DestroyWindow(window);
1064 static void test_texture_load_ckey(void)
1066 IDirectDraw2 *ddraw = NULL;
1067 IDirectDrawSurface *src = NULL;
1068 IDirectDrawSurface *dst = NULL;
1069 IDirect3DTexture *src_tex = NULL;
1070 IDirect3DTexture *dst_tex = NULL;
1071 DDSURFACEDESC ddsd;
1072 HRESULT hr;
1073 DDCOLORKEY ckey;
1075 if (!(ddraw = create_ddraw()))
1077 skip("Failed to create a ddraw object, skipping test.\n");
1078 return;
1080 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
1081 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1083 memset(&ddsd, 0, sizeof(ddsd));
1084 ddsd.dwSize = sizeof(ddsd);
1085 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
1086 ddsd.dwHeight = 128;
1087 ddsd.dwWidth = 128;
1088 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
1089 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &src, NULL);
1090 ok(SUCCEEDED(hr), "Failed to create source texture, hr %#x.\n", hr);
1091 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1092 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &dst, NULL);
1093 ok(SUCCEEDED(hr), "Failed to create destination texture, hr %#x.\n", hr);
1095 hr = IDirectDrawSurface_QueryInterface(src, &IID_IDirect3DTexture, (void **)&src_tex);
1096 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get Direct3DTexture interface, hr %#x.\n", hr);
1097 if (FAILED(hr))
1099 /* 64 bit ddraw does not support d3d */
1100 skip("Could not get Direct3DTexture interface, skipping texture::Load color keying tests.\n");
1101 goto done;
1103 hr = IDirectDrawSurface_QueryInterface(dst, &IID_IDirect3DTexture, (void **)&dst_tex);
1104 ok(SUCCEEDED(hr), "Failed to get Direct3DTexture interface, hr %#x.\n", hr);
1106 /* No surface has a color key */
1107 hr = IDirect3DTexture_Load(dst_tex, src_tex);
1108 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDCAPS), "Got unexpected hr %#x.\n", hr);
1109 if (FAILED(hr))
1111 /* Testbot Windows NT VMs */
1112 skip("IDirect3DTexture::Load does not work, skipping color keying tests.\n");
1113 goto done;
1116 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0xdeadbeef;
1117 hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1118 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1119 ok(ckey.dwColorSpaceLowValue == 0xdeadbeef, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1120 ok(ckey.dwColorSpaceHighValue == 0xdeadbeef, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1122 /* Source surface has a color key */
1123 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
1124 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
1125 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1126 hr = IDirect3DTexture_Load(dst_tex, src_tex);
1127 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1128 hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1129 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1130 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1131 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1133 /* Both surfaces have a color key: Dest ckey is overwritten */
1134 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x000000ff;
1135 hr = IDirectDrawSurface_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1136 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1137 hr = IDirect3DTexture_Load(dst_tex, src_tex);
1138 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1139 hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1140 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1141 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1142 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1144 /* Only the destination has a color key: It is not deleted */
1145 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, NULL);
1146 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1147 hr = IDirectDrawSurface_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
1148 ok(hr == DDERR_NOCOLORKEY, "Got unexpected 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 done:
1157 if (dst_tex) IDirect3DTexture_Release(dst_tex);
1158 if (src_tex) IDirect3DTexture_Release(src_tex);
1159 if (dst) IDirectDrawSurface_Release(dst);
1160 if (src) IDirectDrawSurface_Release(src);
1161 if (ddraw) IDirectDraw2_Release(ddraw);
1164 static ULONG get_refcount(IUnknown *test_iface)
1166 IUnknown_AddRef(test_iface);
1167 return IUnknown_Release(test_iface);
1170 static void test_viewport(void)
1172 IDirectDraw2 *ddraw;
1173 IDirect3D2 *d3d;
1174 HRESULT hr;
1175 ULONG ref, old_d3d_ref;
1176 IDirect3DViewport *viewport;
1177 IDirect3DViewport2 *viewport2, *another_vp, *test_vp;
1178 IDirect3DViewport3 *viewport3;
1179 IDirectDrawGammaControl *gamma;
1180 IUnknown *unknown;
1181 IDirect3DDevice2 *device;
1182 HWND window;
1184 if (!(ddraw = create_ddraw()))
1186 skip("Failed to create a ddraw object, skipping test.\n");
1187 return;
1189 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1190 0, 0, 640, 480, 0, 0, 0, 0);
1191 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1193 skip("Failed to create a 3D device, skipping test.\n");
1194 IDirectDraw_Release(ddraw);
1195 DestroyWindow(window);
1196 return;
1199 hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d);
1200 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get d3d interface, hr %#x.\n", hr);
1201 if (FAILED(hr))
1203 skip("D3D interface is not available, skipping test.\n");
1204 IDirectDraw2_Release(ddraw);
1205 return;
1207 old_d3d_ref = get_refcount((IUnknown *)d3d);
1209 hr = IDirect3D2_CreateViewport(d3d, &viewport2, NULL);
1210 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1211 ref = get_refcount((IUnknown *)viewport2);
1212 ok(ref == 1, "Initial IDirect3DViewport2 refcount is %u\n", ref);
1213 ref = get_refcount((IUnknown *)d3d);
1214 ok(ref == old_d3d_ref, "IDirect3D2 refcount is %u\n", ref);
1216 gamma = (IDirectDrawGammaControl *)0xdeadbeef;
1217 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IDirectDrawGammaControl, (void **)&gamma);
1218 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
1219 ok(gamma == NULL, "Interface not set to NULL by failed QI call: %p\n", gamma);
1220 if (SUCCEEDED(hr)) IDirectDrawGammaControl_Release(gamma);
1221 /* NULL iid: Segfaults */
1223 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IDirect3DViewport, (void **)&viewport);
1224 ok(SUCCEEDED(hr), "Failed to QI IDirect3DViewport, hr %#x.\n", hr);
1225 if (viewport)
1227 ref = get_refcount((IUnknown *)viewport);
1228 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
1229 ref = get_refcount((IUnknown *)viewport2);
1230 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
1231 IDirect3DViewport_Release(viewport);
1232 viewport = NULL;
1235 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IDirect3DViewport3, (void **)&viewport3);
1236 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to QI IDirect3DViewport3, hr %#x.\n", hr);
1237 if (viewport3)
1239 ref = get_refcount((IUnknown *)viewport2);
1240 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
1241 ref = get_refcount((IUnknown *)viewport3);
1242 ok(ref == 2, "IDirect3DViewport3 refcount is %u\n", ref);
1243 IDirect3DViewport3_Release(viewport3);
1246 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IUnknown, (void **)&unknown);
1247 ok(SUCCEEDED(hr), "Failed to QI IUnknown, hr %#x.\n", hr);
1248 if (unknown)
1250 ref = get_refcount((IUnknown *)viewport2);
1251 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
1252 ref = get_refcount(unknown);
1253 ok(ref == 2, "IUnknown refcount is %u\n", ref);
1254 IUnknown_Release(unknown);
1257 /* AddViewport(NULL): Segfault */
1258 hr = IDirect3DDevice2_DeleteViewport(device, NULL);
1259 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1260 hr = IDirect3DDevice2_GetCurrentViewport(device, NULL);
1261 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1263 hr = IDirect3D2_CreateViewport(d3d, &another_vp, NULL);
1264 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1266 /* Setting a viewport not in the viewport list fails */
1267 hr = IDirect3DDevice2_SetCurrentViewport(device, another_vp);
1268 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1270 hr = IDirect3DDevice2_AddViewport(device, viewport2);
1271 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1272 ref = get_refcount((IUnknown *) viewport2);
1273 ok(ref == 2, "viewport2 refcount is %d\n", ref);
1274 hr = IDirect3DDevice2_AddViewport(device, another_vp);
1275 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1276 ref = get_refcount((IUnknown *) another_vp);
1277 ok(ref == 2, "another_vp refcount is %d\n", ref);
1279 test_vp = (IDirect3DViewport2 *) 0xbaadc0de;
1280 hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
1281 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1282 ok(test_vp == (IDirect3DViewport2 *) 0xbaadc0de, "Got unexpected pointer %p\n", test_vp);
1284 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport2);
1285 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1286 ref = get_refcount((IUnknown *) viewport2);
1287 ok(ref == 3, "viewport2 refcount is %d\n", ref);
1288 ref = get_refcount((IUnknown *) device);
1289 ok(ref == 1, "device refcount is %d\n", ref);
1291 test_vp = NULL;
1292 hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
1293 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1294 ok(test_vp == viewport2, "Got unexpected viewport %p\n", test_vp);
1295 ref = get_refcount((IUnknown *) viewport2);
1296 ok(ref == 4, "viewport2 refcount is %d\n", ref);
1297 if(test_vp) IDirect3DViewport2_Release(test_vp);
1299 /* GetCurrentViewport with a viewport set and NULL input param: Segfault */
1301 /* Cannot set the viewport to NULL */
1302 hr = IDirect3DDevice2_SetCurrentViewport(device, NULL);
1303 ok(hr == DDERR_INVALIDPARAMS, "Failed to set viewport to NULL, hr %#x.\n", hr);
1304 test_vp = NULL;
1305 hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
1306 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1307 ok(test_vp == viewport2, "Got unexpected viewport %p\n", test_vp);
1308 if(test_vp) IDirect3DViewport2_Release(test_vp);
1310 /* SetCurrentViewport properly releases the old viewport's reference */
1311 hr = IDirect3DDevice2_SetCurrentViewport(device, another_vp);
1312 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1313 ref = get_refcount((IUnknown *) viewport2);
1314 ok(ref == 2, "viewport2 refcount is %d\n", ref);
1315 ref = get_refcount((IUnknown *) another_vp);
1316 ok(ref == 3, "another_vp refcount is %d\n", ref);
1318 /* Deleting the viewport removes the reference added by AddViewport, but not
1319 * the one added by SetCurrentViewport. */
1320 hr = IDirect3DDevice2_DeleteViewport(device, another_vp);
1321 ok(SUCCEEDED(hr), "Failed to delete viewport from device, hr %#x.\n", hr);
1322 ref = get_refcount((IUnknown *) another_vp);
1323 todo_wine ok(ref == 2, "IDirect3DViewport2 refcount is %d\n", ref);
1325 /* GetCurrentViewport fails though */
1326 test_vp = NULL;
1327 hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
1328 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1329 ok(test_vp == NULL, "Got unexpected viewport %p\n", test_vp);
1330 if(test_vp) IDirect3DViewport2_Release(test_vp);
1332 /* Setting a different viewport does not free the leaked reference. How
1333 * do I get rid of it? Leak the viewport for now. */
1334 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport2);
1335 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1336 ref = get_refcount((IUnknown *) viewport2);
1337 ok(ref == 3, "viewport2 refcount is %d\n", ref);
1338 ref = get_refcount((IUnknown *) another_vp);
1339 todo_wine ok(ref == 2, "another_vp refcount is %d\n", ref);
1341 /* Destroying the device removes the viewport, but does not free the reference
1342 * added by SetCurrentViewport. */
1343 IDirect3DDevice2_Release(device);
1344 ref = get_refcount((IUnknown *) viewport2);
1345 todo_wine ok(ref == 2, "viewport2 refcount is %d\n", ref);
1347 IDirect3DViewport2_Release(another_vp);
1348 IDirect3DViewport2_Release(viewport2);
1349 IDirect3D2_Release(d3d);
1350 DestroyWindow(window);
1351 IDirectDraw2_Release(ddraw);
1354 static void test_zenable(void)
1356 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1357 static D3DTLVERTEX tquad[] =
1359 {{ 0.0f}, {480.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1360 {{ 0.0f}, { 0.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1361 {{640.0f}, {480.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1362 {{640.0f}, { 0.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1364 IDirect3DMaterial2 *background;
1365 IDirect3DViewport2 *viewport;
1366 IDirect3DDevice2 *device;
1367 IDirectDrawSurface *rt;
1368 IDirectDraw2 *ddraw;
1369 D3DCOLOR color;
1370 HWND window;
1371 HRESULT hr;
1372 UINT x, y;
1373 UINT i, j;
1375 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1376 0, 0, 640, 480, 0, 0, 0, 0);
1377 if (!(ddraw = create_ddraw()))
1379 skip("Failed to create a ddraw object, skipping test.\n");
1380 DestroyWindow(window);
1381 return;
1383 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1385 skip("Failed to create a 3D device, skipping test.\n");
1386 IDirectDraw2_Release(ddraw);
1387 DestroyWindow(window);
1388 return;
1391 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1392 viewport = create_viewport(device, 0, 0, 640, 480);
1393 viewport_set_background(device, viewport, background);
1394 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1395 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1397 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1398 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
1400 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1401 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1402 hr = IDirect3DDevice2_BeginScene(device);
1403 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1404 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, tquad, 4, 0);
1405 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1406 hr = IDirect3DDevice2_EndScene(device);
1407 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1409 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1410 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1411 for (i = 0; i < 4; ++i)
1413 for (j = 0; j < 4; ++j)
1415 x = 80 * ((2 * j) + 1);
1416 y = 60 * ((2 * i) + 1);
1417 color = get_surface_color(rt, x, y);
1418 ok(compare_color(color, 0x0000ff00, 1),
1419 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1422 IDirectDrawSurface_Release(rt);
1424 destroy_viewport(device, viewport);
1425 destroy_material(background);
1426 IDirect3DDevice2_Release(device);
1427 IDirectDraw2_Release(ddraw);
1428 DestroyWindow(window);
1431 static void test_ck_rgba(void)
1433 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1434 static D3DTLVERTEX tquad[] =
1436 {{ 0.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1437 {{ 0.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1438 {{640.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1439 {{640.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1440 {{ 0.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1441 {{ 0.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1442 {{640.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1443 {{640.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1445 static const struct
1447 D3DCOLOR fill_color;
1448 BOOL color_key;
1449 BOOL blend;
1450 D3DCOLOR result1;
1451 D3DCOLOR result2;
1453 tests[] =
1455 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x000000ff},
1456 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x000000ff},
1457 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00},
1458 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00},
1459 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00807f00},
1460 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x0000ff00},
1461 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00},
1462 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00},
1465 D3DTEXTUREHANDLE texture_handle;
1466 IDirect3DMaterial2 *background;
1467 IDirectDrawSurface *surface;
1468 IDirect3DViewport2 *viewport;
1469 IDirect3DTexture2 *texture;
1470 DDSURFACEDESC surface_desc;
1471 IDirect3DDevice2 *device;
1472 IDirectDrawSurface *rt;
1473 IDirectDraw2 *ddraw;
1474 D3DCOLOR color;
1475 HWND window;
1476 DDBLTFX fx;
1477 HRESULT hr;
1478 UINT i;
1480 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1481 0, 0, 640, 480, 0, 0, 0, 0);
1482 if (!(ddraw = create_ddraw()))
1484 skip("Failed to create a ddraw object, skipping test.\n");
1485 DestroyWindow(window);
1486 return;
1488 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1490 skip("Failed to create a 3D device, skipping test.\n");
1491 IDirectDraw2_Release(ddraw);
1492 DestroyWindow(window);
1493 return;
1496 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1497 viewport = create_viewport(device, 0, 0, 640, 480);
1498 viewport_set_background(device, viewport, background);
1499 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1500 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1502 memset(&surface_desc, 0, sizeof(surface_desc));
1503 surface_desc.dwSize = sizeof(surface_desc);
1504 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1505 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1506 surface_desc.dwWidth = 256;
1507 surface_desc.dwHeight = 256;
1508 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1509 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1510 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1511 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1512 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1513 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1514 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1515 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1516 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1517 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1518 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1519 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
1520 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1521 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
1522 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1523 IDirect3DTexture2_Release(texture);
1525 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1526 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1527 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1528 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1529 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1530 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1532 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1533 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1535 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
1537 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1538 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1539 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1540 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1542 memset(&fx, 0, sizeof(fx));
1543 fx.dwSize = sizeof(fx);
1544 U5(fx).dwFillColor = tests[i].fill_color;
1545 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1546 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1548 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
1549 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1550 hr = IDirect3DDevice2_BeginScene(device);
1551 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1552 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[0], 4, 0);
1553 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1554 hr = IDirect3DDevice2_EndScene(device);
1555 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1557 color = get_surface_color(rt, 320, 240);
1558 if (i == 2)
1559 todo_wine ok(compare_color(color, tests[i].result1, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1560 tests[i].result1, i, color);
1561 else
1562 ok(compare_color(color, tests[i].result1, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1563 tests[i].result1, i, color);
1565 U5(fx).dwFillColor = 0xff0000ff;
1566 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1567 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1569 hr = IDirect3DDevice2_BeginScene(device);
1570 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1571 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[4], 4, 0);
1572 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1573 hr = IDirect3DDevice2_EndScene(device);
1574 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1576 /* This tests that fragments that are masked out by the color key are
1577 * discarded, instead of just fully transparent. */
1578 color = get_surface_color(rt, 320, 240);
1579 if (i == 2)
1580 todo_wine ok(compare_color(color, tests[i].result2, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1581 tests[i].result2, i, color);
1582 else
1583 ok(compare_color(color, tests[i].result2, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1584 tests[i].result2, i, color);
1587 IDirectDrawSurface_Release(rt);
1588 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1589 ok(SUCCEEDED(hr), "Failed to unset texture, hr %#x.\n", hr);
1590 IDirectDrawSurface_Release(surface);
1591 destroy_viewport(device, viewport);
1592 destroy_material(background);
1593 IDirect3DDevice2_Release(device);
1594 IDirectDraw2_Release(ddraw);
1595 DestroyWindow(window);
1598 static void test_ck_default(void)
1600 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1601 static D3DTLVERTEX tquad[] =
1603 {{ 0.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1604 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1605 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1606 {{640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1608 IDirectDrawSurface *surface, *rt;
1609 D3DTEXTUREHANDLE texture_handle;
1610 IDirect3DMaterial2 *background;
1611 IDirect3DViewport2 *viewport;
1612 DDSURFACEDESC surface_desc;
1613 IDirect3DTexture2 *texture;
1614 IDirect3DDevice2 *device;
1615 IDirectDraw2 *ddraw;
1616 D3DCOLOR color;
1617 DWORD value;
1618 HWND window;
1619 DDBLTFX fx;
1620 HRESULT hr;
1622 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1623 0, 0, 640, 480, 0, 0, 0, 0);
1625 if (!(ddraw = create_ddraw()))
1627 skip("Failed to create a ddraw object, skipping test.\n");
1628 DestroyWindow(window);
1629 return;
1631 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1633 skip("Failed to create a 3D device, skipping test.\n");
1634 IDirectDraw2_Release(ddraw);
1635 DestroyWindow(window);
1636 return;
1639 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1640 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1642 background = create_diffuse_material(device, 0.0, 1.0f, 0.0f, 1.0f);
1643 viewport = create_viewport(device, 0, 0, 640, 480);
1644 viewport_set_background(device, viewport, background);
1645 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1646 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1648 memset(&surface_desc, 0, sizeof(surface_desc));
1649 surface_desc.dwSize = sizeof(surface_desc);
1650 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1651 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1652 surface_desc.dwWidth = 256;
1653 surface_desc.dwHeight = 256;
1654 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1655 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
1656 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1657 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1658 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1659 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1660 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
1661 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
1662 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1663 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1664 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
1665 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1666 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
1667 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1668 IDirect3DTexture_Release(texture);
1670 memset(&fx, 0, sizeof(fx));
1671 fx.dwSize = sizeof(fx);
1672 U5(fx).dwFillColor = 0x000000ff;
1673 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1674 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
1676 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1677 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1678 hr = IDirect3DDevice2_BeginScene(device);
1679 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1680 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1681 ok(SUCCEEDED(hr), "Failed to set texture handle, hr %#x.\n", hr);
1682 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1683 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1684 ok(!value, "Got unexpected color keying state %#x.\n", value);
1685 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[0], 4, 0);
1686 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1687 hr = IDirect3DDevice2_EndScene(device);
1688 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1689 color = get_surface_color(rt, 320, 240);
1690 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1692 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1693 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1694 hr = IDirect3DDevice2_BeginScene(device);
1695 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1696 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
1697 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1698 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[0], 4, 0);
1699 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1700 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1701 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1702 ok(!!value, "Got unexpected color keying state %#x.\n", value);
1703 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1704 ok(SUCCEEDED(hr), "Failed to set texture handle, hr %#x.\n", hr);
1705 hr = IDirect3DDevice2_EndScene(device);
1706 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1707 color = get_surface_color(rt, 320, 240);
1708 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1710 IDirectDrawSurface_Release(surface);
1711 destroy_viewport(device, viewport);
1712 destroy_material(background);
1713 IDirectDrawSurface_Release(rt);
1714 IDirect3DDevice2_Release(device);
1715 IDirectDraw2_Release(ddraw);
1716 DestroyWindow(window);
1719 static void test_ck_complex(void)
1721 IDirectDrawSurface *surface, *mipmap, *tmp;
1722 DDSCAPS caps = {DDSCAPS_COMPLEX};
1723 DDSURFACEDESC surface_desc;
1724 IDirect3DDevice2 *device;
1725 DDCOLORKEY color_key;
1726 IDirectDraw2 *ddraw;
1727 unsigned int i;
1728 ULONG refcount;
1729 HWND window;
1730 HRESULT hr;
1732 if (!(ddraw = create_ddraw()))
1734 skip("Failed to create a ddraw object, skipping test.\n");
1735 return;
1738 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1739 0, 0, 640, 480, 0, 0, 0, 0);
1740 if (!(device = create_device(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
1742 skip("Failed to create a 3D device, skipping test.\n");
1743 DestroyWindow(window);
1744 IDirectDraw2_Release(ddraw);
1745 return;
1747 IDirect3DDevice2_Release(device);
1749 memset(&surface_desc, 0, sizeof(surface_desc));
1750 surface_desc.dwSize = sizeof(surface_desc);
1751 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1752 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1753 surface_desc.dwWidth = 128;
1754 surface_desc.dwHeight = 128;
1755 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1756 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1758 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1759 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1760 color_key.dwColorSpaceLowValue = 0x0000ff00;
1761 color_key.dwColorSpaceHighValue = 0x0000ff00;
1762 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1763 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1764 memset(&color_key, 0, sizeof(color_key));
1765 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1766 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1767 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1768 color_key.dwColorSpaceLowValue);
1769 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1770 color_key.dwColorSpaceHighValue);
1772 mipmap = surface;
1773 IDirectDrawSurface_AddRef(mipmap);
1774 for (i = 0; i < 7; ++i)
1776 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
1777 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
1779 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1780 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1781 color_key.dwColorSpaceLowValue = 0x000000ff;
1782 color_key.dwColorSpaceHighValue = 0x000000ff;
1783 hr = IDirectDrawSurface_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1784 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x, i %u.\n", hr, i);
1785 memset(&color_key, 0, sizeof(color_key));
1786 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1787 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x, i %u.\n", hr, i);
1788 ok(color_key.dwColorSpaceLowValue == 0x000000ff, "Got unexpected value 0x%08x, i %u.\n",
1789 color_key.dwColorSpaceLowValue, i);
1790 ok(color_key.dwColorSpaceHighValue == 0x000000ff, "Got unexpected value 0x%08x, i %u.\n",
1791 color_key.dwColorSpaceHighValue, i);
1793 IDirectDrawSurface_Release(mipmap);
1794 mipmap = tmp;
1797 memset(&color_key, 0, sizeof(color_key));
1798 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1799 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1800 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1801 color_key.dwColorSpaceLowValue);
1802 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1803 color_key.dwColorSpaceHighValue);
1805 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
1806 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
1807 IDirectDrawSurface_Release(mipmap);
1808 refcount = IDirectDrawSurface_Release(surface);
1809 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1811 memset(&surface_desc, 0, sizeof(surface_desc));
1812 surface_desc.dwSize = sizeof(surface_desc);
1813 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
1814 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
1815 surface_desc.dwBackBufferCount = 1;
1816 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1817 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1819 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1820 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1821 color_key.dwColorSpaceLowValue = 0x0000ff00;
1822 color_key.dwColorSpaceHighValue = 0x0000ff00;
1823 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1824 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1825 memset(&color_key, 0, sizeof(color_key));
1826 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1827 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1828 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1829 color_key.dwColorSpaceLowValue);
1830 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1831 color_key.dwColorSpaceHighValue);
1833 hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &tmp);
1834 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
1836 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1837 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1838 color_key.dwColorSpaceLowValue = 0x0000ff00;
1839 color_key.dwColorSpaceHighValue = 0x0000ff00;
1840 hr = IDirectDrawSurface_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1841 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1842 memset(&color_key, 0, sizeof(color_key));
1843 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1844 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1845 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1846 color_key.dwColorSpaceLowValue);
1847 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1848 color_key.dwColorSpaceHighValue);
1850 IDirectDrawSurface_Release(tmp);
1852 refcount = IDirectDrawSurface_Release(surface);
1853 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1854 refcount = IDirectDraw2_Release(ddraw);
1855 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1856 DestroyWindow(window);
1859 struct qi_test
1861 REFIID iid;
1862 REFIID refcount_iid;
1863 HRESULT hr;
1866 static void test_qi(const char *test_name, IUnknown *base_iface,
1867 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
1869 ULONG refcount, expected_refcount;
1870 IUnknown *iface1, *iface2;
1871 HRESULT hr;
1872 UINT i, j;
1874 for (i = 0; i < entry_count; ++i)
1876 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
1877 ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
1878 if (SUCCEEDED(hr))
1880 for (j = 0; j < entry_count; ++j)
1882 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
1883 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
1884 if (SUCCEEDED(hr))
1886 expected_refcount = 0;
1887 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
1888 ++expected_refcount;
1889 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
1890 ++expected_refcount;
1891 refcount = IUnknown_Release(iface2);
1892 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
1893 refcount, test_name, i, j, expected_refcount);
1897 expected_refcount = 0;
1898 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
1899 ++expected_refcount;
1900 refcount = IUnknown_Release(iface1);
1901 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
1902 refcount, test_name, i, expected_refcount);
1907 static void test_surface_qi(void)
1909 static const struct qi_test tests[] =
1911 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface, S_OK },
1912 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface, S_OK },
1913 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
1914 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1915 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
1916 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
1917 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
1918 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
1919 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
1920 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
1921 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
1922 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
1923 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
1924 {&IID_IDirect3D7, NULL, E_INVALIDARG },
1925 {&IID_IDirect3D3, NULL, E_INVALIDARG },
1926 {&IID_IDirect3D2, NULL, E_INVALIDARG },
1927 {&IID_IDirect3D, NULL, E_INVALIDARG },
1928 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
1929 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
1930 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
1931 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
1932 {&IID_IDirectDraw, NULL, E_INVALIDARG },
1933 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
1934 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
1935 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
1936 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
1937 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
1938 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
1939 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
1940 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
1941 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
1942 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
1943 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
1944 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
1945 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
1948 IDirectDrawSurface *surface;
1949 DDSURFACEDESC surface_desc;
1950 IDirect3DDevice2 *device;
1951 IDirectDraw2 *ddraw;
1952 HWND window;
1953 HRESULT hr;
1955 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
1957 win_skip("DirectDrawCreateEx not available, skipping test.\n");
1958 return;
1961 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1962 0, 0, 640, 480, 0, 0, 0, 0);
1963 if (!(ddraw = create_ddraw()))
1965 skip("Failed to create a ddraw object, skipping test.\n");
1966 DestroyWindow(window);
1967 return;
1969 /* Try to create a D3D device to see if the ddraw implementation supports
1970 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
1971 * doesn't support e.g. the IDirect3DTexture interfaces. */
1972 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1974 skip("Failed to create a 3D device, skipping test.\n");
1975 IDirectDraw2_Release(ddraw);
1976 DestroyWindow(window);
1977 return;
1979 IDirect3DDevice_Release(device);
1981 memset(&surface_desc, 0, sizeof(surface_desc));
1982 surface_desc.dwSize = sizeof(surface_desc);
1983 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1984 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1985 surface_desc.dwWidth = 512;
1986 surface_desc.dwHeight = 512;
1987 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1988 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1990 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface, tests, sizeof(tests) / sizeof(*tests));
1992 IDirectDrawSurface_Release(surface);
1993 IDirectDraw2_Release(ddraw);
1994 DestroyWindow(window);
1997 static void test_device_qi(void)
1999 static const struct qi_test tests[] =
2001 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
2002 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
2003 {&IID_IDirectDrawGammaControl, NULL, E_NOINTERFACE},
2004 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2005 {&IID_IDirectDrawSurface7, NULL, E_NOINTERFACE},
2006 {&IID_IDirectDrawSurface4, NULL, E_NOINTERFACE},
2007 {&IID_IDirectDrawSurface3, NULL, E_NOINTERFACE},
2008 {&IID_IDirectDrawSurface2, NULL, E_NOINTERFACE},
2009 {&IID_IDirectDrawSurface, NULL, E_NOINTERFACE},
2010 {&IID_IDirect3DDevice7, NULL, E_NOINTERFACE},
2011 {&IID_IDirect3DDevice3, NULL, E_NOINTERFACE},
2012 {&IID_IDirect3DDevice2, &IID_IDirect3DDevice2, S_OK },
2013 {&IID_IDirect3DDevice, &IID_IDirect3DDevice2, S_OK },
2014 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
2015 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
2016 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
2017 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
2018 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
2019 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
2020 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
2021 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
2022 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
2023 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
2024 {&IID_IDirect3D, NULL, E_NOINTERFACE},
2025 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
2026 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
2027 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
2028 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
2029 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
2030 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
2031 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
2032 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
2033 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
2034 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
2035 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
2036 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
2037 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
2038 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
2039 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
2040 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
2041 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
2042 {&IID_IUnknown, &IID_IDirect3DDevice2, S_OK },
2045 IDirect3DDevice2 *device;
2046 IDirectDraw2 *ddraw;
2047 HWND window;
2049 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2050 0, 0, 640, 480, 0, 0, 0, 0);
2051 if (!(ddraw = create_ddraw()))
2053 skip("Failed to create a ddraw object, skipping test.\n");
2054 DestroyWindow(window);
2055 return;
2057 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
2059 skip("Failed to create a 3D device, skipping test.\n");
2060 IDirectDraw2_Release(ddraw);
2061 DestroyWindow(window);
2062 return;
2065 test_qi("device_qi", (IUnknown *)device, &IID_IDirect3DDevice2, tests, sizeof(tests) / sizeof(*tests));
2067 IDirect3DDevice2_Release(device);
2068 IDirectDraw2_Release(ddraw);
2069 DestroyWindow(window);
2072 static void test_wndproc(void)
2074 LONG_PTR proc, ddraw_proc;
2075 IDirectDraw2 *ddraw;
2076 WNDCLASSA wc = {0};
2077 HWND window;
2078 HRESULT hr;
2079 ULONG ref;
2081 static const UINT messages[] =
2083 WM_WINDOWPOSCHANGING,
2084 WM_MOVE,
2085 WM_SIZE,
2086 WM_WINDOWPOSCHANGING,
2087 WM_ACTIVATE,
2088 WM_SETFOCUS,
2092 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
2093 if (!(ddraw = create_ddraw()))
2095 skip("Failed to create a ddraw object, skipping test.\n");
2096 return;
2099 wc.lpfnWndProc = test_proc;
2100 wc.lpszClassName = "ddraw_test_wndproc_wc";
2101 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2103 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
2104 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
2106 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2107 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2108 (LONG_PTR)test_proc, proc);
2109 expect_messages = messages;
2110 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2111 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2112 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2113 expect_messages = NULL;
2114 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2115 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2116 (LONG_PTR)test_proc, proc);
2117 ref = IDirectDraw2_Release(ddraw);
2118 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2119 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2120 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2121 (LONG_PTR)test_proc, proc);
2123 /* DDSCL_NORMAL doesn't. */
2124 ddraw = create_ddraw();
2125 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2126 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2127 (LONG_PTR)test_proc, proc);
2128 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2129 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2130 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2131 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2132 (LONG_PTR)test_proc, proc);
2133 ref = IDirectDraw2_Release(ddraw);
2134 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2135 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2136 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2137 (LONG_PTR)test_proc, proc);
2139 /* The original window proc is only restored by ddraw if the current
2140 * window proc matches the one ddraw set. This also affects switching
2141 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
2142 ddraw = create_ddraw();
2143 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2144 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2145 (LONG_PTR)test_proc, proc);
2146 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2147 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2148 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2149 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2150 (LONG_PTR)test_proc, proc);
2151 ddraw_proc = proc;
2152 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2153 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2154 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2155 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2156 (LONG_PTR)test_proc, proc);
2157 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2158 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2159 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2160 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2161 (LONG_PTR)test_proc, proc);
2162 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2163 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2164 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2165 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2166 (LONG_PTR)DefWindowProcA, proc);
2167 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2168 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2169 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc);
2170 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2171 (LONG_PTR)DefWindowProcA, proc);
2172 ref = IDirectDraw2_Release(ddraw);
2173 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2174 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2175 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2176 (LONG_PTR)test_proc, proc);
2178 ddraw = create_ddraw();
2179 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2180 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2181 (LONG_PTR)test_proc, proc);
2182 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2183 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2184 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2185 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2186 (LONG_PTR)test_proc, proc);
2187 ref = IDirectDraw2_Release(ddraw);
2188 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2189 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2190 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2191 (LONG_PTR)DefWindowProcA, proc);
2193 fix_wndproc(window, (LONG_PTR)test_proc);
2194 expect_messages = NULL;
2195 DestroyWindow(window);
2196 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2199 static void test_window_style(void)
2201 LONG style, exstyle, tmp;
2202 RECT fullscreen_rect, r;
2203 IDirectDraw2 *ddraw;
2204 HWND window;
2205 HRESULT hr;
2206 ULONG ref;
2208 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2209 0, 0, 100, 100, 0, 0, 0, 0);
2210 if (!(ddraw = create_ddraw()))
2212 skip("Failed to create a ddraw object, skipping test.\n");
2213 DestroyWindow(window);
2214 return;
2217 style = GetWindowLongA(window, GWL_STYLE);
2218 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
2219 SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2221 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2222 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2224 tmp = GetWindowLongA(window, GWL_STYLE);
2225 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2226 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2227 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2229 GetWindowRect(window, &r);
2230 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2231 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2232 r.left, r.top, r.right, r.bottom);
2233 GetClientRect(window, &r);
2234 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2236 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2237 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2239 tmp = GetWindowLongA(window, GWL_STYLE);
2240 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2241 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2242 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2244 ref = IDirectDraw2_Release(ddraw);
2245 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2247 DestroyWindow(window);
2250 static void test_redundant_mode_set(void)
2252 DDSURFACEDESC surface_desc = {0};
2253 IDirectDraw2 *ddraw;
2254 HWND window;
2255 HRESULT hr;
2256 RECT r, s;
2257 ULONG ref;
2259 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2260 0, 0, 100, 100, 0, 0, 0, 0);
2261 if (!(ddraw = create_ddraw()))
2263 skip("Failed to create a ddraw object, skipping test.\n");
2264 DestroyWindow(window);
2265 return;
2268 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2269 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2271 surface_desc.dwSize = sizeof(surface_desc);
2272 hr = IDirectDraw2_GetDisplayMode(ddraw, &surface_desc);
2273 ok(SUCCEEDED(hr), "GetDipslayMode failed, hr %#x.\n", hr);
2275 hr = IDirectDraw2_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2276 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount, 0, 0);
2277 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2279 GetWindowRect(window, &r);
2280 r.right /= 2;
2281 r.bottom /= 2;
2282 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
2283 GetWindowRect(window, &s);
2284 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2285 r.left, r.top, r.right, r.bottom,
2286 s.left, s.top, s.right, s.bottom);
2288 hr = IDirectDraw2_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2289 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount, 0, 0);
2290 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2292 GetWindowRect(window, &s);
2293 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2294 r.left, r.top, r.right, r.bottom,
2295 s.left, s.top, s.right, s.bottom);
2297 ref = IDirectDraw2_Release(ddraw);
2298 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2300 DestroyWindow(window);
2303 static SIZE screen_size, screen_size2;
2305 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2307 if (message == WM_SIZE)
2309 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2310 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2313 return test_proc(hwnd, message, wparam, lparam);
2316 static LRESULT CALLBACK mode_set_proc2(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2318 if (message == WM_SIZE)
2320 screen_size2.cx = GetSystemMetrics(SM_CXSCREEN);
2321 screen_size2.cy = GetSystemMetrics(SM_CYSCREEN);
2324 return test_proc(hwnd, message, wparam, lparam);
2327 static void test_coop_level_mode_set(void)
2329 IDirectDrawSurface *primary;
2330 RECT fullscreen_rect, r, s;
2331 IDirectDraw2 *ddraw;
2332 DDSURFACEDESC ddsd;
2333 WNDCLASSA wc = {0};
2334 HWND window, window2;
2335 HRESULT hr;
2336 ULONG ref;
2338 static const UINT exclusive_messages[] =
2340 WM_WINDOWPOSCHANGING,
2341 WM_WINDOWPOSCHANGED,
2342 WM_SIZE,
2343 WM_DISPLAYCHANGE,
2347 static const UINT normal_messages[] =
2349 WM_DISPLAYCHANGE,
2353 if (!(ddraw = create_ddraw()))
2355 skip("Failed to create a ddraw object, skipping test.\n");
2356 return;
2358 wc.lpfnWndProc = mode_set_proc;
2359 wc.lpszClassName = "ddraw_test_wndproc_wc";
2360 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2361 wc.lpfnWndProc = mode_set_proc2;
2362 wc.lpszClassName = "ddraw_test_wndproc_wc2";
2363 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2365 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
2366 0, 0, 100, 100, 0, 0, 0, 0);
2367 window2 = CreateWindowA("ddraw_test_wndproc_wc2", "ddraw_test", WS_OVERLAPPEDWINDOW,
2368 0, 0, 100, 100, 0, 0, 0, 0);
2370 SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2371 SetRect(&s, 0, 0, 640, 480);
2373 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2374 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2376 GetWindowRect(window, &r);
2377 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2378 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2379 r.left, r.top, r.right, r.bottom);
2381 memset(&ddsd, 0, sizeof(ddsd));
2382 ddsd.dwSize = sizeof(ddsd);
2383 ddsd.dwFlags = DDSD_CAPS;
2384 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2386 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2387 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2388 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2389 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2390 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2391 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2392 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2393 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2395 GetWindowRect(window, &r);
2396 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2397 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2398 r.left, r.top, r.right, r.bottom);
2400 expect_messages = exclusive_messages;
2401 screen_size.cx = 0;
2402 screen_size.cy = 0;
2404 hr = IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 32, 0, 0);
2405 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2407 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2408 expect_messages = NULL;
2409 ok(screen_size.cx == s.right && screen_size.cy == s.bottom,
2410 "Expected screen size %ux%u, got %ux%u.\n",
2411 s.right, s.bottom, screen_size.cx, screen_size.cy);
2413 GetWindowRect(window, &r);
2414 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2415 s.left, s.top, s.right, s.bottom,
2416 r.left, r.top, r.right, r.bottom);
2418 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2419 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2420 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2421 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2422 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2423 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2424 IDirectDrawSurface_Release(primary);
2426 memset(&ddsd, 0, sizeof(ddsd));
2427 ddsd.dwSize = sizeof(ddsd);
2428 ddsd.dwFlags = DDSD_CAPS;
2429 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2431 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2432 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2433 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2434 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2435 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2436 s.right - s.left, ddsd.dwWidth);
2437 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2438 s.bottom - s.top, ddsd.dwHeight);
2440 GetWindowRect(window, &r);
2441 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2442 s.left, s.top, s.right, s.bottom,
2443 r.left, r.top, r.right, r.bottom);
2445 expect_messages = exclusive_messages;
2446 screen_size.cx = 0;
2447 screen_size.cy = 0;
2449 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2450 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2452 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2453 expect_messages = NULL;
2454 ok(screen_size.cx == fullscreen_rect.right && screen_size.cy == fullscreen_rect.bottom,
2455 "Expected screen size %ux%u, got %ux%u.\n",
2456 fullscreen_rect.right, fullscreen_rect.bottom, screen_size.cx, screen_size.cy);
2458 GetWindowRect(window, &r);
2459 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2460 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2461 r.left, r.top, r.right, r.bottom);
2463 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2464 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2465 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2466 s.right - s.left, ddsd.dwWidth);
2467 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2468 s.bottom - s.top, ddsd.dwHeight);
2469 IDirectDrawSurface_Release(primary);
2471 memset(&ddsd, 0, sizeof(ddsd));
2472 ddsd.dwSize = sizeof(ddsd);
2473 ddsd.dwFlags = DDSD_CAPS;
2474 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2476 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2477 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2478 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2479 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2480 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2481 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2482 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2483 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2485 GetWindowRect(window, &r);
2486 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2487 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2488 r.left, r.top, r.right, r.bottom);
2490 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2491 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2493 GetWindowRect(window, &r);
2494 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2495 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2496 r.left, r.top, r.right, r.bottom);
2498 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2499 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2500 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2501 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2502 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2503 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2504 IDirectDrawSurface_Release(primary);
2506 memset(&ddsd, 0, sizeof(ddsd));
2507 ddsd.dwSize = sizeof(ddsd);
2508 ddsd.dwFlags = DDSD_CAPS;
2509 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2511 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2512 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2513 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2514 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2515 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2516 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2517 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2518 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2520 GetWindowRect(window, &r);
2521 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2522 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2523 r.left, r.top, r.right, r.bottom);
2525 expect_messages = normal_messages;
2526 screen_size.cx = 0;
2527 screen_size.cy = 0;
2529 hr = IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 32, 0, 0);
2530 ok(SUCCEEDED(hr) || broken(hr == DDERR_NOEXCLUSIVEMODE) /* NT4 testbot */,
2531 "SetDisplayMode failed, hr %#x.\n", hr);
2532 if (hr == DDERR_NOEXCLUSIVEMODE)
2534 win_skip("Broken SetDisplayMode(), skipping remaining tests.\n");
2535 IDirectDrawSurface_Release(primary);
2536 IDirectDraw2_Release(ddraw);
2537 goto done;
2540 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2541 expect_messages = NULL;
2542 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2544 GetWindowRect(window, &r);
2545 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2546 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2547 r.left, r.top, r.right, r.bottom);
2549 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2550 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2551 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2552 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2553 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2554 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2555 IDirectDrawSurface_Release(primary);
2557 memset(&ddsd, 0, sizeof(ddsd));
2558 ddsd.dwSize = sizeof(ddsd);
2559 ddsd.dwFlags = DDSD_CAPS;
2560 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2562 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2563 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2564 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2565 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2566 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2567 s.right - s.left, ddsd.dwWidth);
2568 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2569 s.bottom - s.top, ddsd.dwHeight);
2571 GetWindowRect(window, &r);
2572 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2573 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2574 r.left, r.top, r.right, r.bottom);
2576 expect_messages = normal_messages;
2577 screen_size.cx = 0;
2578 screen_size.cy = 0;
2580 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2581 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2583 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2584 expect_messages = NULL;
2585 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2587 GetWindowRect(window, &r);
2588 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2589 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2590 r.left, r.top, r.right, r.bottom);
2592 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2593 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2594 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2595 s.right - s.left, ddsd.dwWidth);
2596 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2597 s.bottom - s.top, ddsd.dwHeight);
2598 IDirectDrawSurface_Release(primary);
2600 memset(&ddsd, 0, sizeof(ddsd));
2601 ddsd.dwSize = sizeof(ddsd);
2602 ddsd.dwFlags = DDSD_CAPS;
2603 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2605 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2606 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2607 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2608 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2609 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2610 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2611 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2612 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2614 GetWindowRect(window, &r);
2615 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2616 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2617 r.left, r.top, r.right, r.bottom);
2619 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
2620 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
2621 * not DDSCL_FULLSCREEN. */
2622 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2623 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2625 GetWindowRect(window, &r);
2626 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2627 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2628 r.left, r.top, r.right, r.bottom);
2630 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2631 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2632 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2633 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2634 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2635 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2636 IDirectDrawSurface_Release(primary);
2638 memset(&ddsd, 0, sizeof(ddsd));
2639 ddsd.dwSize = sizeof(ddsd);
2640 ddsd.dwFlags = DDSD_CAPS;
2641 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2643 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2644 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2645 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2646 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2647 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2648 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2649 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2650 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2652 GetWindowRect(window, &r);
2653 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2654 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2655 r.left, r.top, r.right, r.bottom);
2657 expect_messages = normal_messages;
2658 screen_size.cx = 0;
2659 screen_size.cy = 0;
2661 hr = IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 32, 0, 0);
2662 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2664 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2665 expect_messages = NULL;
2666 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2668 GetWindowRect(window, &r);
2669 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2670 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2671 r.left, r.top, r.right, r.bottom);
2673 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2674 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2675 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2676 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2677 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2678 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2679 IDirectDrawSurface_Release(primary);
2681 memset(&ddsd, 0, sizeof(ddsd));
2682 ddsd.dwSize = sizeof(ddsd);
2683 ddsd.dwFlags = DDSD_CAPS;
2684 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2686 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2687 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2688 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2689 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2690 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2691 s.right - s.left, ddsd.dwWidth);
2692 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2693 s.bottom - s.top, ddsd.dwHeight);
2695 GetWindowRect(window, &r);
2696 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2697 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2698 r.left, r.top, r.right, r.bottom);
2700 expect_messages = normal_messages;
2701 screen_size.cx = 0;
2702 screen_size.cy = 0;
2704 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2705 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2707 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2708 expect_messages = NULL;
2709 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2711 GetWindowRect(window, &r);
2712 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2713 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2714 r.left, r.top, r.right, r.bottom);
2716 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2717 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2718 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2719 s.right - s.left, ddsd.dwWidth);
2720 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2721 s.bottom - s.top, ddsd.dwHeight);
2722 IDirectDrawSurface_Release(primary);
2724 memset(&ddsd, 0, sizeof(ddsd));
2725 ddsd.dwSize = sizeof(ddsd);
2726 ddsd.dwFlags = DDSD_CAPS;
2727 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2729 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2730 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2731 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2732 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2733 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2734 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2735 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2736 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2737 IDirectDrawSurface_Release(primary);
2739 GetWindowRect(window, &r);
2740 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2741 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2742 r.left, r.top, r.right, r.bottom);
2744 /* Changing the coop level from EXCLUSIVE to NORMAL restores the screen resolution */
2745 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2746 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2747 hr = IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 32, 0, 0);
2748 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2750 expect_messages = exclusive_messages;
2751 screen_size.cx = 0;
2752 screen_size.cy = 0;
2754 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2755 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2757 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2758 expect_messages = NULL;
2759 ok(screen_size.cx == fullscreen_rect.right && screen_size.cy == fullscreen_rect.bottom,
2760 "Expected screen size %ux%u, got %ux%u.\n",
2761 fullscreen_rect.right, fullscreen_rect.bottom, screen_size.cx, screen_size.cy);
2763 GetWindowRect(window, &r);
2764 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2765 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2766 r.left, r.top, r.right, r.bottom);
2768 memset(&ddsd, 0, sizeof(ddsd));
2769 ddsd.dwSize = sizeof(ddsd);
2770 ddsd.dwFlags = DDSD_CAPS;
2771 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2773 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2774 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2775 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2776 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2777 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2778 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2779 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2780 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2781 IDirectDrawSurface_Release(primary);
2783 /* The screen restore is a property of DDSCL_EXCLUSIVE */
2784 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2785 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2786 hr = IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 32, 0, 0);
2787 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2789 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2790 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2792 memset(&ddsd, 0, sizeof(ddsd));
2793 ddsd.dwSize = sizeof(ddsd);
2794 ddsd.dwFlags = DDSD_CAPS;
2795 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2797 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2798 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2799 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2800 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2801 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2802 s.right - s.left, ddsd.dwWidth);
2803 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2804 s.bottom - s.top, ddsd.dwHeight);
2805 IDirectDrawSurface_Release(primary);
2807 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2808 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2810 /* If the window is changed at the same time, messages are sent to the new window. */
2811 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2812 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2813 hr = IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 32, 0, 0);
2814 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2816 expect_messages = exclusive_messages;
2817 screen_size.cx = 0;
2818 screen_size.cy = 0;
2819 screen_size2.cx = 0;
2820 screen_size2.cy = 0;
2822 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
2823 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2825 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2826 expect_messages = NULL;
2827 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n",
2828 screen_size.cx, screen_size.cy);
2829 ok(screen_size2.cx == fullscreen_rect.right && screen_size2.cy == fullscreen_rect.bottom,
2830 "Expected screen size 2 %ux%u, got %ux%u.\n",
2831 fullscreen_rect.right, fullscreen_rect.bottom, screen_size2.cx, screen_size2.cy);
2833 GetWindowRect(window, &r);
2834 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2835 s.left, s.top, s.right, s.bottom,
2836 r.left, r.top, r.right, r.bottom);
2837 GetWindowRect(window2, &r);
2838 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2839 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2840 r.left, r.top, r.right, r.bottom);
2842 memset(&ddsd, 0, sizeof(ddsd));
2843 ddsd.dwSize = sizeof(ddsd);
2844 ddsd.dwFlags = DDSD_CAPS;
2845 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2847 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2848 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2849 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2850 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2851 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2852 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2853 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2854 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2855 IDirectDrawSurface_Release(primary);
2857 ref = IDirectDraw2_Release(ddraw);
2858 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2860 GetWindowRect(window, &r);
2861 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2862 s.left, s.top, s.right, s.bottom,
2863 r.left, r.top, r.right, r.bottom);
2865 done:
2866 expect_messages = NULL;
2867 DestroyWindow(window);
2868 DestroyWindow(window2);
2869 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2870 UnregisterClassA("ddraw_test_wndproc_wc2", GetModuleHandleA(NULL));
2873 static void test_coop_level_mode_set_multi(void)
2875 IDirectDraw2 *ddraw1, *ddraw2;
2876 UINT orig_w, orig_h, w, h;
2877 HWND window;
2878 HRESULT hr;
2879 ULONG ref;
2881 if (!(ddraw1 = create_ddraw()))
2883 skip("Failed to create a ddraw object, skipping test.\n");
2884 return;
2887 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2888 0, 0, 100, 100, 0, 0, 0, 0);
2890 orig_w = GetSystemMetrics(SM_CXSCREEN);
2891 orig_h = GetSystemMetrics(SM_CYSCREEN);
2893 /* With just a single ddraw object, the display mode is restored on
2894 * release. */
2895 hr = IDirectDraw2_SetDisplayMode(ddraw1, 800, 600, 32, 0, 0);
2896 ok(SUCCEEDED(hr) || broken(hr == DDERR_NOEXCLUSIVEMODE) /* NT4 testbot */,
2897 "SetDisplayMode failed, hr %#x.\n", hr);
2898 if (hr == DDERR_NOEXCLUSIVEMODE)
2900 win_skip("Broken SetDisplayMode(), skipping test.\n");
2901 IDirectDraw2_Release(ddraw1);
2902 DestroyWindow(window);
2903 return;
2905 w = GetSystemMetrics(SM_CXSCREEN);
2906 ok(w == 800, "Got unexpected screen width %u.\n", w);
2907 h = GetSystemMetrics(SM_CYSCREEN);
2908 ok(h == 600, "Got unexpected screen height %u.\n", h);
2910 ref = IDirectDraw2_Release(ddraw1);
2911 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2912 w = GetSystemMetrics(SM_CXSCREEN);
2913 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2914 h = GetSystemMetrics(SM_CYSCREEN);
2915 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2917 /* When there are multiple ddraw objects, the display mode is restored to
2918 * the initial mode, before the first SetDisplayMode() call. */
2919 ddraw1 = create_ddraw();
2920 hr = IDirectDraw2_SetDisplayMode(ddraw1, 800, 600, 32, 0, 0);
2921 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2922 w = GetSystemMetrics(SM_CXSCREEN);
2923 ok(w == 800, "Got unexpected screen width %u.\n", w);
2924 h = GetSystemMetrics(SM_CYSCREEN);
2925 ok(h == 600, "Got unexpected screen height %u.\n", h);
2927 ddraw2 = create_ddraw();
2928 hr = IDirectDraw2_SetDisplayMode(ddraw2, 640, 480, 32, 0, 0);
2929 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2930 w = GetSystemMetrics(SM_CXSCREEN);
2931 ok(w == 640, "Got unexpected screen width %u.\n", w);
2932 h = GetSystemMetrics(SM_CYSCREEN);
2933 ok(h == 480, "Got unexpected screen height %u.\n", h);
2935 ref = IDirectDraw2_Release(ddraw2);
2936 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2937 w = GetSystemMetrics(SM_CXSCREEN);
2938 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2939 h = GetSystemMetrics(SM_CYSCREEN);
2940 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2942 ref = IDirectDraw2_Release(ddraw1);
2943 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2944 w = GetSystemMetrics(SM_CXSCREEN);
2945 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2946 h = GetSystemMetrics(SM_CYSCREEN);
2947 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2949 /* Regardless of release ordering. */
2950 ddraw1 = create_ddraw();
2951 hr = IDirectDraw2_SetDisplayMode(ddraw1, 800, 600, 32, 0, 0);
2952 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2953 w = GetSystemMetrics(SM_CXSCREEN);
2954 ok(w == 800, "Got unexpected screen width %u.\n", w);
2955 h = GetSystemMetrics(SM_CYSCREEN);
2956 ok(h == 600, "Got unexpected screen height %u.\n", h);
2958 ddraw2 = create_ddraw();
2959 hr = IDirectDraw2_SetDisplayMode(ddraw2, 640, 480, 32, 0, 0);
2960 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2961 w = GetSystemMetrics(SM_CXSCREEN);
2962 ok(w == 640, "Got unexpected screen width %u.\n", w);
2963 h = GetSystemMetrics(SM_CYSCREEN);
2964 ok(h == 480, "Got unexpected screen height %u.\n", h);
2966 ref = IDirectDraw2_Release(ddraw1);
2967 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2968 w = GetSystemMetrics(SM_CXSCREEN);
2969 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2970 h = GetSystemMetrics(SM_CYSCREEN);
2971 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2973 ref = IDirectDraw2_Release(ddraw2);
2974 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2975 w = GetSystemMetrics(SM_CXSCREEN);
2976 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2977 h = GetSystemMetrics(SM_CYSCREEN);
2978 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2980 /* But only for ddraw objects that called SetDisplayMode(). */
2981 ddraw1 = create_ddraw();
2982 ddraw2 = create_ddraw();
2983 hr = IDirectDraw2_SetDisplayMode(ddraw2, 640, 480, 32, 0, 0);
2984 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2985 w = GetSystemMetrics(SM_CXSCREEN);
2986 ok(w == 640, "Got unexpected screen width %u.\n", w);
2987 h = GetSystemMetrics(SM_CYSCREEN);
2988 ok(h == 480, "Got unexpected screen height %u.\n", h);
2990 ref = IDirectDraw2_Release(ddraw1);
2991 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2992 w = GetSystemMetrics(SM_CXSCREEN);
2993 ok(w == 640, "Got unexpected screen width %u.\n", w);
2994 h = GetSystemMetrics(SM_CYSCREEN);
2995 ok(h == 480, "Got unexpected screen height %u.\n", h);
2997 ref = IDirectDraw2_Release(ddraw2);
2998 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2999 w = GetSystemMetrics(SM_CXSCREEN);
3000 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
3001 h = GetSystemMetrics(SM_CYSCREEN);
3002 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
3004 /* If there's a ddraw object that's currently in exclusive mode, it blocks
3005 * restoring the display mode. */
3006 ddraw1 = create_ddraw();
3007 hr = IDirectDraw2_SetDisplayMode(ddraw1, 800, 600, 32, 0, 0);
3008 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
3009 w = GetSystemMetrics(SM_CXSCREEN);
3010 ok(w == 800, "Got unexpected screen width %u.\n", w);
3011 h = GetSystemMetrics(SM_CYSCREEN);
3012 ok(h == 600, "Got unexpected screen height %u.\n", h);
3014 ddraw2 = create_ddraw();
3015 hr = IDirectDraw2_SetDisplayMode(ddraw2, 640, 480, 32, 0, 0);
3016 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
3017 w = GetSystemMetrics(SM_CXSCREEN);
3018 ok(w == 640, "Got unexpected screen width %u.\n", w);
3019 h = GetSystemMetrics(SM_CYSCREEN);
3020 ok(h == 480, "Got unexpected screen height %u.\n", h);
3022 hr = IDirectDraw2_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3023 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3025 ref = IDirectDraw2_Release(ddraw1);
3026 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3027 w = GetSystemMetrics(SM_CXSCREEN);
3028 ok(w == 640, "Got unexpected screen width %u.\n", w);
3029 h = GetSystemMetrics(SM_CYSCREEN);
3030 ok(h == 480, "Got unexpected screen height %u.\n", h);
3032 ref = IDirectDraw2_Release(ddraw2);
3033 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3034 w = GetSystemMetrics(SM_CXSCREEN);
3035 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
3036 h = GetSystemMetrics(SM_CYSCREEN);
3037 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
3039 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
3040 ddraw1 = create_ddraw();
3041 hr = IDirectDraw2_SetDisplayMode(ddraw1, 800, 600, 32, 0, 0);
3042 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
3043 w = GetSystemMetrics(SM_CXSCREEN);
3044 ok(w == 800, "Got unexpected screen width %u.\n", w);
3045 h = GetSystemMetrics(SM_CYSCREEN);
3046 ok(h == 600, "Got unexpected screen height %u.\n", h);
3048 hr = IDirectDraw2_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3049 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3051 ddraw2 = create_ddraw();
3052 hr = IDirectDraw2_SetDisplayMode(ddraw2, 640, 480, 32, 0, 0);
3053 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
3055 ref = IDirectDraw2_Release(ddraw1);
3056 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3057 w = GetSystemMetrics(SM_CXSCREEN);
3058 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
3059 h = GetSystemMetrics(SM_CYSCREEN);
3060 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
3062 ref = IDirectDraw2_Release(ddraw2);
3063 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3064 w = GetSystemMetrics(SM_CXSCREEN);
3065 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
3066 h = GetSystemMetrics(SM_CYSCREEN);
3067 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
3069 DestroyWindow(window);
3072 static void test_initialize(void)
3074 IDirectDraw2 *ddraw;
3075 HRESULT hr;
3077 if (!(ddraw = create_ddraw()))
3079 skip("Failed to create a ddraw object, skipping test.\n");
3080 return;
3083 hr = IDirectDraw2_Initialize(ddraw, NULL);
3084 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
3085 IDirectDraw2_Release(ddraw);
3087 CoInitialize(NULL);
3088 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw2, (void **)&ddraw);
3089 ok(SUCCEEDED(hr), "Failed to create IDirectDraw2 instance, hr %#x.\n", hr);
3090 hr = IDirectDraw2_Initialize(ddraw, NULL);
3091 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
3092 hr = IDirectDraw2_Initialize(ddraw, NULL);
3093 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
3094 IDirectDraw2_Release(ddraw);
3095 CoUninitialize();
3098 static void test_coop_level_surf_create(void)
3100 IDirectDrawSurface *surface;
3101 IDirectDraw2 *ddraw;
3102 DDSURFACEDESC ddsd;
3103 HRESULT hr;
3105 if (!(ddraw = create_ddraw()))
3107 skip("Failed to create a ddraw object, skipping test.\n");
3108 return;
3111 memset(&ddsd, 0, sizeof(ddsd));
3112 ddsd.dwSize = sizeof(ddsd);
3113 ddsd.dwFlags = DDSD_CAPS;
3114 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3115 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
3116 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
3118 IDirectDraw2_Release(ddraw);
3121 static void test_coop_level_multi_window(void)
3123 HWND window1, window2;
3124 IDirectDraw2 *ddraw;
3125 HRESULT hr;
3127 window1 = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
3128 0, 0, 640, 480, 0, 0, 0, 0);
3129 window2 = CreateWindowA("static", "ddraw_test2", WS_OVERLAPPEDWINDOW,
3130 0, 0, 640, 480, 0, 0, 0, 0);
3131 if (!(ddraw = create_ddraw()))
3133 skip("Failed to create a ddraw object, skipping test.\n");
3134 DestroyWindow(window2);
3135 DestroyWindow(window1);
3136 return;
3139 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
3140 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3141 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3142 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3143 ok(IsWindow(window1), "Window 1 was destroyed.\n");
3144 ok(IsWindow(window2), "Window 2 was destroyed.\n");
3146 IDirectDraw2_Release(ddraw);
3147 DestroyWindow(window2);
3148 DestroyWindow(window1);
3151 static void test_clear_rect_count(void)
3153 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
3154 IDirect3DMaterial2 *white, *red, *green, *blue;
3155 IDirect3DViewport2 *viewport;
3156 IDirect3DDevice2 *device;
3157 IDirectDrawSurface *rt;
3158 IDirectDraw2 *ddraw;
3159 D3DCOLOR color;
3160 HWND window;
3161 HRESULT hr;
3163 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3164 0, 0, 640, 480, 0, 0, 0, 0);
3165 if (!(ddraw = create_ddraw()))
3167 skip("Failed to create a ddraw object, skipping test.\n");
3168 DestroyWindow(window);
3169 return;
3171 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
3173 skip("Failed to create a 3D device, skipping test.\n");
3174 IDirectDraw2_Release(ddraw);
3175 DestroyWindow(window);
3176 return;
3179 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
3180 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3182 white = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
3183 red = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
3184 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
3185 blue = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
3187 viewport = create_viewport(device, 0, 0, 640, 480);
3188 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
3189 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
3191 viewport_set_background(device, viewport, white);
3192 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
3193 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3194 viewport_set_background(device, viewport, red);
3195 hr = IDirect3DViewport2_Clear(viewport, 0, &clear_rect, D3DCLEAR_TARGET);
3196 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3197 viewport_set_background(device, viewport, green);
3198 hr = IDirect3DViewport2_Clear(viewport, 0, NULL, D3DCLEAR_TARGET);
3199 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3200 viewport_set_background(device, viewport, blue);
3201 hr = IDirect3DViewport2_Clear(viewport, 0, &clear_rect, D3DCLEAR_TARGET);
3202 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3204 color = get_surface_color(rt, 320, 240);
3205 ok(compare_color(color, 0x00ffffff, 1), "Got unexpected color 0x%08x.\n", color);
3207 IDirectDrawSurface_Release(rt);
3208 destroy_viewport(device, viewport);
3209 destroy_material(white);
3210 destroy_material(red);
3211 destroy_material(green);
3212 destroy_material(blue);
3213 IDirect3DDevice2_Release(device);
3214 IDirectDraw2_Release(ddraw);
3215 DestroyWindow(window);
3218 static BOOL test_mode_restored(IDirectDraw2 *ddraw, HWND window)
3220 DDSURFACEDESC ddsd1, ddsd2;
3221 HRESULT hr;
3223 memset(&ddsd1, 0, sizeof(ddsd1));
3224 ddsd1.dwSize = sizeof(ddsd1);
3225 hr = IDirectDraw2_GetDisplayMode(ddraw, &ddsd1);
3226 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
3228 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3229 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3230 hr = IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 32, 0, 0);
3231 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
3232 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3233 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3235 memset(&ddsd2, 0, sizeof(ddsd2));
3236 ddsd2.dwSize = sizeof(ddsd2);
3237 hr = IDirectDraw2_GetDisplayMode(ddraw, &ddsd2);
3238 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
3239 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
3240 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3242 return ddsd1.dwWidth == ddsd2.dwWidth && ddsd1.dwHeight == ddsd2.dwHeight;
3245 static void test_coop_level_versions(void)
3247 HWND window;
3248 IDirectDraw *ddraw;
3249 HRESULT hr;
3250 BOOL restored;
3251 IDirectDrawSurface *surface;
3252 IDirectDraw2 *ddraw2;
3253 DDSURFACEDESC ddsd;
3255 window = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
3256 0, 0, 640, 480, 0, 0, 0, 0);
3258 if (!(ddraw2 = create_ddraw()))
3259 goto done;
3260 /* Newly created ddraw objects restore the mode on ddraw2+::SetCooperativeLevel(NORMAL) */
3261 restored = test_mode_restored(ddraw2, window);
3262 ok(restored, "Display mode not restored in new ddraw object\n");
3264 /* A failing ddraw1::SetCooperativeLevel call does not have an effect */
3265 hr = IDirectDraw2_QueryInterface(ddraw2, &IID_IDirectDraw, (void **)&ddraw);
3266 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3268 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
3269 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
3270 restored = test_mode_restored(ddraw2, window);
3271 ok(restored, "Display mode not restored after bad ddraw1::SetCooperativeLevel call\n");
3273 /* A successful one does */
3274 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3275 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3276 restored = test_mode_restored(ddraw2, window);
3277 ok(!restored, "Display mode restored after good ddraw1::SetCooperativeLevel call\n");
3279 IDirectDraw_Release(ddraw);
3280 IDirectDraw2_Release(ddraw2);
3282 if (!(ddraw2 = create_ddraw()))
3283 goto done;
3284 hr = IDirectDraw2_QueryInterface(ddraw2, &IID_IDirectDraw, (void **)&ddraw);
3285 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3287 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_SETFOCUSWINDOW);
3288 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3289 restored = test_mode_restored(ddraw2, window);
3290 ok(!restored, "Display mode restored after ddraw1::SetCooperativeLevel(SETFOCUSWINDOW) call\n");
3292 IDirectDraw_Release(ddraw);
3293 IDirectDraw2_Release(ddraw2);
3295 /* A failing call does not restore the ddraw2+ behavior */
3296 if (!(ddraw2 = create_ddraw()))
3297 goto done;
3298 hr = IDirectDraw2_QueryInterface(ddraw2, &IID_IDirectDraw, (void **)&ddraw);
3299 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3301 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3302 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3303 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
3304 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
3305 restored = test_mode_restored(ddraw2, window);
3306 ok(!restored, "Display mode restored after good-bad ddraw1::SetCooperativeLevel() call sequence\n");
3308 IDirectDraw_Release(ddraw);
3309 IDirectDraw2_Release(ddraw2);
3311 /* Neither does a sequence of successful calls with the new interface */
3312 if (!(ddraw2 = create_ddraw()))
3313 goto done;
3314 hr = IDirectDraw2_QueryInterface(ddraw2, &IID_IDirectDraw, (void **)&ddraw);
3315 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3317 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3318 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3319 hr = IDirectDraw2_SetCooperativeLevel(ddraw2, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
3320 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3321 hr = IDirectDraw2_SetCooperativeLevel(ddraw2, window, DDSCL_NORMAL);
3322 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3324 restored = test_mode_restored(ddraw2, window);
3325 ok(!restored, "Display mode restored after ddraw1-ddraw2 SetCooperativeLevel() call sequence\n");
3326 IDirectDraw_Release(ddraw);
3327 IDirectDraw2_Release(ddraw2);
3329 /* ddraw1::CreateSurface does not triger the ddraw1 behavior */
3330 if (!(ddraw2 = create_ddraw()))
3331 goto done;
3332 hr = IDirectDraw2_QueryInterface(ddraw2, &IID_IDirectDraw, (void **)&ddraw);
3333 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3335 hr = IDirectDraw2_SetCooperativeLevel(ddraw2, window, DDSCL_NORMAL);
3336 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3338 memset(&ddsd, 0, sizeof(ddsd));
3339 ddsd.dwSize = sizeof(ddsd);
3340 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
3341 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
3342 ddsd.dwWidth = ddsd.dwHeight = 8;
3343 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
3344 ok(SUCCEEDED(hr), "CreateSurface failed, hr %#x.\n", hr);
3345 IDirectDrawSurface_Release(surface);
3346 restored = test_mode_restored(ddraw2, window);
3347 ok(restored, "Display mode not restored after ddraw1::CreateSurface() call\n");
3349 IDirectDraw_Release(ddraw);
3350 IDirectDraw2_Release(ddraw2);
3352 done:
3353 DestroyWindow(window);
3356 static void test_lighting_interface_versions(void)
3358 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
3359 IDirect3DMaterial2 *emissive, *background;
3360 IDirect3DViewport2 *viewport;
3361 IDirect3DDevice2 *device;
3362 IDirectDrawSurface *rt;
3363 IDirectDraw2 *ddraw;
3364 IDirect3D2 *d3d;
3365 D3DCOLOR color;
3366 HWND window;
3367 HRESULT hr;
3368 D3DMATERIALHANDLE mat_handle;
3369 D3DMATERIAL mat_desc;
3370 DWORD rs;
3371 unsigned int i;
3372 ULONG ref;
3373 static D3DVERTEX quad[] =
3375 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
3376 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
3377 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
3378 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
3380 static D3DLVERTEX lquad[] =
3382 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
3383 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
3384 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
3385 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
3387 static D3DTLVERTEX tlquad[] =
3389 {{ 0.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
3390 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
3391 {{ 640.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
3392 {{ 640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
3394 static const struct
3396 D3DVERTEXTYPE vertextype;
3397 void *data;
3398 DWORD d3drs_lighting, d3drs_specular;
3399 DWORD draw_flags;
3400 D3DCOLOR color;
3402 tests[] =
3404 /* Lighting is enabled when D3DVT_VERTEX is used and D3DDP_DONOTLIGHT is not
3405 * set. D3DVT_VERTEX has diffuse = 0xffffffff and specular = 0x00000000, as
3406 * in later d3d versions */
3407 { D3DVT_VERTEX, quad, FALSE, FALSE, 0, 0x0000ff00},
3408 { D3DVT_VERTEX, quad, TRUE, FALSE, 0, 0x0000ff00},
3409 { D3DVT_VERTEX, quad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
3410 { D3DVT_VERTEX, quad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
3411 { D3DVT_VERTEX, quad, FALSE, TRUE, 0, 0x0000ff00},
3412 { D3DVT_VERTEX, quad, TRUE, TRUE, 0, 0x0000ff00},
3413 { D3DVT_VERTEX, quad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
3414 { D3DVT_VERTEX, quad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
3416 { D3DVT_LVERTEX, lquad, FALSE, FALSE, 0, 0x00ff0000},
3417 { D3DVT_LVERTEX, lquad, TRUE, FALSE, 0, 0x00ff0000},
3418 { D3DVT_LVERTEX, lquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
3419 { D3DVT_LVERTEX, lquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
3420 { D3DVT_LVERTEX, lquad, FALSE, TRUE, 0, 0x00ff8080},
3421 { D3DVT_LVERTEX, lquad, TRUE, TRUE, 0, 0x00ff8080},
3422 { D3DVT_LVERTEX, lquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
3423 { D3DVT_LVERTEX, lquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
3425 { D3DVT_TLVERTEX, tlquad, FALSE, FALSE, 0, 0x000000ff},
3426 { D3DVT_TLVERTEX, tlquad, TRUE, FALSE, 0, 0x000000ff},
3427 { D3DVT_TLVERTEX, tlquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
3428 { D3DVT_TLVERTEX, tlquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
3429 { D3DVT_TLVERTEX, tlquad, FALSE, TRUE, 0, 0x008080ff},
3430 { D3DVT_TLVERTEX, tlquad, TRUE, TRUE, 0, 0x008080ff},
3431 { D3DVT_TLVERTEX, tlquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
3432 { D3DVT_TLVERTEX, tlquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
3435 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3436 0, 0, 640, 480, 0, 0, 0, 0);
3437 if (!(ddraw = create_ddraw()))
3439 skip("Failed to create a ddraw object, skipping test.\n");
3440 DestroyWindow(window);
3441 return;
3443 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
3445 skip("Failed to create a 3D device, skipping test.\n");
3446 IDirectDraw2_Release(ddraw);
3447 DestroyWindow(window);
3448 return;
3450 hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d);
3451 ok(SUCCEEDED(hr), "Failed to get IDirect3D2 interface, hr %#x.\n", hr);
3453 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
3454 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3456 viewport = create_viewport(device, 0, 0, 640, 480);
3457 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
3458 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
3460 memset(&mat_desc, 0, sizeof(mat_desc));
3461 mat_desc.dwSize = sizeof(mat_desc);
3462 U2(U3(mat_desc).dcvEmissive).g = 1.0f;
3463 hr = IDirect3D2_CreateMaterial(d3d, &emissive, NULL);
3464 ok(SUCCEEDED(hr), "Failed to create material, hr %#x.\n", hr);
3465 hr = IDirect3DMaterial2_SetMaterial(emissive, &mat_desc);
3466 ok(SUCCEEDED(hr), "Failed to set material, hr %#x.\n", hr);
3467 hr = IDirect3DMaterial2_GetHandle(emissive, device, &mat_handle);
3468 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
3469 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
3470 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
3471 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
3472 ok(SUCCEEDED(hr), "Failed to disable z test, hr %#x.\n", hr);
3474 background = create_diffuse_material(device, 0.1f, 0.1f, 0.1f, 0.1f);
3475 hr = IDirect3DMaterial2_GetHandle(background, device, &mat_handle);
3476 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
3477 hr = IDirect3DViewport2_SetBackground(viewport, mat_handle);
3478 ok(SUCCEEDED(hr), "Failed to set background material, hr %#x.\n", hr);
3480 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, &rs);
3481 ok(SUCCEEDED(hr), "Failed to get specularenable render state, hr %#x.\n", hr);
3482 ok(rs == TRUE, "Initial D3DRENDERSTATE_SPECULARENABLE is %#x, expected TRUE.\n", rs);
3484 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
3486 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
3487 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3489 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, tests[i].d3drs_lighting);
3490 ok(SUCCEEDED(hr), "Failed to set lighting render state, hr %#x.\n", hr);
3491 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE,
3492 tests[i].d3drs_specular);
3493 ok(SUCCEEDED(hr), "Failed to set specularenable render state, hr %#x.\n", hr);
3495 hr = IDirect3DDevice2_BeginScene(device);
3496 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3497 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
3498 tests[i].vertextype, tests[i].data, 4, tests[i].draw_flags | D3DDP_WAIT);
3499 hr = IDirect3DDevice2_EndScene(device);
3500 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3502 color = get_surface_color(rt, 320, 240);
3503 ok(compare_color(color, tests[i].color, 1),
3504 "Got unexpected color 0x%08x, expected 0x%08x, test %u.\n",
3505 color, tests[i].color, i);
3508 IDirect3DMaterial2_Release(background);
3509 IDirect3DMaterial2_Release(emissive);
3510 IDirectDrawSurface_Release(rt);
3511 IDirect3DDevice2_Release(device);
3512 IDirect3D2_Release(d3d);
3513 ref = IDirectDraw2_Release(ddraw);
3514 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
3515 DestroyWindow(window);
3518 static struct
3520 BOOL received;
3521 IDirectDraw2 *ddraw;
3522 HWND window;
3523 DWORD coop_level;
3524 } activateapp_testdata;
3526 static LRESULT CALLBACK activateapp_test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
3528 if (message == WM_ACTIVATEAPP)
3530 if (activateapp_testdata.ddraw)
3532 HRESULT hr;
3533 activateapp_testdata.received = FALSE;
3534 hr = IDirectDraw2_SetCooperativeLevel(activateapp_testdata.ddraw,
3535 activateapp_testdata.window, activateapp_testdata.coop_level);
3536 ok(SUCCEEDED(hr), "Recursive SetCooperativeLevel call failed, hr %#x.\n", hr);
3537 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP during recursive SetCooperativeLevel call.\n");
3539 activateapp_testdata.received = TRUE;
3542 return DefWindowProcA(hwnd, message, wparam, lparam);
3545 static void test_coop_level_activateapp(void)
3547 IDirectDraw2 *ddraw;
3548 HRESULT hr;
3549 HWND window;
3550 WNDCLASSA wc = {0};
3551 DDSURFACEDESC ddsd;
3552 IDirectDrawSurface *surface;
3554 if (!(ddraw = create_ddraw()))
3556 skip("Failed to create a ddraw object, skipping test.\n");
3557 return;
3560 wc.lpfnWndProc = activateapp_test_proc;
3561 wc.lpszClassName = "ddraw_test_wndproc_wc";
3562 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3564 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
3565 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
3567 /* Exclusive with window already active. */
3568 SetActiveWindow(window);
3569 activateapp_testdata.received = FALSE;
3570 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3571 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3572 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP although window was already active.\n");
3573 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3574 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3576 /* Exclusive with window not active. */
3577 SetActiveWindow(NULL);
3578 activateapp_testdata.received = FALSE;
3579 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3580 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3581 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
3582 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3583 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3585 /* Normal with window not active, then exclusive with the same window. */
3586 SetActiveWindow(NULL);
3587 activateapp_testdata.received = FALSE;
3588 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3589 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3590 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP when setting DDSCL_NORMAL.\n");
3591 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3592 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3593 /* Except in the first SetCooperativeLevel call, Windows XP randomly does not send
3594 * WM_ACTIVATEAPP. Windows 7 sends the message reliably. Mark the XP behavior broken. */
3595 ok(activateapp_testdata.received || broken(!activateapp_testdata.received),
3596 "Expected WM_ACTIVATEAPP, but did not receive it.\n");
3597 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3598 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3600 /* Recursive set of DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. */
3601 SetActiveWindow(NULL);
3602 activateapp_testdata.received = FALSE;
3603 activateapp_testdata.ddraw = ddraw;
3604 activateapp_testdata.window = window;
3605 activateapp_testdata.coop_level = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
3606 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3607 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3608 ok(activateapp_testdata.received || broken(!activateapp_testdata.received),
3609 "Expected WM_ACTIVATEAPP, but did not receive it.\n");
3610 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3611 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3613 /* The recursive call seems to have some bad effect on native ddraw, despite (apparently)
3614 * succeeding. Another switch to exclusive and back to normal is needed to release the
3615 * window properly. Without doing this, SetCooperativeLevel(EXCLUSIVE) will not send
3616 * WM_ACTIVATEAPP messages. */
3617 activateapp_testdata.ddraw = NULL;
3618 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3619 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3620 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3621 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3623 /* Setting DDSCL_NORMAL with recursive invocation. */
3624 SetActiveWindow(NULL);
3625 activateapp_testdata.received = FALSE;
3626 activateapp_testdata.ddraw = ddraw;
3627 activateapp_testdata.window = window;
3628 activateapp_testdata.coop_level = DDSCL_NORMAL;
3629 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3630 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3631 ok(activateapp_testdata.received || broken(!activateapp_testdata.received),
3632 "Expected WM_ACTIVATEAPP, but did not receive it.\n");
3634 /* DDraw is in exlusive mode now. */
3635 memset(&ddsd, 0, sizeof(ddsd));
3636 ddsd.dwSize = sizeof(ddsd);
3637 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
3638 ddsd.dwBackBufferCount = 1;
3639 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
3640 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
3641 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
3642 IDirectDrawSurface_Release(surface);
3644 /* Recover again, just to be sure. */
3645 activateapp_testdata.ddraw = NULL;
3646 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3647 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3648 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3649 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3651 DestroyWindow(window);
3652 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
3653 IDirectDraw2_Release(ddraw);
3656 struct format_support_check
3658 const DDPIXELFORMAT *format;
3659 BOOL supported;
3662 static HRESULT WINAPI test_unsupported_formats_cb(DDSURFACEDESC *desc, void *ctx)
3664 struct format_support_check *format = ctx;
3666 if (!memcmp(format->format, &desc->ddpfPixelFormat, sizeof(*format->format)))
3668 format->supported = TRUE;
3669 return DDENUMRET_CANCEL;
3672 return DDENUMRET_OK;
3675 static void test_unsupported_formats(void)
3677 HRESULT hr;
3678 BOOL expect_success;
3679 HWND window;
3680 IDirectDraw2 *ddraw;
3681 IDirect3DDevice2 *device;
3682 IDirectDrawSurface *surface;
3683 DDSURFACEDESC ddsd;
3684 unsigned int i, j;
3685 DWORD expected_caps;
3686 static const struct
3688 const char *name;
3689 DDPIXELFORMAT fmt;
3691 formats[] =
3694 "D3DFMT_A8R8G8B8",
3696 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
3697 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
3701 "D3DFMT_P8",
3703 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
3704 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
3708 static const DWORD caps[] = {0, DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY};
3710 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3711 0, 0, 640, 480, 0, 0, 0, 0);
3712 if (!(ddraw = create_ddraw()))
3714 skip("Failed to create a ddraw object, skipping test.\n");
3715 DestroyWindow(window);
3716 return;
3718 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
3720 skip("Failed to create a 3D device, skipping test.\n");
3721 IDirectDraw2_Release(ddraw);
3722 DestroyWindow(window);
3723 return;
3726 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
3728 struct format_support_check check = {&formats[i].fmt, FALSE};
3729 hr = IDirect3DDevice2_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
3730 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
3732 for (j = 0; j < sizeof(caps) / sizeof(*caps); j++)
3734 memset(&ddsd, 0, sizeof(ddsd));
3735 ddsd.dwSize = sizeof(ddsd);
3736 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
3737 ddsd.ddpfPixelFormat = formats[i].fmt;
3738 ddsd.dwWidth = 4;
3739 ddsd.dwHeight = 4;
3740 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | caps[j];
3742 if (caps[j] & DDSCAPS_VIDEOMEMORY && !check.supported)
3743 expect_success = FALSE;
3744 else
3745 expect_success = TRUE;
3747 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
3748 ok(SUCCEEDED(hr) == expect_success,
3749 "Got unexpected hr %#x for format %s, caps %#x, expected %s.\n",
3750 hr, formats[i].name, caps[j], expect_success ? "success" : "failure");
3751 if (FAILED(hr))
3752 continue;
3754 memset(&ddsd, 0, sizeof(ddsd));
3755 ddsd.dwSize = sizeof(ddsd);
3756 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &ddsd);
3757 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3759 if (caps[j] & DDSCAPS_VIDEOMEMORY)
3760 expected_caps = DDSCAPS_VIDEOMEMORY;
3761 else if (caps[j] & DDSCAPS_SYSTEMMEMORY)
3762 expected_caps = DDSCAPS_SYSTEMMEMORY;
3763 else if (check.supported)
3764 expected_caps = DDSCAPS_VIDEOMEMORY;
3765 else
3766 expected_caps = DDSCAPS_SYSTEMMEMORY;
3768 ok(ddsd.ddsCaps.dwCaps & expected_caps,
3769 "Expected capability %#x, format %s, input cap %#x.\n",
3770 expected_caps, formats[i].name, caps[j]);
3772 IDirectDrawSurface_Release(surface);
3776 IDirect3DDevice2_Release(device);
3777 IDirectDraw2_Release(ddraw);
3778 DestroyWindow(window);
3781 static void test_rt_caps(void)
3783 PALETTEENTRY palette_entries[256];
3784 IDirectDrawPalette *palette;
3785 IDirectDraw2 *ddraw;
3786 DWORD z_depth = 0;
3787 IDirect3D2 *d3d;
3788 unsigned int i;
3789 ULONG refcount;
3790 HWND window;
3791 HRESULT hr;
3793 static const DDPIXELFORMAT p8_fmt =
3795 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
3796 {8}, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000},
3799 static const struct
3801 const DDPIXELFORMAT *pf;
3802 DWORD caps_in;
3803 DWORD caps_out;
3804 HRESULT create_device_hr;
3805 HRESULT set_rt_hr;
3806 HRESULT alternative_set_rt_hr;
3807 BOOL create_may_fail;
3809 test_data[] =
3812 NULL,
3813 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
3814 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3815 D3D_OK,
3816 D3D_OK,
3817 D3D_OK,
3818 FALSE,
3821 NULL,
3822 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
3823 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3824 D3D_OK,
3825 D3D_OK,
3826 D3D_OK,
3827 FALSE,
3830 NULL,
3831 DDSCAPS_OFFSCREENPLAIN,
3832 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3833 DDERR_INVALIDCAPS,
3834 DDERR_INVALIDCAPS,
3835 DDERR_INVALIDCAPS,
3836 FALSE,
3839 NULL,
3840 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3841 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3842 D3DERR_SURFACENOTINVIDMEM,
3843 D3D_OK,
3844 D3D_OK,
3845 FALSE,
3848 NULL,
3849 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3850 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3851 DDERR_INVALIDCAPS,
3852 DDERR_INVALIDCAPS,
3853 DDERR_INVALIDCAPS,
3854 FALSE,
3857 NULL,
3858 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
3859 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3860 D3D_OK,
3861 D3D_OK,
3862 D3D_OK,
3863 FALSE,
3866 NULL,
3867 DDSCAPS_3DDEVICE,
3868 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3869 D3D_OK,
3870 D3D_OK,
3871 D3D_OK,
3872 FALSE,
3875 NULL,
3877 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3878 DDERR_INVALIDCAPS,
3879 DDERR_INVALIDCAPS,
3880 DDERR_INVALIDCAPS,
3881 FALSE,
3884 NULL,
3885 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3886 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3887 D3DERR_SURFACENOTINVIDMEM,
3888 D3D_OK,
3889 D3D_OK,
3890 FALSE,
3893 NULL,
3894 DDSCAPS_SYSTEMMEMORY,
3895 DDSCAPS_SYSTEMMEMORY,
3896 DDERR_INVALIDCAPS,
3897 DDERR_INVALIDCAPS,
3898 DDERR_INVALIDCAPS,
3899 FALSE,
3902 &p8_fmt,
3904 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3905 DDERR_INVALIDCAPS,
3906 DDERR_INVALIDCAPS,
3907 DDERR_INVALIDCAPS,
3908 FALSE,
3911 &p8_fmt,
3912 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
3913 ~0U /* AMD r200 */,
3914 DDERR_NOPALETTEATTACHED,
3915 DDERR_INVALIDCAPS,
3916 DDERR_INVALIDCAPS,
3917 FALSE,
3920 &p8_fmt,
3921 DDSCAPS_OFFSCREENPLAIN,
3922 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3923 DDERR_INVALIDCAPS,
3924 DDERR_INVALIDCAPS,
3925 DDERR_INVALIDCAPS,
3926 FALSE,
3929 &p8_fmt,
3930 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3931 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3932 DDERR_NOPALETTEATTACHED,
3933 DDERR_INVALIDCAPS,
3934 DDERR_INVALIDCAPS,
3935 FALSE,
3938 &p8_fmt,
3939 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3940 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3941 DDERR_INVALIDCAPS,
3942 DDERR_INVALIDCAPS,
3943 DDERR_INVALIDCAPS,
3944 FALSE,
3947 NULL,
3948 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
3949 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
3950 DDERR_INVALIDCAPS,
3951 DDERR_INVALIDPIXELFORMAT,
3952 DDERR_INVALIDCAPS,
3953 TRUE /* AMD Evergreen */,
3956 NULL,
3957 DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
3958 ~0U /* AMD Evergreen */,
3959 DDERR_INVALIDCAPS,
3960 DDERR_INVALIDPIXELFORMAT,
3961 DDERR_INVALIDCAPS,
3962 FALSE,
3965 NULL,
3966 DDSCAPS_ZBUFFER,
3967 ~0U /* AMD Evergreen */,
3968 DDERR_INVALIDCAPS,
3969 DDERR_INVALIDCAPS,
3970 DDERR_INVALIDCAPS,
3971 FALSE,
3974 NULL,
3975 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
3976 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
3977 DDERR_INVALIDCAPS,
3978 DDERR_INVALIDPIXELFORMAT,
3979 DDERR_INVALIDPIXELFORMAT,
3980 TRUE /* Nvidia Kepler */,
3983 NULL,
3984 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
3985 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
3986 DDERR_INVALIDCAPS,
3987 DDERR_INVALIDCAPS,
3988 DDERR_INVALIDCAPS,
3989 TRUE /* Nvidia Kepler */,
3993 if (!(ddraw = create_ddraw()))
3995 skip("Failed to create a ddraw object, skipping test.\n");
3996 return;
3999 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4000 0, 0, 640, 480, 0, 0, 0, 0);
4001 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4002 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4004 if (FAILED(hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d)))
4006 skip("D3D interface is not available, skipping test.\n");
4007 goto done;
4010 hr = IDirect3D2_EnumDevices(d3d, enum_z_fmt, &z_depth);
4011 if (FAILED(hr) || !z_depth)
4013 skip("No depth buffer formats available, skipping test.\n");
4014 IDirect3D2_Release(d3d);
4015 goto done;
4018 memset(palette_entries, 0, sizeof(palette_entries));
4019 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
4020 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
4022 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
4024 IDirectDrawSurface *surface, *rt, *expected_rt, *tmp;
4025 DDSURFACEDESC surface_desc;
4026 IDirect3DDevice2 *device;
4028 memset(&surface_desc, 0, sizeof(surface_desc));
4029 surface_desc.dwSize = sizeof(surface_desc);
4030 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4031 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
4032 if (test_data[i].pf)
4034 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
4035 surface_desc.ddpfPixelFormat = *test_data[i].pf;
4037 if (test_data[i].caps_in & DDSCAPS_ZBUFFER)
4039 surface_desc.dwFlags |= DDSD_ZBUFFERBITDEPTH;
4040 U2(surface_desc).dwZBufferBitDepth = z_depth;
4042 surface_desc.dwWidth = 640;
4043 surface_desc.dwHeight = 480;
4044 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
4045 ok(SUCCEEDED(hr) || broken(test_data[i].create_may_fail),
4046 "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
4047 i, test_data[i].caps_in, hr);
4048 if (FAILED(hr))
4049 continue;
4051 memset(&surface_desc, 0, sizeof(surface_desc));
4052 surface_desc.dwSize = sizeof(surface_desc);
4053 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
4054 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
4055 ok(test_data[i].caps_out == ~0U || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out,
4056 "Test %u: Got unexpected caps %#x, expected %#x.\n",
4057 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
4059 hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device);
4060 ok(hr == test_data[i].create_device_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n",
4061 i, hr, test_data[i].create_device_hr);
4062 if (FAILED(hr))
4064 if (hr == DDERR_NOPALETTEATTACHED)
4066 hr = IDirectDrawSurface_SetPalette(surface, palette);
4067 ok(SUCCEEDED(hr), "Test %u: Failed to set palette, hr %#x.\n", i, hr);
4068 hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device);
4069 if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
4070 ok(hr == DDERR_INVALIDPIXELFORMAT, "Test %u: Got unexpected hr %#x.\n", i, hr);
4071 else
4072 ok(hr == D3DERR_SURFACENOTINVIDMEM, "Test %u: Got unexpected hr %#x.\n", i, hr);
4074 IDirectDrawSurface_Release(surface);
4076 memset(&surface_desc, 0, sizeof(surface_desc));
4077 surface_desc.dwSize = sizeof(surface_desc);
4078 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4079 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
4080 surface_desc.dwWidth = 640;
4081 surface_desc.dwHeight = 480;
4082 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
4083 ok(SUCCEEDED(hr), "Test %u: Failed to create surface, hr %#x.\n", i, hr);
4085 hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device);
4086 ok(SUCCEEDED(hr), "Test %u: Failed to create device, hr %#x.\n", i, hr);
4089 memset(&surface_desc, 0, sizeof(surface_desc));
4090 surface_desc.dwSize = sizeof(surface_desc);
4091 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4092 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
4093 if (test_data[i].pf)
4095 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
4096 surface_desc.ddpfPixelFormat = *test_data[i].pf;
4098 if (test_data[i].caps_in & DDSCAPS_ZBUFFER)
4100 surface_desc.dwFlags |= DDSD_ZBUFFERBITDEPTH;
4101 U2(surface_desc).dwZBufferBitDepth = z_depth;
4103 surface_desc.dwWidth = 640;
4104 surface_desc.dwHeight = 480;
4105 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &rt, NULL);
4106 ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
4107 i, test_data[i].caps_in, hr);
4109 hr = IDirect3DDevice2_SetRenderTarget(device, rt, 0);
4110 ok(hr == test_data[i].set_rt_hr || broken(hr == test_data[i].alternative_set_rt_hr),
4111 "Test %u: Got unexpected hr %#x, expected %#x.\n",
4112 i, hr, test_data[i].set_rt_hr);
4113 if (SUCCEEDED(hr) || hr == DDERR_INVALIDPIXELFORMAT)
4114 expected_rt = rt;
4115 else
4116 expected_rt = surface;
4118 /* It appears the surface is set as render target in this case, but no
4119 * reference is taken. */
4120 if (hr == DDERR_INVALIDPIXELFORMAT)
4122 refcount = IDirectDrawSurface_AddRef(rt);
4123 ok(refcount == 2, "Test %u: Got unexpected refcount %u.\n", i, refcount);
4126 hr = IDirect3DDevice2_GetRenderTarget(device, &tmp);
4127 ok(SUCCEEDED(hr), "Test %u: Failed to get render target, hr %#x.\n", i, hr);
4128 ok(tmp == expected_rt, "Test %u: Got unexpected rt %p.\n", i, tmp);
4130 IDirectDrawSurface_Release(tmp);
4131 IDirectDrawSurface_Release(rt);
4132 refcount = IDirect3DDevice2_Release(device);
4133 ok(refcount == 0, "Test %u: The device was not properly freed, refcount %u.\n", i, refcount);
4134 refcount = IDirectDrawSurface_Release(surface);
4135 ok(refcount == 0, "Test %u: The surface was not properly freed, refcount %u.\n", i, refcount);
4138 IDirectDrawPalette_Release(palette);
4139 IDirect3D2_Release(d3d);
4141 done:
4142 refcount = IDirectDraw2_Release(ddraw);
4143 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
4144 DestroyWindow(window);
4147 static void test_primary_caps(void)
4149 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
4150 IDirectDrawSurface *surface;
4151 DDSURFACEDESC surface_desc;
4152 IDirectDraw2 *ddraw;
4153 unsigned int i;
4154 ULONG refcount;
4155 HWND window;
4156 HRESULT hr;
4158 static const struct
4160 DWORD coop_level;
4161 DWORD caps_in;
4162 DWORD back_buffer_count;
4163 HRESULT hr;
4164 DWORD caps_out;
4166 test_data[] =
4169 DDSCL_NORMAL,
4170 DDSCAPS_PRIMARYSURFACE,
4171 ~0u,
4172 DD_OK,
4173 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE,
4176 DDSCL_NORMAL,
4177 DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE,
4178 ~0u,
4179 DDERR_INVALIDCAPS,
4180 ~0u,
4183 DDSCL_NORMAL,
4184 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
4185 ~0u,
4186 DDERR_INVALIDCAPS,
4187 ~0u,
4190 DDSCL_NORMAL,
4191 DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER,
4192 ~0u,
4193 DDERR_INVALIDCAPS,
4194 ~0u,
4197 DDSCL_NORMAL,
4198 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP,
4199 ~0u,
4200 DDERR_INVALIDCAPS,
4201 ~0u,
4204 DDSCL_NORMAL,
4205 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX,
4206 ~0u,
4207 DDERR_INVALIDCAPS,
4208 ~0u,
4211 DDSCL_NORMAL,
4212 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
4213 ~0u,
4214 DDERR_INVALIDCAPS,
4215 ~0u,
4218 DDSCL_NORMAL,
4219 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
4221 DDERR_INVALIDCAPS,
4222 ~0u,
4225 DDSCL_NORMAL,
4226 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
4228 DDERR_NOEXCLUSIVEMODE,
4229 ~0u,
4232 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
4233 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
4235 DDERR_INVALIDCAPS,
4236 ~0u,
4239 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
4240 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
4242 DD_OK,
4243 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX,
4246 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
4247 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER,
4249 DDERR_INVALIDCAPS,
4250 ~0u,
4253 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
4254 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_BACKBUFFER,
4256 DDERR_INVALIDCAPS,
4257 ~0u,
4261 if (!(ddraw = create_ddraw()))
4263 skip("Failed to create a ddraw object, skipping test.\n");
4264 return;
4267 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4268 0, 0, 640, 480, 0, 0, 0, 0);
4270 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
4272 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, test_data[i].coop_level);
4273 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4275 memset(&surface_desc, 0, sizeof(surface_desc));
4276 surface_desc.dwSize = sizeof(surface_desc);
4277 surface_desc.dwFlags = DDSD_CAPS;
4278 if (test_data[i].back_buffer_count != ~0u)
4279 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
4280 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
4281 surface_desc.dwBackBufferCount = test_data[i].back_buffer_count;
4282 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
4283 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
4284 if (FAILED(hr))
4285 continue;
4287 memset(&surface_desc, 0, sizeof(surface_desc));
4288 surface_desc.dwSize = sizeof(surface_desc);
4289 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
4290 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
4291 ok((surface_desc.ddsCaps.dwCaps & ~placement) == test_data[i].caps_out,
4292 "Test %u: Got unexpected caps %#x, expected %#x.\n",
4293 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
4295 IDirectDrawSurface_Release(surface);
4298 refcount = IDirectDraw2_Release(ddraw);
4299 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
4300 DestroyWindow(window);
4303 static void test_surface_lock(void)
4305 IDirectDraw2 *ddraw;
4306 IDirect3D2 *d3d = NULL;
4307 IDirectDrawSurface *surface;
4308 HRESULT hr;
4309 HWND window;
4310 unsigned int i;
4311 DDSURFACEDESC ddsd;
4312 ULONG refcount;
4313 DWORD z_depth = 0;
4314 static const struct
4316 DWORD caps;
4317 const char *name;
4319 tests[] =
4322 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
4323 "videomemory offscreenplain"
4326 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
4327 "systemmemory offscreenplain"
4330 DDSCAPS_PRIMARYSURFACE,
4331 "primary"
4334 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
4335 "videomemory texture"
4338 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
4339 "systemmemory texture"
4342 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
4343 "render target"
4346 DDSCAPS_ZBUFFER,
4347 "Z buffer"
4351 if (!(ddraw = create_ddraw()))
4353 skip("Failed to create a ddraw object, skipping test.\n");
4354 return;
4357 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4358 0, 0, 640, 480, 0, 0, 0, 0);
4359 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4360 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4362 if (FAILED(hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d)))
4364 skip("D3D interface is not available, skipping test.\n");
4365 goto done;
4368 hr = IDirect3D2_EnumDevices(d3d, enum_z_fmt, &z_depth);
4369 if (FAILED(hr) || !z_depth)
4371 skip("No depth buffer formats available, skipping test.\n");
4372 goto done;
4375 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
4377 memset(&ddsd, 0, sizeof(ddsd)),
4378 ddsd.dwSize = sizeof(ddsd);
4379 ddsd.dwFlags = DDSD_CAPS;
4380 if (!(tests[i].caps & DDSCAPS_PRIMARYSURFACE))
4382 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
4383 ddsd.dwWidth = 64;
4384 ddsd.dwHeight = 64;
4386 if (tests[i].caps & DDSCAPS_ZBUFFER)
4388 ddsd.dwFlags |= DDSD_ZBUFFERBITDEPTH;
4389 U2(ddsd).dwZBufferBitDepth = z_depth;
4391 ddsd.ddsCaps.dwCaps = tests[i].caps;
4393 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
4394 ok(SUCCEEDED(hr), "Failed to create surface, type %s, hr %#x.\n", tests[i].name, hr);
4396 memset(&ddsd, 0, sizeof(ddsd)),
4397 ddsd.dwSize = sizeof(ddsd);
4398 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
4399 ok(SUCCEEDED(hr), "Failed to lock surface, type %s, hr %#x.\n", tests[i].name, hr);
4400 if (SUCCEEDED(hr))
4402 hr = IDirectDrawSurface_Unlock(surface, NULL);
4403 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
4406 IDirectDrawSurface_Release(surface);
4409 done:
4410 if (d3d)
4411 IDirect3D2_Release(d3d);
4412 refcount = IDirectDraw2_Release(ddraw);
4413 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
4414 DestroyWindow(window);
4417 static void test_surface_discard(void)
4419 IDirectDraw2 *ddraw;
4420 HRESULT hr;
4421 HWND window;
4422 DDSURFACEDESC ddsd;
4423 IDirectDrawSurface *surface, *primary;
4424 void *addr;
4425 static const struct
4427 DWORD caps;
4428 BOOL discard;
4430 tests[] =
4432 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, TRUE},
4433 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, FALSE},
4434 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, TRUE},
4435 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, FALSE},
4437 unsigned int i;
4439 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4440 0, 0, 640, 480, 0, 0, 0, 0);
4441 if (!(ddraw = create_ddraw()))
4443 skip("Failed to create a ddraw object, skipping test.\n");
4444 DestroyWindow(window);
4445 return;
4447 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4448 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4450 memset(&ddsd, 0, sizeof(ddsd));
4451 ddsd.dwSize = sizeof(ddsd);
4452 ddsd.dwFlags = DDSD_CAPS;
4453 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4454 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
4456 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
4458 BOOL discarded;
4460 memset(&ddsd, 0, sizeof(ddsd));
4461 ddsd.dwSize = sizeof(ddsd);
4462 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4463 ddsd.ddsCaps.dwCaps = tests[i].caps;
4464 ddsd.dwWidth = 64;
4465 ddsd.dwHeight = 64;
4466 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
4467 if (FAILED(hr))
4469 skip("Failed to create surface, skipping.\n");
4470 continue;
4473 memset(&ddsd, 0, sizeof(ddsd));
4474 ddsd.dwSize = sizeof(ddsd);
4475 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
4476 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
4477 addr = ddsd.lpSurface;
4478 hr = IDirectDrawSurface_Unlock(surface, NULL);
4479 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4481 memset(&ddsd, 0, sizeof(ddsd));
4482 ddsd.dwSize = sizeof(ddsd);
4483 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL);
4484 ok(SUCCEEDED(hr) , "Failed to lock surface, hr %#x.\n", hr);
4485 discarded = ddsd.lpSurface != addr;
4486 hr = IDirectDrawSurface_Unlock(surface, NULL);
4487 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4489 hr = IDirectDrawSurface_Blt(primary, NULL, surface, NULL, DDBLT_WAIT, NULL);
4490 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
4492 memset(&ddsd, 0, sizeof(ddsd));
4493 ddsd.dwSize = sizeof(ddsd);
4494 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL);
4495 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
4496 discarded |= ddsd.lpSurface != addr;
4497 hr = IDirectDrawSurface_Unlock(surface, NULL);
4498 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4500 IDirectDrawSurface_Release(surface);
4502 /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler,
4503 * AMD r500, evergreen). Windows XP, at least on AMD r200, never changes the pointer. */
4504 ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i);
4507 IDirectDrawSurface_Release(primary);
4508 IDirectDraw2_Release(ddraw);
4509 DestroyWindow(window);
4512 static void test_flip(void)
4514 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
4515 IDirectDrawSurface *primary, *backbuffer1, *backbuffer2, *backbuffer3, *surface;
4516 DDSCAPS caps = {DDSCAPS_FLIP};
4517 DDSURFACEDESC surface_desc;
4518 BOOL sysmem_primary;
4519 IDirectDraw2 *ddraw;
4520 D3DCOLOR color;
4521 ULONG refcount;
4522 HWND window;
4523 DDBLTFX fx;
4524 HRESULT hr;
4526 if (!(ddraw = create_ddraw()))
4528 skip("Failed to create a ddraw object, skipping test.\n");
4529 return;
4532 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4533 0, 0, 640, 480, 0, 0, 0, 0);
4535 hr = IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 32, 0, 0);
4536 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
4537 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4538 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4540 memset(&surface_desc, 0, sizeof(surface_desc));
4541 surface_desc.dwSize = sizeof(surface_desc);
4542 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
4543 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
4544 surface_desc.dwBackBufferCount = 3;
4545 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
4546 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4548 memset(&surface_desc, 0, sizeof(surface_desc));
4549 surface_desc.dwSize = sizeof(surface_desc);
4550 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &surface_desc);
4551 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4552 ok((surface_desc.ddsCaps.dwCaps & ~placement)
4553 == (DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX),
4554 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
4555 sysmem_primary = surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
4557 hr = IDirectDrawSurface_GetAttachedSurface(primary, &caps, &backbuffer1);
4558 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
4559 memset(&surface_desc, 0, sizeof(surface_desc));
4560 surface_desc.dwSize = sizeof(surface_desc);
4561 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer1, &surface_desc);
4562 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4563 ok(!surface_desc.dwBackBufferCount, "Got unexpected back buffer count %u.\n", surface_desc.dwBackBufferCount);
4564 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_BACKBUFFER),
4565 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
4567 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer1, &caps, &backbuffer2);
4568 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
4569 memset(&surface_desc, 0, sizeof(surface_desc));
4570 surface_desc.dwSize = sizeof(surface_desc);
4571 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer2, &surface_desc);
4572 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4573 ok(!surface_desc.dwBackBufferCount, "Got unexpected back buffer count %u.\n", surface_desc.dwBackBufferCount);
4574 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX),
4575 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
4577 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer2, &caps, &backbuffer3);
4578 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
4579 memset(&surface_desc, 0, sizeof(surface_desc));
4580 surface_desc.dwSize = sizeof(surface_desc);
4581 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer3, &surface_desc);
4582 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4583 ok(!surface_desc.dwBackBufferCount, "Got unexpected back buffer count %u.\n", surface_desc.dwBackBufferCount);
4584 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX),
4585 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
4587 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer3, &caps, &surface);
4588 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
4589 ok(surface == primary, "Got unexpected surface %p, expected %p.\n", surface, primary);
4590 IDirectDrawSurface_Release(surface);
4592 memset(&surface_desc, 0, sizeof(surface_desc));
4593 surface_desc.dwSize = sizeof(surface_desc);
4594 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4595 surface_desc.ddsCaps.dwCaps = 0;
4596 surface_desc.dwWidth = 640;
4597 surface_desc.dwHeight = 480;
4598 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
4599 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4600 hr = IDirectDrawSurface_Flip(primary, surface, DDFLIP_WAIT);
4601 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
4602 IDirectDrawSurface_Release(surface);
4604 hr = IDirectDrawSurface_Flip(primary, primary, DDFLIP_WAIT);
4605 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
4606 hr = IDirectDrawSurface_Flip(backbuffer1, NULL, DDFLIP_WAIT);
4607 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
4608 hr = IDirectDrawSurface_Flip(backbuffer2, NULL, DDFLIP_WAIT);
4609 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
4610 hr = IDirectDrawSurface_Flip(backbuffer3, NULL, DDFLIP_WAIT);
4611 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
4613 memset(&fx, 0, sizeof(fx));
4614 fx.dwSize = sizeof(fx);
4615 U5(fx).dwFillColor = 0xffff0000;
4616 hr = IDirectDrawSurface_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4617 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
4618 U5(fx).dwFillColor = 0xff00ff00;
4619 hr = IDirectDrawSurface_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4620 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
4621 U5(fx).dwFillColor = 0xff0000ff;
4622 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4623 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
4625 hr = IDirectDrawSurface_Flip(primary, NULL, DDFLIP_WAIT);
4626 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
4627 color = get_surface_color(backbuffer1, 320, 240);
4628 /* The testbot seems to just copy the contents of one surface to all the
4629 * others, instead of properly flipping. */
4630 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
4631 "Got unexpected color 0x%08x.\n", color);
4632 color = get_surface_color(backbuffer2, 320, 240);
4633 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
4634 U5(fx).dwFillColor = 0xffff0000;
4635 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4636 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
4638 hr = IDirectDrawSurface_Flip(primary, NULL, DDFLIP_WAIT);
4639 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
4640 color = get_surface_color(backbuffer1, 320, 240);
4641 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
4642 "Got unexpected color 0x%08x.\n", color);
4643 color = get_surface_color(backbuffer2, 320, 240);
4644 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
4645 U5(fx).dwFillColor = 0xff00ff00;
4646 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4647 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
4649 hr = IDirectDrawSurface_Flip(primary, NULL, DDFLIP_WAIT);
4650 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
4651 color = get_surface_color(backbuffer1, 320, 240);
4652 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
4653 "Got unexpected color 0x%08x.\n", color);
4654 color = get_surface_color(backbuffer2, 320, 240);
4655 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
4656 U5(fx).dwFillColor = 0xff0000ff;
4657 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4658 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
4660 hr = IDirectDrawSurface_Flip(primary, backbuffer1, DDFLIP_WAIT);
4661 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
4662 color = get_surface_color(backbuffer2, 320, 240);
4663 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
4664 "Got unexpected color 0x%08x.\n", color);
4665 color = get_surface_color(backbuffer3, 320, 240);
4666 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
4667 U5(fx).dwFillColor = 0xffff0000;
4668 hr = IDirectDrawSurface_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4669 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
4671 hr = IDirectDrawSurface_Flip(primary, backbuffer2, DDFLIP_WAIT);
4672 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
4673 color = get_surface_color(backbuffer1, 320, 240);
4674 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
4675 color = get_surface_color(backbuffer3, 320, 240);
4676 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
4677 "Got unexpected color 0x%08x.\n", color);
4678 U5(fx).dwFillColor = 0xff00ff00;
4679 hr = IDirectDrawSurface_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4680 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
4682 hr = IDirectDrawSurface_Flip(primary, backbuffer3, DDFLIP_WAIT);
4683 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
4684 color = get_surface_color(backbuffer1, 320, 240);
4685 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
4686 "Got unexpected color 0x%08x.\n", color);
4687 color = get_surface_color(backbuffer2, 320, 240);
4688 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
4690 IDirectDrawSurface_Release(backbuffer3);
4691 IDirectDrawSurface_Release(backbuffer2);
4692 IDirectDrawSurface_Release(backbuffer1);
4693 IDirectDrawSurface_Release(primary);
4694 refcount = IDirectDraw2_Release(ddraw);
4695 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
4696 DestroyWindow(window);
4699 static void reset_ddsd(DDSURFACEDESC *ddsd)
4701 memset(ddsd, 0, sizeof(*ddsd));
4702 ddsd->dwSize = sizeof(*ddsd);
4705 static void test_set_surface_desc(void)
4707 IDirectDraw2 *ddraw;
4708 HWND window;
4709 HRESULT hr;
4710 DDSURFACEDESC ddsd;
4711 IDirectDrawSurface *surface;
4712 IDirectDrawSurface3 *surface3;
4713 BYTE data[16*16*4];
4714 ULONG ref;
4715 unsigned int i;
4716 static const struct
4718 DWORD caps;
4719 BOOL supported;
4720 const char *name;
4722 invalid_caps_tests[] =
4724 {DDSCAPS_VIDEOMEMORY, FALSE, "videomemory plain"},
4725 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, TRUE, "systemmemory texture"},
4726 {DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY, FALSE, "systemmemory primary"},
4729 if (!(ddraw = create_ddraw()))
4731 skip("Failed to create a ddraw object, skipping test.\n");
4732 return;
4735 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4736 0, 0, 640, 480, 0, 0, 0, 0);
4738 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4739 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4741 reset_ddsd(&ddsd);
4742 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
4743 ddsd.dwWidth = 8;
4744 ddsd.dwHeight = 8;
4745 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
4746 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
4747 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
4748 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
4749 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
4750 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
4751 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY;
4753 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
4754 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4756 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
4757 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface3 interface, hr %#x.\n", hr);
4758 IDirectDrawSurface_Release(surface);
4760 reset_ddsd(&ddsd);
4761 ddsd.dwFlags = DDSD_LPSURFACE;
4762 ddsd.lpSurface = data;
4763 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4764 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
4766 /* Redundantly setting the same lpSurface is not an error. */
4767 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4768 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
4769 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
4770 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4771 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
4772 ok(ddsd.lpSurface == NULL, "lpSurface is %p, expected NULL.\n", ddsd.lpSurface);
4774 hr = IDirectDrawSurface3_Lock(surface3, NULL, &ddsd, 0, NULL);
4775 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
4776 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
4777 ok(ddsd.lpSurface == data, "lpSurface is %p, expected %p.\n", data, data);
4778 hr = IDirectDrawSurface3_Unlock(surface3, NULL);
4779 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4781 reset_ddsd(&ddsd);
4782 ddsd.dwFlags = DDSD_LPSURFACE;
4783 ddsd.lpSurface = data;
4784 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 1);
4785 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with flags=1 returned %#x.\n", hr);
4787 ddsd.lpSurface = NULL;
4788 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4789 ok(hr == DDERR_INVALIDPARAMS, "Setting lpSurface=NULL returned %#x.\n", hr);
4791 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, NULL, 0);
4792 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with NULL desc returned %#x.\n", hr);
4794 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
4795 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4796 ok(ddsd.ddsCaps.dwCaps == DDSCAPS_SYSTEMMEMORY, "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
4798 /* Setting the caps is an error. This also means the original description cannot be reapplied. */
4799 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4800 ok(hr == DDERR_INVALIDPARAMS, "Setting the original desc returned %#x.\n", hr);
4802 ddsd.dwFlags = DDSD_CAPS;
4803 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4804 ok(hr == DDERR_INVALIDPARAMS, "Setting DDSD_CAPS returned %#x.\n", hr);
4806 /* dwCaps = 0 is allowed, but ignored. */
4807 ddsd.dwFlags = DDSD_CAPS | DDSD_LPSURFACE;
4808 ddsd.lpSurface = data;
4809 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4810 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
4811 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY;
4812 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4813 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
4814 ddsd.ddsCaps.dwCaps = 0;
4815 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4816 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
4818 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
4819 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4820 ok(ddsd.ddsCaps.dwCaps == DDSCAPS_SYSTEMMEMORY, "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
4822 /* Setting the height is allowed, but it cannot be set to 0, and only if LPSURFACE is set too. */
4823 reset_ddsd(&ddsd);
4824 ddsd.dwFlags = DDSD_HEIGHT;
4825 ddsd.dwHeight = 16;
4826 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4827 ok(hr == DDERR_INVALIDPARAMS, "Setting height without lpSurface returned %#x.\n", hr);
4829 ddsd.lpSurface = data;
4830 ddsd.dwFlags = DDSD_HEIGHT | DDSD_LPSURFACE;
4831 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4832 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
4834 ddsd.dwHeight = 0;
4835 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4836 ok(hr == DDERR_INVALIDPARAMS, "Setting height=0 returned %#x.\n", hr);
4838 reset_ddsd(&ddsd);
4839 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
4840 ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr);
4841 ok(ddsd.dwWidth == 8, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
4842 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
4844 /* Pitch and width can be set, but only together, and only with LPSURFACE. They must not be 0. */
4845 reset_ddsd(&ddsd);
4846 ddsd.dwFlags = DDSD_PITCH;
4847 U1(ddsd).lPitch = 8 * 4;
4848 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4849 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch without lpSurface or width returned %#x.\n", hr);
4851 ddsd.dwFlags = DDSD_WIDTH;
4852 ddsd.dwWidth = 16;
4853 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4854 ok(hr == DDERR_INVALIDPARAMS, "Setting width without lpSurface or pitch returned %#x.\n", hr);
4856 ddsd.dwFlags = DDSD_PITCH | DDSD_LPSURFACE;
4857 ddsd.lpSurface = data;
4858 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4859 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch and lpSurface without width returned %#x.\n", hr);
4861 ddsd.dwFlags = DDSD_WIDTH | DDSD_LPSURFACE;
4862 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4863 ok(hr == DDERR_INVALIDPARAMS, "Setting width and lpSurface without pitch returned %#x.\n", hr);
4865 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
4866 U1(ddsd).lPitch = 16 * 4;
4867 ddsd.dwWidth = 16;
4868 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4869 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
4871 reset_ddsd(&ddsd);
4872 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
4873 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4874 ok(ddsd.dwWidth == 16, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
4875 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
4876 ok(U1(ddsd).lPitch == 16 * 4, "SetSurfaceDesc: Expected pitch 64, got %u.\n", U1(ddsd).lPitch);
4878 /* The pitch must be 32 bit aligned and > 0, but is not verified for sanity otherwise.
4880 * VMware rejects those calls, but all real drivers accept it. Mark the VMware behavior broken. */
4881 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
4882 U1(ddsd).lPitch = 4 * 4;
4883 ddsd.lpSurface = data;
4884 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4885 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
4887 U1(ddsd).lPitch = 4;
4888 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4889 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
4891 U1(ddsd).lPitch = 16 * 4 + 1;
4892 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4893 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
4895 U1(ddsd).lPitch = 16 * 4 + 3;
4896 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4897 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
4899 U1(ddsd).lPitch = -4;
4900 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4901 ok(hr == DDERR_INVALIDPARAMS, "Setting negative pitch returned %#x.\n", hr);
4903 U1(ddsd).lPitch = 16 * 4;
4904 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4905 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
4907 reset_ddsd(&ddsd);
4908 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
4909 U1(ddsd).lPitch = 0;
4910 ddsd.dwWidth = 16;
4911 ddsd.lpSurface = data;
4912 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4913 ok(hr == DDERR_INVALIDPARAMS, "Setting zero pitch returned %#x.\n", hr);
4915 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
4916 U1(ddsd).lPitch = 16 * 4;
4917 ddsd.dwWidth = 0;
4918 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4919 ok(hr == DDERR_INVALIDPARAMS, "Setting zero width returned %#x.\n", hr);
4921 /* Setting the pixelformat without LPSURFACE is an error, but with LPSURFACE it works. */
4922 ddsd.dwFlags = DDSD_PIXELFORMAT;
4923 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
4924 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
4925 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
4926 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
4927 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
4928 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
4929 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4930 ok(hr == DDERR_INVALIDPARAMS, "Setting the pixel format returned %#x.\n", hr);
4932 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_LPSURFACE;
4933 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4934 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
4936 /* Can't set color keys. */
4937 reset_ddsd(&ddsd);
4938 ddsd.dwFlags = DDSD_CKSRCBLT;
4939 ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff0000;
4940 ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff0000;
4941 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4942 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
4944 ddsd.dwFlags = DDSD_CKSRCBLT | DDSD_LPSURFACE;
4945 ddsd.lpSurface = data;
4946 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4947 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
4949 IDirectDrawSurface3_Release(surface3);
4951 /* SetSurfaceDesc needs systemmemory surfaces.
4953 * As a sidenote, fourcc surfaces aren't allowed in sysmem, thus testing DDSD_LINEARSIZE is moot. */
4954 for (i = 0; i < sizeof(invalid_caps_tests) / sizeof(*invalid_caps_tests); i++)
4956 reset_ddsd(&ddsd);
4957 ddsd.dwFlags = DDSD_CAPS;
4958 ddsd.ddsCaps.dwCaps = invalid_caps_tests[i].caps;
4959 if (!(invalid_caps_tests[i].caps & DDSCAPS_PRIMARYSURFACE))
4961 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
4962 ddsd.dwWidth = 8;
4963 ddsd.dwHeight = 8;
4964 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
4965 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
4966 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
4967 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
4968 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
4969 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
4972 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
4973 ok(SUCCEEDED(hr) || hr == DDERR_NODIRECTDRAWHW, "Failed to create surface, hr %#x.\n", hr);
4974 if (FAILED(hr))
4976 skip("Cannot create a %s surface, skipping vidmem SetSurfaceDesc test.\n",
4977 invalid_caps_tests[i].name);
4978 goto done;
4980 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
4981 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface3 interface, hr %#x.\n", hr);
4982 IDirectDrawSurface_Release(surface);
4984 reset_ddsd(&ddsd);
4985 ddsd.dwFlags = DDSD_LPSURFACE;
4986 ddsd.lpSurface = data;
4987 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4988 if (invalid_caps_tests[i].supported)
4990 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
4992 else
4994 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
4995 invalid_caps_tests[i].name, hr);
4997 /* Check priority of error conditions. */
4998 ddsd.dwFlags = DDSD_WIDTH;
4999 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5000 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
5001 invalid_caps_tests[i].name, hr);
5004 IDirectDrawSurface3_Release(surface3);
5007 done:
5008 ref = IDirectDraw2_Release(ddraw);
5009 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
5010 DestroyWindow(window);
5013 static void test_user_memory_getdc(void)
5015 IDirectDraw2 *ddraw;
5016 HWND window;
5017 HRESULT hr;
5018 DDSURFACEDESC ddsd;
5019 IDirectDrawSurface *surface;
5020 IDirectDrawSurface3 *surface3;
5021 DWORD data[16][16];
5022 ULONG ref;
5023 HDC dc;
5024 unsigned int x, y;
5026 if (!(ddraw = create_ddraw()))
5028 skip("Failed to create a ddraw object, skipping test.\n");
5029 return;
5032 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5033 0, 0, 640, 480, 0, 0, 0, 0);
5035 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5036 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5038 reset_ddsd(&ddsd);
5039 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
5040 ddsd.dwWidth = 16;
5041 ddsd.dwHeight = 16;
5042 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
5043 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
5044 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
5045 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5046 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5047 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
5048 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY;
5049 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
5050 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5052 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
5053 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface3 interface, hr %#x.\n", hr);
5054 IDirectDrawSurface_Release(surface);
5056 memset(data, 0xaa, sizeof(data));
5057 reset_ddsd(&ddsd);
5058 ddsd.dwFlags = DDSD_LPSURFACE;
5059 ddsd.lpSurface = data;
5060 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5061 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5063 hr = IDirectDrawSurface3_GetDC(surface3, &dc);
5064 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
5065 BitBlt(dc, 0, 0, 16, 8, NULL, 0, 0, WHITENESS);
5066 BitBlt(dc, 0, 8, 16, 8, NULL, 0, 0, BLACKNESS);
5067 hr = IDirectDrawSurface3_ReleaseDC(surface3, dc);
5068 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
5070 ok(data[0][0] == 0xffffffff, "Expected color 0xffffffff, got %#x.\n", data[0][0]);
5071 ok(data[15][15] == 0x00000000, "Expected color 0x00000000, got %#x.\n", data[15][15]);
5073 ddsd.dwFlags = DDSD_LPSURFACE | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH;
5074 ddsd.lpSurface = data;
5075 ddsd.dwWidth = 4;
5076 ddsd.dwHeight = 8;
5077 U1(ddsd).lPitch = sizeof(*data);
5078 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
5079 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
5081 memset(data, 0xaa, sizeof(data));
5082 hr = IDirectDrawSurface3_GetDC(surface3, &dc);
5083 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
5084 BitBlt(dc, 0, 0, 4, 8, NULL, 0, 0, BLACKNESS);
5085 BitBlt(dc, 1, 1, 2, 2, NULL, 0, 0, WHITENESS);
5086 hr = IDirectDrawSurface3_ReleaseDC(surface3, dc);
5087 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
5089 for (y = 0; y < 4; y++)
5091 for (x = 0; x < 4; x++)
5093 if ((x == 1 || x == 2) && (y == 1 || y == 2))
5094 ok(data[y][x] == 0xffffffff, "Expected color 0xffffffff on position %ux%u, got %#x.\n",
5095 x, y, data[y][x]);
5096 else
5097 ok(data[y][x] == 0x00000000, "Expected color 0xaaaaaaaa on position %ux%u, got %#x.\n",
5098 x, y, data[y][x]);
5101 ok(data[0][5] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 5x0, got %#x.\n",
5102 data[0][5]);
5103 ok(data[7][3] == 0x00000000, "Expected color 0x00000000 on position 3x7, got %#x.\n",
5104 data[7][3]);
5105 ok(data[7][4] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 4x7, got %#x.\n",
5106 data[7][4]);
5107 ok(data[8][0] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 0x8, got %#x.\n",
5108 data[8][0]);
5110 IDirectDrawSurface3_Release(surface3);
5111 ref = IDirectDraw2_Release(ddraw);
5112 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
5113 DestroyWindow(window);
5116 static void test_sysmem_overlay(void)
5118 IDirectDraw2 *ddraw;
5119 HWND window;
5120 HRESULT hr;
5121 DDSURFACEDESC ddsd;
5122 IDirectDrawSurface *surface;
5123 ULONG ref;
5125 if (!(ddraw = create_ddraw()))
5127 skip("Failed to create a ddraw object, skipping test.\n");
5128 return;
5131 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5132 0, 0, 640, 480, 0, 0, 0, 0);
5134 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5135 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5137 reset_ddsd(&ddsd);
5138 ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
5139 ddsd.dwWidth = 16;
5140 ddsd.dwHeight = 16;
5141 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OVERLAY;
5142 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
5143 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
5144 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
5145 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5146 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5147 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
5148 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
5149 ok(hr == DDERR_NOOVERLAYHW, "Got unexpected hr %#x.\n", hr);
5151 ref = IDirectDraw2_Release(ddraw);
5152 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
5153 DestroyWindow(window);
5156 static void test_primary_palette(void)
5158 DDSCAPS surface_caps = {DDSCAPS_FLIP};
5159 IDirectDrawSurface *primary, *backbuffer;
5160 PALETTEENTRY palette_entries[256];
5161 IDirectDrawPalette *palette, *tmp;
5162 DDSURFACEDESC surface_desc;
5163 IDirectDraw2 *ddraw;
5164 DWORD palette_caps;
5165 ULONG refcount;
5166 HWND window;
5167 HRESULT hr;
5169 if (!(ddraw = create_ddraw()))
5171 skip("Failed to create a ddraw object, skipping test.\n");
5172 return;
5175 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5176 0, 0, 640, 480, 0, 0, 0, 0);
5177 hr = IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 8, 0, 0);
5178 if (hr == E_NOTIMPL)
5180 win_skip("changing display mode is not supported (8bpp)\n");
5181 IDirectDraw2_Release(ddraw);
5182 DestroyWindow(window);
5183 return;
5185 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
5186 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5187 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5189 memset(&surface_desc, 0, sizeof(surface_desc));
5190 surface_desc.dwSize = sizeof(surface_desc);
5191 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
5192 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
5193 surface_desc.dwBackBufferCount = 1;
5194 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
5195 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5196 hr = IDirectDrawSurface_GetAttachedSurface(primary, &surface_caps, &backbuffer);
5197 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
5199 memset(palette_entries, 0, sizeof(palette_entries));
5200 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_entries, &palette, NULL);
5201 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
5202 refcount = get_refcount((IUnknown *)palette);
5203 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
5205 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
5206 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
5207 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
5209 hr = IDirectDrawSurface_SetPalette(primary, palette);
5210 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
5211 refcount = get_refcount((IUnknown *)palette);
5212 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
5214 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
5215 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
5216 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE | DDPCAPS_ALLOW256),
5217 "Got unexpected palette caps %#x.\n", palette_caps);
5219 hr = IDirectDrawSurface_SetPalette(primary, NULL);
5220 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
5221 refcount = get_refcount((IUnknown *)palette);
5222 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
5224 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
5225 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
5226 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
5228 hr = IDirectDrawSurface_SetPalette(primary, palette);
5229 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
5230 refcount = get_refcount((IUnknown *)palette);
5231 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
5233 hr = IDirectDrawSurface_GetPalette(primary, &tmp);
5234 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
5235 ok(tmp == palette, "Got unexpected palette %p, expected %p.\n", tmp, palette);
5236 IDirectDrawPalette_Release(tmp);
5237 hr = IDirectDrawSurface_GetPalette(backbuffer, &tmp);
5238 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
5240 refcount = IDirectDrawPalette_Release(palette);
5241 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
5242 refcount = IDirectDrawPalette_Release(palette);
5243 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5245 /* Note that this only seems to work when the palette is attached to the
5246 * primary surface. When attached to a regular surface, attempting to get
5247 * the palette here will cause an access violation. */
5248 hr = IDirectDrawSurface_GetPalette(primary, &tmp);
5249 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
5251 refcount = IDirectDrawSurface_Release(backbuffer);
5252 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
5253 refcount = IDirectDrawSurface_Release(primary);
5254 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5255 refcount = IDirectDraw2_Release(ddraw);
5256 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5257 DestroyWindow(window);
5260 static HRESULT WINAPI surface_counter(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
5262 UINT *surface_count = context;
5264 ++(*surface_count);
5265 IDirectDrawSurface_Release(surface);
5267 return DDENUMRET_OK;
5270 static void test_surface_attachment(void)
5272 IDirectDrawSurface *surface1, *surface2, *surface3, *surface4;
5273 DDSCAPS caps = {DDSCAPS_TEXTURE};
5274 DDSURFACEDESC surface_desc;
5275 IDirectDraw2 *ddraw;
5276 UINT surface_count;
5277 ULONG refcount;
5278 HWND window;
5279 HRESULT hr;
5281 if (!(ddraw = create_ddraw()))
5283 skip("Failed to create a ddraw object, skipping test.\n");
5284 return;
5287 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5288 0, 0, 640, 480, 0, 0, 0, 0);
5289 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5290 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5292 memset(&surface_desc, 0, sizeof(surface_desc));
5293 surface_desc.dwSize = sizeof(surface_desc);
5294 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
5295 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
5296 U2(surface_desc).dwMipMapCount = 3;
5297 surface_desc.dwWidth = 128;
5298 surface_desc.dwHeight = 128;
5299 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
5300 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5302 hr = IDirectDrawSurface_GetAttachedSurface(surface1, &caps, &surface2);
5303 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
5304 hr = IDirectDrawSurface_GetAttachedSurface(surface2, &caps, &surface3);
5305 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
5306 hr = IDirectDrawSurface_GetAttachedSurface(surface3, &caps, &surface4);
5307 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
5309 surface_count = 0;
5310 IDirectDrawSurface_EnumAttachedSurfaces(surface1, &surface_count, surface_counter);
5311 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
5312 surface_count = 0;
5313 IDirectDrawSurface_EnumAttachedSurfaces(surface2, &surface_count, surface_counter);
5314 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
5315 surface_count = 0;
5316 IDirectDrawSurface_EnumAttachedSurfaces(surface3, &surface_count, surface_counter);
5317 ok(!surface_count, "Got unexpected surface_count %u.\n", surface_count);
5319 memset(&surface_desc, 0, sizeof(surface_desc));
5320 surface_desc.dwSize = sizeof(surface_desc);
5321 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5322 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5323 surface_desc.dwWidth = 16;
5324 surface_desc.dwHeight = 16;
5325 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
5326 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5328 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
5329 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5330 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
5331 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5332 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface4);
5333 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5334 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface3);
5335 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5336 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface4);
5337 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5338 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface2);
5339 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5341 IDirectDrawSurface_Release(surface4);
5343 memset(&surface_desc, 0, sizeof(surface_desc));
5344 surface_desc.dwSize = sizeof(surface_desc);
5345 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5346 surface_desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
5347 surface_desc.dwWidth = 16;
5348 surface_desc.dwHeight = 16;
5349 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
5350 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5352 if (SUCCEEDED(hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4)))
5354 skip("Running on refrast, skipping some tests.\n");
5355 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface4);
5356 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
5358 else
5360 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5361 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
5362 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5363 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface4);
5364 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5365 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface3);
5366 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5367 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface4);
5368 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5369 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface2);
5370 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5373 IDirectDrawSurface_Release(surface4);
5374 IDirectDrawSurface_Release(surface3);
5375 IDirectDrawSurface_Release(surface2);
5376 IDirectDrawSurface_Release(surface1);
5378 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5379 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5381 /* Try a single primary and two offscreen plain surfaces. */
5382 memset(&surface_desc, 0, sizeof(surface_desc));
5383 surface_desc.dwSize = sizeof(surface_desc);
5384 surface_desc.dwFlags = DDSD_CAPS;
5385 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
5386 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
5387 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5389 memset(&surface_desc, 0, sizeof(surface_desc));
5390 surface_desc.dwSize = sizeof(surface_desc);
5391 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5392 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5393 surface_desc.dwWidth = GetSystemMetrics(SM_CXSCREEN);
5394 surface_desc.dwHeight = GetSystemMetrics(SM_CYSCREEN);
5395 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
5396 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5398 memset(&surface_desc, 0, sizeof(surface_desc));
5399 surface_desc.dwSize = sizeof(surface_desc);
5400 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5401 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5402 surface_desc.dwWidth = GetSystemMetrics(SM_CXSCREEN);
5403 surface_desc.dwHeight = GetSystemMetrics(SM_CYSCREEN);
5404 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
5405 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5407 /* This one has a different size. */
5408 memset(&surface_desc, 0, sizeof(surface_desc));
5409 surface_desc.dwSize = sizeof(surface_desc);
5410 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5411 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5412 surface_desc.dwWidth = 128;
5413 surface_desc.dwHeight = 128;
5414 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
5415 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5417 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
5418 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
5419 /* Try the reverse without detaching first. */
5420 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
5421 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
5422 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
5423 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
5425 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
5426 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
5427 /* Try to detach reversed. */
5428 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
5429 ok(hr == DDERR_CANNOTDETACHSURFACE, "Got unexpected hr %#x.\n", hr);
5430 hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface1);
5431 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
5433 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface3);
5434 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
5435 hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface3);
5436 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
5438 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
5439 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5440 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
5441 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5443 IDirectDrawSurface_Release(surface4);
5444 IDirectDrawSurface_Release(surface3);
5445 IDirectDrawSurface_Release(surface2);
5446 IDirectDrawSurface_Release(surface1);
5448 /* Test DeleteAttachedSurface() and automatic detachment of attached surfaces on release. */
5449 memset(&surface_desc, 0, sizeof(surface_desc));
5450 surface_desc.dwSize = sizeof(surface_desc);
5451 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
5452 surface_desc.dwWidth = 64;
5453 surface_desc.dwHeight = 64;
5454 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
5455 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
5456 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
5457 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 16;
5458 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0xf800;
5459 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x07e0;
5460 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x001f;
5461 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
5462 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5463 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
5464 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5466 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
5467 surface_desc.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
5468 U1(surface_desc.ddpfPixelFormat).dwZBufferBitDepth = 16;
5469 U3(surface_desc.ddpfPixelFormat).dwZBitMask = 0x0000ffff;
5470 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
5471 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5473 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
5474 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
5475 refcount = get_refcount((IUnknown *)surface2);
5476 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
5477 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
5478 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
5480 /* Attaching while already attached to other surface. */
5481 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface2);
5482 todo_wine ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
5483 hr = IDirectDrawSurface_DeleteAttachedSurface(surface3, 0, surface2);
5484 todo_wine ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
5485 IDirectDrawSurface_Release(surface3);
5487 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
5488 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
5489 refcount = get_refcount((IUnknown *)surface2);
5490 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
5492 /* Automatic detachment on release. */
5493 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
5494 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
5495 refcount = get_refcount((IUnknown *)surface2);
5496 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
5497 refcount = IDirectDrawSurface_Release(surface1);
5498 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5499 refcount = IDirectDrawSurface_Release(surface2);
5500 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5501 refcount = IDirectDraw2_Release(ddraw);
5502 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5503 DestroyWindow(window);
5506 static void test_pixel_format(void)
5508 HWND window, window2 = NULL;
5509 HDC hdc, hdc2 = NULL;
5510 HMODULE gl = NULL;
5511 int format, test_format;
5512 PIXELFORMATDESCRIPTOR pfd;
5513 IDirectDraw2 *ddraw = NULL;
5514 IDirectDrawClipper *clipper = NULL;
5515 DDSURFACEDESC ddsd;
5516 IDirectDrawSurface *primary = NULL;
5517 DDBLTFX fx;
5518 HRESULT hr;
5520 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
5521 100, 100, 160, 160, NULL, NULL, NULL, NULL);
5522 if (!window)
5524 skip("Failed to create window\n");
5525 return;
5528 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
5529 100, 100, 160, 160, NULL, NULL, NULL, NULL);
5531 hdc = GetDC(window);
5532 if (!hdc)
5534 skip("Failed to get DC\n");
5535 goto cleanup;
5538 if (window2)
5539 hdc2 = GetDC(window2);
5541 gl = LoadLibraryA("opengl32.dll");
5542 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
5544 format = GetPixelFormat(hdc);
5545 ok(format == 0, "new window has pixel format %d\n", format);
5547 ZeroMemory(&pfd, sizeof(pfd));
5548 pfd.nSize = sizeof(pfd);
5549 pfd.nVersion = 1;
5550 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
5551 pfd.iPixelType = PFD_TYPE_RGBA;
5552 pfd.iLayerType = PFD_MAIN_PLANE;
5553 format = ChoosePixelFormat(hdc, &pfd);
5554 if (format <= 0)
5556 skip("no pixel format available\n");
5557 goto cleanup;
5560 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
5562 skip("failed to set pixel format\n");
5563 goto cleanup;
5566 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
5568 skip("failed to set pixel format on second window\n");
5569 if (hdc2)
5571 ReleaseDC(window2, hdc2);
5572 hdc2 = NULL;
5576 ddraw = create_ddraw();
5577 if (!ddraw)
5579 skip("Failed to create ddraw object\n");
5580 goto cleanup;
5583 test_format = GetPixelFormat(hdc);
5584 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
5586 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5587 if (FAILED(hr))
5589 skip("Failed to set cooperative level, hr %#x.\n", hr);
5590 goto cleanup;
5593 test_format = GetPixelFormat(hdc);
5594 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
5596 if (hdc2)
5598 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
5599 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
5600 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window2);
5601 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
5603 test_format = GetPixelFormat(hdc);
5604 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
5606 test_format = GetPixelFormat(hdc2);
5607 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
5610 memset(&ddsd, 0, sizeof(ddsd));
5611 ddsd.dwSize = sizeof(ddsd);
5612 ddsd.dwFlags = DDSD_CAPS;
5613 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
5615 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
5616 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
5618 test_format = GetPixelFormat(hdc);
5619 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
5621 if (hdc2)
5623 test_format = GetPixelFormat(hdc2);
5624 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
5627 if (clipper)
5629 hr = IDirectDrawSurface2_SetClipper(primary, clipper);
5630 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
5632 test_format = GetPixelFormat(hdc);
5633 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
5635 test_format = GetPixelFormat(hdc2);
5636 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
5639 memset(&fx, 0, sizeof(fx));
5640 fx.dwSize = sizeof(fx);
5641 hr = IDirectDrawSurface2_Blt(primary, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
5642 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
5644 test_format = GetPixelFormat(hdc);
5645 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
5647 if (hdc2)
5649 test_format = GetPixelFormat(hdc2);
5650 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
5653 cleanup:
5654 if (primary) IDirectDrawSurface2_Release(primary);
5655 if (clipper) IDirectDrawClipper_Release(clipper);
5656 if (ddraw) IDirectDraw2_Release(ddraw);
5657 if (gl) FreeLibrary(gl);
5658 if (hdc) ReleaseDC(window, hdc);
5659 if (hdc2) ReleaseDC(window2, hdc2);
5660 if (window) DestroyWindow(window);
5661 if (window2) DestroyWindow(window2);
5664 START_TEST(ddraw2)
5666 test_coop_level_create_device_window();
5667 test_clipper_blt();
5668 test_coop_level_d3d_state();
5669 test_surface_interface_mismatch();
5670 test_coop_level_threaded();
5671 test_depth_blit();
5672 test_texture_load_ckey();
5673 test_viewport();
5674 test_zenable();
5675 test_ck_rgba();
5676 test_ck_default();
5677 test_ck_complex();
5678 test_surface_qi();
5679 test_device_qi();
5680 test_wndproc();
5681 test_window_style();
5682 test_redundant_mode_set();
5683 test_coop_level_mode_set();
5684 test_coop_level_mode_set_multi();
5685 test_initialize();
5686 test_coop_level_surf_create();
5687 test_coop_level_multi_window();
5688 test_clear_rect_count();
5689 test_coop_level_versions();
5690 test_lighting_interface_versions();
5691 test_coop_level_activateapp();
5692 test_unsupported_formats();
5693 test_rt_caps();
5694 test_primary_caps();
5695 test_surface_lock();
5696 test_surface_discard();
5697 test_flip();
5698 test_set_surface_desc();
5699 test_user_memory_getdc();
5700 test_sysmem_overlay();
5701 test_primary_palette();
5702 test_surface_attachment();
5703 test_pixel_format();