ddraw/tests: Nvidia has an off-by-one rectangle handling bug.
[wine/multimedia.git] / dlls / ddraw / tests / ddraw2.c
blob921abbda063a30094d1ef9b0d3e74f07a49df8ce
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 HRESULT set_display_mode(IDirectDraw2 *ddraw, DWORD width, DWORD height)
115 if (SUCCEEDED(IDirectDraw2_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
116 return DD_OK;
117 return IDirectDraw2_SetDisplayMode(ddraw, width, height, 24, 0, 0);
120 static D3DCOLOR get_surface_color(IDirectDrawSurface *surface, UINT x, UINT y)
122 RECT rect = {x, y, x + 1, y + 1};
123 DDSURFACEDESC surface_desc;
124 D3DCOLOR color;
125 HRESULT hr;
127 memset(&surface_desc, 0, sizeof(surface_desc));
128 surface_desc.dwSize = sizeof(surface_desc);
130 hr = IDirectDrawSurface_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
131 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
132 if (FAILED(hr))
133 return 0xdeadbeef;
135 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
137 hr = IDirectDrawSurface_Unlock(surface, NULL);
138 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
140 return color;
143 static DWORD get_device_z_depth(IDirect3DDevice2 *device)
145 DDSCAPS caps = {DDSCAPS_ZBUFFER};
146 IDirectDrawSurface *ds, *rt;
147 DDSURFACEDESC desc;
148 HRESULT hr;
150 if (FAILED(IDirect3DDevice2_GetRenderTarget(device, &rt)))
151 return 0;
153 hr = IDirectDrawSurface_GetAttachedSurface(rt, &caps, &ds);
154 IDirectDrawSurface_Release(rt);
155 if (FAILED(hr))
156 return 0;
158 desc.dwSize = sizeof(desc);
159 hr = IDirectDrawSurface_GetSurfaceDesc(ds, &desc);
160 IDirectDrawSurface_Release(ds);
161 if (FAILED(hr))
162 return 0;
164 return U2(desc).dwZBufferBitDepth;
167 static IDirectDraw2 *create_ddraw(void)
169 IDirectDraw2 *ddraw2;
170 IDirectDraw *ddraw1;
171 HRESULT hr;
173 if (FAILED(DirectDrawCreate(NULL, &ddraw1, NULL)))
174 return NULL;
176 hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw2, (void **)&ddraw2);
177 IDirectDraw_Release(ddraw1);
178 if (FAILED(hr))
179 return NULL;
181 return ddraw2;
184 static IDirect3DDevice2 *create_device(IDirectDraw2 *ddraw, HWND window, DWORD coop_level)
186 static const DWORD z_depths[] = {32, 24, 16};
187 IDirectDrawSurface *surface, *ds;
188 IDirect3DDevice2 *device = NULL;
189 DDSURFACEDESC surface_desc;
190 IDirect3D2 *d3d;
191 unsigned int i;
192 HRESULT hr;
194 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, coop_level);
195 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
197 memset(&surface_desc, 0, sizeof(surface_desc));
198 surface_desc.dwSize = sizeof(surface_desc);
199 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
200 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
201 surface_desc.dwWidth = 640;
202 surface_desc.dwHeight = 480;
204 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
205 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
207 if (coop_level & DDSCL_NORMAL)
209 IDirectDrawClipper *clipper;
211 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
212 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
213 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
214 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
215 hr = IDirectDrawSurface_SetClipper(surface, clipper);
216 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\n", hr);
217 IDirectDrawClipper_Release(clipper);
220 hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d);
221 if (FAILED(hr))
223 IDirectDrawSurface_Release(surface);
224 return NULL;
227 /* We used to use EnumDevices() for this, but it seems
228 * D3DDEVICEDESC.dwDeviceZBufferBitDepth only has a very casual
229 * relationship with reality. */
230 for (i = 0; i < sizeof(z_depths) / sizeof(*z_depths); ++i)
232 memset(&surface_desc, 0, sizeof(surface_desc));
233 surface_desc.dwSize = sizeof(surface_desc);
234 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
235 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
236 U2(surface_desc).dwZBufferBitDepth = z_depths[i];
237 surface_desc.dwWidth = 640;
238 surface_desc.dwHeight = 480;
239 if (FAILED(hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &ds, NULL)))
240 continue;
242 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
243 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
244 IDirectDrawSurface_Release(ds);
245 if (FAILED(hr))
246 continue;
248 if (SUCCEEDED(hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device)))
249 break;
251 IDirectDrawSurface_DeleteAttachedSurface(surface, 0, ds);
254 IDirect3D2_Release(d3d);
255 IDirectDrawSurface_Release(surface);
256 return device;
259 static IDirect3DViewport2 *create_viewport(IDirect3DDevice2 *device, UINT x, UINT y, UINT w, UINT h)
261 IDirect3DViewport2 *viewport;
262 D3DVIEWPORT2 vp;
263 IDirect3D2 *d3d;
264 HRESULT hr;
266 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
267 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
268 hr = IDirect3D2_CreateViewport(d3d, &viewport, NULL);
269 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
270 hr = IDirect3DDevice2_AddViewport(device, viewport);
271 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
272 memset(&vp, 0, sizeof(vp));
273 vp.dwSize = sizeof(vp);
274 vp.dwX = x;
275 vp.dwY = y;
276 vp.dwWidth = w;
277 vp.dwHeight = h;
278 vp.dvClipX = -1.0f;
279 vp.dvClipY = 1.0f;
280 vp.dvClipWidth = 2.0f;
281 vp.dvClipHeight = 2.0f;
282 vp.dvMinZ = 0.0f;
283 vp.dvMaxZ = 1.0f;
284 hr = IDirect3DViewport2_SetViewport2(viewport, &vp);
285 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
286 IDirect3D2_Release(d3d);
288 return viewport;
291 static void viewport_set_background(IDirect3DDevice2 *device, IDirect3DViewport2 *viewport,
292 IDirect3DMaterial2 *material)
294 D3DMATERIALHANDLE material_handle;
295 HRESULT hr;
297 hr = IDirect3DMaterial2_GetHandle(material, device, &material_handle);
298 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
299 hr = IDirect3DViewport2_SetBackground(viewport, material_handle);
300 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
303 static void destroy_viewport(IDirect3DDevice2 *device, IDirect3DViewport2 *viewport)
305 HRESULT hr;
307 hr = IDirect3DDevice2_DeleteViewport(device, viewport);
308 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
309 IDirect3DViewport2_Release(viewport);
312 static IDirect3DMaterial2 *create_diffuse_material(IDirect3DDevice2 *device, float r, float g, float b, float a)
314 IDirect3DMaterial2 *material;
315 D3DMATERIAL mat;
316 IDirect3D2 *d3d;
317 HRESULT hr;
319 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
320 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
321 hr = IDirect3D2_CreateMaterial(d3d, &material, NULL);
322 ok(SUCCEEDED(hr), "Failed to create material, hr %#x.\n", hr);
323 memset(&mat, 0, sizeof(mat));
324 mat.dwSize = sizeof(mat);
325 U1(U(mat).diffuse).r = r;
326 U2(U(mat).diffuse).g = g;
327 U3(U(mat).diffuse).b = b;
328 U4(U(mat).diffuse).a = a;
329 hr = IDirect3DMaterial2_SetMaterial(material, &mat);
330 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
331 IDirect3D2_Release(d3d);
333 return material;
336 static void destroy_material(IDirect3DMaterial2 *material)
338 IDirect3DMaterial2_Release(material);
341 static const UINT *expect_messages;
343 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
345 if (expect_messages && message == *expect_messages)
346 ++expect_messages;
348 return DefWindowProcA(hwnd, message, wparam, lparam);
351 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
352 * interface. This prevents subsequent SetCooperativeLevel() calls on a
353 * different window from failing with DDERR_HWNDALREADYSET. */
354 static void fix_wndproc(HWND window, LONG_PTR proc)
356 IDirectDraw2 *ddraw;
357 HRESULT hr;
359 if (!(ddraw = create_ddraw()))
360 return;
362 SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
363 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
364 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
365 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
366 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
368 IDirectDraw2_Release(ddraw);
371 static HRESULT CALLBACK restore_callback(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
373 HRESULT hr = IDirectDrawSurface_Restore(surface);
374 ok(SUCCEEDED(hr), "Failed to restore surface, hr %#x.\n", hr);
375 IDirectDrawSurface_Release(surface);
377 return DDENUMRET_OK;
380 static HRESULT restore_surfaces(IDirectDraw2 *ddraw)
382 return IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
383 NULL, NULL, restore_callback);
386 static void test_coop_level_create_device_window(void)
388 HWND focus_window, device_window;
389 IDirectDraw2 *ddraw;
390 HRESULT hr;
392 focus_window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
393 0, 0, 640, 480, 0, 0, 0, 0);
394 ddraw = create_ddraw();
395 ok(!!ddraw, "Failed to create a ddraw object.\n");
397 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
398 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
399 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
400 ok(!device_window, "Unexpected device window found.\n");
401 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
402 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
403 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
404 ok(!device_window, "Unexpected device window found.\n");
405 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
406 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
407 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
408 ok(!device_window, "Unexpected device window found.\n");
409 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
410 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
411 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
412 ok(!device_window, "Unexpected device window found.\n");
413 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
414 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
415 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
416 ok(!device_window, "Unexpected device window found.\n");
418 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
419 if (broken(hr == DDERR_INVALIDPARAMS))
421 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
422 IDirectDraw2_Release(ddraw);
423 DestroyWindow(focus_window);
424 return;
427 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
428 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
429 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
430 ok(!device_window, "Unexpected device window found.\n");
431 hr = IDirectDraw2_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
432 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
433 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
434 ok(!device_window, "Unexpected device window found.\n");
436 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
437 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
438 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
439 ok(!device_window, "Unexpected device window found.\n");
440 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
441 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
442 ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
443 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
444 ok(!!device_window, "Device window not found.\n");
446 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
447 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
448 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
449 ok(!device_window, "Unexpected device window found.\n");
450 hr = IDirectDraw2_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
451 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
452 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
453 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
454 ok(!!device_window, "Device window not found.\n");
456 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
457 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
458 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
459 ok(!device_window, "Unexpected device window found.\n");
460 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
461 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
462 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
463 ok(!device_window, "Unexpected device window found.\n");
464 hr = IDirectDraw2_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
465 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
466 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
467 ok(!device_window, "Unexpected device window found.\n");
468 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
469 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
470 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
471 ok(!!device_window, "Device window not found.\n");
473 IDirectDraw2_Release(ddraw);
474 DestroyWindow(focus_window);
477 static void test_clipper_blt(void)
479 IDirectDrawSurface *src_surface, *dst_surface;
480 RECT client_rect, src_rect;
481 IDirectDrawClipper *clipper;
482 DDSURFACEDESC surface_desc;
483 unsigned int i, j, x, y;
484 IDirectDraw2 *ddraw;
485 RGNDATA *rgn_data;
486 D3DCOLOR color;
487 HRGN r1, r2;
488 HWND window;
489 DDBLTFX fx;
490 HRESULT hr;
491 DWORD *ptr;
492 DWORD ret;
494 static const DWORD src_data[] =
496 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
497 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
498 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
500 static const D3DCOLOR expected1[] =
502 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
503 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
504 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
505 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
507 /* Nvidia on Windows seems to have an off-by-one error
508 * when processing source rectangles. Our left = 1 and
509 * right = 5 input reads from x = {1, 2, 3}. x = 4 is
510 * read as well, but only for the edge pixels on the
511 * output image. The bug happens on the y axis as well,
512 * but we only read one row there, and all source rows
513 * contain the same data. This bug is not dependent on
514 * the presence of a clipper. */
515 static const D3DCOLOR expected1_broken[] =
517 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
518 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
519 0x00000000, 0x00000000, 0x00ff0000, 0x00ff0000,
520 0x00000000, 0x00000000, 0x0000ff00, 0x00ff0000,
522 static const D3DCOLOR expected2[] =
524 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
525 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
526 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
527 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
530 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
531 10, 10, 640, 480, 0, 0, 0, 0);
532 ShowWindow(window, SW_SHOW);
533 ddraw = create_ddraw();
534 ok(!!ddraw, "Failed to create a ddraw object.\n");
536 ret = GetClientRect(window, &client_rect);
537 ok(ret, "Failed to get client rect.\n");
538 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
539 ok(ret, "Failed to map client rect.\n");
541 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
542 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
544 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
545 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
546 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
547 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
548 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
549 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
550 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
551 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
552 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
553 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
554 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
555 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
556 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
557 ok(rgn_data->rdh.nCount >= 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
558 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
559 "Got unexpected bounding rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
560 rgn_data->rdh.rcBound.left, rgn_data->rdh.rcBound.top,
561 rgn_data->rdh.rcBound.right, rgn_data->rdh.rcBound.bottom,
562 client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
563 HeapFree(GetProcessHeap(), 0, rgn_data);
565 r1 = CreateRectRgn(0, 0, 320, 240);
566 ok(!!r1, "Failed to create region.\n");
567 r2 = CreateRectRgn(320, 240, 640, 480);
568 ok(!!r2, "Failed to create region.\n");
569 CombineRgn(r1, r1, r2, RGN_OR);
570 ret = GetRegionData(r1, 0, NULL);
571 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
572 ret = GetRegionData(r1, ret, rgn_data);
573 ok(!!ret, "Failed to get region data.\n");
575 DeleteObject(r2);
576 DeleteObject(r1);
578 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
579 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
580 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
581 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
582 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
583 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
585 HeapFree(GetProcessHeap(), 0, rgn_data);
587 memset(&surface_desc, 0, sizeof(surface_desc));
588 surface_desc.dwSize = sizeof(surface_desc);
589 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
590 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
591 surface_desc.dwWidth = 640;
592 surface_desc.dwHeight = 480;
593 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
594 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
595 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
596 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
597 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
598 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
600 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
601 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
602 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
603 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
605 memset(&fx, 0, sizeof(fx));
606 fx.dwSize = sizeof(fx);
607 hr = IDirectDrawSurface_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
608 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
609 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
610 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
612 hr = IDirectDrawSurface_Lock(src_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
613 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
614 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
615 ptr = surface_desc.lpSurface;
616 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
617 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
618 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
619 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
620 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
622 hr = IDirectDrawSurface_SetClipper(dst_surface, clipper);
623 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
625 SetRect(&src_rect, 1, 1, 5, 2);
626 hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
627 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
628 for (i = 0; i < 4; ++i)
630 for (j = 0; j < 4; ++j)
632 x = 80 * ((2 * j) + 1);
633 y = 60 * ((2 * i) + 1);
634 color = get_surface_color(dst_surface, x, y);
635 ok(compare_color(color, expected1[i * 4 + j], 1)
636 || broken(compare_color(color, expected1_broken[i * 4 + j], 1)),
637 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
641 U5(fx).dwFillColor = 0xff0000ff;
642 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
643 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
644 for (i = 0; i < 4; ++i)
646 for (j = 0; j < 4; ++j)
648 x = 80 * ((2 * j) + 1);
649 y = 60 * ((2 * i) + 1);
650 color = get_surface_color(dst_surface, x, y);
651 ok(compare_color(color, expected2[i * 4 + j], 1),
652 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
656 hr = IDirectDrawSurface_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
657 ok(hr == DDERR_BLTFASTCANTCLIP || broken(hr == E_NOTIMPL /* NT4 */), "Got unexpected hr %#x.\n", hr);
659 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
660 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
661 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
662 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
663 DestroyWindow(window);
664 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
665 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
666 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
667 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
668 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
669 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
670 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
671 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
672 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
673 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
674 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
675 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
677 IDirectDrawSurface_Release(dst_surface);
678 IDirectDrawSurface_Release(src_surface);
679 IDirectDrawClipper_Release(clipper);
680 IDirectDraw2_Release(ddraw);
683 static void test_coop_level_d3d_state(void)
685 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
686 IDirectDrawSurface *rt, *surface;
687 IDirect3DMaterial2 *background;
688 IDirect3DViewport2 *viewport;
689 IDirect3DDevice2 *device;
690 D3DMATERIAL material;
691 IDirectDraw2 *ddraw;
692 D3DCOLOR color;
693 DWORD value;
694 HWND window;
695 HRESULT hr;
697 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
698 0, 0, 640, 480, 0, 0, 0, 0);
699 ddraw = create_ddraw();
700 ok(!!ddraw, "Failed to create a ddraw object.\n");
701 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
703 skip("Failed to create a 3D device, skipping test.\n");
704 IDirectDraw2_Release(ddraw);
705 DestroyWindow(window);
706 return;
709 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
710 viewport = create_viewport(device, 0, 0, 640, 480);
711 viewport_set_background(device, viewport, background);
713 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
714 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
715 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
716 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
717 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
718 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
719 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
720 ok(!value, "Got unexpected alpha blend enable state %#x.\n", value);
721 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
722 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
723 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
724 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
725 color = get_surface_color(rt, 320, 240);
726 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
728 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
729 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
730 hr = IDirectDrawSurface_IsLost(rt);
731 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
732 hr = restore_surfaces(ddraw);
733 ok(SUCCEEDED(hr), "Failed to restore surfaces, hr %#x.\n", hr);
735 memset(&material, 0, sizeof(material));
736 material.dwSize = sizeof(material);
737 U1(U(material).diffuse).r = 0.0f;
738 U2(U(material).diffuse).g = 1.0f;
739 U3(U(material).diffuse).b = 0.0f;
740 U4(U(material).diffuse).a = 1.0f;
741 hr = IDirect3DMaterial2_SetMaterial(background, &material);
742 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
744 hr = IDirect3DDevice2_GetRenderTarget(device, &surface);
745 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
746 ok(surface == rt, "Got unexpected surface %p.\n", surface);
747 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
748 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
749 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
750 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
751 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
752 ok(!!value, "Got unexpected alpha blend enable state %#x.\n", value);
753 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
754 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
755 color = get_surface_color(rt, 320, 240);
756 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
758 destroy_viewport(device, viewport);
759 destroy_material(background);
760 IDirectDrawSurface_Release(surface);
761 IDirectDrawSurface_Release(rt);
762 IDirect3DDevice2_Release(device);
763 IDirectDraw2_Release(ddraw);
764 DestroyWindow(window);
767 static void test_surface_interface_mismatch(void)
769 IDirectDraw2 *ddraw = NULL;
770 IDirect3D2 *d3d = NULL;
771 IDirectDrawSurface *surface = NULL, *ds;
772 IDirectDrawSurface3 *surface3 = NULL;
773 IDirect3DDevice2 *device = NULL;
774 IDirect3DViewport2 *viewport = NULL;
775 IDirect3DMaterial2 *background = NULL;
776 DDSURFACEDESC surface_desc;
777 DWORD z_depth = 0;
778 ULONG refcount;
779 HRESULT hr;
780 D3DCOLOR color;
781 HWND window;
782 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
784 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
785 0, 0, 640, 480, 0, 0, 0, 0);
786 ddraw = create_ddraw();
787 ok(!!ddraw, "Failed to create a ddraw object.\n");
788 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
790 skip("Failed to create a 3D device, skipping test.\n");
791 IDirectDraw2_Release(ddraw);
792 DestroyWindow(window);
793 return;
795 z_depth = get_device_z_depth(device);
796 ok(!!z_depth, "Failed to get device z depth.\n");
797 IDirect3DDevice2_Release(device);
798 device = NULL;
800 memset(&surface_desc, 0, sizeof(surface_desc));
801 surface_desc.dwSize = sizeof(surface_desc);
802 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
803 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
804 surface_desc.dwWidth = 640;
805 surface_desc.dwHeight = 480;
807 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
808 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
810 hr = IDirectDrawSurface2_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
811 if (FAILED(hr))
813 skip("Failed to get the IDirectDrawSurface3 interface, skipping test.\n");
814 goto cleanup;
817 if (FAILED(hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d)))
819 skip("D3D interface is not available, skipping test.\n");
820 goto cleanup;
823 memset(&surface_desc, 0, sizeof(surface_desc));
824 surface_desc.dwSize = sizeof(surface_desc);
825 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
826 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
827 U2(surface_desc).dwZBufferBitDepth = z_depth;
828 surface_desc.dwWidth = 640;
829 surface_desc.dwHeight = 480;
830 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &ds, NULL);
831 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
832 if (FAILED(hr))
833 goto cleanup;
835 /* Using a different surface interface version still works */
836 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
837 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
838 refcount = IDirectDrawSurface_Release(ds);
839 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
840 if (FAILED(hr))
841 goto cleanup;
843 /* Here too */
844 hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, (IDirectDrawSurface *)surface3, &device);
845 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
846 if (FAILED(hr))
847 goto cleanup;
849 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
850 viewport = create_viewport(device, 0, 0, 640, 480);
851 viewport_set_background(device, viewport, background);
853 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
854 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
855 color = get_surface_color(surface, 320, 240);
856 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
858 cleanup:
859 if (viewport)
860 destroy_viewport(device, viewport);
861 if (background)
862 destroy_material(background);
863 if (surface3) IDirectDrawSurface3_Release(surface3);
864 if (surface) IDirectDrawSurface_Release(surface);
865 if (device) IDirect3DDevice2_Release(device);
866 if (d3d) IDirect3D2_Release(d3d);
867 if (ddraw) IDirectDraw2_Release(ddraw);
868 DestroyWindow(window);
871 static void test_coop_level_threaded(void)
873 struct create_window_thread_param p;
874 IDirectDraw2 *ddraw;
875 HRESULT hr;
877 ddraw = create_ddraw();
878 ok(!!ddraw, "Failed to create a ddraw object.\n");
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 ddraw = create_ddraw();
922 ok(!!ddraw, "Failed to create a ddraw object.\n");
923 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
925 skip("Failed to create a 3D device, skipping test.\n");
926 IDirectDraw2_Release(ddraw);
927 DestroyWindow(window);
928 return;
931 ds1 = get_depth_stencil(device);
933 memset(&ddsd_new, 0, sizeof(ddsd_new));
934 ddsd_new.dwSize = sizeof(ddsd_new);
935 memset(&ddsd_existing, 0, sizeof(ddsd_existing));
936 ddsd_existing.dwSize = sizeof(ddsd_existing);
937 hr = IDirectDrawSurface_GetSurfaceDesc(ds1, &ddsd_existing);
938 ddsd_new.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
939 ddsd_new.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
940 ddsd_new.dwWidth = ddsd_existing.dwWidth;
941 ddsd_new.dwHeight = ddsd_existing.dwHeight;
942 ddsd_new.ddpfPixelFormat = ddsd_existing.ddpfPixelFormat;
943 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd_new, &ds2, NULL);
944 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
945 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd_new, &ds3, NULL);
946 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
948 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
949 viewport = create_viewport(device, 0, 0, ddsd_existing.dwWidth, ddsd_existing.dwHeight);
950 viewport_set_background(device, viewport, background);
951 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
952 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
954 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
955 ok(SUCCEEDED(hr), "Failed to enable z testing, hr %#x.\n", hr);
956 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
957 ok(SUCCEEDED(hr), "Failed to set the z function, hr %#x.\n", hr);
959 U1(d3drect).x1 = U2(d3drect).y1 = 0;
960 U3(d3drect).x2 = ddsd_existing.dwWidth; U4(d3drect).y2 = ddsd_existing.dwHeight;
961 hr = IDirect3DViewport2_Clear(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER);
962 ok(SUCCEEDED(hr), "Failed to clear the z buffer, hr %#x.\n", hr);
964 /* Partial blit. */
965 SetRect(&src_rect, 0, 0, 320, 240);
966 SetRect(&dst_rect, 0, 0, 320, 240);
967 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
968 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
969 /* Different locations. */
970 SetRect(&src_rect, 0, 0, 320, 240);
971 SetRect(&dst_rect, 320, 240, 640, 480);
972 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
973 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
974 /* Streched. */
975 SetRect(&src_rect, 0, 0, 320, 240);
976 SetRect(&dst_rect, 0, 0, 640, 480);
977 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
978 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
979 /* Flipped. */
980 SetRect(&src_rect, 0, 480, 640, 0);
981 SetRect(&dst_rect, 0, 0, 640, 480);
982 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
983 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
984 SetRect(&src_rect, 0, 0, 640, 480);
985 SetRect(&dst_rect, 0, 480, 640, 0);
986 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
987 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
988 /* Full, explicit. */
989 SetRect(&src_rect, 0, 0, 640, 480);
990 SetRect(&dst_rect, 0, 0, 640, 480);
991 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
992 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
993 /* Depth -> color blit: Succeeds on Win7 + Radeon HD 5700, fails on WinXP + Radeon X1600 */
995 /* Depth blit inside a BeginScene / EndScene pair */
996 hr = IDirect3DDevice2_BeginScene(device);
997 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
998 /* From the current depth stencil */
999 hr = IDirectDrawSurface_Blt(ds2, NULL, ds1, NULL, DDBLT_WAIT, NULL);
1000 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1001 /* To the current depth stencil */
1002 hr = IDirectDrawSurface_Blt(ds1, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1003 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1004 /* Between unbound surfaces */
1005 hr = IDirectDrawSurface_Blt(ds3, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1006 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1007 hr = IDirect3DDevice2_EndScene(device);
1008 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1010 /* Avoid changing the depth stencil, it doesn't work properly on Windows.
1011 * Instead use DDBLT_DEPTHFILL to clear the depth stencil. Unfortunately
1012 * drivers disagree on the meaning of dwFillDepth. Only 0 seems to produce
1013 * a reliable result(z = 0.0) */
1014 memset(&fx, 0, sizeof(fx));
1015 fx.dwSize = sizeof(fx);
1016 U5(fx).dwFillDepth = 0;
1017 hr = IDirectDrawSurface_Blt(ds2, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
1018 ok(SUCCEEDED(hr), "Failed to clear the source z buffer, hr %#x.\n", hr);
1020 /* This clears the Z buffer with 1.0 */
1021 hr = IDirect3DViewport2_Clear(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET);
1022 ok(SUCCEEDED(hr), "Failed to clear the color and z buffers, hr %#x.\n", hr);
1024 SetRect(&dst_rect, 0, 0, 320, 240);
1025 hr = IDirectDrawSurface_Blt(ds1, &dst_rect, ds2, NULL, DDBLT_WAIT, NULL);
1026 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1027 IDirectDrawSurface_Release(ds3);
1028 IDirectDrawSurface_Release(ds2);
1029 IDirectDrawSurface_Release(ds1);
1031 hr = IDirect3DDevice2_BeginScene(device);
1032 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
1033 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad1, 4, 0);
1034 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1035 hr = IDirect3DDevice2_EndScene(device);
1036 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1038 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1039 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1040 for (i = 0; i < 4; ++i)
1042 for (j = 0; j < 4; ++j)
1044 unsigned int x = 80 * ((2 * j) + 1);
1045 unsigned int y = 60 * ((2 * i) + 1);
1046 color = get_surface_color(rt, x, y);
1047 ok(compare_color(color, expected_colors[i][j], 1),
1048 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
1051 IDirectDrawSurface_Release(rt);
1053 destroy_viewport(device, viewport);
1054 destroy_material(background);
1055 IDirect3DDevice2_Release(device);
1056 IDirectDraw2_Release(ddraw);
1057 DestroyWindow(window);
1060 static void test_texture_load_ckey(void)
1062 IDirectDraw2 *ddraw = NULL;
1063 IDirectDrawSurface *src = NULL;
1064 IDirectDrawSurface *dst = NULL;
1065 IDirect3DTexture *src_tex = NULL;
1066 IDirect3DTexture *dst_tex = NULL;
1067 DDSURFACEDESC ddsd;
1068 HRESULT hr;
1069 DDCOLORKEY ckey;
1071 ddraw = create_ddraw();
1072 ok(!!ddraw, "Failed to create a ddraw object.\n");
1073 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
1074 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1076 memset(&ddsd, 0, sizeof(ddsd));
1077 ddsd.dwSize = sizeof(ddsd);
1078 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
1079 ddsd.dwHeight = 128;
1080 ddsd.dwWidth = 128;
1081 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
1082 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &src, NULL);
1083 ok(SUCCEEDED(hr), "Failed to create source texture, hr %#x.\n", hr);
1084 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1085 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &dst, NULL);
1086 ok(SUCCEEDED(hr), "Failed to create destination texture, hr %#x.\n", hr);
1088 hr = IDirectDrawSurface_QueryInterface(src, &IID_IDirect3DTexture, (void **)&src_tex);
1089 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get Direct3DTexture interface, hr %#x.\n", hr);
1090 if (FAILED(hr))
1092 /* 64 bit ddraw does not support d3d */
1093 skip("Could not get Direct3DTexture interface, skipping texture::Load color keying tests.\n");
1094 goto done;
1096 hr = IDirectDrawSurface_QueryInterface(dst, &IID_IDirect3DTexture, (void **)&dst_tex);
1097 ok(SUCCEEDED(hr), "Failed to get Direct3DTexture interface, hr %#x.\n", hr);
1099 /* No surface has a color key */
1100 hr = IDirect3DTexture_Load(dst_tex, src_tex);
1101 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDCAPS), "Got unexpected hr %#x.\n", hr);
1102 if (FAILED(hr))
1104 /* Testbot Windows NT VMs */
1105 skip("IDirect3DTexture::Load does not work, skipping color keying tests.\n");
1106 goto done;
1109 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0xdeadbeef;
1110 hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1111 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1112 ok(ckey.dwColorSpaceLowValue == 0xdeadbeef, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1113 ok(ckey.dwColorSpaceHighValue == 0xdeadbeef, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1115 /* Source surface has a color key */
1116 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
1117 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
1118 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1119 hr = IDirect3DTexture_Load(dst_tex, src_tex);
1120 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1121 hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1122 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1123 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1124 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1126 /* Both surfaces have a color key: Dest ckey is overwritten */
1127 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x000000ff;
1128 hr = IDirectDrawSurface_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1129 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1130 hr = IDirect3DTexture_Load(dst_tex, src_tex);
1131 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1132 hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1133 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1134 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1135 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1137 /* Only the destination has a color key: It is not deleted */
1138 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, NULL);
1139 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1140 hr = IDirectDrawSurface_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
1141 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1142 hr = IDirect3DTexture_Load(dst_tex, src_tex);
1143 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1144 hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1145 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1146 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1147 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1149 done:
1150 if (dst_tex) IDirect3DTexture_Release(dst_tex);
1151 if (src_tex) IDirect3DTexture_Release(src_tex);
1152 if (dst) IDirectDrawSurface_Release(dst);
1153 if (src) IDirectDrawSurface_Release(src);
1154 if (ddraw) IDirectDraw2_Release(ddraw);
1157 static ULONG get_refcount(IUnknown *test_iface)
1159 IUnknown_AddRef(test_iface);
1160 return IUnknown_Release(test_iface);
1163 static void test_viewport(void)
1165 IDirectDraw2 *ddraw;
1166 IDirect3D2 *d3d;
1167 HRESULT hr;
1168 ULONG ref, old_d3d_ref;
1169 IDirect3DViewport *viewport;
1170 IDirect3DViewport2 *viewport2, *another_vp, *test_vp;
1171 IDirect3DViewport3 *viewport3;
1172 IDirectDrawGammaControl *gamma;
1173 IUnknown *unknown;
1174 IDirect3DDevice2 *device;
1175 HWND window;
1177 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1178 0, 0, 640, 480, 0, 0, 0, 0);
1179 ddraw = create_ddraw();
1180 ok(!!ddraw, "Failed to create a ddraw object.\n");
1181 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1183 skip("Failed to create a 3D device, skipping test.\n");
1184 IDirectDraw_Release(ddraw);
1185 DestroyWindow(window);
1186 return;
1189 hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d);
1190 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get d3d interface, hr %#x.\n", hr);
1191 if (FAILED(hr))
1193 skip("D3D interface is not available, skipping test.\n");
1194 IDirectDraw2_Release(ddraw);
1195 return;
1197 old_d3d_ref = get_refcount((IUnknown *)d3d);
1199 hr = IDirect3D2_CreateViewport(d3d, &viewport2, NULL);
1200 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1201 ref = get_refcount((IUnknown *)viewport2);
1202 ok(ref == 1, "Initial IDirect3DViewport2 refcount is %u\n", ref);
1203 ref = get_refcount((IUnknown *)d3d);
1204 ok(ref == old_d3d_ref, "IDirect3D2 refcount is %u\n", ref);
1206 gamma = (IDirectDrawGammaControl *)0xdeadbeef;
1207 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IDirectDrawGammaControl, (void **)&gamma);
1208 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
1209 ok(gamma == NULL, "Interface not set to NULL by failed QI call: %p\n", gamma);
1210 if (SUCCEEDED(hr)) IDirectDrawGammaControl_Release(gamma);
1211 /* NULL iid: Segfaults */
1213 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IDirect3DViewport, (void **)&viewport);
1214 ok(SUCCEEDED(hr), "Failed to QI IDirect3DViewport, hr %#x.\n", hr);
1215 if (viewport)
1217 ref = get_refcount((IUnknown *)viewport);
1218 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
1219 ref = get_refcount((IUnknown *)viewport2);
1220 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
1221 IDirect3DViewport_Release(viewport);
1222 viewport = NULL;
1225 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IDirect3DViewport3, (void **)&viewport3);
1226 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to QI IDirect3DViewport3, hr %#x.\n", hr);
1227 if (viewport3)
1229 ref = get_refcount((IUnknown *)viewport2);
1230 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
1231 ref = get_refcount((IUnknown *)viewport3);
1232 ok(ref == 2, "IDirect3DViewport3 refcount is %u\n", ref);
1233 IDirect3DViewport3_Release(viewport3);
1236 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IUnknown, (void **)&unknown);
1237 ok(SUCCEEDED(hr), "Failed to QI IUnknown, hr %#x.\n", hr);
1238 if (unknown)
1240 ref = get_refcount((IUnknown *)viewport2);
1241 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
1242 ref = get_refcount(unknown);
1243 ok(ref == 2, "IUnknown refcount is %u\n", ref);
1244 IUnknown_Release(unknown);
1247 /* AddViewport(NULL): Segfault */
1248 hr = IDirect3DDevice2_DeleteViewport(device, NULL);
1249 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1250 hr = IDirect3DDevice2_GetCurrentViewport(device, NULL);
1251 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1253 hr = IDirect3D2_CreateViewport(d3d, &another_vp, NULL);
1254 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1256 /* Setting a viewport not in the viewport list fails */
1257 hr = IDirect3DDevice2_SetCurrentViewport(device, another_vp);
1258 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1260 hr = IDirect3DDevice2_AddViewport(device, viewport2);
1261 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1262 ref = get_refcount((IUnknown *) viewport2);
1263 ok(ref == 2, "viewport2 refcount is %d\n", ref);
1264 hr = IDirect3DDevice2_AddViewport(device, another_vp);
1265 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1266 ref = get_refcount((IUnknown *) another_vp);
1267 ok(ref == 2, "another_vp refcount is %d\n", ref);
1269 test_vp = (IDirect3DViewport2 *) 0xbaadc0de;
1270 hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
1271 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1272 ok(test_vp == (IDirect3DViewport2 *) 0xbaadc0de, "Got unexpected pointer %p\n", test_vp);
1274 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport2);
1275 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1276 ref = get_refcount((IUnknown *) viewport2);
1277 ok(ref == 3, "viewport2 refcount is %d\n", ref);
1278 ref = get_refcount((IUnknown *) device);
1279 ok(ref == 1, "device refcount is %d\n", ref);
1281 test_vp = NULL;
1282 hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
1283 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1284 ok(test_vp == viewport2, "Got unexpected viewport %p\n", test_vp);
1285 ref = get_refcount((IUnknown *) viewport2);
1286 ok(ref == 4, "viewport2 refcount is %d\n", ref);
1287 if(test_vp) IDirect3DViewport2_Release(test_vp);
1289 /* GetCurrentViewport with a viewport set and NULL input param: Segfault */
1291 /* Cannot set the viewport to NULL */
1292 hr = IDirect3DDevice2_SetCurrentViewport(device, NULL);
1293 ok(hr == DDERR_INVALIDPARAMS, "Failed to set viewport to NULL, hr %#x.\n", hr);
1294 test_vp = NULL;
1295 hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
1296 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1297 ok(test_vp == viewport2, "Got unexpected viewport %p\n", test_vp);
1298 if(test_vp) IDirect3DViewport2_Release(test_vp);
1300 /* SetCurrentViewport properly releases the old viewport's reference */
1301 hr = IDirect3DDevice2_SetCurrentViewport(device, another_vp);
1302 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1303 ref = get_refcount((IUnknown *) viewport2);
1304 ok(ref == 2, "viewport2 refcount is %d\n", ref);
1305 ref = get_refcount((IUnknown *) another_vp);
1306 ok(ref == 3, "another_vp refcount is %d\n", ref);
1308 /* Deleting the viewport removes the reference added by AddViewport, but not
1309 * the one added by SetCurrentViewport. */
1310 hr = IDirect3DDevice2_DeleteViewport(device, another_vp);
1311 ok(SUCCEEDED(hr), "Failed to delete viewport from device, hr %#x.\n", hr);
1312 ref = get_refcount((IUnknown *) another_vp);
1313 todo_wine ok(ref == 2, "IDirect3DViewport2 refcount is %d\n", ref);
1315 /* GetCurrentViewport fails though */
1316 test_vp = NULL;
1317 hr = IDirect3DDevice2_GetCurrentViewport(device, &test_vp);
1318 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1319 ok(test_vp == NULL, "Got unexpected viewport %p\n", test_vp);
1320 if(test_vp) IDirect3DViewport2_Release(test_vp);
1322 /* Setting a different viewport does not free the leaked reference. How
1323 * do I get rid of it? Leak the viewport for now. */
1324 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport2);
1325 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1326 ref = get_refcount((IUnknown *) viewport2);
1327 ok(ref == 3, "viewport2 refcount is %d\n", ref);
1328 ref = get_refcount((IUnknown *) another_vp);
1329 todo_wine ok(ref == 2, "another_vp refcount is %d\n", ref);
1331 /* Destroying the device removes the viewport, but does not free the reference
1332 * added by SetCurrentViewport. */
1333 IDirect3DDevice2_Release(device);
1334 ref = get_refcount((IUnknown *) viewport2);
1335 todo_wine ok(ref == 2, "viewport2 refcount is %d\n", ref);
1337 IDirect3DViewport2_Release(another_vp);
1338 IDirect3DViewport2_Release(viewport2);
1339 IDirect3D2_Release(d3d);
1340 DestroyWindow(window);
1341 IDirectDraw2_Release(ddraw);
1344 static void test_zenable(void)
1346 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1347 static D3DTLVERTEX tquad[] =
1349 {{ 0.0f}, {480.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1350 {{ 0.0f}, { 0.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1351 {{640.0f}, {480.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1352 {{640.0f}, { 0.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1354 IDirect3DMaterial2 *background;
1355 IDirect3DViewport2 *viewport;
1356 IDirect3DDevice2 *device;
1357 IDirectDrawSurface *rt;
1358 IDirectDraw2 *ddraw;
1359 D3DCOLOR color;
1360 HWND window;
1361 HRESULT hr;
1362 UINT x, y;
1363 UINT i, j;
1365 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1366 0, 0, 640, 480, 0, 0, 0, 0);
1367 ddraw = create_ddraw();
1368 ok(!!ddraw, "Failed to create a ddraw object.\n");
1369 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1371 skip("Failed to create a 3D device, skipping test.\n");
1372 IDirectDraw2_Release(ddraw);
1373 DestroyWindow(window);
1374 return;
1377 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1378 viewport = create_viewport(device, 0, 0, 640, 480);
1379 viewport_set_background(device, viewport, background);
1380 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1381 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1383 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1384 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
1386 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1387 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1388 hr = IDirect3DDevice2_BeginScene(device);
1389 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1390 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, tquad, 4, 0);
1391 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1392 hr = IDirect3DDevice2_EndScene(device);
1393 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1395 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1396 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1397 for (i = 0; i < 4; ++i)
1399 for (j = 0; j < 4; ++j)
1401 x = 80 * ((2 * j) + 1);
1402 y = 60 * ((2 * i) + 1);
1403 color = get_surface_color(rt, x, y);
1404 ok(compare_color(color, 0x0000ff00, 1),
1405 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1408 IDirectDrawSurface_Release(rt);
1410 destroy_viewport(device, viewport);
1411 destroy_material(background);
1412 IDirect3DDevice2_Release(device);
1413 IDirectDraw2_Release(ddraw);
1414 DestroyWindow(window);
1417 static void test_ck_rgba(void)
1419 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1420 static D3DTLVERTEX tquad[] =
1422 {{ 0.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1423 {{ 0.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1424 {{640.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1425 {{640.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1426 {{ 0.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1427 {{ 0.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1428 {{640.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1429 {{640.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1431 static const struct
1433 D3DCOLOR fill_color;
1434 BOOL color_key;
1435 BOOL blend;
1436 D3DCOLOR result1;
1437 D3DCOLOR result2;
1439 tests[] =
1441 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x000000ff},
1442 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x000000ff},
1443 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00},
1444 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00},
1445 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00807f00},
1446 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x0000ff00},
1447 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00},
1448 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00},
1451 D3DTEXTUREHANDLE texture_handle;
1452 IDirect3DMaterial2 *background;
1453 IDirectDrawSurface *surface;
1454 IDirect3DViewport2 *viewport;
1455 IDirect3DTexture2 *texture;
1456 DDSURFACEDESC surface_desc;
1457 IDirect3DDevice2 *device;
1458 IDirectDrawSurface *rt;
1459 IDirectDraw2 *ddraw;
1460 D3DCOLOR color;
1461 HWND window;
1462 DDBLTFX fx;
1463 HRESULT hr;
1464 UINT i;
1466 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1467 0, 0, 640, 480, 0, 0, 0, 0);
1468 ddraw = create_ddraw();
1469 ok(!!ddraw, "Failed to create a ddraw object.\n");
1470 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1472 skip("Failed to create a 3D device, skipping test.\n");
1473 IDirectDraw2_Release(ddraw);
1474 DestroyWindow(window);
1475 return;
1478 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1479 viewport = create_viewport(device, 0, 0, 640, 480);
1480 viewport_set_background(device, viewport, background);
1481 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1482 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1484 memset(&surface_desc, 0, sizeof(surface_desc));
1485 surface_desc.dwSize = sizeof(surface_desc);
1486 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1487 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1488 surface_desc.dwWidth = 256;
1489 surface_desc.dwHeight = 256;
1490 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1491 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1492 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1493 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1494 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1495 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1496 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1497 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1498 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1499 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1500 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1501 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
1502 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1503 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
1504 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1505 IDirect3DTexture2_Release(texture);
1507 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1508 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1509 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1510 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1511 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1512 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1514 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1515 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1517 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
1519 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1520 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1521 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1522 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1524 memset(&fx, 0, sizeof(fx));
1525 fx.dwSize = sizeof(fx);
1526 U5(fx).dwFillColor = tests[i].fill_color;
1527 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1528 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1530 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
1531 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1532 hr = IDirect3DDevice2_BeginScene(device);
1533 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1534 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[0], 4, 0);
1535 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1536 hr = IDirect3DDevice2_EndScene(device);
1537 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1539 color = get_surface_color(rt, 320, 240);
1540 if (i == 2)
1541 todo_wine ok(compare_color(color, tests[i].result1, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1542 tests[i].result1, i, color);
1543 else
1544 ok(compare_color(color, tests[i].result1, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1545 tests[i].result1, i, color);
1547 U5(fx).dwFillColor = 0xff0000ff;
1548 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1549 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1551 hr = IDirect3DDevice2_BeginScene(device);
1552 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1553 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[4], 4, 0);
1554 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1555 hr = IDirect3DDevice2_EndScene(device);
1556 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1558 /* This tests that fragments that are masked out by the color key are
1559 * discarded, instead of just fully transparent. */
1560 color = get_surface_color(rt, 320, 240);
1561 if (i == 2)
1562 todo_wine ok(compare_color(color, tests[i].result2, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1563 tests[i].result2, i, color);
1564 else
1565 ok(compare_color(color, tests[i].result2, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1566 tests[i].result2, i, color);
1569 IDirectDrawSurface_Release(rt);
1570 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1571 ok(SUCCEEDED(hr), "Failed to unset texture, hr %#x.\n", hr);
1572 IDirectDrawSurface_Release(surface);
1573 destroy_viewport(device, viewport);
1574 destroy_material(background);
1575 IDirect3DDevice2_Release(device);
1576 IDirectDraw2_Release(ddraw);
1577 DestroyWindow(window);
1580 static void test_ck_default(void)
1582 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1583 static D3DTLVERTEX tquad[] =
1585 {{ 0.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1586 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1587 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1588 {{640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1590 IDirectDrawSurface *surface, *rt;
1591 D3DTEXTUREHANDLE texture_handle;
1592 IDirect3DMaterial2 *background;
1593 IDirect3DViewport2 *viewport;
1594 DDSURFACEDESC surface_desc;
1595 IDirect3DTexture2 *texture;
1596 IDirect3DDevice2 *device;
1597 IDirectDraw2 *ddraw;
1598 D3DCOLOR color;
1599 DWORD value;
1600 HWND window;
1601 DDBLTFX fx;
1602 HRESULT hr;
1604 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1605 0, 0, 640, 480, 0, 0, 0, 0);
1606 ddraw = create_ddraw();
1607 ok(!!ddraw, "Failed to create a ddraw object.\n");
1608 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1610 skip("Failed to create a 3D device, skipping test.\n");
1611 IDirectDraw2_Release(ddraw);
1612 DestroyWindow(window);
1613 return;
1616 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1617 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1619 background = create_diffuse_material(device, 0.0, 1.0f, 0.0f, 1.0f);
1620 viewport = create_viewport(device, 0, 0, 640, 480);
1621 viewport_set_background(device, viewport, background);
1622 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1623 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1625 memset(&surface_desc, 0, sizeof(surface_desc));
1626 surface_desc.dwSize = sizeof(surface_desc);
1627 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1628 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1629 surface_desc.dwWidth = 256;
1630 surface_desc.dwHeight = 256;
1631 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1632 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
1633 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1634 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1635 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1636 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1637 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
1638 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
1639 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1640 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1641 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
1642 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1643 hr = IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
1644 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1645 IDirect3DTexture_Release(texture);
1647 memset(&fx, 0, sizeof(fx));
1648 fx.dwSize = sizeof(fx);
1649 U5(fx).dwFillColor = 0x000000ff;
1650 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1651 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
1653 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1654 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1655 hr = IDirect3DDevice2_BeginScene(device);
1656 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1657 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1658 ok(SUCCEEDED(hr), "Failed to set texture handle, hr %#x.\n", hr);
1659 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1660 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1661 ok(!value, "Got unexpected color keying state %#x.\n", value);
1662 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[0], 4, 0);
1663 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1664 hr = IDirect3DDevice2_EndScene(device);
1665 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1666 color = get_surface_color(rt, 320, 240);
1667 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1669 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1670 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1671 hr = IDirect3DDevice2_BeginScene(device);
1672 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1673 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
1674 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1675 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[0], 4, 0);
1676 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1677 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1678 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1679 ok(!!value, "Got unexpected color keying state %#x.\n", value);
1680 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1681 ok(SUCCEEDED(hr), "Failed to set texture handle, hr %#x.\n", hr);
1682 hr = IDirect3DDevice2_EndScene(device);
1683 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1684 color = get_surface_color(rt, 320, 240);
1685 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1687 IDirectDrawSurface_Release(surface);
1688 destroy_viewport(device, viewport);
1689 destroy_material(background);
1690 IDirectDrawSurface_Release(rt);
1691 IDirect3DDevice2_Release(device);
1692 IDirectDraw2_Release(ddraw);
1693 DestroyWindow(window);
1696 static void test_ck_complex(void)
1698 IDirectDrawSurface *surface, *mipmap, *tmp;
1699 DDSCAPS caps = {DDSCAPS_COMPLEX};
1700 DDSURFACEDESC surface_desc;
1701 IDirect3DDevice2 *device;
1702 DDCOLORKEY color_key;
1703 IDirectDraw2 *ddraw;
1704 unsigned int i;
1705 ULONG refcount;
1706 HWND window;
1707 HRESULT hr;
1709 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1710 0, 0, 640, 480, 0, 0, 0, 0);
1711 ddraw = create_ddraw();
1712 ok(!!ddraw, "Failed to create a ddraw object.\n");
1713 if (!(device = create_device(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
1715 skip("Failed to create a 3D device, skipping test.\n");
1716 DestroyWindow(window);
1717 IDirectDraw2_Release(ddraw);
1718 return;
1720 IDirect3DDevice2_Release(device);
1722 memset(&surface_desc, 0, sizeof(surface_desc));
1723 surface_desc.dwSize = sizeof(surface_desc);
1724 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1725 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1726 surface_desc.dwWidth = 128;
1727 surface_desc.dwHeight = 128;
1728 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1729 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1731 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1732 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1733 color_key.dwColorSpaceLowValue = 0x0000ff00;
1734 color_key.dwColorSpaceHighValue = 0x0000ff00;
1735 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1736 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1737 memset(&color_key, 0, sizeof(color_key));
1738 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1739 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1740 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1741 color_key.dwColorSpaceLowValue);
1742 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1743 color_key.dwColorSpaceHighValue);
1745 mipmap = surface;
1746 IDirectDrawSurface_AddRef(mipmap);
1747 for (i = 0; i < 7; ++i)
1749 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
1750 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
1752 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1753 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1754 color_key.dwColorSpaceLowValue = 0x000000ff;
1755 color_key.dwColorSpaceHighValue = 0x000000ff;
1756 hr = IDirectDrawSurface_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1757 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x, i %u.\n", hr, i);
1758 memset(&color_key, 0, sizeof(color_key));
1759 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1760 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x, i %u.\n", hr, i);
1761 ok(color_key.dwColorSpaceLowValue == 0x000000ff, "Got unexpected value 0x%08x, i %u.\n",
1762 color_key.dwColorSpaceLowValue, i);
1763 ok(color_key.dwColorSpaceHighValue == 0x000000ff, "Got unexpected value 0x%08x, i %u.\n",
1764 color_key.dwColorSpaceHighValue, i);
1766 IDirectDrawSurface_Release(mipmap);
1767 mipmap = tmp;
1770 memset(&color_key, 0, sizeof(color_key));
1771 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1772 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1773 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1774 color_key.dwColorSpaceLowValue);
1775 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1776 color_key.dwColorSpaceHighValue);
1778 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
1779 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
1780 IDirectDrawSurface_Release(mipmap);
1781 refcount = IDirectDrawSurface_Release(surface);
1782 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1784 memset(&surface_desc, 0, sizeof(surface_desc));
1785 surface_desc.dwSize = sizeof(surface_desc);
1786 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
1787 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
1788 surface_desc.dwBackBufferCount = 1;
1789 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1790 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1792 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1793 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1794 color_key.dwColorSpaceLowValue = 0x0000ff00;
1795 color_key.dwColorSpaceHighValue = 0x0000ff00;
1796 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1797 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1798 memset(&color_key, 0, sizeof(color_key));
1799 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1800 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1801 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1802 color_key.dwColorSpaceLowValue);
1803 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1804 color_key.dwColorSpaceHighValue);
1806 hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &tmp);
1807 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
1809 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1810 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1811 color_key.dwColorSpaceLowValue = 0x0000ff00;
1812 color_key.dwColorSpaceHighValue = 0x0000ff00;
1813 hr = IDirectDrawSurface_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1814 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1815 memset(&color_key, 0, sizeof(color_key));
1816 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1817 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1818 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1819 color_key.dwColorSpaceLowValue);
1820 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1821 color_key.dwColorSpaceHighValue);
1823 IDirectDrawSurface_Release(tmp);
1825 refcount = IDirectDrawSurface_Release(surface);
1826 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1827 refcount = IDirectDraw2_Release(ddraw);
1828 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1829 DestroyWindow(window);
1832 struct qi_test
1834 REFIID iid;
1835 REFIID refcount_iid;
1836 HRESULT hr;
1839 static void test_qi(const char *test_name, IUnknown *base_iface,
1840 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
1842 ULONG refcount, expected_refcount;
1843 IUnknown *iface1, *iface2;
1844 HRESULT hr;
1845 UINT i, j;
1847 for (i = 0; i < entry_count; ++i)
1849 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
1850 ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
1851 if (SUCCEEDED(hr))
1853 for (j = 0; j < entry_count; ++j)
1855 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
1856 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
1857 if (SUCCEEDED(hr))
1859 expected_refcount = 0;
1860 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
1861 ++expected_refcount;
1862 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
1863 ++expected_refcount;
1864 refcount = IUnknown_Release(iface2);
1865 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
1866 refcount, test_name, i, j, expected_refcount);
1870 expected_refcount = 0;
1871 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
1872 ++expected_refcount;
1873 refcount = IUnknown_Release(iface1);
1874 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
1875 refcount, test_name, i, expected_refcount);
1880 static void test_surface_qi(void)
1882 static const struct qi_test tests[] =
1884 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface, S_OK },
1885 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface, S_OK },
1886 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
1887 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1888 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
1889 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
1890 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
1891 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
1892 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
1893 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
1894 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
1895 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
1896 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
1897 {&IID_IDirect3D7, NULL, E_INVALIDARG },
1898 {&IID_IDirect3D3, NULL, E_INVALIDARG },
1899 {&IID_IDirect3D2, NULL, E_INVALIDARG },
1900 {&IID_IDirect3D, NULL, E_INVALIDARG },
1901 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
1902 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
1903 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
1904 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
1905 {&IID_IDirectDraw, NULL, E_INVALIDARG },
1906 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
1907 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
1908 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
1909 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
1910 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
1911 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
1912 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
1913 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
1914 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
1915 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
1916 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
1917 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
1918 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
1921 IDirectDrawSurface *surface;
1922 DDSURFACEDESC surface_desc;
1923 IDirect3DDevice2 *device;
1924 IDirectDraw2 *ddraw;
1925 HWND window;
1926 HRESULT hr;
1928 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
1930 win_skip("DirectDrawCreateEx not available, skipping test.\n");
1931 return;
1934 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1935 0, 0, 640, 480, 0, 0, 0, 0);
1936 ddraw = create_ddraw();
1937 ok(!!ddraw, "Failed to create a ddraw object.\n");
1938 /* Try to create a D3D device to see if the ddraw implementation supports
1939 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
1940 * doesn't support e.g. the IDirect3DTexture interfaces. */
1941 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1943 skip("Failed to create a 3D device, skipping test.\n");
1944 IDirectDraw2_Release(ddraw);
1945 DestroyWindow(window);
1946 return;
1948 IDirect3DDevice_Release(device);
1950 memset(&surface_desc, 0, sizeof(surface_desc));
1951 surface_desc.dwSize = sizeof(surface_desc);
1952 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1953 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1954 surface_desc.dwWidth = 512;
1955 surface_desc.dwHeight = 512;
1956 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1957 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1959 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface, tests, sizeof(tests) / sizeof(*tests));
1961 IDirectDrawSurface_Release(surface);
1962 IDirectDraw2_Release(ddraw);
1963 DestroyWindow(window);
1966 static void test_device_qi(void)
1968 static const struct qi_test tests[] =
1970 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
1971 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
1972 {&IID_IDirectDrawGammaControl, NULL, E_NOINTERFACE},
1973 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1974 {&IID_IDirectDrawSurface7, NULL, E_NOINTERFACE},
1975 {&IID_IDirectDrawSurface4, NULL, E_NOINTERFACE},
1976 {&IID_IDirectDrawSurface3, NULL, E_NOINTERFACE},
1977 {&IID_IDirectDrawSurface2, NULL, E_NOINTERFACE},
1978 {&IID_IDirectDrawSurface, NULL, E_NOINTERFACE},
1979 {&IID_IDirect3DDevice7, NULL, E_NOINTERFACE},
1980 {&IID_IDirect3DDevice3, NULL, E_NOINTERFACE},
1981 {&IID_IDirect3DDevice2, &IID_IDirect3DDevice2, S_OK },
1982 {&IID_IDirect3DDevice, &IID_IDirect3DDevice2, S_OK },
1983 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
1984 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
1985 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
1986 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
1987 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
1988 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
1989 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
1990 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
1991 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
1992 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
1993 {&IID_IDirect3D, NULL, E_NOINTERFACE},
1994 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
1995 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
1996 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
1997 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
1998 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
1999 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
2000 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
2001 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
2002 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
2003 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
2004 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
2005 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
2006 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
2007 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
2008 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
2009 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
2010 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
2011 {&IID_IUnknown, &IID_IDirect3DDevice2, S_OK },
2014 IDirect3DDevice2 *device;
2015 IDirectDraw2 *ddraw;
2016 HWND window;
2018 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2019 0, 0, 640, 480, 0, 0, 0, 0);
2020 ddraw = create_ddraw();
2021 ok(!!ddraw, "Failed to create a ddraw object.\n");
2022 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
2024 skip("Failed to create a 3D device, skipping test.\n");
2025 IDirectDraw2_Release(ddraw);
2026 DestroyWindow(window);
2027 return;
2030 test_qi("device_qi", (IUnknown *)device, &IID_IDirect3DDevice2, tests, sizeof(tests) / sizeof(*tests));
2032 IDirect3DDevice2_Release(device);
2033 IDirectDraw2_Release(ddraw);
2034 DestroyWindow(window);
2037 static void test_wndproc(void)
2039 LONG_PTR proc, ddraw_proc;
2040 IDirectDraw2 *ddraw;
2041 WNDCLASSA wc = {0};
2042 HWND window;
2043 HRESULT hr;
2044 ULONG ref;
2046 static const UINT messages[] =
2048 WM_WINDOWPOSCHANGING,
2049 WM_MOVE,
2050 WM_SIZE,
2051 WM_WINDOWPOSCHANGING,
2052 WM_ACTIVATE,
2053 WM_SETFOCUS,
2057 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
2058 ddraw = create_ddraw();
2059 ok(!!ddraw, "Failed to create a ddraw object.\n");
2061 wc.lpfnWndProc = test_proc;
2062 wc.lpszClassName = "ddraw_test_wndproc_wc";
2063 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2065 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
2066 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
2068 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2069 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2070 (LONG_PTR)test_proc, proc);
2071 expect_messages = messages;
2072 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2073 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2074 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2075 expect_messages = NULL;
2076 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2077 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2078 (LONG_PTR)test_proc, proc);
2079 ref = IDirectDraw2_Release(ddraw);
2080 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2081 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2082 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2083 (LONG_PTR)test_proc, proc);
2085 /* DDSCL_NORMAL doesn't. */
2086 ddraw = create_ddraw();
2087 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2088 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2089 (LONG_PTR)test_proc, proc);
2090 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2091 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2092 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2093 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2094 (LONG_PTR)test_proc, proc);
2095 ref = IDirectDraw2_Release(ddraw);
2096 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2097 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2098 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2099 (LONG_PTR)test_proc, proc);
2101 /* The original window proc is only restored by ddraw if the current
2102 * window proc matches the one ddraw set. This also affects switching
2103 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
2104 ddraw = create_ddraw();
2105 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2106 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2107 (LONG_PTR)test_proc, proc);
2108 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2109 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2110 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2111 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2112 (LONG_PTR)test_proc, proc);
2113 ddraw_proc = proc;
2114 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2115 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2116 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2117 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2118 (LONG_PTR)test_proc, proc);
2119 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2120 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2121 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2122 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2123 (LONG_PTR)test_proc, proc);
2124 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2125 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2126 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2127 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2128 (LONG_PTR)DefWindowProcA, proc);
2129 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2130 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2131 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc);
2132 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2133 (LONG_PTR)DefWindowProcA, proc);
2134 ref = IDirectDraw2_Release(ddraw);
2135 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2136 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2137 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2138 (LONG_PTR)test_proc, proc);
2140 ddraw = create_ddraw();
2141 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2142 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2143 (LONG_PTR)test_proc, proc);
2144 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2145 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2146 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2147 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2148 (LONG_PTR)test_proc, proc);
2149 ref = IDirectDraw2_Release(ddraw);
2150 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2151 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2152 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2153 (LONG_PTR)DefWindowProcA, proc);
2155 fix_wndproc(window, (LONG_PTR)test_proc);
2156 expect_messages = NULL;
2157 DestroyWindow(window);
2158 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2161 static void test_window_style(void)
2163 LONG style, exstyle, tmp;
2164 RECT fullscreen_rect, r;
2165 IDirectDraw2 *ddraw;
2166 HWND window;
2167 HRESULT hr;
2168 ULONG ref;
2170 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2171 0, 0, 100, 100, 0, 0, 0, 0);
2172 ddraw = create_ddraw();
2173 ok(!!ddraw, "Failed to create a ddraw object.\n");
2175 style = GetWindowLongA(window, GWL_STYLE);
2176 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
2177 SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2179 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2180 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2182 tmp = GetWindowLongA(window, GWL_STYLE);
2183 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2184 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2185 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2187 GetWindowRect(window, &r);
2188 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2189 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2190 r.left, r.top, r.right, r.bottom);
2191 GetClientRect(window, &r);
2192 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2194 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2195 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2197 tmp = GetWindowLongA(window, GWL_STYLE);
2198 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2199 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2200 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2202 ref = IDirectDraw2_Release(ddraw);
2203 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2205 DestroyWindow(window);
2208 static void test_redundant_mode_set(void)
2210 DDSURFACEDESC surface_desc = {0};
2211 IDirectDraw2 *ddraw;
2212 HWND window;
2213 HRESULT hr;
2214 RECT r, s;
2215 ULONG ref;
2217 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2218 0, 0, 100, 100, 0, 0, 0, 0);
2219 ddraw = create_ddraw();
2220 ok(!!ddraw, "Failed to create a ddraw object.\n");
2222 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2223 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2225 surface_desc.dwSize = sizeof(surface_desc);
2226 hr = IDirectDraw2_GetDisplayMode(ddraw, &surface_desc);
2227 ok(SUCCEEDED(hr), "GetDipslayMode failed, hr %#x.\n", hr);
2229 hr = IDirectDraw2_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2230 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount, 0, 0);
2231 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2233 GetWindowRect(window, &r);
2234 r.right /= 2;
2235 r.bottom /= 2;
2236 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
2237 GetWindowRect(window, &s);
2238 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2239 r.left, r.top, r.right, r.bottom,
2240 s.left, s.top, s.right, s.bottom);
2242 hr = IDirectDraw2_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2243 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount, 0, 0);
2244 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2246 GetWindowRect(window, &s);
2247 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2248 r.left, r.top, r.right, r.bottom,
2249 s.left, s.top, s.right, s.bottom);
2251 ref = IDirectDraw2_Release(ddraw);
2252 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2254 DestroyWindow(window);
2257 static SIZE screen_size, screen_size2;
2259 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2261 if (message == WM_SIZE)
2263 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2264 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2267 return test_proc(hwnd, message, wparam, lparam);
2270 static LRESULT CALLBACK mode_set_proc2(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2272 if (message == WM_SIZE)
2274 screen_size2.cx = GetSystemMetrics(SM_CXSCREEN);
2275 screen_size2.cy = GetSystemMetrics(SM_CYSCREEN);
2278 return test_proc(hwnd, message, wparam, lparam);
2281 static void test_coop_level_mode_set(void)
2283 IDirectDrawSurface *primary;
2284 RECT fullscreen_rect, r, s;
2285 IDirectDraw2 *ddraw;
2286 DDSURFACEDESC ddsd;
2287 WNDCLASSA wc = {0};
2288 HWND window, window2;
2289 HRESULT hr;
2290 ULONG ref;
2292 static const UINT exclusive_messages[] =
2294 WM_WINDOWPOSCHANGING,
2295 WM_WINDOWPOSCHANGED,
2296 WM_SIZE,
2297 WM_DISPLAYCHANGE,
2301 static const UINT normal_messages[] =
2303 WM_DISPLAYCHANGE,
2307 ddraw = create_ddraw();
2308 ok(!!ddraw, "Failed to create a ddraw object.\n");
2310 wc.lpfnWndProc = mode_set_proc;
2311 wc.lpszClassName = "ddraw_test_wndproc_wc";
2312 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2313 wc.lpfnWndProc = mode_set_proc2;
2314 wc.lpszClassName = "ddraw_test_wndproc_wc2";
2315 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2317 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
2318 0, 0, 100, 100, 0, 0, 0, 0);
2319 window2 = CreateWindowA("ddraw_test_wndproc_wc2", "ddraw_test", WS_OVERLAPPEDWINDOW,
2320 0, 0, 100, 100, 0, 0, 0, 0);
2322 SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2323 SetRect(&s, 0, 0, 640, 480);
2325 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2326 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2328 GetWindowRect(window, &r);
2329 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2330 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2331 r.left, r.top, r.right, r.bottom);
2333 memset(&ddsd, 0, sizeof(ddsd));
2334 ddsd.dwSize = sizeof(ddsd);
2335 ddsd.dwFlags = DDSD_CAPS;
2336 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2338 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2339 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2340 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2341 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2342 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2343 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2344 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2345 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2347 GetWindowRect(window, &r);
2348 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2349 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2350 r.left, r.top, r.right, r.bottom);
2352 expect_messages = exclusive_messages;
2353 screen_size.cx = 0;
2354 screen_size.cy = 0;
2356 hr = set_display_mode(ddraw, 640, 480);
2357 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2359 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2360 expect_messages = NULL;
2361 ok(screen_size.cx == s.right && screen_size.cy == s.bottom,
2362 "Expected screen size %ux%u, got %ux%u.\n",
2363 s.right, s.bottom, screen_size.cx, screen_size.cy);
2365 GetWindowRect(window, &r);
2366 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2367 s.left, s.top, s.right, s.bottom,
2368 r.left, r.top, r.right, r.bottom);
2370 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2371 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2372 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2373 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2374 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2375 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2376 IDirectDrawSurface_Release(primary);
2378 memset(&ddsd, 0, sizeof(ddsd));
2379 ddsd.dwSize = sizeof(ddsd);
2380 ddsd.dwFlags = DDSD_CAPS;
2381 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2383 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2384 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2385 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2386 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2387 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2388 s.right - s.left, ddsd.dwWidth);
2389 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2390 s.bottom - s.top, ddsd.dwHeight);
2392 GetWindowRect(window, &r);
2393 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2394 s.left, s.top, s.right, s.bottom,
2395 r.left, r.top, r.right, r.bottom);
2397 expect_messages = exclusive_messages;
2398 screen_size.cx = 0;
2399 screen_size.cy = 0;
2401 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2402 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2404 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2405 expect_messages = NULL;
2406 ok(screen_size.cx == fullscreen_rect.right && screen_size.cy == fullscreen_rect.bottom,
2407 "Expected screen size %ux%u, got %ux%u.\n",
2408 fullscreen_rect.right, fullscreen_rect.bottom, screen_size.cx, screen_size.cy);
2410 GetWindowRect(window, &r);
2411 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2412 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2413 r.left, r.top, r.right, r.bottom);
2415 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2416 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2417 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2418 s.right - s.left, ddsd.dwWidth);
2419 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2420 s.bottom - s.top, ddsd.dwHeight);
2421 IDirectDrawSurface_Release(primary);
2423 memset(&ddsd, 0, sizeof(ddsd));
2424 ddsd.dwSize = sizeof(ddsd);
2425 ddsd.dwFlags = DDSD_CAPS;
2426 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2428 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2429 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2430 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2431 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2432 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2433 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2434 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2435 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2437 GetWindowRect(window, &r);
2438 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2439 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2440 r.left, r.top, r.right, r.bottom);
2442 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2443 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2445 GetWindowRect(window, &r);
2446 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2447 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2448 r.left, r.top, r.right, r.bottom);
2450 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2451 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2452 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2453 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2454 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2455 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2456 IDirectDrawSurface_Release(primary);
2458 memset(&ddsd, 0, sizeof(ddsd));
2459 ddsd.dwSize = sizeof(ddsd);
2460 ddsd.dwFlags = DDSD_CAPS;
2461 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2463 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2464 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2465 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2466 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2467 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2468 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2469 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2470 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2472 GetWindowRect(window, &r);
2473 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2474 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2475 r.left, r.top, r.right, r.bottom);
2477 expect_messages = normal_messages;
2478 screen_size.cx = 0;
2479 screen_size.cy = 0;
2481 hr = set_display_mode(ddraw, 640, 480);
2482 if (hr == DDERR_NOEXCLUSIVEMODE /* NT4 testbot */)
2484 win_skip("Broken SetDisplayMode(), skipping remaining tests.\n");
2485 IDirectDrawSurface_Release(primary);
2486 IDirectDraw2_Release(ddraw);
2487 goto done;
2489 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2491 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2492 expect_messages = NULL;
2493 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2495 GetWindowRect(window, &r);
2496 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2497 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2498 r.left, r.top, r.right, r.bottom);
2500 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2501 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2502 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2503 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2504 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2505 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2506 IDirectDrawSurface_Release(primary);
2508 memset(&ddsd, 0, sizeof(ddsd));
2509 ddsd.dwSize = sizeof(ddsd);
2510 ddsd.dwFlags = DDSD_CAPS;
2511 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2513 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2514 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2515 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2516 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2517 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2518 s.right - s.left, ddsd.dwWidth);
2519 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2520 s.bottom - s.top, ddsd.dwHeight);
2522 GetWindowRect(window, &r);
2523 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2524 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2525 r.left, r.top, r.right, r.bottom);
2527 expect_messages = normal_messages;
2528 screen_size.cx = 0;
2529 screen_size.cy = 0;
2531 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2532 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2534 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2535 expect_messages = NULL;
2536 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2538 GetWindowRect(window, &r);
2539 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2540 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2541 r.left, r.top, r.right, r.bottom);
2543 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2544 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2545 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2546 s.right - s.left, ddsd.dwWidth);
2547 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2548 s.bottom - s.top, ddsd.dwHeight);
2549 IDirectDrawSurface_Release(primary);
2551 memset(&ddsd, 0, sizeof(ddsd));
2552 ddsd.dwSize = sizeof(ddsd);
2553 ddsd.dwFlags = DDSD_CAPS;
2554 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2556 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2557 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2558 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2559 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2560 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2561 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2562 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2563 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2565 GetWindowRect(window, &r);
2566 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2567 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2568 r.left, r.top, r.right, r.bottom);
2570 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
2571 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
2572 * not DDSCL_FULLSCREEN. */
2573 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2574 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2576 GetWindowRect(window, &r);
2577 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2578 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2579 r.left, r.top, r.right, r.bottom);
2581 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2582 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2583 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2584 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2585 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2586 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2587 IDirectDrawSurface_Release(primary);
2589 memset(&ddsd, 0, sizeof(ddsd));
2590 ddsd.dwSize = sizeof(ddsd);
2591 ddsd.dwFlags = DDSD_CAPS;
2592 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2594 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2595 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2596 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2597 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2598 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2599 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2600 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2601 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2603 GetWindowRect(window, &r);
2604 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2605 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2606 r.left, r.top, r.right, r.bottom);
2608 expect_messages = normal_messages;
2609 screen_size.cx = 0;
2610 screen_size.cy = 0;
2612 hr = set_display_mode(ddraw, 640, 480);
2613 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2615 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2616 expect_messages = NULL;
2617 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2619 GetWindowRect(window, &r);
2620 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2621 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2622 r.left, r.top, r.right, r.bottom);
2624 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2625 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2626 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2627 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2628 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2629 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2630 IDirectDrawSurface_Release(primary);
2632 memset(&ddsd, 0, sizeof(ddsd));
2633 ddsd.dwSize = sizeof(ddsd);
2634 ddsd.dwFlags = DDSD_CAPS;
2635 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2637 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2638 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2639 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2640 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2641 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2642 s.right - s.left, ddsd.dwWidth);
2643 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2644 s.bottom - s.top, ddsd.dwHeight);
2646 GetWindowRect(window, &r);
2647 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2648 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2649 r.left, r.top, r.right, r.bottom);
2651 expect_messages = normal_messages;
2652 screen_size.cx = 0;
2653 screen_size.cy = 0;
2655 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2656 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2658 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2659 expect_messages = NULL;
2660 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2662 GetWindowRect(window, &r);
2663 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2664 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2665 r.left, r.top, r.right, r.bottom);
2667 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2668 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2669 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2670 s.right - s.left, ddsd.dwWidth);
2671 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2672 s.bottom - s.top, ddsd.dwHeight);
2673 IDirectDrawSurface_Release(primary);
2675 memset(&ddsd, 0, sizeof(ddsd));
2676 ddsd.dwSize = sizeof(ddsd);
2677 ddsd.dwFlags = DDSD_CAPS;
2678 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2680 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2681 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2682 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2683 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2684 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2685 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2686 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2687 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2688 IDirectDrawSurface_Release(primary);
2690 GetWindowRect(window, &r);
2691 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2692 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2693 r.left, r.top, r.right, r.bottom);
2695 /* Changing the coop level from EXCLUSIVE to NORMAL restores the screen resolution */
2696 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2697 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2698 hr = set_display_mode(ddraw, 640, 480);
2699 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2701 expect_messages = exclusive_messages;
2702 screen_size.cx = 0;
2703 screen_size.cy = 0;
2705 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2706 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2708 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2709 expect_messages = NULL;
2710 ok(screen_size.cx == fullscreen_rect.right && screen_size.cy == fullscreen_rect.bottom,
2711 "Expected screen size %ux%u, got %ux%u.\n",
2712 fullscreen_rect.right, fullscreen_rect.bottom, screen_size.cx, screen_size.cy);
2714 GetWindowRect(window, &r);
2715 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2716 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2717 r.left, r.top, r.right, r.bottom);
2719 memset(&ddsd, 0, sizeof(ddsd));
2720 ddsd.dwSize = sizeof(ddsd);
2721 ddsd.dwFlags = DDSD_CAPS;
2722 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2724 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2725 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2726 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2727 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2728 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2729 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2730 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2731 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2732 IDirectDrawSurface_Release(primary);
2734 /* The screen restore is a property of DDSCL_EXCLUSIVE */
2735 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2736 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2737 hr = set_display_mode(ddraw, 640, 480);
2738 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2740 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2741 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2743 memset(&ddsd, 0, sizeof(ddsd));
2744 ddsd.dwSize = sizeof(ddsd);
2745 ddsd.dwFlags = DDSD_CAPS;
2746 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2748 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2749 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2750 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2751 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2752 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2753 s.right - s.left, ddsd.dwWidth);
2754 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2755 s.bottom - s.top, ddsd.dwHeight);
2756 IDirectDrawSurface_Release(primary);
2758 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2759 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2761 /* If the window is changed at the same time, messages are sent to the new window. */
2762 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2763 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2764 hr = set_display_mode(ddraw, 640, 480);
2765 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2767 expect_messages = exclusive_messages;
2768 screen_size.cx = 0;
2769 screen_size.cy = 0;
2770 screen_size2.cx = 0;
2771 screen_size2.cy = 0;
2773 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
2774 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2776 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2777 expect_messages = NULL;
2778 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n",
2779 screen_size.cx, screen_size.cy);
2780 ok(screen_size2.cx == fullscreen_rect.right && screen_size2.cy == fullscreen_rect.bottom,
2781 "Expected screen size 2 %ux%u, got %ux%u.\n",
2782 fullscreen_rect.right, fullscreen_rect.bottom, screen_size2.cx, screen_size2.cy);
2784 GetWindowRect(window, &r);
2785 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2786 s.left, s.top, s.right, s.bottom,
2787 r.left, r.top, r.right, r.bottom);
2788 GetWindowRect(window2, &r);
2789 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2790 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2791 r.left, r.top, r.right, r.bottom);
2793 memset(&ddsd, 0, sizeof(ddsd));
2794 ddsd.dwSize = sizeof(ddsd);
2795 ddsd.dwFlags = DDSD_CAPS;
2796 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2798 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
2799 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2800 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2801 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2802 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2803 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2804 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2805 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2806 IDirectDrawSurface_Release(primary);
2808 ref = IDirectDraw2_Release(ddraw);
2809 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2811 GetWindowRect(window, &r);
2812 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2813 s.left, s.top, s.right, s.bottom,
2814 r.left, r.top, r.right, r.bottom);
2816 done:
2817 expect_messages = NULL;
2818 DestroyWindow(window);
2819 DestroyWindow(window2);
2820 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2821 UnregisterClassA("ddraw_test_wndproc_wc2", GetModuleHandleA(NULL));
2824 static void test_coop_level_mode_set_multi(void)
2826 IDirectDraw2 *ddraw1, *ddraw2;
2827 UINT orig_w, orig_h, w, h;
2828 HWND window;
2829 HRESULT hr;
2830 ULONG ref;
2832 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2833 0, 0, 100, 100, 0, 0, 0, 0);
2834 ddraw1 = create_ddraw();
2835 ok(!!ddraw1, "Failed to create a ddraw object.\n");
2837 orig_w = GetSystemMetrics(SM_CXSCREEN);
2838 orig_h = GetSystemMetrics(SM_CYSCREEN);
2840 /* With just a single ddraw object, the display mode is restored on
2841 * release. */
2842 hr = set_display_mode(ddraw1, 800, 600);
2843 if (hr == DDERR_NOEXCLUSIVEMODE /* NT4 testbot */)
2845 win_skip("Broken SetDisplayMode(), skipping test.\n");
2846 IDirectDraw2_Release(ddraw1);
2847 DestroyWindow(window);
2848 return;
2850 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2851 w = GetSystemMetrics(SM_CXSCREEN);
2852 ok(w == 800, "Got unexpected screen width %u.\n", w);
2853 h = GetSystemMetrics(SM_CYSCREEN);
2854 ok(h == 600, "Got unexpected screen height %u.\n", h);
2856 ref = IDirectDraw2_Release(ddraw1);
2857 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2858 w = GetSystemMetrics(SM_CXSCREEN);
2859 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2860 h = GetSystemMetrics(SM_CYSCREEN);
2861 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2863 /* When there are multiple ddraw objects, the display mode is restored to
2864 * the initial mode, before the first SetDisplayMode() call. */
2865 ddraw1 = create_ddraw();
2866 hr = set_display_mode(ddraw1, 800, 600);
2867 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2868 w = GetSystemMetrics(SM_CXSCREEN);
2869 ok(w == 800, "Got unexpected screen width %u.\n", w);
2870 h = GetSystemMetrics(SM_CYSCREEN);
2871 ok(h == 600, "Got unexpected screen height %u.\n", h);
2873 ddraw2 = create_ddraw();
2874 hr = set_display_mode(ddraw2, 640, 480);
2875 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2876 w = GetSystemMetrics(SM_CXSCREEN);
2877 ok(w == 640, "Got unexpected screen width %u.\n", w);
2878 h = GetSystemMetrics(SM_CYSCREEN);
2879 ok(h == 480, "Got unexpected screen height %u.\n", h);
2881 ref = IDirectDraw2_Release(ddraw2);
2882 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2883 w = GetSystemMetrics(SM_CXSCREEN);
2884 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2885 h = GetSystemMetrics(SM_CYSCREEN);
2886 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2888 ref = IDirectDraw2_Release(ddraw1);
2889 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2890 w = GetSystemMetrics(SM_CXSCREEN);
2891 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2892 h = GetSystemMetrics(SM_CYSCREEN);
2893 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2895 /* Regardless of release ordering. */
2896 ddraw1 = create_ddraw();
2897 hr = set_display_mode(ddraw1, 800, 600);
2898 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2899 w = GetSystemMetrics(SM_CXSCREEN);
2900 ok(w == 800, "Got unexpected screen width %u.\n", w);
2901 h = GetSystemMetrics(SM_CYSCREEN);
2902 ok(h == 600, "Got unexpected screen height %u.\n", h);
2904 ddraw2 = create_ddraw();
2905 hr = set_display_mode(ddraw2, 640, 480);
2906 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2907 w = GetSystemMetrics(SM_CXSCREEN);
2908 ok(w == 640, "Got unexpected screen width %u.\n", w);
2909 h = GetSystemMetrics(SM_CYSCREEN);
2910 ok(h == 480, "Got unexpected screen height %u.\n", h);
2912 ref = IDirectDraw2_Release(ddraw1);
2913 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2914 w = GetSystemMetrics(SM_CXSCREEN);
2915 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2916 h = GetSystemMetrics(SM_CYSCREEN);
2917 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2919 ref = IDirectDraw2_Release(ddraw2);
2920 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2921 w = GetSystemMetrics(SM_CXSCREEN);
2922 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2923 h = GetSystemMetrics(SM_CYSCREEN);
2924 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2926 /* But only for ddraw objects that called SetDisplayMode(). */
2927 ddraw1 = create_ddraw();
2928 ddraw2 = create_ddraw();
2929 hr = set_display_mode(ddraw2, 640, 480);
2930 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2931 w = GetSystemMetrics(SM_CXSCREEN);
2932 ok(w == 640, "Got unexpected screen width %u.\n", w);
2933 h = GetSystemMetrics(SM_CYSCREEN);
2934 ok(h == 480, "Got unexpected screen height %u.\n", h);
2936 ref = IDirectDraw2_Release(ddraw1);
2937 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2938 w = GetSystemMetrics(SM_CXSCREEN);
2939 ok(w == 640, "Got unexpected screen width %u.\n", w);
2940 h = GetSystemMetrics(SM_CYSCREEN);
2941 ok(h == 480, "Got unexpected screen height %u.\n", h);
2943 ref = IDirectDraw2_Release(ddraw2);
2944 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2945 w = GetSystemMetrics(SM_CXSCREEN);
2946 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2947 h = GetSystemMetrics(SM_CYSCREEN);
2948 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2950 /* If there's a ddraw object that's currently in exclusive mode, it blocks
2951 * restoring the display mode. */
2952 ddraw1 = create_ddraw();
2953 hr = set_display_mode(ddraw1, 800, 600);
2954 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2955 w = GetSystemMetrics(SM_CXSCREEN);
2956 ok(w == 800, "Got unexpected screen width %u.\n", w);
2957 h = GetSystemMetrics(SM_CYSCREEN);
2958 ok(h == 600, "Got unexpected screen height %u.\n", h);
2960 ddraw2 = create_ddraw();
2961 hr = set_display_mode(ddraw2, 640, 480);
2962 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2963 w = GetSystemMetrics(SM_CXSCREEN);
2964 ok(w == 640, "Got unexpected screen width %u.\n", w);
2965 h = GetSystemMetrics(SM_CYSCREEN);
2966 ok(h == 480, "Got unexpected screen height %u.\n", h);
2968 hr = IDirectDraw2_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2969 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2971 ref = IDirectDraw2_Release(ddraw1);
2972 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2973 w = GetSystemMetrics(SM_CXSCREEN);
2974 ok(w == 640, "Got unexpected screen width %u.\n", w);
2975 h = GetSystemMetrics(SM_CYSCREEN);
2976 ok(h == 480, "Got unexpected screen height %u.\n", h);
2978 ref = IDirectDraw2_Release(ddraw2);
2979 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2980 w = GetSystemMetrics(SM_CXSCREEN);
2981 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2982 h = GetSystemMetrics(SM_CYSCREEN);
2983 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2985 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
2986 ddraw1 = create_ddraw();
2987 hr = set_display_mode(ddraw1, 800, 600);
2988 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2989 w = GetSystemMetrics(SM_CXSCREEN);
2990 ok(w == 800, "Got unexpected screen width %u.\n", w);
2991 h = GetSystemMetrics(SM_CYSCREEN);
2992 ok(h == 600, "Got unexpected screen height %u.\n", h);
2994 hr = IDirectDraw2_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2995 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2997 ddraw2 = create_ddraw();
2998 hr = set_display_mode(ddraw2, 640, 480);
2999 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
3001 ref = IDirectDraw2_Release(ddraw1);
3002 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3003 w = GetSystemMetrics(SM_CXSCREEN);
3004 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
3005 h = GetSystemMetrics(SM_CYSCREEN);
3006 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
3008 ref = IDirectDraw2_Release(ddraw2);
3009 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3010 w = GetSystemMetrics(SM_CXSCREEN);
3011 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
3012 h = GetSystemMetrics(SM_CYSCREEN);
3013 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
3015 DestroyWindow(window);
3018 static void test_initialize(void)
3020 IDirectDraw2 *ddraw;
3021 HRESULT hr;
3023 ddraw = create_ddraw();
3024 ok(!!ddraw, "Failed to create a ddraw object.\n");
3026 hr = IDirectDraw2_Initialize(ddraw, NULL);
3027 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
3028 IDirectDraw2_Release(ddraw);
3030 CoInitialize(NULL);
3031 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw2, (void **)&ddraw);
3032 ok(SUCCEEDED(hr), "Failed to create IDirectDraw2 instance, hr %#x.\n", hr);
3033 hr = IDirectDraw2_Initialize(ddraw, NULL);
3034 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
3035 hr = IDirectDraw2_Initialize(ddraw, NULL);
3036 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
3037 IDirectDraw2_Release(ddraw);
3038 CoUninitialize();
3041 static void test_coop_level_surf_create(void)
3043 IDirectDrawSurface *surface;
3044 IDirectDraw2 *ddraw;
3045 DDSURFACEDESC ddsd;
3046 HRESULT hr;
3048 ddraw = create_ddraw();
3049 ok(!!ddraw, "Failed to create a ddraw object.\n");
3051 memset(&ddsd, 0, sizeof(ddsd));
3052 ddsd.dwSize = sizeof(ddsd);
3053 ddsd.dwFlags = DDSD_CAPS;
3054 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3055 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
3056 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
3058 IDirectDraw2_Release(ddraw);
3061 static void test_coop_level_multi_window(void)
3063 HWND window1, window2;
3064 IDirectDraw2 *ddraw;
3065 HRESULT hr;
3067 window1 = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
3068 0, 0, 640, 480, 0, 0, 0, 0);
3069 window2 = CreateWindowA("static", "ddraw_test2", WS_OVERLAPPEDWINDOW,
3070 0, 0, 640, 480, 0, 0, 0, 0);
3071 ddraw = create_ddraw();
3072 ok(!!ddraw, "Failed to create a ddraw object.\n");
3074 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
3075 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3076 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3077 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3078 ok(IsWindow(window1), "Window 1 was destroyed.\n");
3079 ok(IsWindow(window2), "Window 2 was destroyed.\n");
3081 IDirectDraw2_Release(ddraw);
3082 DestroyWindow(window2);
3083 DestroyWindow(window1);
3086 static void test_clear_rect_count(void)
3088 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
3089 IDirect3DMaterial2 *white, *red, *green, *blue;
3090 IDirect3DViewport2 *viewport;
3091 IDirect3DDevice2 *device;
3092 IDirectDrawSurface *rt;
3093 IDirectDraw2 *ddraw;
3094 D3DCOLOR color;
3095 HWND window;
3096 HRESULT hr;
3098 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3099 0, 0, 640, 480, 0, 0, 0, 0);
3100 ddraw = create_ddraw();
3101 ok(!!ddraw, "Failed to create a ddraw object.\n");
3102 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
3104 skip("Failed to create a 3D device, skipping test.\n");
3105 IDirectDraw2_Release(ddraw);
3106 DestroyWindow(window);
3107 return;
3110 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
3111 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3113 white = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
3114 red = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
3115 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
3116 blue = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
3118 viewport = create_viewport(device, 0, 0, 640, 480);
3119 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
3120 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
3122 viewport_set_background(device, viewport, white);
3123 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
3124 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3125 viewport_set_background(device, viewport, red);
3126 hr = IDirect3DViewport2_Clear(viewport, 0, &clear_rect, D3DCLEAR_TARGET);
3127 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3128 viewport_set_background(device, viewport, green);
3129 hr = IDirect3DViewport2_Clear(viewport, 0, NULL, D3DCLEAR_TARGET);
3130 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3131 viewport_set_background(device, viewport, blue);
3132 hr = IDirect3DViewport2_Clear(viewport, 0, &clear_rect, D3DCLEAR_TARGET);
3133 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3135 color = get_surface_color(rt, 320, 240);
3136 ok(compare_color(color, 0x00ffffff, 1), "Got unexpected color 0x%08x.\n", color);
3138 IDirectDrawSurface_Release(rt);
3139 destroy_viewport(device, viewport);
3140 destroy_material(white);
3141 destroy_material(red);
3142 destroy_material(green);
3143 destroy_material(blue);
3144 IDirect3DDevice2_Release(device);
3145 IDirectDraw2_Release(ddraw);
3146 DestroyWindow(window);
3149 static BOOL test_mode_restored(IDirectDraw2 *ddraw, HWND window)
3151 DDSURFACEDESC ddsd1, ddsd2;
3152 HRESULT hr;
3154 memset(&ddsd1, 0, sizeof(ddsd1));
3155 ddsd1.dwSize = sizeof(ddsd1);
3156 hr = IDirectDraw2_GetDisplayMode(ddraw, &ddsd1);
3157 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
3159 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3160 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3161 hr = set_display_mode(ddraw, 640, 480);
3162 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3163 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3164 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3166 memset(&ddsd2, 0, sizeof(ddsd2));
3167 ddsd2.dwSize = sizeof(ddsd2);
3168 hr = IDirectDraw2_GetDisplayMode(ddraw, &ddsd2);
3169 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
3170 hr = IDirectDraw2_RestoreDisplayMode(ddraw);
3171 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3173 return ddsd1.dwWidth == ddsd2.dwWidth && ddsd1.dwHeight == ddsd2.dwHeight;
3176 static void test_coop_level_versions(void)
3178 HWND window;
3179 IDirectDraw *ddraw;
3180 HRESULT hr;
3181 BOOL restored;
3182 IDirectDrawSurface *surface;
3183 IDirectDraw2 *ddraw2;
3184 DDSURFACEDESC ddsd;
3186 window = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
3187 0, 0, 640, 480, 0, 0, 0, 0);
3189 ddraw2 = create_ddraw();
3190 ok(!!ddraw2, "Failed to create a ddraw object.\n");
3191 /* Newly created ddraw objects restore the mode on ddraw2+::SetCooperativeLevel(NORMAL) */
3192 restored = test_mode_restored(ddraw2, window);
3193 ok(restored, "Display mode not restored in new ddraw object\n");
3195 /* A failing ddraw1::SetCooperativeLevel call does not have an effect */
3196 hr = IDirectDraw2_QueryInterface(ddraw2, &IID_IDirectDraw, (void **)&ddraw);
3197 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3199 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
3200 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
3201 restored = test_mode_restored(ddraw2, window);
3202 ok(restored, "Display mode not restored after bad ddraw1::SetCooperativeLevel call\n");
3204 /* A successful one does */
3205 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3206 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3207 restored = test_mode_restored(ddraw2, window);
3208 ok(!restored, "Display mode restored after good ddraw1::SetCooperativeLevel call\n");
3210 IDirectDraw_Release(ddraw);
3211 IDirectDraw2_Release(ddraw2);
3213 ddraw2 = create_ddraw();
3214 ok(!!ddraw2, "Failed to create a ddraw object.\n");
3215 hr = IDirectDraw2_QueryInterface(ddraw2, &IID_IDirectDraw, (void **)&ddraw);
3216 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3218 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_SETFOCUSWINDOW);
3219 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3220 restored = test_mode_restored(ddraw2, window);
3221 ok(!restored, "Display mode restored after ddraw1::SetCooperativeLevel(SETFOCUSWINDOW) call\n");
3223 IDirectDraw_Release(ddraw);
3224 IDirectDraw2_Release(ddraw2);
3226 /* A failing call does not restore the ddraw2+ behavior */
3227 ddraw2 = create_ddraw();
3228 ok(!!ddraw2, "Failed to create a ddraw object.\n");
3229 hr = IDirectDraw2_QueryInterface(ddraw2, &IID_IDirectDraw, (void **)&ddraw);
3230 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3232 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3233 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3234 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
3235 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
3236 restored = test_mode_restored(ddraw2, window);
3237 ok(!restored, "Display mode restored after good-bad ddraw1::SetCooperativeLevel() call sequence\n");
3239 IDirectDraw_Release(ddraw);
3240 IDirectDraw2_Release(ddraw2);
3242 /* Neither does a sequence of successful calls with the new interface */
3243 ddraw2 = create_ddraw();
3244 ok(!!ddraw2, "Failed to create a ddraw object.\n");
3245 hr = IDirectDraw2_QueryInterface(ddraw2, &IID_IDirectDraw, (void **)&ddraw);
3246 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3248 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3249 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3250 hr = IDirectDraw2_SetCooperativeLevel(ddraw2, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
3251 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3252 hr = IDirectDraw2_SetCooperativeLevel(ddraw2, window, DDSCL_NORMAL);
3253 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3255 restored = test_mode_restored(ddraw2, window);
3256 ok(!restored, "Display mode restored after ddraw1-ddraw2 SetCooperativeLevel() call sequence\n");
3257 IDirectDraw_Release(ddraw);
3258 IDirectDraw2_Release(ddraw2);
3260 /* ddraw1::CreateSurface does not triger the ddraw1 behavior */
3261 ddraw2 = create_ddraw();
3262 ok(!!ddraw2, "Failed to create a ddraw object.\n");
3263 hr = IDirectDraw2_QueryInterface(ddraw2, &IID_IDirectDraw, (void **)&ddraw);
3264 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3266 hr = IDirectDraw2_SetCooperativeLevel(ddraw2, window, DDSCL_NORMAL);
3267 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3269 memset(&ddsd, 0, sizeof(ddsd));
3270 ddsd.dwSize = sizeof(ddsd);
3271 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
3272 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
3273 ddsd.dwWidth = ddsd.dwHeight = 8;
3274 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
3275 ok(SUCCEEDED(hr), "CreateSurface failed, hr %#x.\n", hr);
3276 IDirectDrawSurface_Release(surface);
3277 restored = test_mode_restored(ddraw2, window);
3278 ok(restored, "Display mode not restored after ddraw1::CreateSurface() call\n");
3280 IDirectDraw_Release(ddraw);
3281 IDirectDraw2_Release(ddraw2);
3282 DestroyWindow(window);
3285 static void test_lighting_interface_versions(void)
3287 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
3288 IDirect3DMaterial2 *emissive, *background;
3289 IDirect3DViewport2 *viewport;
3290 IDirect3DDevice2 *device;
3291 IDirectDrawSurface *rt;
3292 IDirectDraw2 *ddraw;
3293 IDirect3D2 *d3d;
3294 D3DCOLOR color;
3295 HWND window;
3296 HRESULT hr;
3297 D3DMATERIALHANDLE mat_handle;
3298 D3DMATERIAL mat_desc;
3299 DWORD rs;
3300 unsigned int i;
3301 ULONG ref;
3302 static D3DVERTEX quad[] =
3304 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
3305 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
3306 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
3307 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
3309 static D3DLVERTEX lquad[] =
3311 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
3312 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
3313 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
3314 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
3316 static D3DTLVERTEX tlquad[] =
3318 {{ 0.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
3319 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
3320 {{ 640.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
3321 {{ 640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
3323 static const struct
3325 D3DVERTEXTYPE vertextype;
3326 void *data;
3327 DWORD d3drs_lighting, d3drs_specular;
3328 DWORD draw_flags;
3329 D3DCOLOR color;
3331 tests[] =
3333 /* Lighting is enabled when D3DVT_VERTEX is used and D3DDP_DONOTLIGHT is not
3334 * set. D3DVT_VERTEX has diffuse = 0xffffffff and specular = 0x00000000, as
3335 * in later d3d versions */
3336 { D3DVT_VERTEX, quad, FALSE, FALSE, 0, 0x0000ff00},
3337 { D3DVT_VERTEX, quad, TRUE, FALSE, 0, 0x0000ff00},
3338 { D3DVT_VERTEX, quad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
3339 { D3DVT_VERTEX, quad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
3340 { D3DVT_VERTEX, quad, FALSE, TRUE, 0, 0x0000ff00},
3341 { D3DVT_VERTEX, quad, TRUE, TRUE, 0, 0x0000ff00},
3342 { D3DVT_VERTEX, quad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
3343 { D3DVT_VERTEX, quad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
3345 { D3DVT_LVERTEX, lquad, FALSE, FALSE, 0, 0x00ff0000},
3346 { D3DVT_LVERTEX, lquad, TRUE, FALSE, 0, 0x00ff0000},
3347 { D3DVT_LVERTEX, lquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
3348 { D3DVT_LVERTEX, lquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
3349 { D3DVT_LVERTEX, lquad, FALSE, TRUE, 0, 0x00ff8080},
3350 { D3DVT_LVERTEX, lquad, TRUE, TRUE, 0, 0x00ff8080},
3351 { D3DVT_LVERTEX, lquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
3352 { D3DVT_LVERTEX, lquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
3354 { D3DVT_TLVERTEX, tlquad, FALSE, FALSE, 0, 0x000000ff},
3355 { D3DVT_TLVERTEX, tlquad, TRUE, FALSE, 0, 0x000000ff},
3356 { D3DVT_TLVERTEX, tlquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
3357 { D3DVT_TLVERTEX, tlquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
3358 { D3DVT_TLVERTEX, tlquad, FALSE, TRUE, 0, 0x008080ff},
3359 { D3DVT_TLVERTEX, tlquad, TRUE, TRUE, 0, 0x008080ff},
3360 { D3DVT_TLVERTEX, tlquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
3361 { D3DVT_TLVERTEX, tlquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
3364 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3365 0, 0, 640, 480, 0, 0, 0, 0);
3366 ddraw = create_ddraw();
3367 ok(!!ddraw, "Failed to create a ddraw object.\n");
3368 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
3370 skip("Failed to create a 3D device, skipping test.\n");
3371 IDirectDraw2_Release(ddraw);
3372 DestroyWindow(window);
3373 return;
3375 hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d);
3376 ok(SUCCEEDED(hr), "Failed to get IDirect3D2 interface, hr %#x.\n", hr);
3378 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
3379 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3381 viewport = create_viewport(device, 0, 0, 640, 480);
3382 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
3383 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
3385 memset(&mat_desc, 0, sizeof(mat_desc));
3386 mat_desc.dwSize = sizeof(mat_desc);
3387 U2(U3(mat_desc).dcvEmissive).g = 1.0f;
3388 hr = IDirect3D2_CreateMaterial(d3d, &emissive, NULL);
3389 ok(SUCCEEDED(hr), "Failed to create material, hr %#x.\n", hr);
3390 hr = IDirect3DMaterial2_SetMaterial(emissive, &mat_desc);
3391 ok(SUCCEEDED(hr), "Failed to set material, hr %#x.\n", hr);
3392 hr = IDirect3DMaterial2_GetHandle(emissive, device, &mat_handle);
3393 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
3394 hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
3395 ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
3396 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
3397 ok(SUCCEEDED(hr), "Failed to disable z test, hr %#x.\n", hr);
3399 background = create_diffuse_material(device, 0.1f, 0.1f, 0.1f, 0.1f);
3400 hr = IDirect3DMaterial2_GetHandle(background, device, &mat_handle);
3401 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
3402 hr = IDirect3DViewport2_SetBackground(viewport, mat_handle);
3403 ok(SUCCEEDED(hr), "Failed to set background material, hr %#x.\n", hr);
3405 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, &rs);
3406 ok(SUCCEEDED(hr), "Failed to get specularenable render state, hr %#x.\n", hr);
3407 ok(rs == TRUE, "Initial D3DRENDERSTATE_SPECULARENABLE is %#x, expected TRUE.\n", rs);
3409 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
3411 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
3412 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
3414 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, tests[i].d3drs_lighting);
3415 ok(SUCCEEDED(hr), "Failed to set lighting render state, hr %#x.\n", hr);
3416 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE,
3417 tests[i].d3drs_specular);
3418 ok(SUCCEEDED(hr), "Failed to set specularenable render state, hr %#x.\n", hr);
3420 hr = IDirect3DDevice2_BeginScene(device);
3421 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3422 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
3423 tests[i].vertextype, tests[i].data, 4, tests[i].draw_flags | D3DDP_WAIT);
3424 hr = IDirect3DDevice2_EndScene(device);
3425 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3427 color = get_surface_color(rt, 320, 240);
3428 ok(compare_color(color, tests[i].color, 1),
3429 "Got unexpected color 0x%08x, expected 0x%08x, test %u.\n",
3430 color, tests[i].color, i);
3433 IDirect3DMaterial2_Release(background);
3434 IDirect3DMaterial2_Release(emissive);
3435 IDirectDrawSurface_Release(rt);
3436 IDirect3DDevice2_Release(device);
3437 IDirect3D2_Release(d3d);
3438 ref = IDirectDraw2_Release(ddraw);
3439 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
3440 DestroyWindow(window);
3443 static struct
3445 BOOL received;
3446 IDirectDraw2 *ddraw;
3447 HWND window;
3448 DWORD coop_level;
3449 } activateapp_testdata;
3451 static LRESULT CALLBACK activateapp_test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
3453 if (message == WM_ACTIVATEAPP)
3455 if (activateapp_testdata.ddraw)
3457 HRESULT hr;
3458 activateapp_testdata.received = FALSE;
3459 hr = IDirectDraw2_SetCooperativeLevel(activateapp_testdata.ddraw,
3460 activateapp_testdata.window, activateapp_testdata.coop_level);
3461 ok(SUCCEEDED(hr), "Recursive SetCooperativeLevel call failed, hr %#x.\n", hr);
3462 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP during recursive SetCooperativeLevel call.\n");
3464 activateapp_testdata.received = TRUE;
3467 return DefWindowProcA(hwnd, message, wparam, lparam);
3470 static void test_coop_level_activateapp(void)
3472 IDirectDraw2 *ddraw;
3473 HRESULT hr;
3474 HWND window;
3475 WNDCLASSA wc = {0};
3476 DDSURFACEDESC ddsd;
3477 IDirectDrawSurface *surface;
3479 ddraw = create_ddraw();
3480 ok(!!ddraw, "Failed to create a ddraw object.\n");
3482 wc.lpfnWndProc = activateapp_test_proc;
3483 wc.lpszClassName = "ddraw_test_wndproc_wc";
3484 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3486 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
3487 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
3489 /* Exclusive with window already active. */
3490 SetActiveWindow(window);
3491 activateapp_testdata.received = FALSE;
3492 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3493 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3494 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP although window was already active.\n");
3495 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3496 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3498 /* Exclusive with window not active. */
3499 SetActiveWindow(NULL);
3500 activateapp_testdata.received = FALSE;
3501 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3502 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3503 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
3504 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3505 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3507 /* Normal with window not active, then exclusive with the same window. */
3508 SetActiveWindow(NULL);
3509 activateapp_testdata.received = FALSE;
3510 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3511 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3512 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP when setting DDSCL_NORMAL.\n");
3513 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3514 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3515 /* Except in the first SetCooperativeLevel call, Windows XP randomly does not send
3516 * WM_ACTIVATEAPP. Windows 7 sends the message reliably. Mark the XP behavior broken. */
3517 ok(activateapp_testdata.received || broken(!activateapp_testdata.received),
3518 "Expected WM_ACTIVATEAPP, but did not receive it.\n");
3519 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3520 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3522 /* Recursive set of DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. */
3523 SetActiveWindow(NULL);
3524 activateapp_testdata.received = FALSE;
3525 activateapp_testdata.ddraw = ddraw;
3526 activateapp_testdata.window = window;
3527 activateapp_testdata.coop_level = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
3528 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3529 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3530 ok(activateapp_testdata.received || broken(!activateapp_testdata.received),
3531 "Expected WM_ACTIVATEAPP, but did not receive it.\n");
3532 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3533 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3535 /* The recursive call seems to have some bad effect on native ddraw, despite (apparently)
3536 * succeeding. Another switch to exclusive and back to normal is needed to release the
3537 * window properly. Without doing this, SetCooperativeLevel(EXCLUSIVE) will not send
3538 * WM_ACTIVATEAPP messages. */
3539 activateapp_testdata.ddraw = NULL;
3540 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3541 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3542 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3543 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3545 /* Setting DDSCL_NORMAL with recursive invocation. */
3546 SetActiveWindow(NULL);
3547 activateapp_testdata.received = FALSE;
3548 activateapp_testdata.ddraw = ddraw;
3549 activateapp_testdata.window = window;
3550 activateapp_testdata.coop_level = DDSCL_NORMAL;
3551 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3552 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3553 ok(activateapp_testdata.received || broken(!activateapp_testdata.received),
3554 "Expected WM_ACTIVATEAPP, but did not receive it.\n");
3556 /* DDraw is in exlusive mode now. */
3557 memset(&ddsd, 0, sizeof(ddsd));
3558 ddsd.dwSize = sizeof(ddsd);
3559 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
3560 ddsd.dwBackBufferCount = 1;
3561 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
3562 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
3563 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
3564 IDirectDrawSurface_Release(surface);
3566 /* Recover again, just to be sure. */
3567 activateapp_testdata.ddraw = NULL;
3568 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3569 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3570 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3571 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3573 DestroyWindow(window);
3574 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
3575 IDirectDraw2_Release(ddraw);
3578 struct format_support_check
3580 const DDPIXELFORMAT *format;
3581 BOOL supported;
3584 static HRESULT WINAPI test_unsupported_formats_cb(DDSURFACEDESC *desc, void *ctx)
3586 struct format_support_check *format = ctx;
3588 if (!memcmp(format->format, &desc->ddpfPixelFormat, sizeof(*format->format)))
3590 format->supported = TRUE;
3591 return DDENUMRET_CANCEL;
3594 return DDENUMRET_OK;
3597 static void test_unsupported_formats(void)
3599 HRESULT hr;
3600 BOOL expect_success;
3601 HWND window;
3602 IDirectDraw2 *ddraw;
3603 IDirect3DDevice2 *device;
3604 IDirectDrawSurface *surface;
3605 DDSURFACEDESC ddsd;
3606 unsigned int i, j;
3607 DWORD expected_caps;
3608 static const struct
3610 const char *name;
3611 DDPIXELFORMAT fmt;
3613 formats[] =
3616 "D3DFMT_A8R8G8B8",
3618 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
3619 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
3623 "D3DFMT_P8",
3625 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
3626 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
3630 static const DWORD caps[] = {0, DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY};
3632 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3633 0, 0, 640, 480, 0, 0, 0, 0);
3634 ddraw = create_ddraw();
3635 ok(!!ddraw, "Failed to create a ddraw object.\n");
3636 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
3638 skip("Failed to create a 3D device, skipping test.\n");
3639 IDirectDraw2_Release(ddraw);
3640 DestroyWindow(window);
3641 return;
3644 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
3646 struct format_support_check check = {&formats[i].fmt, FALSE};
3647 hr = IDirect3DDevice2_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
3648 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
3650 for (j = 0; j < sizeof(caps) / sizeof(*caps); j++)
3652 memset(&ddsd, 0, sizeof(ddsd));
3653 ddsd.dwSize = sizeof(ddsd);
3654 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
3655 ddsd.ddpfPixelFormat = formats[i].fmt;
3656 ddsd.dwWidth = 4;
3657 ddsd.dwHeight = 4;
3658 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | caps[j];
3660 if (caps[j] & DDSCAPS_VIDEOMEMORY && !check.supported)
3661 expect_success = FALSE;
3662 else
3663 expect_success = TRUE;
3665 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
3666 ok(SUCCEEDED(hr) == expect_success,
3667 "Got unexpected hr %#x for format %s, caps %#x, expected %s.\n",
3668 hr, formats[i].name, caps[j], expect_success ? "success" : "failure");
3669 if (FAILED(hr))
3670 continue;
3672 memset(&ddsd, 0, sizeof(ddsd));
3673 ddsd.dwSize = sizeof(ddsd);
3674 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &ddsd);
3675 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3677 if (caps[j] & DDSCAPS_VIDEOMEMORY)
3678 expected_caps = DDSCAPS_VIDEOMEMORY;
3679 else if (caps[j] & DDSCAPS_SYSTEMMEMORY)
3680 expected_caps = DDSCAPS_SYSTEMMEMORY;
3681 else if (check.supported)
3682 expected_caps = DDSCAPS_VIDEOMEMORY;
3683 else
3684 expected_caps = DDSCAPS_SYSTEMMEMORY;
3686 ok(ddsd.ddsCaps.dwCaps & expected_caps,
3687 "Expected capability %#x, format %s, input cap %#x.\n",
3688 expected_caps, formats[i].name, caps[j]);
3690 IDirectDrawSurface_Release(surface);
3694 IDirect3DDevice2_Release(device);
3695 IDirectDraw2_Release(ddraw);
3696 DestroyWindow(window);
3699 static void test_rt_caps(void)
3701 PALETTEENTRY palette_entries[256];
3702 IDirectDrawPalette *palette;
3703 IDirect3DDevice2 *device;
3704 IDirectDraw2 *ddraw;
3705 DWORD z_depth = 0;
3706 IDirect3D2 *d3d;
3707 unsigned int i;
3708 ULONG refcount;
3709 HWND window;
3710 HRESULT hr;
3712 static const DDPIXELFORMAT p8_fmt =
3714 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
3715 {8}, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000},
3718 static const struct
3720 const DDPIXELFORMAT *pf;
3721 DWORD caps_in;
3722 DWORD caps_out;
3723 HRESULT create_device_hr;
3724 HRESULT set_rt_hr;
3725 HRESULT alternative_set_rt_hr;
3726 BOOL create_may_fail;
3728 test_data[] =
3731 NULL,
3732 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
3733 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3734 D3D_OK,
3735 D3D_OK,
3736 D3D_OK,
3737 FALSE,
3740 NULL,
3741 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
3742 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3743 D3D_OK,
3744 D3D_OK,
3745 D3D_OK,
3746 FALSE,
3749 NULL,
3750 DDSCAPS_OFFSCREENPLAIN,
3751 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3752 DDERR_INVALIDCAPS,
3753 DDERR_INVALIDCAPS,
3754 DDERR_INVALIDCAPS,
3755 FALSE,
3758 NULL,
3759 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3760 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3761 D3DERR_SURFACENOTINVIDMEM,
3762 D3D_OK,
3763 D3D_OK,
3764 FALSE,
3767 NULL,
3768 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3769 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3770 DDERR_INVALIDCAPS,
3771 DDERR_INVALIDCAPS,
3772 DDERR_INVALIDCAPS,
3773 FALSE,
3776 NULL,
3777 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
3778 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3779 D3D_OK,
3780 D3D_OK,
3781 D3D_OK,
3782 FALSE,
3785 NULL,
3786 DDSCAPS_3DDEVICE,
3787 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3788 D3D_OK,
3789 D3D_OK,
3790 D3D_OK,
3791 FALSE,
3794 NULL,
3796 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3797 DDERR_INVALIDCAPS,
3798 DDERR_INVALIDCAPS,
3799 DDERR_INVALIDCAPS,
3800 FALSE,
3803 NULL,
3804 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3805 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3806 D3DERR_SURFACENOTINVIDMEM,
3807 D3D_OK,
3808 D3D_OK,
3809 FALSE,
3812 NULL,
3813 DDSCAPS_SYSTEMMEMORY,
3814 DDSCAPS_SYSTEMMEMORY,
3815 DDERR_INVALIDCAPS,
3816 DDERR_INVALIDCAPS,
3817 DDERR_INVALIDCAPS,
3818 FALSE,
3821 &p8_fmt,
3823 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3824 DDERR_INVALIDCAPS,
3825 DDERR_INVALIDCAPS,
3826 DDERR_INVALIDCAPS,
3827 FALSE,
3830 &p8_fmt,
3831 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
3832 ~0U /* AMD r200 */,
3833 DDERR_NOPALETTEATTACHED,
3834 DDERR_INVALIDCAPS,
3835 DDERR_INVALIDCAPS,
3836 FALSE,
3839 &p8_fmt,
3840 DDSCAPS_OFFSCREENPLAIN,
3841 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3842 DDERR_INVALIDCAPS,
3843 DDERR_INVALIDCAPS,
3844 DDERR_INVALIDCAPS,
3845 FALSE,
3848 &p8_fmt,
3849 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3850 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3851 DDERR_NOPALETTEATTACHED,
3852 DDERR_INVALIDCAPS,
3853 DDERR_INVALIDCAPS,
3854 FALSE,
3857 &p8_fmt,
3858 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3859 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3860 DDERR_INVALIDCAPS,
3861 DDERR_INVALIDCAPS,
3862 DDERR_INVALIDCAPS,
3863 FALSE,
3866 NULL,
3867 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
3868 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
3869 DDERR_INVALIDCAPS,
3870 DDERR_INVALIDPIXELFORMAT,
3871 DDERR_INVALIDCAPS,
3872 TRUE /* AMD Evergreen */,
3875 NULL,
3876 DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
3877 ~0U /* AMD Evergreen */,
3878 DDERR_INVALIDCAPS,
3879 DDERR_INVALIDPIXELFORMAT,
3880 DDERR_INVALIDCAPS,
3881 FALSE,
3884 NULL,
3885 DDSCAPS_ZBUFFER,
3886 ~0U /* AMD Evergreen */,
3887 DDERR_INVALIDCAPS,
3888 DDERR_INVALIDCAPS,
3889 DDERR_INVALIDCAPS,
3890 FALSE,
3893 NULL,
3894 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
3895 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
3896 DDERR_INVALIDCAPS,
3897 DDERR_INVALIDPIXELFORMAT,
3898 DDERR_INVALIDPIXELFORMAT,
3899 TRUE /* Nvidia Kepler */,
3902 NULL,
3903 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
3904 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
3905 DDERR_INVALIDCAPS,
3906 DDERR_INVALIDCAPS,
3907 DDERR_INVALIDCAPS,
3908 TRUE /* Nvidia Kepler */,
3912 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3913 0, 0, 640, 480, 0, 0, 0, 0);
3914 ddraw = create_ddraw();
3915 ok(!!ddraw, "Failed to create a ddraw object.\n");
3916 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
3918 skip("Failed to create a 3D device, skipping test.\n");
3919 IDirectDraw2_Release(ddraw);
3920 DestroyWindow(window);
3921 return;
3923 z_depth = get_device_z_depth(device);
3924 ok(!!z_depth, "Failed to get device z depth.\n");
3925 IDirect3DDevice2_Release(device);
3927 if (FAILED(hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d)))
3929 skip("D3D interface is not available, skipping test.\n");
3930 goto done;
3933 memset(palette_entries, 0, sizeof(palette_entries));
3934 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
3935 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
3937 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
3939 IDirectDrawSurface *surface, *rt, *expected_rt, *tmp;
3940 DDSURFACEDESC surface_desc;
3941 IDirect3DDevice2 *device;
3943 memset(&surface_desc, 0, sizeof(surface_desc));
3944 surface_desc.dwSize = sizeof(surface_desc);
3945 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3946 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
3947 if (test_data[i].pf)
3949 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
3950 surface_desc.ddpfPixelFormat = *test_data[i].pf;
3952 if (test_data[i].caps_in & DDSCAPS_ZBUFFER)
3954 surface_desc.dwFlags |= DDSD_ZBUFFERBITDEPTH;
3955 U2(surface_desc).dwZBufferBitDepth = z_depth;
3957 surface_desc.dwWidth = 640;
3958 surface_desc.dwHeight = 480;
3959 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
3960 ok(SUCCEEDED(hr) || broken(test_data[i].create_may_fail),
3961 "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
3962 i, test_data[i].caps_in, hr);
3963 if (FAILED(hr))
3964 continue;
3966 memset(&surface_desc, 0, sizeof(surface_desc));
3967 surface_desc.dwSize = sizeof(surface_desc);
3968 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
3969 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
3970 ok(test_data[i].caps_out == ~0U || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out,
3971 "Test %u: Got unexpected caps %#x, expected %#x.\n",
3972 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
3974 hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device);
3975 ok(hr == test_data[i].create_device_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n",
3976 i, hr, test_data[i].create_device_hr);
3977 if (FAILED(hr))
3979 if (hr == DDERR_NOPALETTEATTACHED)
3981 hr = IDirectDrawSurface_SetPalette(surface, palette);
3982 ok(SUCCEEDED(hr), "Test %u: Failed to set palette, hr %#x.\n", i, hr);
3983 hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device);
3984 if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
3985 ok(hr == DDERR_INVALIDPIXELFORMAT, "Test %u: Got unexpected hr %#x.\n", i, hr);
3986 else
3987 ok(hr == D3DERR_SURFACENOTINVIDMEM, "Test %u: Got unexpected hr %#x.\n", i, hr);
3989 IDirectDrawSurface_Release(surface);
3991 memset(&surface_desc, 0, sizeof(surface_desc));
3992 surface_desc.dwSize = sizeof(surface_desc);
3993 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3994 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
3995 surface_desc.dwWidth = 640;
3996 surface_desc.dwHeight = 480;
3997 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
3998 ok(SUCCEEDED(hr), "Test %u: Failed to create surface, hr %#x.\n", i, hr);
4000 hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device);
4001 ok(SUCCEEDED(hr), "Test %u: Failed to create device, hr %#x.\n", i, hr);
4004 memset(&surface_desc, 0, sizeof(surface_desc));
4005 surface_desc.dwSize = sizeof(surface_desc);
4006 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4007 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
4008 if (test_data[i].pf)
4010 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
4011 surface_desc.ddpfPixelFormat = *test_data[i].pf;
4013 if (test_data[i].caps_in & DDSCAPS_ZBUFFER)
4015 surface_desc.dwFlags |= DDSD_ZBUFFERBITDEPTH;
4016 U2(surface_desc).dwZBufferBitDepth = z_depth;
4018 surface_desc.dwWidth = 640;
4019 surface_desc.dwHeight = 480;
4020 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &rt, NULL);
4021 ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
4022 i, test_data[i].caps_in, hr);
4024 hr = IDirect3DDevice2_SetRenderTarget(device, rt, 0);
4025 ok(hr == test_data[i].set_rt_hr || broken(hr == test_data[i].alternative_set_rt_hr),
4026 "Test %u: Got unexpected hr %#x, expected %#x.\n",
4027 i, hr, test_data[i].set_rt_hr);
4028 if (SUCCEEDED(hr) || hr == DDERR_INVALIDPIXELFORMAT)
4029 expected_rt = rt;
4030 else
4031 expected_rt = surface;
4033 /* It appears the surface is set as render target in this case, but no
4034 * reference is taken. */
4035 if (hr == DDERR_INVALIDPIXELFORMAT)
4037 refcount = IDirectDrawSurface_AddRef(rt);
4038 ok(refcount == 2, "Test %u: Got unexpected refcount %u.\n", i, refcount);
4041 hr = IDirect3DDevice2_GetRenderTarget(device, &tmp);
4042 ok(SUCCEEDED(hr), "Test %u: Failed to get render target, hr %#x.\n", i, hr);
4043 ok(tmp == expected_rt, "Test %u: Got unexpected rt %p.\n", i, tmp);
4045 IDirectDrawSurface_Release(tmp);
4046 IDirectDrawSurface_Release(rt);
4047 refcount = IDirect3DDevice2_Release(device);
4048 ok(refcount == 0, "Test %u: The device was not properly freed, refcount %u.\n", i, refcount);
4049 refcount = IDirectDrawSurface_Release(surface);
4050 ok(refcount == 0, "Test %u: The surface was not properly freed, refcount %u.\n", i, refcount);
4053 IDirectDrawPalette_Release(palette);
4054 IDirect3D2_Release(d3d);
4056 done:
4057 refcount = IDirectDraw2_Release(ddraw);
4058 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
4059 DestroyWindow(window);
4062 static void test_primary_caps(void)
4064 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
4065 IDirectDrawSurface *surface;
4066 DDSURFACEDESC surface_desc;
4067 IDirectDraw2 *ddraw;
4068 unsigned int i;
4069 ULONG refcount;
4070 HWND window;
4071 HRESULT hr;
4073 static const struct
4075 DWORD coop_level;
4076 DWORD caps_in;
4077 DWORD back_buffer_count;
4078 HRESULT hr;
4079 DWORD caps_out;
4081 test_data[] =
4084 DDSCL_NORMAL,
4085 DDSCAPS_PRIMARYSURFACE,
4086 ~0u,
4087 DD_OK,
4088 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE,
4091 DDSCL_NORMAL,
4092 DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE,
4093 ~0u,
4094 DDERR_INVALIDCAPS,
4095 ~0u,
4098 DDSCL_NORMAL,
4099 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
4100 ~0u,
4101 DDERR_INVALIDCAPS,
4102 ~0u,
4105 DDSCL_NORMAL,
4106 DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER,
4107 ~0u,
4108 DDERR_INVALIDCAPS,
4109 ~0u,
4112 DDSCL_NORMAL,
4113 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP,
4114 ~0u,
4115 DDERR_INVALIDCAPS,
4116 ~0u,
4119 DDSCL_NORMAL,
4120 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX,
4121 ~0u,
4122 DDERR_INVALIDCAPS,
4123 ~0u,
4126 DDSCL_NORMAL,
4127 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
4128 ~0u,
4129 DDERR_INVALIDCAPS,
4130 ~0u,
4133 DDSCL_NORMAL,
4134 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
4136 DDERR_INVALIDCAPS,
4137 ~0u,
4140 DDSCL_NORMAL,
4141 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
4143 DDERR_NOEXCLUSIVEMODE,
4144 ~0u,
4147 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
4148 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
4150 DDERR_INVALIDCAPS,
4151 ~0u,
4154 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
4155 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
4157 DD_OK,
4158 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX,
4161 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
4162 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER,
4164 DDERR_INVALIDCAPS,
4165 ~0u,
4168 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
4169 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_BACKBUFFER,
4171 DDERR_INVALIDCAPS,
4172 ~0u,
4176 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4177 0, 0, 640, 480, 0, 0, 0, 0);
4178 ddraw = create_ddraw();
4179 ok(!!ddraw, "Failed to create a ddraw object.\n");
4181 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
4183 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, test_data[i].coop_level);
4184 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4186 memset(&surface_desc, 0, sizeof(surface_desc));
4187 surface_desc.dwSize = sizeof(surface_desc);
4188 surface_desc.dwFlags = DDSD_CAPS;
4189 if (test_data[i].back_buffer_count != ~0u)
4190 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
4191 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
4192 surface_desc.dwBackBufferCount = test_data[i].back_buffer_count;
4193 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
4194 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
4195 if (FAILED(hr))
4196 continue;
4198 memset(&surface_desc, 0, sizeof(surface_desc));
4199 surface_desc.dwSize = sizeof(surface_desc);
4200 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
4201 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
4202 ok((surface_desc.ddsCaps.dwCaps & ~placement) == test_data[i].caps_out,
4203 "Test %u: Got unexpected caps %#x, expected %#x.\n",
4204 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
4206 IDirectDrawSurface_Release(surface);
4209 refcount = IDirectDraw2_Release(ddraw);
4210 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
4211 DestroyWindow(window);
4214 static void test_surface_lock(void)
4216 IDirectDraw2 *ddraw;
4217 IDirectDrawSurface *surface;
4218 IDirect3DDevice2 *device;
4219 HRESULT hr;
4220 HWND window;
4221 unsigned int i;
4222 DDSURFACEDESC ddsd;
4223 ULONG refcount;
4224 DWORD z_depth = 0;
4225 static const struct
4227 DWORD caps;
4228 const char *name;
4230 tests[] =
4233 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
4234 "videomemory offscreenplain"
4237 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
4238 "systemmemory offscreenplain"
4241 DDSCAPS_PRIMARYSURFACE,
4242 "primary"
4245 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
4246 "videomemory texture"
4249 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
4250 "systemmemory texture"
4253 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
4254 "render target"
4257 DDSCAPS_ZBUFFER,
4258 "Z buffer"
4262 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4263 0, 0, 640, 480, 0, 0, 0, 0);
4264 ddraw = create_ddraw();
4265 ok(!!ddraw, "Failed to create a ddraw object.\n");
4266 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
4268 skip("Failed to create a 3D device, skipping test.\n");
4269 IDirectDraw2_Release(ddraw);
4270 DestroyWindow(window);
4271 return;
4273 z_depth = get_device_z_depth(device);
4274 ok(!!z_depth, "Failed to get device z depth.\n");
4275 IDirect3DDevice2_Release(device);
4277 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
4279 memset(&ddsd, 0, sizeof(ddsd));
4280 ddsd.dwSize = sizeof(ddsd);
4281 ddsd.dwFlags = DDSD_CAPS;
4282 if (!(tests[i].caps & DDSCAPS_PRIMARYSURFACE))
4284 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
4285 ddsd.dwWidth = 64;
4286 ddsd.dwHeight = 64;
4288 if (tests[i].caps & DDSCAPS_ZBUFFER)
4290 ddsd.dwFlags |= DDSD_ZBUFFERBITDEPTH;
4291 U2(ddsd).dwZBufferBitDepth = z_depth;
4293 ddsd.ddsCaps.dwCaps = tests[i].caps;
4295 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
4296 ok(SUCCEEDED(hr), "Failed to create surface, type %s, hr %#x.\n", tests[i].name, hr);
4298 memset(&ddsd, 0, sizeof(ddsd));
4299 ddsd.dwSize = sizeof(ddsd);
4300 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
4301 ok(SUCCEEDED(hr), "Failed to lock surface, type %s, hr %#x.\n", tests[i].name, hr);
4302 if (SUCCEEDED(hr))
4304 hr = IDirectDrawSurface_Unlock(surface, NULL);
4305 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
4308 IDirectDrawSurface_Release(surface);
4311 refcount = IDirectDraw2_Release(ddraw);
4312 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
4313 DestroyWindow(window);
4316 static void test_surface_discard(void)
4318 IDirectDraw2 *ddraw;
4319 HRESULT hr;
4320 HWND window;
4321 DDSURFACEDESC ddsd;
4322 IDirectDrawSurface *surface, *primary;
4323 void *addr;
4324 static const struct
4326 DWORD caps;
4327 BOOL discard;
4329 tests[] =
4331 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, TRUE},
4332 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, FALSE},
4333 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, TRUE},
4334 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, FALSE},
4336 unsigned int i;
4338 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4339 0, 0, 640, 480, 0, 0, 0, 0);
4340 ddraw = create_ddraw();
4341 ok(!!ddraw, "Failed to create a ddraw object.\n");
4342 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4343 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4345 memset(&ddsd, 0, sizeof(ddsd));
4346 ddsd.dwSize = sizeof(ddsd);
4347 ddsd.dwFlags = DDSD_CAPS;
4348 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4349 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
4351 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
4353 BOOL discarded;
4355 memset(&ddsd, 0, sizeof(ddsd));
4356 ddsd.dwSize = sizeof(ddsd);
4357 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4358 ddsd.ddsCaps.dwCaps = tests[i].caps;
4359 ddsd.dwWidth = 64;
4360 ddsd.dwHeight = 64;
4361 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
4362 if (FAILED(hr))
4364 skip("Failed to create surface, skipping.\n");
4365 continue;
4368 memset(&ddsd, 0, sizeof(ddsd));
4369 ddsd.dwSize = sizeof(ddsd);
4370 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
4371 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
4372 addr = ddsd.lpSurface;
4373 hr = IDirectDrawSurface_Unlock(surface, NULL);
4374 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4376 memset(&ddsd, 0, sizeof(ddsd));
4377 ddsd.dwSize = sizeof(ddsd);
4378 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL);
4379 ok(SUCCEEDED(hr) , "Failed to lock surface, hr %#x.\n", hr);
4380 discarded = ddsd.lpSurface != addr;
4381 hr = IDirectDrawSurface_Unlock(surface, NULL);
4382 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4384 hr = IDirectDrawSurface_Blt(primary, NULL, surface, NULL, DDBLT_WAIT, NULL);
4385 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
4387 memset(&ddsd, 0, sizeof(ddsd));
4388 ddsd.dwSize = sizeof(ddsd);
4389 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL);
4390 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
4391 discarded |= ddsd.lpSurface != addr;
4392 hr = IDirectDrawSurface_Unlock(surface, NULL);
4393 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4395 IDirectDrawSurface_Release(surface);
4397 /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler,
4398 * AMD r500, evergreen). Windows XP, at least on AMD r200, never changes the pointer. */
4399 ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i);
4402 IDirectDrawSurface_Release(primary);
4403 IDirectDraw2_Release(ddraw);
4404 DestroyWindow(window);
4407 static void test_flip(void)
4409 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
4410 IDirectDrawSurface *primary, *backbuffer1, *backbuffer2, *backbuffer3, *surface;
4411 DDSCAPS caps = {DDSCAPS_FLIP};
4412 DDSURFACEDESC surface_desc;
4413 BOOL sysmem_primary;
4414 IDirectDraw2 *ddraw;
4415 D3DCOLOR color;
4416 ULONG refcount;
4417 HWND window;
4418 DDBLTFX fx;
4419 HRESULT hr;
4421 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4422 0, 0, 640, 480, 0, 0, 0, 0);
4423 ddraw = create_ddraw();
4424 ok(!!ddraw, "Failed to create a ddraw object.\n");
4426 hr = set_display_mode(ddraw, 640, 480);
4427 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
4428 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4429 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4431 memset(&surface_desc, 0, sizeof(surface_desc));
4432 surface_desc.dwSize = sizeof(surface_desc);
4433 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
4434 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
4435 surface_desc.dwBackBufferCount = 3;
4436 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
4437 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4439 memset(&surface_desc, 0, sizeof(surface_desc));
4440 surface_desc.dwSize = sizeof(surface_desc);
4441 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &surface_desc);
4442 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4443 ok((surface_desc.ddsCaps.dwCaps & ~placement)
4444 == (DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX),
4445 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
4446 sysmem_primary = surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
4448 hr = IDirectDrawSurface_GetAttachedSurface(primary, &caps, &backbuffer1);
4449 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
4450 memset(&surface_desc, 0, sizeof(surface_desc));
4451 surface_desc.dwSize = sizeof(surface_desc);
4452 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer1, &surface_desc);
4453 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4454 ok(!surface_desc.dwBackBufferCount, "Got unexpected back buffer count %u.\n", surface_desc.dwBackBufferCount);
4455 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_BACKBUFFER),
4456 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
4458 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer1, &caps, &backbuffer2);
4459 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
4460 memset(&surface_desc, 0, sizeof(surface_desc));
4461 surface_desc.dwSize = sizeof(surface_desc);
4462 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer2, &surface_desc);
4463 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4464 ok(!surface_desc.dwBackBufferCount, "Got unexpected back buffer count %u.\n", surface_desc.dwBackBufferCount);
4465 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX),
4466 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
4468 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer2, &caps, &backbuffer3);
4469 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
4470 memset(&surface_desc, 0, sizeof(surface_desc));
4471 surface_desc.dwSize = sizeof(surface_desc);
4472 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer3, &surface_desc);
4473 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4474 ok(!surface_desc.dwBackBufferCount, "Got unexpected back buffer count %u.\n", surface_desc.dwBackBufferCount);
4475 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX),
4476 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
4478 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer3, &caps, &surface);
4479 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
4480 ok(surface == primary, "Got unexpected surface %p, expected %p.\n", surface, primary);
4481 IDirectDrawSurface_Release(surface);
4483 memset(&surface_desc, 0, sizeof(surface_desc));
4484 surface_desc.dwSize = sizeof(surface_desc);
4485 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4486 surface_desc.ddsCaps.dwCaps = 0;
4487 surface_desc.dwWidth = 640;
4488 surface_desc.dwHeight = 480;
4489 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
4490 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4491 hr = IDirectDrawSurface_Flip(primary, surface, DDFLIP_WAIT);
4492 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
4493 IDirectDrawSurface_Release(surface);
4495 hr = IDirectDrawSurface_Flip(primary, primary, DDFLIP_WAIT);
4496 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
4497 hr = IDirectDrawSurface_Flip(backbuffer1, NULL, DDFLIP_WAIT);
4498 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
4499 hr = IDirectDrawSurface_Flip(backbuffer2, NULL, DDFLIP_WAIT);
4500 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
4501 hr = IDirectDrawSurface_Flip(backbuffer3, NULL, DDFLIP_WAIT);
4502 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
4504 memset(&fx, 0, sizeof(fx));
4505 fx.dwSize = sizeof(fx);
4506 U5(fx).dwFillColor = 0xffff0000;
4507 hr = IDirectDrawSurface_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4508 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
4509 U5(fx).dwFillColor = 0xff00ff00;
4510 hr = IDirectDrawSurface_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4511 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
4512 U5(fx).dwFillColor = 0xff0000ff;
4513 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4514 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
4516 hr = IDirectDrawSurface_Flip(primary, NULL, DDFLIP_WAIT);
4517 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
4518 color = get_surface_color(backbuffer1, 320, 240);
4519 /* The testbot seems to just copy the contents of one surface to all the
4520 * others, instead of properly flipping. */
4521 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
4522 "Got unexpected color 0x%08x.\n", color);
4523 color = get_surface_color(backbuffer2, 320, 240);
4524 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
4525 U5(fx).dwFillColor = 0xffff0000;
4526 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4527 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
4529 hr = IDirectDrawSurface_Flip(primary, NULL, DDFLIP_WAIT);
4530 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
4531 color = get_surface_color(backbuffer1, 320, 240);
4532 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
4533 "Got unexpected color 0x%08x.\n", color);
4534 color = get_surface_color(backbuffer2, 320, 240);
4535 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
4536 U5(fx).dwFillColor = 0xff00ff00;
4537 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4538 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
4540 hr = IDirectDrawSurface_Flip(primary, NULL, DDFLIP_WAIT);
4541 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
4542 color = get_surface_color(backbuffer1, 320, 240);
4543 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
4544 "Got unexpected color 0x%08x.\n", color);
4545 color = get_surface_color(backbuffer2, 320, 240);
4546 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
4547 U5(fx).dwFillColor = 0xff0000ff;
4548 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4549 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
4551 hr = IDirectDrawSurface_Flip(primary, backbuffer1, DDFLIP_WAIT);
4552 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
4553 color = get_surface_color(backbuffer2, 320, 240);
4554 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
4555 "Got unexpected color 0x%08x.\n", color);
4556 color = get_surface_color(backbuffer3, 320, 240);
4557 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
4558 U5(fx).dwFillColor = 0xffff0000;
4559 hr = IDirectDrawSurface_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4560 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
4562 hr = IDirectDrawSurface_Flip(primary, backbuffer2, DDFLIP_WAIT);
4563 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
4564 color = get_surface_color(backbuffer1, 320, 240);
4565 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
4566 color = get_surface_color(backbuffer3, 320, 240);
4567 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
4568 "Got unexpected color 0x%08x.\n", color);
4569 U5(fx).dwFillColor = 0xff00ff00;
4570 hr = IDirectDrawSurface_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4571 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
4573 hr = IDirectDrawSurface_Flip(primary, backbuffer3, DDFLIP_WAIT);
4574 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
4575 color = get_surface_color(backbuffer1, 320, 240);
4576 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
4577 "Got unexpected color 0x%08x.\n", color);
4578 color = get_surface_color(backbuffer2, 320, 240);
4579 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
4581 IDirectDrawSurface_Release(backbuffer3);
4582 IDirectDrawSurface_Release(backbuffer2);
4583 IDirectDrawSurface_Release(backbuffer1);
4584 IDirectDrawSurface_Release(primary);
4585 refcount = IDirectDraw2_Release(ddraw);
4586 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
4587 DestroyWindow(window);
4590 static void reset_ddsd(DDSURFACEDESC *ddsd)
4592 memset(ddsd, 0, sizeof(*ddsd));
4593 ddsd->dwSize = sizeof(*ddsd);
4596 static void test_set_surface_desc(void)
4598 IDirectDraw2 *ddraw;
4599 HWND window;
4600 HRESULT hr;
4601 DDSURFACEDESC ddsd;
4602 IDirectDrawSurface *surface;
4603 IDirectDrawSurface3 *surface3;
4604 BYTE data[16*16*4];
4605 ULONG ref;
4606 unsigned int i;
4607 static const struct
4609 DWORD caps;
4610 BOOL supported;
4611 const char *name;
4613 invalid_caps_tests[] =
4615 {DDSCAPS_VIDEOMEMORY, FALSE, "videomemory plain"},
4616 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, TRUE, "systemmemory texture"},
4617 {DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY, FALSE, "systemmemory primary"},
4620 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4621 0, 0, 640, 480, 0, 0, 0, 0);
4622 ddraw = create_ddraw();
4623 ok(!!ddraw, "Failed to create a ddraw object.\n");
4624 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4625 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4627 reset_ddsd(&ddsd);
4628 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
4629 ddsd.dwWidth = 8;
4630 ddsd.dwHeight = 8;
4631 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
4632 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
4633 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
4634 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
4635 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
4636 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
4637 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
4639 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
4640 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4642 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
4643 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface3 interface, hr %#x.\n", hr);
4644 IDirectDrawSurface_Release(surface);
4646 reset_ddsd(&ddsd);
4647 ddsd.dwFlags = DDSD_LPSURFACE;
4648 ddsd.lpSurface = data;
4649 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4650 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
4652 /* Redundantly setting the same lpSurface is not an error. */
4653 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4654 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
4655 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
4656 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4657 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
4658 ok(ddsd.lpSurface == NULL, "lpSurface is %p, expected NULL.\n", ddsd.lpSurface);
4660 hr = IDirectDrawSurface3_Lock(surface3, NULL, &ddsd, 0, NULL);
4661 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
4662 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
4663 ok(ddsd.lpSurface == data, "lpSurface is %p, expected %p.\n", data, data);
4664 hr = IDirectDrawSurface3_Unlock(surface3, NULL);
4665 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4667 reset_ddsd(&ddsd);
4668 ddsd.dwFlags = DDSD_LPSURFACE;
4669 ddsd.lpSurface = data;
4670 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 1);
4671 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with flags=1 returned %#x.\n", hr);
4673 ddsd.lpSurface = NULL;
4674 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4675 ok(hr == DDERR_INVALIDPARAMS, "Setting lpSurface=NULL returned %#x.\n", hr);
4677 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, NULL, 0);
4678 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with NULL desc returned %#x.\n", hr);
4680 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
4681 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4682 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
4683 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
4685 /* Setting the caps is an error. This also means the original description cannot be reapplied. */
4686 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4687 ok(hr == DDERR_INVALIDPARAMS, "Setting the original desc returned %#x.\n", hr);
4689 ddsd.dwFlags = DDSD_CAPS;
4690 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4691 ok(hr == DDERR_INVALIDPARAMS, "Setting DDSD_CAPS returned %#x.\n", hr);
4693 /* dwCaps = 0 is allowed, but ignored. */
4694 ddsd.dwFlags = DDSD_CAPS | DDSD_LPSURFACE;
4695 ddsd.lpSurface = data;
4696 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4697 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
4698 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
4699 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4700 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
4701 ddsd.ddsCaps.dwCaps = 0;
4702 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4703 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
4705 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
4706 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4707 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
4708 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
4710 /* Setting the height is allowed, but it cannot be set to 0, and only if LPSURFACE is set too. */
4711 reset_ddsd(&ddsd);
4712 ddsd.dwFlags = DDSD_HEIGHT;
4713 ddsd.dwHeight = 16;
4714 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4715 ok(hr == DDERR_INVALIDPARAMS, "Setting height without lpSurface returned %#x.\n", hr);
4717 ddsd.lpSurface = data;
4718 ddsd.dwFlags = DDSD_HEIGHT | DDSD_LPSURFACE;
4719 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4720 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
4722 ddsd.dwHeight = 0;
4723 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4724 ok(hr == DDERR_INVALIDPARAMS, "Setting height=0 returned %#x.\n", hr);
4726 reset_ddsd(&ddsd);
4727 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
4728 ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr);
4729 ok(ddsd.dwWidth == 8, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
4730 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
4732 /* Pitch and width can be set, but only together, and only with LPSURFACE. They must not be 0. */
4733 reset_ddsd(&ddsd);
4734 ddsd.dwFlags = DDSD_PITCH;
4735 U1(ddsd).lPitch = 8 * 4;
4736 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4737 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch without lpSurface or width returned %#x.\n", hr);
4739 ddsd.dwFlags = DDSD_WIDTH;
4740 ddsd.dwWidth = 16;
4741 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4742 ok(hr == DDERR_INVALIDPARAMS, "Setting width without lpSurface or pitch returned %#x.\n", hr);
4744 ddsd.dwFlags = DDSD_PITCH | DDSD_LPSURFACE;
4745 ddsd.lpSurface = data;
4746 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4747 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch and lpSurface without width returned %#x.\n", hr);
4749 ddsd.dwFlags = DDSD_WIDTH | DDSD_LPSURFACE;
4750 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4751 ok(hr == DDERR_INVALIDPARAMS, "Setting width and lpSurface without pitch returned %#x.\n", hr);
4753 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
4754 U1(ddsd).lPitch = 16 * 4;
4755 ddsd.dwWidth = 16;
4756 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4757 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
4759 reset_ddsd(&ddsd);
4760 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
4761 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4762 ok(ddsd.dwWidth == 16, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
4763 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
4764 ok(U1(ddsd).lPitch == 16 * 4, "SetSurfaceDesc: Expected pitch 64, got %u.\n", U1(ddsd).lPitch);
4766 /* The pitch must be 32 bit aligned and > 0, but is not verified for sanity otherwise.
4768 * VMware rejects those calls, but all real drivers accept it. Mark the VMware behavior broken. */
4769 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
4770 U1(ddsd).lPitch = 4 * 4;
4771 ddsd.lpSurface = data;
4772 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4773 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
4775 U1(ddsd).lPitch = 4;
4776 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4777 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
4779 U1(ddsd).lPitch = 16 * 4 + 1;
4780 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4781 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
4783 U1(ddsd).lPitch = 16 * 4 + 3;
4784 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4785 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
4787 U1(ddsd).lPitch = -4;
4788 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4789 ok(hr == DDERR_INVALIDPARAMS, "Setting negative pitch returned %#x.\n", hr);
4791 U1(ddsd).lPitch = 16 * 4;
4792 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4793 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
4795 reset_ddsd(&ddsd);
4796 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
4797 U1(ddsd).lPitch = 0;
4798 ddsd.dwWidth = 16;
4799 ddsd.lpSurface = data;
4800 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4801 ok(hr == DDERR_INVALIDPARAMS, "Setting zero pitch returned %#x.\n", hr);
4803 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
4804 U1(ddsd).lPitch = 16 * 4;
4805 ddsd.dwWidth = 0;
4806 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4807 ok(hr == DDERR_INVALIDPARAMS, "Setting zero width returned %#x.\n", hr);
4809 /* Setting the pixelformat without LPSURFACE is an error, but with LPSURFACE it works. */
4810 ddsd.dwFlags = DDSD_PIXELFORMAT;
4811 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
4812 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
4813 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
4814 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
4815 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
4816 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
4817 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4818 ok(hr == DDERR_INVALIDPARAMS, "Setting the pixel format returned %#x.\n", hr);
4820 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_LPSURFACE;
4821 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4822 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
4824 /* Can't set color keys. */
4825 reset_ddsd(&ddsd);
4826 ddsd.dwFlags = DDSD_CKSRCBLT;
4827 ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff0000;
4828 ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff0000;
4829 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4830 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
4832 ddsd.dwFlags = DDSD_CKSRCBLT | DDSD_LPSURFACE;
4833 ddsd.lpSurface = data;
4834 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4835 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
4837 IDirectDrawSurface3_Release(surface3);
4839 /* SetSurfaceDesc needs systemmemory surfaces.
4841 * As a sidenote, fourcc surfaces aren't allowed in sysmem, thus testing DDSD_LINEARSIZE is moot. */
4842 for (i = 0; i < sizeof(invalid_caps_tests) / sizeof(*invalid_caps_tests); i++)
4844 reset_ddsd(&ddsd);
4845 ddsd.dwFlags = DDSD_CAPS;
4846 ddsd.ddsCaps.dwCaps = invalid_caps_tests[i].caps;
4847 if (!(invalid_caps_tests[i].caps & DDSCAPS_PRIMARYSURFACE))
4849 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
4850 ddsd.dwWidth = 8;
4851 ddsd.dwHeight = 8;
4852 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
4853 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
4854 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
4855 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
4856 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
4857 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
4860 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
4861 ok(SUCCEEDED(hr) || hr == DDERR_NODIRECTDRAWHW, "Failed to create surface, hr %#x.\n", hr);
4862 if (FAILED(hr))
4864 skip("Cannot create a %s surface, skipping vidmem SetSurfaceDesc test.\n",
4865 invalid_caps_tests[i].name);
4866 goto done;
4868 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
4869 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface3 interface, hr %#x.\n", hr);
4870 IDirectDrawSurface_Release(surface);
4872 reset_ddsd(&ddsd);
4873 ddsd.dwFlags = DDSD_LPSURFACE;
4874 ddsd.lpSurface = data;
4875 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4876 if (invalid_caps_tests[i].supported)
4878 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
4880 else
4882 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
4883 invalid_caps_tests[i].name, hr);
4885 /* Check priority of error conditions. */
4886 ddsd.dwFlags = DDSD_WIDTH;
4887 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4888 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
4889 invalid_caps_tests[i].name, hr);
4892 IDirectDrawSurface3_Release(surface3);
4895 done:
4896 ref = IDirectDraw2_Release(ddraw);
4897 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
4898 DestroyWindow(window);
4901 static void test_user_memory_getdc(void)
4903 IDirectDraw2 *ddraw;
4904 HWND window;
4905 HRESULT hr;
4906 DDSURFACEDESC ddsd;
4907 IDirectDrawSurface *surface;
4908 IDirectDrawSurface3 *surface3;
4909 DWORD data[16][16];
4910 ULONG ref;
4911 HDC dc;
4912 unsigned int x, y;
4914 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4915 0, 0, 640, 480, 0, 0, 0, 0);
4916 ddraw = create_ddraw();
4917 ok(!!ddraw, "Failed to create a ddraw object.\n");
4919 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4920 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4922 reset_ddsd(&ddsd);
4923 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
4924 ddsd.dwWidth = 16;
4925 ddsd.dwHeight = 16;
4926 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
4927 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
4928 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
4929 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
4930 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
4931 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
4932 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
4933 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
4934 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4936 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
4937 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface3 interface, hr %#x.\n", hr);
4938 IDirectDrawSurface_Release(surface);
4940 memset(data, 0xaa, sizeof(data));
4941 reset_ddsd(&ddsd);
4942 ddsd.dwFlags = DDSD_LPSURFACE;
4943 ddsd.lpSurface = data;
4944 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4945 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
4947 hr = IDirectDrawSurface3_GetDC(surface3, &dc);
4948 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
4949 BitBlt(dc, 0, 0, 16, 8, NULL, 0, 0, WHITENESS);
4950 BitBlt(dc, 0, 8, 16, 8, NULL, 0, 0, BLACKNESS);
4951 hr = IDirectDrawSurface3_ReleaseDC(surface3, dc);
4952 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
4954 ok(data[0][0] == 0xffffffff, "Expected color 0xffffffff, got %#x.\n", data[0][0]);
4955 ok(data[15][15] == 0x00000000, "Expected color 0x00000000, got %#x.\n", data[15][15]);
4957 ddsd.dwFlags = DDSD_LPSURFACE | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH;
4958 ddsd.lpSurface = data;
4959 ddsd.dwWidth = 4;
4960 ddsd.dwHeight = 8;
4961 U1(ddsd).lPitch = sizeof(*data);
4962 hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4963 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
4965 memset(data, 0xaa, sizeof(data));
4966 hr = IDirectDrawSurface3_GetDC(surface3, &dc);
4967 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
4968 BitBlt(dc, 0, 0, 4, 8, NULL, 0, 0, BLACKNESS);
4969 BitBlt(dc, 1, 1, 2, 2, NULL, 0, 0, WHITENESS);
4970 hr = IDirectDrawSurface3_ReleaseDC(surface3, dc);
4971 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
4973 for (y = 0; y < 4; y++)
4975 for (x = 0; x < 4; x++)
4977 if ((x == 1 || x == 2) && (y == 1 || y == 2))
4978 ok(data[y][x] == 0xffffffff, "Expected color 0xffffffff on position %ux%u, got %#x.\n",
4979 x, y, data[y][x]);
4980 else
4981 ok(data[y][x] == 0x00000000, "Expected color 0xaaaaaaaa on position %ux%u, got %#x.\n",
4982 x, y, data[y][x]);
4985 ok(data[0][5] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 5x0, got %#x.\n",
4986 data[0][5]);
4987 ok(data[7][3] == 0x00000000, "Expected color 0x00000000 on position 3x7, got %#x.\n",
4988 data[7][3]);
4989 ok(data[7][4] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 4x7, got %#x.\n",
4990 data[7][4]);
4991 ok(data[8][0] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 0x8, got %#x.\n",
4992 data[8][0]);
4994 IDirectDrawSurface3_Release(surface3);
4995 ref = IDirectDraw2_Release(ddraw);
4996 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
4997 DestroyWindow(window);
5000 static void test_sysmem_overlay(void)
5002 IDirectDraw2 *ddraw;
5003 HWND window;
5004 HRESULT hr;
5005 DDSURFACEDESC ddsd;
5006 IDirectDrawSurface *surface;
5007 ULONG ref;
5009 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5010 0, 0, 640, 480, 0, 0, 0, 0);
5011 ddraw = create_ddraw();
5012 ok(!!ddraw, "Failed to create a ddraw object.\n");
5014 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5015 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5017 reset_ddsd(&ddsd);
5018 ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
5019 ddsd.dwWidth = 16;
5020 ddsd.dwHeight = 16;
5021 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OVERLAY;
5022 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
5023 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
5024 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
5025 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5026 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5027 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
5028 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL);
5029 ok(hr == DDERR_NOOVERLAYHW, "Got unexpected hr %#x.\n", hr);
5031 ref = IDirectDraw2_Release(ddraw);
5032 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
5033 DestroyWindow(window);
5036 static void test_primary_palette(void)
5038 DDSCAPS surface_caps = {DDSCAPS_FLIP};
5039 IDirectDrawSurface *primary, *backbuffer;
5040 PALETTEENTRY palette_entries[256];
5041 IDirectDrawPalette *palette, *tmp;
5042 DDSURFACEDESC surface_desc;
5043 IDirectDraw2 *ddraw;
5044 DWORD palette_caps;
5045 ULONG refcount;
5046 HWND window;
5047 HRESULT hr;
5049 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5050 0, 0, 640, 480, 0, 0, 0, 0);
5051 ddraw = create_ddraw();
5052 ok(!!ddraw, "Failed to create a ddraw object.\n");
5053 if (FAILED(hr = IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
5055 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
5056 IDirectDraw2_Release(ddraw);
5057 DestroyWindow(window);
5058 return;
5060 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
5061 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5062 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5064 memset(&surface_desc, 0, sizeof(surface_desc));
5065 surface_desc.dwSize = sizeof(surface_desc);
5066 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
5067 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
5068 surface_desc.dwBackBufferCount = 1;
5069 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
5070 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5071 hr = IDirectDrawSurface_GetAttachedSurface(primary, &surface_caps, &backbuffer);
5072 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
5074 memset(palette_entries, 0, sizeof(palette_entries));
5075 hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_entries, &palette, NULL);
5076 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
5077 refcount = get_refcount((IUnknown *)palette);
5078 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
5080 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
5081 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
5082 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
5084 hr = IDirectDrawSurface_SetPalette(primary, palette);
5085 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
5086 refcount = get_refcount((IUnknown *)palette);
5087 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
5089 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
5090 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
5091 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE | DDPCAPS_ALLOW256),
5092 "Got unexpected palette caps %#x.\n", palette_caps);
5094 hr = IDirectDrawSurface_SetPalette(primary, NULL);
5095 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
5096 refcount = get_refcount((IUnknown *)palette);
5097 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
5099 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
5100 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
5101 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
5103 hr = IDirectDrawSurface_SetPalette(primary, palette);
5104 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
5105 refcount = get_refcount((IUnknown *)palette);
5106 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
5108 hr = IDirectDrawSurface_GetPalette(primary, &tmp);
5109 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
5110 ok(tmp == palette, "Got unexpected palette %p, expected %p.\n", tmp, palette);
5111 IDirectDrawPalette_Release(tmp);
5112 hr = IDirectDrawSurface_GetPalette(backbuffer, &tmp);
5113 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
5115 refcount = IDirectDrawPalette_Release(palette);
5116 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
5117 refcount = IDirectDrawPalette_Release(palette);
5118 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5120 /* Note that this only seems to work when the palette is attached to the
5121 * primary surface. When attached to a regular surface, attempting to get
5122 * the palette here will cause an access violation. */
5123 hr = IDirectDrawSurface_GetPalette(primary, &tmp);
5124 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
5126 refcount = IDirectDrawSurface_Release(backbuffer);
5127 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
5128 refcount = IDirectDrawSurface_Release(primary);
5129 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5130 refcount = IDirectDraw2_Release(ddraw);
5131 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5132 DestroyWindow(window);
5135 static HRESULT WINAPI surface_counter(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
5137 UINT *surface_count = context;
5139 ++(*surface_count);
5140 IDirectDrawSurface_Release(surface);
5142 return DDENUMRET_OK;
5145 static void test_surface_attachment(void)
5147 IDirectDrawSurface *surface1, *surface2, *surface3, *surface4;
5148 DDSCAPS caps = {DDSCAPS_TEXTURE};
5149 DDSURFACEDESC surface_desc;
5150 IDirectDraw2 *ddraw;
5151 UINT surface_count;
5152 ULONG refcount;
5153 HWND window;
5154 HRESULT hr;
5156 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5157 0, 0, 640, 480, 0, 0, 0, 0);
5158 ddraw = create_ddraw();
5159 ok(!!ddraw, "Failed to create a ddraw object.\n");
5160 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5161 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5163 memset(&surface_desc, 0, sizeof(surface_desc));
5164 surface_desc.dwSize = sizeof(surface_desc);
5165 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
5166 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
5167 U2(surface_desc).dwMipMapCount = 3;
5168 surface_desc.dwWidth = 128;
5169 surface_desc.dwHeight = 128;
5170 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
5171 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5173 hr = IDirectDrawSurface_GetAttachedSurface(surface1, &caps, &surface2);
5174 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
5175 hr = IDirectDrawSurface_GetAttachedSurface(surface2, &caps, &surface3);
5176 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
5177 hr = IDirectDrawSurface_GetAttachedSurface(surface3, &caps, &surface4);
5178 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
5180 surface_count = 0;
5181 IDirectDrawSurface_EnumAttachedSurfaces(surface1, &surface_count, surface_counter);
5182 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
5183 surface_count = 0;
5184 IDirectDrawSurface_EnumAttachedSurfaces(surface2, &surface_count, surface_counter);
5185 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
5186 surface_count = 0;
5187 IDirectDrawSurface_EnumAttachedSurfaces(surface3, &surface_count, surface_counter);
5188 ok(!surface_count, "Got unexpected surface_count %u.\n", surface_count);
5190 memset(&surface_desc, 0, sizeof(surface_desc));
5191 surface_desc.dwSize = sizeof(surface_desc);
5192 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5193 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5194 surface_desc.dwWidth = 16;
5195 surface_desc.dwHeight = 16;
5196 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
5197 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5199 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
5200 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5201 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
5202 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5203 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface4);
5204 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5205 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface3);
5206 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5207 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface4);
5208 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5209 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface2);
5210 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5212 IDirectDrawSurface_Release(surface4);
5214 memset(&surface_desc, 0, sizeof(surface_desc));
5215 surface_desc.dwSize = sizeof(surface_desc);
5216 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5217 surface_desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
5218 surface_desc.dwWidth = 16;
5219 surface_desc.dwHeight = 16;
5220 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
5221 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5223 if (SUCCEEDED(hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4)))
5225 skip("Running on refrast, skipping some tests.\n");
5226 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface4);
5227 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
5229 else
5231 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5232 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
5233 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5234 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface4);
5235 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5236 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface3);
5237 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5238 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface4);
5239 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5240 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface2);
5241 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5244 IDirectDrawSurface_Release(surface4);
5245 IDirectDrawSurface_Release(surface3);
5246 IDirectDrawSurface_Release(surface2);
5247 IDirectDrawSurface_Release(surface1);
5249 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5250 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5252 /* Try a single primary and two offscreen plain surfaces. */
5253 memset(&surface_desc, 0, sizeof(surface_desc));
5254 surface_desc.dwSize = sizeof(surface_desc);
5255 surface_desc.dwFlags = DDSD_CAPS;
5256 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
5257 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
5258 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5260 memset(&surface_desc, 0, sizeof(surface_desc));
5261 surface_desc.dwSize = sizeof(surface_desc);
5262 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5263 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5264 surface_desc.dwWidth = GetSystemMetrics(SM_CXSCREEN);
5265 surface_desc.dwHeight = GetSystemMetrics(SM_CYSCREEN);
5266 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
5267 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5269 memset(&surface_desc, 0, sizeof(surface_desc));
5270 surface_desc.dwSize = sizeof(surface_desc);
5271 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5272 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5273 surface_desc.dwWidth = GetSystemMetrics(SM_CXSCREEN);
5274 surface_desc.dwHeight = GetSystemMetrics(SM_CYSCREEN);
5275 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
5276 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5278 /* This one has a different size. */
5279 memset(&surface_desc, 0, sizeof(surface_desc));
5280 surface_desc.dwSize = sizeof(surface_desc);
5281 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5282 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5283 surface_desc.dwWidth = 128;
5284 surface_desc.dwHeight = 128;
5285 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
5286 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5288 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
5289 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
5290 /* Try the reverse without detaching first. */
5291 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
5292 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
5293 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
5294 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
5296 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
5297 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
5298 /* Try to detach reversed. */
5299 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
5300 ok(hr == DDERR_CANNOTDETACHSURFACE, "Got unexpected hr %#x.\n", hr);
5301 hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface1);
5302 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
5304 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface3);
5305 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
5306 hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface3);
5307 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
5309 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
5310 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5311 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
5312 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
5314 IDirectDrawSurface_Release(surface4);
5315 IDirectDrawSurface_Release(surface3);
5316 IDirectDrawSurface_Release(surface2);
5317 IDirectDrawSurface_Release(surface1);
5319 /* Test DeleteAttachedSurface() and automatic detachment of attached surfaces on release. */
5320 memset(&surface_desc, 0, sizeof(surface_desc));
5321 surface_desc.dwSize = sizeof(surface_desc);
5322 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
5323 surface_desc.dwWidth = 64;
5324 surface_desc.dwHeight = 64;
5325 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
5326 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
5327 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
5328 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 16;
5329 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0xf800;
5330 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x07e0;
5331 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x001f;
5332 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
5333 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5334 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
5335 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5337 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
5338 surface_desc.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
5339 U1(surface_desc.ddpfPixelFormat).dwZBufferBitDepth = 16;
5340 U3(surface_desc.ddpfPixelFormat).dwZBitMask = 0x0000ffff;
5341 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
5342 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5344 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
5345 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
5346 refcount = get_refcount((IUnknown *)surface2);
5347 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
5348 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
5349 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
5351 /* Attaching while already attached to other surface. */
5352 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface2);
5353 todo_wine ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
5354 hr = IDirectDrawSurface_DeleteAttachedSurface(surface3, 0, surface2);
5355 todo_wine ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
5356 IDirectDrawSurface_Release(surface3);
5358 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
5359 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
5360 refcount = get_refcount((IUnknown *)surface2);
5361 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
5363 /* Automatic detachment on release. */
5364 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
5365 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
5366 refcount = get_refcount((IUnknown *)surface2);
5367 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
5368 refcount = IDirectDrawSurface_Release(surface1);
5369 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5370 refcount = IDirectDrawSurface_Release(surface2);
5371 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5372 refcount = IDirectDraw2_Release(ddraw);
5373 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5374 DestroyWindow(window);
5377 static void test_pixel_format(void)
5379 HWND window, window2 = NULL;
5380 HDC hdc, hdc2 = NULL;
5381 HMODULE gl = NULL;
5382 int format, test_format;
5383 PIXELFORMATDESCRIPTOR pfd;
5384 IDirectDraw2 *ddraw = NULL;
5385 IDirectDrawClipper *clipper = NULL;
5386 DDSURFACEDESC ddsd;
5387 IDirectDrawSurface *primary = NULL;
5388 DDBLTFX fx;
5389 HRESULT hr;
5391 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
5392 100, 100, 160, 160, NULL, NULL, NULL, NULL);
5393 if (!window)
5395 skip("Failed to create window\n");
5396 return;
5399 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
5400 100, 100, 160, 160, NULL, NULL, NULL, NULL);
5402 hdc = GetDC(window);
5403 if (!hdc)
5405 skip("Failed to get DC\n");
5406 goto cleanup;
5409 if (window2)
5410 hdc2 = GetDC(window2);
5412 gl = LoadLibraryA("opengl32.dll");
5413 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
5415 format = GetPixelFormat(hdc);
5416 ok(format == 0, "new window has pixel format %d\n", format);
5418 ZeroMemory(&pfd, sizeof(pfd));
5419 pfd.nSize = sizeof(pfd);
5420 pfd.nVersion = 1;
5421 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
5422 pfd.iPixelType = PFD_TYPE_RGBA;
5423 pfd.iLayerType = PFD_MAIN_PLANE;
5424 format = ChoosePixelFormat(hdc, &pfd);
5425 if (format <= 0)
5427 skip("no pixel format available\n");
5428 goto cleanup;
5431 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
5433 skip("failed to set pixel format\n");
5434 goto cleanup;
5437 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
5439 skip("failed to set pixel format on second window\n");
5440 if (hdc2)
5442 ReleaseDC(window2, hdc2);
5443 hdc2 = NULL;
5447 ddraw = create_ddraw();
5448 ok(!!ddraw, "Failed to create a ddraw object.\n");
5450 test_format = GetPixelFormat(hdc);
5451 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
5453 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5454 if (FAILED(hr))
5456 skip("Failed to set cooperative level, hr %#x.\n", hr);
5457 goto cleanup;
5460 test_format = GetPixelFormat(hdc);
5461 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
5463 if (hdc2)
5465 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
5466 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
5467 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window2);
5468 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
5470 test_format = GetPixelFormat(hdc);
5471 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
5473 test_format = GetPixelFormat(hdc2);
5474 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
5477 memset(&ddsd, 0, sizeof(ddsd));
5478 ddsd.dwSize = sizeof(ddsd);
5479 ddsd.dwFlags = DDSD_CAPS;
5480 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
5482 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL);
5483 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
5485 test_format = GetPixelFormat(hdc);
5486 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
5488 if (hdc2)
5490 test_format = GetPixelFormat(hdc2);
5491 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
5494 if (clipper)
5496 hr = IDirectDrawSurface2_SetClipper(primary, clipper);
5497 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
5499 test_format = GetPixelFormat(hdc);
5500 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
5502 test_format = GetPixelFormat(hdc2);
5503 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
5506 memset(&fx, 0, sizeof(fx));
5507 fx.dwSize = sizeof(fx);
5508 hr = IDirectDrawSurface2_Blt(primary, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
5509 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
5511 test_format = GetPixelFormat(hdc);
5512 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
5514 if (hdc2)
5516 test_format = GetPixelFormat(hdc2);
5517 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
5520 cleanup:
5521 if (primary) IDirectDrawSurface2_Release(primary);
5522 if (clipper) IDirectDrawClipper_Release(clipper);
5523 if (ddraw) IDirectDraw2_Release(ddraw);
5524 if (gl) FreeLibrary(gl);
5525 if (hdc) ReleaseDC(window, hdc);
5526 if (hdc2) ReleaseDC(window2, hdc2);
5527 if (window) DestroyWindow(window);
5528 if (window2) DestroyWindow(window2);
5531 static void test_create_surface_pitch(void)
5533 IDirectDrawSurface *surface;
5534 DDSURFACEDESC surface_desc;
5535 IDirectDraw2 *ddraw;
5536 unsigned int i;
5537 ULONG refcount;
5538 HWND window;
5539 HRESULT hr;
5540 void *mem;
5542 static const struct
5544 DWORD placement;
5545 DWORD flags_in;
5546 DWORD pitch_in;
5547 HRESULT hr;
5548 DWORD flags_out;
5549 DWORD pitch_out;
5551 test_data[] =
5553 {DDSCAPS_VIDEOMEMORY, 0, 0, DD_OK,
5554 DDSD_PITCH, 0x100},
5555 {DDSCAPS_VIDEOMEMORY, DDSD_PITCH, 0x104, DD_OK,
5556 DDSD_PITCH, 0x100},
5557 {DDSCAPS_VIDEOMEMORY, DDSD_PITCH, 0x0fc, DD_OK,
5558 DDSD_PITCH, 0x100},
5559 {DDSCAPS_VIDEOMEMORY, DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
5560 0, 0 },
5561 {DDSCAPS_SYSTEMMEMORY, 0, 0, DD_OK,
5562 DDSD_PITCH, 0x100},
5563 {DDSCAPS_SYSTEMMEMORY, DDSD_PITCH, 0x104, DD_OK,
5564 DDSD_PITCH, 0x100},
5565 {DDSCAPS_SYSTEMMEMORY, DDSD_PITCH, 0x0fc, DD_OK,
5566 DDSD_PITCH, 0x100},
5567 {DDSCAPS_SYSTEMMEMORY, DDSD_LPSURFACE, 0, DDERR_INVALIDPARAMS,
5568 0, 0 },
5569 {DDSCAPS_SYSTEMMEMORY, DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDPARAMS,
5570 0, 0 },
5572 DWORD flags_mask = DDSD_PITCH | DDSD_LPSURFACE;
5574 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5575 0, 0, 640, 480, 0, 0, 0, 0);
5576 ddraw = create_ddraw();
5577 ok(!!ddraw, "Failed to create a ddraw object.\n");
5578 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5579 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5581 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((64 * 4) + 4) * 64);
5583 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
5585 memset(&surface_desc, 0, sizeof(surface_desc));
5586 surface_desc.dwSize = sizeof(surface_desc);
5587 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | test_data[i].flags_in;
5588 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | test_data[i].placement;
5589 surface_desc.dwWidth = 64;
5590 surface_desc.dwHeight = 64;
5591 U1(surface_desc).lPitch = test_data[i].pitch_in;
5592 surface_desc.lpSurface = mem;
5593 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
5594 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
5595 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
5596 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
5597 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
5598 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
5599 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5600 ok(hr == test_data[i].hr || (test_data[i].placement == DDSCAPS_VIDEOMEMORY && hr == DDERR_NODIRECTDRAWHW),
5601 "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
5602 if (FAILED(hr))
5603 continue;
5605 memset(&surface_desc, 0, sizeof(surface_desc));
5606 surface_desc.dwSize = sizeof(surface_desc);
5607 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
5608 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
5609 ok((surface_desc.dwFlags & flags_mask) == test_data[i].flags_out,
5610 "Test %u: Got unexpected flags %#x, expected %#x.\n",
5611 i, surface_desc.dwFlags & flags_mask, test_data[i].flags_out);
5612 ok(U1(surface_desc).lPitch == test_data[i].pitch_out,
5613 "Test %u: Got unexpected pitch %u, expected %u.\n",
5614 i, U1(surface_desc).lPitch, test_data[i].pitch_out);
5616 IDirectDrawSurface_Release(surface);
5619 HeapFree(GetProcessHeap(), 0, mem);
5620 refcount = IDirectDraw2_Release(ddraw);
5621 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5622 DestroyWindow(window);
5625 static void test_mipmap_lock(void)
5627 IDirectDrawSurface *surface1;
5628 IDirectDrawSurface2 *surface, *surface2;
5629 DDSURFACEDESC surface_desc;
5630 IDirectDraw2 *ddraw;
5631 ULONG refcount;
5632 HWND window;
5633 HRESULT hr;
5634 DDSCAPS caps = {DDSCAPS_COMPLEX};
5635 DDCAPS hal_caps;
5637 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5638 0, 0, 640, 480, 0, 0, 0, 0);
5639 ddraw = create_ddraw();
5640 ok(!!ddraw, "Failed to create a ddraw object.\n");
5641 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5642 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5644 memset(&hal_caps, 0, sizeof(hal_caps));
5645 hal_caps.dwSize = sizeof(hal_caps);
5646 hr = IDirectDraw2_GetCaps(ddraw, &hal_caps, NULL);
5647 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
5648 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
5650 skip("Mipmapped textures not supported, skipping mipmap lock test.\n");
5651 IDirectDraw2_Release(ddraw);
5652 DestroyWindow(window);
5653 return;
5656 memset(&surface_desc, 0, sizeof(surface_desc));
5657 surface_desc.dwSize = sizeof(surface_desc);
5658 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
5659 surface_desc.dwWidth = 4;
5660 surface_desc.dwHeight = 4;
5661 U2(surface_desc).dwMipMapCount = 2;
5662 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP
5663 | DDSCAPS_SYSTEMMEMORY;
5664 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
5665 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5667 hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface2, (void **)&surface);
5668 ok(SUCCEEDED(hr), "Failed to get IDirectDrawSurface2 interface, hr %#x.\n", hr);
5669 IDirectDrawSurface_Release(surface1);
5670 hr = IDirectDrawSurface2_GetAttachedSurface(surface, &caps, &surface2);
5671 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
5673 memset(&surface_desc, 0, sizeof(surface_desc));
5674 surface_desc.dwSize = sizeof(surface_desc);
5675 hr = IDirectDrawSurface2_Lock(surface, NULL, &surface_desc, 0, NULL);
5676 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5677 memset(&surface_desc, 0, sizeof(surface_desc));
5678 surface_desc.dwSize = sizeof(surface_desc);
5679 hr = IDirectDrawSurface2_Lock(surface2, NULL, &surface_desc, 0, NULL);
5680 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5681 IDirectDrawSurface2_Unlock(surface2, NULL);
5682 IDirectDrawSurface2_Unlock(surface, NULL);
5684 IDirectDrawSurface2_Release(surface2);
5685 IDirectDrawSurface2_Release(surface);
5686 refcount = IDirectDraw2_Release(ddraw);
5687 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
5688 DestroyWindow(window);
5691 START_TEST(ddraw2)
5693 IDirectDraw2 *ddraw;
5695 if (!(ddraw = create_ddraw()))
5697 skip("Failed to create a ddraw object, skipping tests.\n");
5698 return;
5700 IDirectDraw2_Release(ddraw);
5702 test_coop_level_create_device_window();
5703 test_clipper_blt();
5704 test_coop_level_d3d_state();
5705 test_surface_interface_mismatch();
5706 test_coop_level_threaded();
5707 test_depth_blit();
5708 test_texture_load_ckey();
5709 test_viewport();
5710 test_zenable();
5711 test_ck_rgba();
5712 test_ck_default();
5713 test_ck_complex();
5714 test_surface_qi();
5715 test_device_qi();
5716 test_wndproc();
5717 test_window_style();
5718 test_redundant_mode_set();
5719 test_coop_level_mode_set();
5720 test_coop_level_mode_set_multi();
5721 test_initialize();
5722 test_coop_level_surf_create();
5723 test_coop_level_multi_window();
5724 test_clear_rect_count();
5725 test_coop_level_versions();
5726 test_lighting_interface_versions();
5727 test_coop_level_activateapp();
5728 test_unsupported_formats();
5729 test_rt_caps();
5730 test_primary_caps();
5731 test_surface_lock();
5732 test_surface_discard();
5733 test_flip();
5734 test_set_surface_desc();
5735 test_user_memory_getdc();
5736 test_sysmem_overlay();
5737 test_primary_palette();
5738 test_surface_attachment();
5739 test_pixel_format();
5740 test_create_surface_pitch();
5741 test_mipmap_lock();