ddraw/tests: Test that DirectDraw doesn't modify the pixel format of the window it...
[wine/multimedia.git] / dlls / ddraw / tests / ddraw1.c
blobfb98dada719a9c000cd3804224cc757bc4c765ac
1 /*
2 * Copyright 2011-2012 Henri Verbeet for CodeWeavers
3 * Copyright 2012-2013 Stefan Dösinger for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define COBJMACROS
21 #include "wine/test.h"
22 #include "d3d.h"
24 struct create_window_thread_param
26 HWND window;
27 HANDLE window_created;
28 HANDLE destroy_window;
29 HANDLE thread;
32 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
34 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
35 c1 >>= 8; c2 >>= 8;
36 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
37 c1 >>= 8; c2 >>= 8;
38 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
39 c1 >>= 8; c2 >>= 8;
40 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
41 return TRUE;
44 static DWORD WINAPI create_window_thread_proc(void *param)
46 struct create_window_thread_param *p = param;
47 DWORD res;
48 BOOL ret;
50 p->window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
51 0, 0, 640, 480, 0, 0, 0, 0);
52 ret = SetEvent(p->window_created);
53 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
55 for (;;)
57 MSG msg;
59 while (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 D3DCOLOR get_surface_color(IDirectDrawSurface *surface, UINT x, UINT y)
101 RECT rect = {x, y, x + 1, y + 1};
102 DDSURFACEDESC surface_desc;
103 D3DCOLOR color;
104 HRESULT hr;
106 memset(&surface_desc, 0, sizeof(surface_desc));
107 surface_desc.dwSize = sizeof(surface_desc);
109 hr = IDirectDrawSurface_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
110 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
111 if (FAILED(hr))
112 return 0xdeadbeef;
114 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
116 hr = IDirectDrawSurface_Unlock(surface, NULL);
117 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
119 return color;
122 static void emit_process_vertices(void **ptr, WORD base_idx, DWORD vertex_count)
124 D3DINSTRUCTION *inst = *ptr;
125 D3DPROCESSVERTICES *pv = (D3DPROCESSVERTICES *)(inst + 1);
127 inst->bOpcode = D3DOP_PROCESSVERTICES;
128 inst->bSize = sizeof(*pv);
129 inst->wCount = 1;
131 pv->dwFlags = D3DPROCESSVERTICES_COPY;
132 pv->wStart = base_idx;
133 pv->wDest = 0;
134 pv->dwCount = vertex_count;
135 pv->dwReserved = 0;
137 *ptr = pv + 1;
140 static void emit_set_rs(void **ptr, D3DRENDERSTATETYPE state, DWORD value)
142 D3DINSTRUCTION *inst = *ptr;
143 D3DSTATE *rs = (D3DSTATE *)(inst + 1);
145 inst->bOpcode = D3DOP_STATERENDER;
146 inst->bSize = sizeof(*rs);
147 inst->wCount = 1;
149 U1(*rs).drstRenderStateType = state;
150 U2(*rs).dwArg[0] = value;
152 *ptr = rs + 1;
155 static void emit_tquad(void **ptr, WORD base_idx)
157 D3DINSTRUCTION *inst = *ptr;
158 D3DTRIANGLE *tri = (D3DTRIANGLE *)(inst + 1);
160 inst->bOpcode = D3DOP_TRIANGLE;
161 inst->bSize = sizeof(*tri);
162 inst->wCount = 2;
164 U1(*tri).v1 = base_idx;
165 U2(*tri).v2 = base_idx + 1;
166 U3(*tri).v3 = base_idx + 2;
167 tri->wFlags = D3DTRIFLAG_START;
168 ++tri;
170 U1(*tri).v1 = base_idx + 2;
171 U2(*tri).v2 = base_idx + 1;
172 U3(*tri).v3 = base_idx + 3;
173 tri->wFlags = D3DTRIFLAG_ODD;
174 ++tri;
176 *ptr = tri;
179 static void emit_end(void **ptr)
181 D3DINSTRUCTION *inst = *ptr;
183 inst->bOpcode = D3DOP_EXIT;
184 inst->bSize = 0;
185 inst->wCount = 0;
187 *ptr = inst + 1;
190 static void set_execute_data(IDirect3DExecuteBuffer *execute_buffer, UINT vertex_count, UINT offset, UINT len)
192 D3DEXECUTEDATA exec_data;
193 HRESULT hr;
195 memset(&exec_data, 0, sizeof(exec_data));
196 exec_data.dwSize = sizeof(exec_data);
197 exec_data.dwVertexCount = vertex_count;
198 exec_data.dwInstructionOffset = offset;
199 exec_data.dwInstructionLength = len;
200 hr = IDirect3DExecuteBuffer_SetExecuteData(execute_buffer, &exec_data);
201 ok(SUCCEEDED(hr), "Failed to set execute data, hr %#x.\n", hr);
204 static HRESULT CALLBACK enum_z_fmt(GUID *guid, char *description, char *name,
205 D3DDEVICEDESC *hal_desc, D3DDEVICEDESC *hel_desc, void *ctx)
207 DWORD *z_depth = ctx;
209 if (!IsEqualGUID(&IID_IDirect3DHALDevice, guid))
210 return D3DENUMRET_OK;
212 if (hal_desc->dwDeviceZBufferBitDepth & DDBD_32)
213 *z_depth = 32;
214 else if (hal_desc->dwDeviceZBufferBitDepth & DDBD_24)
215 *z_depth = 24;
216 else if (hal_desc->dwDeviceZBufferBitDepth & DDBD_16)
217 *z_depth = 16;
219 return DDENUMRET_OK;
222 static IDirectDraw *create_ddraw(void)
224 IDirectDraw *ddraw;
226 if (FAILED(DirectDrawCreate(NULL, &ddraw, NULL)))
227 return NULL;
229 return ddraw;
232 static IDirect3DDevice *create_device(IDirectDraw *ddraw, HWND window, DWORD coop_level)
234 IDirectDrawSurface *surface, *ds;
235 IDirect3DDevice *device = NULL;
236 DDSURFACEDESC surface_desc;
237 DWORD z_depth = 0;
238 IDirect3D *d3d;
239 HRESULT hr;
241 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, coop_level);
242 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
244 memset(&surface_desc, 0, sizeof(surface_desc));
245 surface_desc.dwSize = sizeof(surface_desc);
246 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
247 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
248 surface_desc.dwWidth = 640;
249 surface_desc.dwHeight = 480;
251 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
252 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
254 if (coop_level & DDSCL_NORMAL)
256 IDirectDrawClipper *clipper;
258 hr = IDirectDraw_CreateClipper(ddraw, 0, &clipper, NULL);
259 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
260 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
261 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
262 hr = IDirectDrawSurface_SetClipper(surface, clipper);
263 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\n", hr);
264 IDirectDrawClipper_Release(clipper);
267 hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d);
268 if (FAILED(hr))
270 IDirectDrawSurface_Release(surface);
271 return NULL;
274 hr = IDirect3D_EnumDevices(d3d, enum_z_fmt, &z_depth);
275 ok(SUCCEEDED(hr), "Failed to enumerate z-formats, hr %#x.\n", hr);
276 IDirect3D_Release(d3d);
277 if (FAILED(hr) || !z_depth)
279 IDirectDrawSurface_Release(surface);
280 return NULL;
283 memset(&surface_desc, 0, sizeof(surface_desc));
284 surface_desc.dwSize = sizeof(surface_desc);
285 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
286 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
287 U2(surface_desc).dwZBufferBitDepth = z_depth;
288 surface_desc.dwWidth = 640;
289 surface_desc.dwHeight = 480;
290 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &ds, NULL);
291 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
292 if (FAILED(hr))
294 IDirectDrawSurface_Release(surface);
295 return NULL;
298 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
299 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
300 IDirectDrawSurface_Release(ds);
301 if (FAILED(hr))
303 IDirectDrawSurface_Release(surface);
304 return NULL;
307 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DHALDevice, (void **)&device);
308 IDirectDrawSurface_Release(surface);
309 if (FAILED(hr))
310 return NULL;
312 return device;
315 static IDirect3DViewport *create_viewport(IDirect3DDevice *device, UINT x, UINT y, UINT w, UINT h)
317 IDirect3DViewport *viewport;
318 D3DVIEWPORT vp;
319 IDirect3D *d3d;
320 HRESULT hr;
322 hr = IDirect3DDevice_GetDirect3D(device, &d3d);
323 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
324 hr = IDirect3D_CreateViewport(d3d, &viewport, NULL);
325 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
326 hr = IDirect3DDevice_AddViewport(device, viewport);
327 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
328 memset(&vp, 0, sizeof(vp));
329 vp.dwSize = sizeof(vp);
330 vp.dwX = x;
331 vp.dwY = y;
332 vp.dwWidth = w;
333 vp.dwHeight = h;
334 vp.dvScaleX = (float)w / 2.0f;
335 vp.dvScaleY = (float)h / 2.0f;
336 vp.dvMaxX = 1.0f;
337 vp.dvMaxY = 1.0f;
338 vp.dvMinZ = 0.0f;
339 vp.dvMaxZ = 1.0f;
340 hr = IDirect3DViewport_SetViewport(viewport, &vp);
341 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
342 IDirect3D_Release(d3d);
344 return viewport;
347 static void viewport_set_background(IDirect3DDevice *device, IDirect3DViewport *viewport,
348 IDirect3DMaterial *material)
350 D3DMATERIALHANDLE material_handle;
351 HRESULT hr;
353 hr = IDirect3DMaterial2_GetHandle(material, device, &material_handle);
354 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
355 hr = IDirect3DViewport2_SetBackground(viewport, material_handle);
356 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
359 static void destroy_viewport(IDirect3DDevice *device, IDirect3DViewport *viewport)
361 HRESULT hr;
363 hr = IDirect3DDevice_DeleteViewport(device, viewport);
364 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
365 IDirect3DViewport_Release(viewport);
368 static IDirect3DMaterial *create_diffuse_material(IDirect3DDevice *device, float r, float g, float b, float a)
370 IDirect3DMaterial *material;
371 D3DMATERIAL mat;
372 IDirect3D *d3d;
373 HRESULT hr;
375 hr = IDirect3DDevice_GetDirect3D(device, &d3d);
376 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
377 hr = IDirect3D_CreateMaterial(d3d, &material, NULL);
378 ok(SUCCEEDED(hr), "Failed to create material, hr %#x.\n", hr);
379 memset(&mat, 0, sizeof(mat));
380 mat.dwSize = sizeof(mat);
381 U1(U(mat).diffuse).r = r;
382 U2(U(mat).diffuse).g = g;
383 U3(U(mat).diffuse).b = b;
384 U4(U(mat).diffuse).a = a;
385 hr = IDirect3DMaterial_SetMaterial(material, &mat);
386 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
387 IDirect3D_Release(d3d);
389 return material;
392 static void destroy_material(IDirect3DMaterial *material)
394 IDirect3DMaterial_Release(material);
397 static const UINT *expect_messages;
399 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
401 if (expect_messages && message == *expect_messages)
402 ++expect_messages;
404 return DefWindowProcA(hwnd, message, wparam, lparam);
407 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
408 * interface. This prevents subsequent SetCooperativeLevel() calls on a
409 * different window from failing with DDERR_HWNDALREADYSET. */
410 static void fix_wndproc(HWND window, LONG_PTR proc)
412 IDirectDraw *ddraw;
413 HRESULT hr;
415 if (!(ddraw = create_ddraw()))
416 return;
418 SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
419 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
420 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
421 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
422 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
424 IDirectDraw_Release(ddraw);
427 static HRESULT CALLBACK restore_callback(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
429 HRESULT hr = IDirectDrawSurface_Restore(surface);
430 ok(SUCCEEDED(hr), "Failed to restore surface, hr %#x.\n", hr);
431 IDirectDrawSurface_Release(surface);
433 return DDENUMRET_OK;
436 static HRESULT restore_surfaces(IDirectDraw *ddraw)
438 return IDirectDraw_EnumSurfaces(ddraw, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
439 NULL, NULL, restore_callback);
442 static void test_coop_level_create_device_window(void)
444 HWND focus_window, device_window;
445 IDirectDraw *ddraw;
446 HRESULT hr;
448 focus_window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
449 0, 0, 640, 480, 0, 0, 0, 0);
450 if (!(ddraw = create_ddraw()))
452 skip("Failed to create a ddraw object, skipping test.\n");
453 DestroyWindow(focus_window);
454 return;
457 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
458 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
459 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
460 ok(!device_window, "Unexpected device window found.\n");
461 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
462 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
463 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
464 ok(!device_window, "Unexpected device window found.\n");
465 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
466 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
467 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
468 ok(!device_window, "Unexpected device window found.\n");
469 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
470 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
471 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
472 ok(!device_window, "Unexpected device window found.\n");
473 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
474 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
475 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
476 ok(!device_window, "Unexpected device window found.\n");
478 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
479 if (broken(hr == DDERR_INVALIDPARAMS))
481 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
482 IDirectDraw_Release(ddraw);
483 DestroyWindow(focus_window);
484 return;
487 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
488 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
489 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
490 ok(!device_window, "Unexpected device window found.\n");
491 hr = IDirectDraw_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
492 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
493 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
494 ok(!device_window, "Unexpected device window found.\n");
496 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
497 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
498 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
499 ok(!device_window, "Unexpected device window found.\n");
500 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
501 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
502 ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
503 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
504 ok(!!device_window, "Device window not found.\n");
506 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
507 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
508 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
509 ok(!device_window, "Unexpected device window found.\n");
510 hr = IDirectDraw_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
511 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
512 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
513 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
514 ok(!!device_window, "Device window not found.\n");
516 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
517 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
518 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
519 ok(!device_window, "Unexpected device window found.\n");
520 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
521 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
522 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
523 ok(!device_window, "Unexpected device window found.\n");
524 hr = IDirectDraw_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
525 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
526 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
527 ok(!device_window, "Unexpected device window found.\n");
528 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
529 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
530 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
531 ok(!!device_window, "Device window not found.\n");
533 IDirectDraw_Release(ddraw);
534 DestroyWindow(focus_window);
537 static void test_clipper_blt(void)
539 IDirectDrawSurface *src_surface, *dst_surface;
540 RECT client_rect, src_rect;
541 IDirectDrawClipper *clipper;
542 DDSURFACEDESC surface_desc;
543 unsigned int i, j, x, y;
544 IDirectDraw *ddraw;
545 RGNDATA *rgn_data;
546 D3DCOLOR color;
547 HRGN r1, r2;
548 HWND window;
549 DDBLTFX fx;
550 HRESULT hr;
551 DWORD *ptr;
552 DWORD ret;
554 static const DWORD src_data[] =
556 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
557 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
558 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
560 static const D3DCOLOR expected1[] =
562 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
563 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
564 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
565 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
567 static const D3DCOLOR expected2[] =
569 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
570 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
571 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
572 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
575 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
576 10, 10, 640, 480, 0, 0, 0, 0);
577 ShowWindow(window, SW_SHOW);
578 if (!(ddraw = create_ddraw()))
580 skip("Failed to create a ddraw object, skipping test.\n");
581 DestroyWindow(window);
582 return;
585 ret = GetClientRect(window, &client_rect);
586 ok(ret, "Failed to get client rect.\n");
587 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
588 ok(ret, "Failed to map client rect.\n");
590 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
591 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
593 hr = IDirectDraw_CreateClipper(ddraw, 0, &clipper, NULL);
594 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
595 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
596 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
597 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
598 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
599 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
600 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
601 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
602 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
603 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
604 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
605 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
606 ok(rgn_data->rdh.nCount >= 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
607 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
608 "Got unexpected bounding rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
609 rgn_data->rdh.rcBound.left, rgn_data->rdh.rcBound.top,
610 rgn_data->rdh.rcBound.right, rgn_data->rdh.rcBound.bottom,
611 client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
612 HeapFree(GetProcessHeap(), 0, rgn_data);
614 r1 = CreateRectRgn(0, 0, 320, 240);
615 ok(!!r1, "Failed to create region.\n");
616 r2 = CreateRectRgn(320, 240, 640, 480);
617 ok(!!r2, "Failed to create region.\n");
618 CombineRgn(r1, r1, r2, RGN_OR);
619 ret = GetRegionData(r1, 0, NULL);
620 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
621 ret = GetRegionData(r1, ret, rgn_data);
622 ok(!!ret, "Failed to get region data.\n");
624 DeleteObject(r2);
625 DeleteObject(r1);
627 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
628 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
629 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
630 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
631 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
632 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
634 HeapFree(GetProcessHeap(), 0, rgn_data);
636 memset(&surface_desc, 0, sizeof(surface_desc));
637 surface_desc.dwSize = sizeof(surface_desc);
638 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
639 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
640 surface_desc.dwWidth = 640;
641 surface_desc.dwHeight = 480;
642 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
643 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
644 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
645 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
646 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
647 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
649 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
650 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
651 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
652 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
654 memset(&fx, 0, sizeof(fx));
655 fx.dwSize = sizeof(fx);
656 hr = IDirectDrawSurface_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
657 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
658 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
659 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
661 hr = IDirectDrawSurface_Lock(src_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
662 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
663 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
664 ptr = surface_desc.lpSurface;
665 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
666 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
667 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
668 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
669 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
671 hr = IDirectDrawSurface_SetClipper(dst_surface, clipper);
672 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
674 SetRect(&src_rect, 1, 1, 5, 2);
675 hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
676 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
677 for (i = 0; i < 4; ++i)
679 for (j = 0; j < 4; ++j)
681 x = 80 * ((2 * j) + 1);
682 y = 60 * ((2 * i) + 1);
683 color = get_surface_color(dst_surface, x, y);
684 ok(compare_color(color, expected1[i * 4 + j], 1),
685 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
689 U5(fx).dwFillColor = 0xff0000ff;
690 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
691 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
692 for (i = 0; i < 4; ++i)
694 for (j = 0; j < 4; ++j)
696 x = 80 * ((2 * j) + 1);
697 y = 60 * ((2 * i) + 1);
698 color = get_surface_color(dst_surface, x, y);
699 ok(compare_color(color, expected2[i * 4 + j], 1),
700 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
704 hr = IDirectDrawSurface_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
705 ok(hr == DDERR_BLTFASTCANTCLIP || broken(hr == E_NOTIMPL /* NT4 */), "Got unexpected hr %#x.\n", hr);
707 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
708 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
709 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
710 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
711 DestroyWindow(window);
712 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
713 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
714 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
715 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
716 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
717 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
718 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
719 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
720 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
721 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
722 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
723 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
725 IDirectDrawSurface_Release(dst_surface);
726 IDirectDrawSurface_Release(src_surface);
727 IDirectDrawClipper_Release(clipper);
728 IDirectDraw_Release(ddraw);
731 static void test_coop_level_d3d_state(void)
733 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
734 IDirectDrawSurface *rt, *surface;
735 IDirect3DMaterial *background;
736 IDirect3DViewport *viewport;
737 IDirect3DDevice *device;
738 D3DMATERIAL material;
739 IDirectDraw *ddraw;
740 D3DCOLOR color;
741 HWND window;
742 HRESULT hr;
744 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
745 0, 0, 640, 480, 0, 0, 0, 0);
746 if (!(ddraw = create_ddraw()))
748 skip("Failed to create a ddraw object, skipping test.\n");
749 DestroyWindow(window);
750 return;
752 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
754 skip("Failed to create a 3D device, skipping test.\n");
755 IDirectDraw_Release(ddraw);
756 DestroyWindow(window);
757 return;
760 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
761 viewport = create_viewport(device, 0, 0, 640, 480);
762 viewport_set_background(device, viewport, background);
764 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
765 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
766 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
767 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
768 color = get_surface_color(rt, 320, 240);
769 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
771 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
772 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
773 hr = IDirectDrawSurface_IsLost(rt);
774 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
775 hr = restore_surfaces(ddraw);
776 ok(SUCCEEDED(hr), "Failed to restore surfaces, hr %#x.\n", hr);
778 memset(&material, 0, sizeof(material));
779 material.dwSize = sizeof(material);
780 U1(U(material).diffuse).r = 0.0f;
781 U2(U(material).diffuse).g = 1.0f;
782 U3(U(material).diffuse).b = 0.0f;
783 U4(U(material).diffuse).a = 1.0f;
784 hr = IDirect3DMaterial_SetMaterial(background, &material);
785 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
787 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&surface);
788 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
789 ok(surface == rt, "Got unexpected surface %p.\n", surface);
790 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
791 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
792 color = get_surface_color(rt, 320, 240);
793 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
795 destroy_viewport(device, viewport);
796 destroy_material(background);
797 IDirectDrawSurface_Release(surface);
798 IDirectDrawSurface_Release(rt);
799 IDirect3DDevice_Release(device);
800 IDirectDraw_Release(ddraw);
801 DestroyWindow(window);
804 static void test_surface_interface_mismatch(void)
806 IDirectDraw *ddraw = NULL;
807 IDirect3D *d3d = NULL;
808 IDirectDrawSurface *surface = NULL, *ds;
809 IDirectDrawSurface3 *surface3 = NULL;
810 IDirect3DDevice *device = NULL;
811 IDirect3DViewport *viewport = NULL;
812 IDirect3DMaterial *background = NULL;
813 DDSURFACEDESC surface_desc;
814 DWORD z_depth = 0;
815 ULONG refcount;
816 HRESULT hr;
817 D3DCOLOR color;
818 HWND window;
819 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
821 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
822 0, 0, 640, 480, 0, 0, 0, 0);
824 if (!(ddraw = create_ddraw()))
826 skip("Failed to create a ddraw object, skipping test.\n");
827 goto cleanup;
830 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
831 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
833 memset(&surface_desc, 0, sizeof(surface_desc));
834 surface_desc.dwSize = sizeof(surface_desc);
835 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
836 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
837 surface_desc.dwWidth = 640;
838 surface_desc.dwHeight = 480;
840 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
841 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
843 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
844 if (FAILED(hr))
846 skip("Failed to get the IDirectDrawSurface3 interface, skipping test.\n");
847 goto cleanup;
850 if (FAILED(hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d)))
852 skip("D3D interface is not available, skipping test.\n");
853 goto cleanup;
856 hr = IDirect3D_EnumDevices(d3d, enum_z_fmt, &z_depth);
857 if (FAILED(hr) || !z_depth)
859 skip("No depth buffer formats available, skipping test.\n");
860 goto cleanup;
863 memset(&surface_desc, 0, sizeof(surface_desc));
864 surface_desc.dwSize = sizeof(surface_desc);
865 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
866 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
867 U2(surface_desc).dwZBufferBitDepth = z_depth;
868 surface_desc.dwWidth = 640;
869 surface_desc.dwHeight = 480;
870 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &ds, NULL);
871 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
872 if (FAILED(hr))
873 goto cleanup;
875 /* Using a different surface interface version still works */
876 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
877 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
878 refcount = IDirectDrawSurface_Release(ds);
879 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
880 if (FAILED(hr))
881 goto cleanup;
883 /* Here too */
884 hr = IDirectDrawSurface3_QueryInterface(surface3, &IID_IDirect3DHALDevice, (void **)&device);
885 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
886 if (FAILED(hr))
887 goto cleanup;
889 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
890 viewport = create_viewport(device, 0, 0, 640, 480);
891 viewport_set_background(device, viewport, background);
893 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
894 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
895 color = get_surface_color(surface, 320, 240);
896 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
898 cleanup:
899 if (viewport)
900 destroy_viewport(device, viewport);
901 if (background)
902 destroy_material(background);
903 if (surface3) IDirectDrawSurface3_Release(surface3);
904 if (surface) IDirectDrawSurface_Release(surface);
905 if (device) IDirect3DDevice_Release(device);
906 if (d3d) IDirect3D_Release(d3d);
907 if (ddraw) IDirectDraw_Release(ddraw);
908 DestroyWindow(window);
911 static void test_coop_level_threaded(void)
913 struct create_window_thread_param p;
914 IDirectDraw *ddraw;
915 HRESULT hr;
917 if (!(ddraw = create_ddraw()))
919 skip("Failed to create a ddraw object, skipping test.\n");
920 return;
922 create_window_thread(&p);
924 hr = IDirectDraw_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
925 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
927 IDirectDraw_Release(ddraw);
928 destroy_window_thread(&p);
931 static ULONG get_refcount(IUnknown *test_iface)
933 IUnknown_AddRef(test_iface);
934 return IUnknown_Release(test_iface);
937 static void test_viewport(void)
939 IDirectDraw *ddraw;
940 IDirect3D *d3d;
941 HRESULT hr;
942 ULONG ref;
943 IDirect3DViewport *viewport, *another_vp;
944 IDirect3DViewport2 *viewport2;
945 IDirect3DViewport3 *viewport3;
946 IDirectDrawGammaControl *gamma;
947 IUnknown *unknown;
948 IDirect3DDevice *device;
949 HWND window;
951 if (!(ddraw = create_ddraw()))
953 skip("Failed to create a ddraw object, skipping test.\n");
954 return;
956 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
957 0, 0, 640, 480, 0, 0, 0, 0);
958 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
960 skip("Failed to create a 3D device, skipping test.\n");
961 IDirectDraw_Release(ddraw);
962 DestroyWindow(window);
963 return;
966 hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d);
967 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
968 ref = get_refcount((IUnknown *) d3d);
969 ok(ref == 2, "IDirect3D refcount is %d\n", ref);
971 hr = IDirect3D_CreateViewport(d3d, &viewport, NULL);
972 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
973 ref = get_refcount((IUnknown *)viewport);
974 ok(ref == 1, "Initial IDirect3DViewport refcount is %u\n", ref);
975 ref = get_refcount((IUnknown *)d3d);
976 ok(ref == 2, "IDirect3D refcount is %u\n", ref);
978 /* E_FAIL return values are returned by Winetestbot Windows NT machines. While not supporting
979 * newer interfaces is legitimate for old ddraw versions, E_FAIL violates Microsoft's rules
980 * for QueryInterface, hence the broken() */
981 gamma = (IDirectDrawGammaControl *)0xdeadbeef;
982 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IDirectDrawGammaControl, (void **)&gamma);
983 ok(hr == E_NOINTERFACE || broken(hr == E_FAIL), "Got unexpected hr %#x.\n", hr);
984 ok(gamma == NULL, "Interface not set to NULL by failed QI call: %p\n", gamma);
985 if (SUCCEEDED(hr)) IDirectDrawGammaControl_Release(gamma);
986 /* NULL iid: Segfaults */
988 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IDirect3DViewport2, (void **)&viewport2);
989 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE || broken(hr == E_FAIL),
990 "Failed to QI IDirect3DViewport2, hr %#x.\n", hr);
991 if (viewport2)
993 ref = get_refcount((IUnknown *)viewport);
994 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
995 ref = get_refcount((IUnknown *)viewport2);
996 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
997 IDirect3DViewport2_Release(viewport2);
998 viewport2 = NULL;
1001 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IDirect3DViewport3, (void **)&viewport3);
1002 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE || broken(hr == E_FAIL),
1003 "Failed to QI IDirect3DViewport3, hr %#x.\n", hr);
1004 if (viewport3)
1006 ref = get_refcount((IUnknown *)viewport);
1007 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
1008 ref = get_refcount((IUnknown *)viewport3);
1009 ok(ref == 2, "IDirect3DViewport3 refcount is %u\n", ref);
1010 IDirect3DViewport3_Release(viewport3);
1013 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IUnknown, (void **)&unknown);
1014 ok(SUCCEEDED(hr), "Failed to QI IUnknown, hr %#x.\n", hr);
1015 if (unknown)
1017 ref = get_refcount((IUnknown *)viewport);
1018 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
1019 ref = get_refcount(unknown);
1020 ok(ref == 2, "IUnknown refcount is %u\n", ref);
1021 IUnknown_Release(unknown);
1024 /* AddViewport(NULL): Segfault */
1025 hr = IDirect3DDevice_DeleteViewport(device, NULL);
1026 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1028 hr = IDirect3D_CreateViewport(d3d, &another_vp, NULL);
1029 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1031 hr = IDirect3DDevice_AddViewport(device, viewport);
1032 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1033 ref = get_refcount((IUnknown *) viewport);
1034 ok(ref == 2, "IDirect3DViewport refcount is %d\n", ref);
1035 hr = IDirect3DDevice_AddViewport(device, another_vp);
1036 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1037 ref = get_refcount((IUnknown *) another_vp);
1038 ok(ref == 2, "IDirect3DViewport refcount is %d\n", ref);
1040 hr = IDirect3DDevice_DeleteViewport(device, another_vp);
1041 ok(SUCCEEDED(hr), "Failed to delete viewport from device, hr %#x.\n", hr);
1042 ref = get_refcount((IUnknown *) another_vp);
1043 ok(ref == 1, "IDirect3DViewport refcount is %d\n", ref);
1045 IDirect3DDevice_Release(device);
1046 ref = get_refcount((IUnknown *) viewport);
1047 ok(ref == 1, "IDirect3DViewport refcount is %d\n", ref);
1049 IDirect3DViewport_Release(another_vp);
1050 IDirect3D_Release(d3d);
1051 IDirect3DViewport_Release(viewport);
1052 DestroyWindow(window);
1053 IDirectDraw_Release(ddraw);
1056 static void test_zenable(void)
1058 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1059 static D3DTLVERTEX tquad[] =
1061 {{ 0.0f}, {480.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1062 {{ 0.0f}, { 0.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1063 {{640.0f}, {480.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1064 {{640.0f}, { 0.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1066 IDirect3DExecuteBuffer *execute_buffer;
1067 D3DEXECUTEBUFFERDESC exec_desc;
1068 IDirect3DMaterial *background;
1069 IDirect3DViewport *viewport;
1070 IDirect3DDevice *device;
1071 IDirectDrawSurface *rt;
1072 IDirectDraw *ddraw;
1073 UINT inst_length;
1074 D3DCOLOR color;
1075 HWND window;
1076 HRESULT hr;
1077 UINT x, y;
1078 UINT i, j;
1079 void *ptr;
1081 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1082 0, 0, 640, 480, 0, 0, 0, 0);
1083 if (!(ddraw = create_ddraw()))
1085 skip("Failed to create a ddraw object, skipping test.\n");
1086 DestroyWindow(window);
1087 return;
1089 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1091 skip("Failed to create a 3D device, skipping test.\n");
1092 IDirectDraw_Release(ddraw);
1093 DestroyWindow(window);
1094 return;
1097 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1098 viewport = create_viewport(device, 0, 0, 640, 480);
1099 viewport_set_background(device, viewport, background);
1101 memset(&exec_desc, 0, sizeof(exec_desc));
1102 exec_desc.dwSize = sizeof(exec_desc);
1103 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
1104 exec_desc.dwBufferSize = 1024;
1105 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
1107 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
1108 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
1109 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
1110 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
1111 memcpy(exec_desc.lpData, tquad, sizeof(tquad));
1112 ptr = ((BYTE *)exec_desc.lpData) + sizeof(tquad);
1113 emit_process_vertices(&ptr, 0, 4);
1114 emit_set_rs(&ptr, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1115 emit_tquad(&ptr, 0);
1116 emit_end(&ptr);
1117 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
1118 inst_length -= sizeof(tquad);
1119 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
1120 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
1122 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1123 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1124 hr = IDirect3DDevice_BeginScene(device);
1125 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1126 set_execute_data(execute_buffer, 4, sizeof(tquad), inst_length);
1127 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1128 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1129 hr = IDirect3DDevice_EndScene(device);
1130 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1132 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
1133 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1134 for (i = 0; i < 4; ++i)
1136 for (j = 0; j < 4; ++j)
1138 x = 80 * ((2 * j) + 1);
1139 y = 60 * ((2 * i) + 1);
1140 color = get_surface_color(rt, x, y);
1141 ok(compare_color(color, 0x0000ff00, 1),
1142 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1145 IDirectDrawSurface_Release(rt);
1147 destroy_viewport(device, viewport);
1148 IDirect3DExecuteBuffer_Release(execute_buffer);
1149 destroy_material(background);
1150 IDirect3DDevice_Release(device);
1151 IDirectDraw_Release(ddraw);
1152 DestroyWindow(window);
1155 static void test_ck_rgba(void)
1157 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1158 static D3DTLVERTEX tquad[] =
1160 {{ 0.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1161 {{ 0.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1162 {{640.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1163 {{640.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1164 {{ 0.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1165 {{ 0.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1166 {{640.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1167 {{640.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1169 static const struct
1171 D3DCOLOR fill_color;
1172 BOOL color_key;
1173 BOOL blend;
1174 D3DCOLOR result1;
1175 D3DCOLOR result2;
1177 tests[] =
1179 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x000000ff},
1180 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x000000ff},
1181 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00},
1182 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00},
1183 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00807f00},
1184 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x0000ff00},
1185 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00},
1186 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00},
1189 IDirect3DExecuteBuffer *execute_buffer;
1190 D3DTEXTUREHANDLE texture_handle;
1191 D3DEXECUTEBUFFERDESC exec_desc;
1192 IDirect3DMaterial *background;
1193 IDirectDrawSurface *surface;
1194 IDirect3DViewport *viewport;
1195 DDSURFACEDESC surface_desc;
1196 IDirect3DTexture *texture;
1197 IDirect3DDevice *device;
1198 IDirectDrawSurface *rt;
1199 IDirectDraw *ddraw;
1200 D3DCOLOR color;
1201 HWND window;
1202 DDBLTFX fx;
1203 HRESULT hr;
1204 UINT i;
1206 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1207 0, 0, 640, 480, 0, 0, 0, 0);
1208 if (!(ddraw = create_ddraw()))
1210 skip("Failed to create a ddraw object, skipping test.\n");
1211 DestroyWindow(window);
1212 return;
1214 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1216 skip("Failed to create a 3D device, skipping test.\n");
1217 IDirectDraw_Release(ddraw);
1218 DestroyWindow(window);
1219 return;
1222 background = create_diffuse_material(device, 1.0, 0.0f, 0.0f, 1.0f);
1223 viewport = create_viewport(device, 0, 0, 640, 480);
1224 viewport_set_background(device, viewport, background);
1226 memset(&surface_desc, 0, sizeof(surface_desc));
1227 surface_desc.dwSize = sizeof(surface_desc);
1228 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1229 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1230 surface_desc.dwWidth = 256;
1231 surface_desc.dwHeight = 256;
1232 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1233 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1234 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1235 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1236 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1237 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1238 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1239 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1240 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1241 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1242 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1243 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
1244 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1245 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
1246 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1247 IDirect3DTexture_Release(texture);
1249 memset(&exec_desc, 0, sizeof(exec_desc));
1250 exec_desc.dwSize = sizeof(exec_desc);
1251 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
1252 exec_desc.dwBufferSize = 1024;
1253 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
1254 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
1255 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
1257 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
1258 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1260 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
1262 UINT draw1_len, draw2_len;
1263 void *ptr;
1265 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
1266 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
1267 memcpy(exec_desc.lpData, tquad, sizeof(tquad));
1268 ptr = ((BYTE *)exec_desc.lpData) + sizeof(tquad);
1269 emit_process_vertices(&ptr, 0, 4);
1270 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1271 emit_set_rs(&ptr, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1272 emit_set_rs(&ptr, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1273 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1274 emit_set_rs(&ptr, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1275 emit_tquad(&ptr, 0);
1276 emit_end(&ptr);
1277 draw1_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - sizeof(tquad);
1278 emit_process_vertices(&ptr, 4, 4);
1279 emit_tquad(&ptr, 0);
1280 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1281 emit_end(&ptr);
1282 draw2_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw1_len;
1283 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
1284 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
1286 memset(&fx, 0, sizeof(fx));
1287 fx.dwSize = sizeof(fx);
1288 U5(fx).dwFillColor = tests[i].fill_color;
1289 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1290 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1292 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
1293 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1294 hr = IDirect3DDevice_BeginScene(device);
1295 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1296 set_execute_data(execute_buffer, 8, sizeof(tquad), draw1_len);
1297 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1298 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1299 hr = IDirect3DDevice_EndScene(device);
1300 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1302 color = get_surface_color(rt, 320, 240);
1303 if (i == 2)
1304 todo_wine ok(compare_color(color, tests[i].result1, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1305 tests[i].result1, i, color);
1306 else
1307 ok(compare_color(color, tests[i].result1, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1308 tests[i].result1, i, color);
1310 U5(fx).dwFillColor = 0xff0000ff;
1311 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1312 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1314 hr = IDirect3DDevice_BeginScene(device);
1315 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1316 set_execute_data(execute_buffer, 8, sizeof(tquad) + draw1_len, draw2_len);
1317 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1318 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1319 hr = IDirect3DDevice_EndScene(device);
1320 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1322 /* This tests that fragments that are masked out by the color key are
1323 * discarded, instead of just fully transparent. */
1324 color = get_surface_color(rt, 320, 240);
1325 if (i == 2)
1326 todo_wine ok(compare_color(color, tests[i].result2, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1327 tests[i].result2, i, color);
1328 else
1329 ok(compare_color(color, tests[i].result2, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1330 tests[i].result2, i, color);
1333 IDirectDrawSurface_Release(rt);
1334 IDirect3DExecuteBuffer_Release(execute_buffer);
1335 IDirectDrawSurface_Release(surface);
1336 destroy_viewport(device, viewport);
1337 destroy_material(background);
1338 IDirect3DDevice_Release(device);
1339 IDirectDraw_Release(ddraw);
1340 DestroyWindow(window);
1343 static void test_ck_default(void)
1345 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1346 static D3DTLVERTEX tquad[] =
1348 {{ 0.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1349 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1350 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1351 {{640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1353 IDirect3DExecuteBuffer *execute_buffer;
1354 IDirectDrawSurface *surface, *rt;
1355 D3DTEXTUREHANDLE texture_handle;
1356 D3DEXECUTEBUFFERDESC exec_desc;
1357 IDirect3DMaterial *background;
1358 UINT draw1_offset, draw1_len;
1359 UINT draw2_offset, draw2_len;
1360 UINT draw3_offset, draw3_len;
1361 UINT draw4_offset, draw4_len;
1362 IDirect3DViewport *viewport;
1363 DDSURFACEDESC surface_desc;
1364 IDirect3DTexture *texture;
1365 IDirect3DDevice *device;
1366 IDirectDraw *ddraw;
1367 D3DCOLOR color;
1368 HWND window;
1369 DDBLTFX fx;
1370 HRESULT hr;
1371 void *ptr;
1373 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1374 0, 0, 640, 480, 0, 0, 0, 0);
1376 if (!(ddraw = create_ddraw()))
1378 skip("Failed to create a ddraw object, skipping test.\n");
1379 DestroyWindow(window);
1380 return;
1382 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1384 skip("Failed to create a 3D device, skipping test.\n");
1385 IDirectDraw_Release(ddraw);
1386 DestroyWindow(window);
1387 return;
1390 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
1391 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1393 background = create_diffuse_material(device, 0.0, 1.0f, 0.0f, 1.0f);
1394 viewport = create_viewport(device, 0, 0, 640, 480);
1395 viewport_set_background(device, viewport, background);
1397 memset(&surface_desc, 0, sizeof(surface_desc));
1398 surface_desc.dwSize = sizeof(surface_desc);
1399 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1400 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1401 surface_desc.dwWidth = 256;
1402 surface_desc.dwHeight = 256;
1403 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1404 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
1405 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1406 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1407 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1408 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1409 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
1410 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
1411 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1412 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1413 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
1414 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1415 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
1416 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1417 IDirect3DTexture_Release(texture);
1419 memset(&fx, 0, sizeof(fx));
1420 fx.dwSize = sizeof(fx);
1421 U5(fx).dwFillColor = 0x000000ff;
1422 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1423 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
1425 memset(&exec_desc, 0, sizeof(exec_desc));
1426 exec_desc.dwSize = sizeof(exec_desc);
1427 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
1428 exec_desc.dwBufferSize = 1024;
1429 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
1430 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
1431 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
1433 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
1434 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
1435 memcpy(exec_desc.lpData, tquad, sizeof(tquad));
1436 ptr = (BYTE *)exec_desc.lpData + sizeof(tquad);
1437 emit_process_vertices(&ptr, 0, 4);
1438 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1439 emit_tquad(&ptr, 0);
1440 emit_end(&ptr);
1441 draw1_offset = sizeof(tquad);
1442 draw1_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw1_offset;
1443 emit_process_vertices(&ptr, 0, 4);
1444 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, FALSE);
1445 emit_tquad(&ptr, 0);
1446 emit_end(&ptr);
1447 draw2_offset = draw1_offset + draw1_len;
1448 draw2_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw2_offset;
1449 emit_process_vertices(&ptr, 0, 4);
1450 emit_tquad(&ptr, 0);
1451 emit_end(&ptr);
1452 draw3_offset = draw2_offset + draw2_len;
1453 draw3_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw3_offset;
1454 emit_process_vertices(&ptr, 0, 4);
1455 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
1456 emit_tquad(&ptr, 0);
1457 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1458 emit_end(&ptr);
1459 draw4_offset = draw3_offset + draw3_len;
1460 draw4_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw4_offset;
1461 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
1462 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
1464 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1465 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1466 hr = IDirect3DDevice_BeginScene(device);
1467 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1468 set_execute_data(execute_buffer, 4, draw1_offset, draw1_len);
1469 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1470 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1471 hr = IDirect3DDevice_EndScene(device);
1472 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1473 color = get_surface_color(rt, 320, 240);
1474 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1476 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1477 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1478 hr = IDirect3DDevice_BeginScene(device);
1479 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1480 set_execute_data(execute_buffer, 4, draw2_offset, draw2_len);
1481 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1482 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1483 hr = IDirect3DDevice_EndScene(device);
1484 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1485 color = get_surface_color(rt, 320, 240);
1486 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1488 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1489 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1490 hr = IDirect3DDevice_BeginScene(device);
1491 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1492 set_execute_data(execute_buffer, 4, draw3_offset, draw3_len);
1493 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1494 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1495 hr = IDirect3DDevice_EndScene(device);
1496 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1497 color = get_surface_color(rt, 320, 240);
1498 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1500 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1501 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1502 hr = IDirect3DDevice_BeginScene(device);
1503 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1504 set_execute_data(execute_buffer, 4, draw4_offset, draw4_len);
1505 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1506 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1507 hr = IDirect3DDevice_EndScene(device);
1508 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1509 color = get_surface_color(rt, 320, 240);
1510 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1512 IDirect3DExecuteBuffer_Release(execute_buffer);
1513 IDirectDrawSurface_Release(surface);
1514 destroy_viewport(device, viewport);
1515 destroy_material(background);
1516 IDirectDrawSurface_Release(rt);
1517 IDirect3DDevice_Release(device);
1518 IDirectDraw_Release(ddraw);
1519 DestroyWindow(window);
1522 static void test_ck_complex(void)
1524 IDirectDrawSurface *surface, *mipmap, *tmp;
1525 DDSCAPS caps = {DDSCAPS_COMPLEX};
1526 DDSURFACEDESC surface_desc;
1527 IDirect3DDevice *device;
1528 DDCOLORKEY color_key;
1529 IDirectDraw *ddraw;
1530 unsigned int i;
1531 ULONG refcount;
1532 HWND window;
1533 HRESULT hr;
1535 if (!(ddraw = create_ddraw()))
1537 skip("Failed to create a ddraw object, skipping test.\n");
1538 return;
1541 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1542 0, 0, 640, 480, 0, 0, 0, 0);
1543 if (!(device = create_device(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
1545 skip("Failed to create a 3D device, skipping test.\n");
1546 DestroyWindow(window);
1547 IDirectDraw2_Release(ddraw);
1548 return;
1550 IDirect3DDevice_Release(device);
1552 memset(&surface_desc, 0, sizeof(surface_desc));
1553 surface_desc.dwSize = sizeof(surface_desc);
1554 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1555 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1556 surface_desc.dwWidth = 128;
1557 surface_desc.dwHeight = 128;
1558 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1559 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1561 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1562 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1563 color_key.dwColorSpaceLowValue = 0x0000ff00;
1564 color_key.dwColorSpaceHighValue = 0x0000ff00;
1565 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1566 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1567 memset(&color_key, 0, sizeof(color_key));
1568 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1569 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1570 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1571 color_key.dwColorSpaceLowValue);
1572 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1573 color_key.dwColorSpaceHighValue);
1575 mipmap = surface;
1576 IDirectDrawSurface_AddRef(mipmap);
1577 for (i = 0; i < 7; ++i)
1579 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
1580 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
1582 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1583 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1584 color_key.dwColorSpaceLowValue = 0x000000ff;
1585 color_key.dwColorSpaceHighValue = 0x000000ff;
1586 hr = IDirectDrawSurface_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1587 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x, i %u.\n", hr, i);
1588 memset(&color_key, 0, sizeof(color_key));
1589 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1590 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x, i %u.\n", hr, i);
1591 ok(color_key.dwColorSpaceLowValue == 0x000000ff, "Got unexpected value 0x%08x, i %u.\n",
1592 color_key.dwColorSpaceLowValue, i);
1593 ok(color_key.dwColorSpaceHighValue == 0x000000ff, "Got unexpected value 0x%08x, i %u.\n",
1594 color_key.dwColorSpaceHighValue, i);
1596 IDirectDrawSurface_Release(mipmap);
1597 mipmap = tmp;
1600 memset(&color_key, 0, sizeof(color_key));
1601 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1602 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1603 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1604 color_key.dwColorSpaceLowValue);
1605 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1606 color_key.dwColorSpaceHighValue);
1608 hr = IDirectDrawSurface_GetAttachedSurface(mipmap, &caps, &tmp);
1609 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
1610 IDirectDrawSurface_Release(mipmap);
1611 refcount = IDirectDrawSurface_Release(surface);
1612 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1614 memset(&surface_desc, 0, sizeof(surface_desc));
1615 surface_desc.dwSize = sizeof(surface_desc);
1616 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
1617 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
1618 surface_desc.dwBackBufferCount = 1;
1619 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1620 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1622 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1623 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1624 color_key.dwColorSpaceLowValue = 0x0000ff00;
1625 color_key.dwColorSpaceHighValue = 0x0000ff00;
1626 hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1627 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1628 memset(&color_key, 0, sizeof(color_key));
1629 hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1630 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1631 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1632 color_key.dwColorSpaceLowValue);
1633 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1634 color_key.dwColorSpaceHighValue);
1636 hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &tmp);
1637 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
1639 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1640 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1641 color_key.dwColorSpaceLowValue = 0x0000ff00;
1642 color_key.dwColorSpaceHighValue = 0x0000ff00;
1643 hr = IDirectDrawSurface_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1644 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1645 memset(&color_key, 0, sizeof(color_key));
1646 hr = IDirectDrawSurface_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1647 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1648 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1649 color_key.dwColorSpaceLowValue);
1650 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1651 color_key.dwColorSpaceHighValue);
1653 IDirectDrawSurface_Release(tmp);
1655 refcount = IDirectDrawSurface_Release(surface);
1656 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1657 refcount = IDirectDraw_Release(ddraw);
1658 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1659 DestroyWindow(window);
1662 struct qi_test
1664 REFIID iid;
1665 REFIID refcount_iid;
1666 HRESULT hr;
1669 static void test_qi(const char *test_name, IUnknown *base_iface,
1670 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
1672 ULONG refcount, expected_refcount;
1673 IUnknown *iface1, *iface2;
1674 HRESULT hr;
1675 UINT i, j;
1677 for (i = 0; i < entry_count; ++i)
1679 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
1680 ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
1681 if (SUCCEEDED(hr))
1683 for (j = 0; j < entry_count; ++j)
1685 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
1686 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
1687 if (SUCCEEDED(hr))
1689 expected_refcount = 0;
1690 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
1691 ++expected_refcount;
1692 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
1693 ++expected_refcount;
1694 refcount = IUnknown_Release(iface2);
1695 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
1696 refcount, test_name, i, j, expected_refcount);
1700 expected_refcount = 0;
1701 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
1702 ++expected_refcount;
1703 refcount = IUnknown_Release(iface1);
1704 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
1705 refcount, test_name, i, expected_refcount);
1710 static void test_surface_qi(void)
1712 static const struct qi_test tests[] =
1714 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface, S_OK },
1715 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface, S_OK },
1716 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
1717 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1718 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
1719 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
1720 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
1721 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
1722 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
1723 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
1724 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
1725 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
1726 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
1727 {&IID_IDirect3D7, NULL, E_INVALIDARG },
1728 {&IID_IDirect3D3, NULL, E_INVALIDARG },
1729 {&IID_IDirect3D2, NULL, E_INVALIDARG },
1730 {&IID_IDirect3D, NULL, E_INVALIDARG },
1731 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
1732 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
1733 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
1734 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
1735 {&IID_IDirectDraw, NULL, E_INVALIDARG },
1736 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
1737 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
1738 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
1739 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
1740 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
1741 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
1742 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
1743 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
1744 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
1745 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
1746 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
1747 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
1748 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
1751 IDirectDrawSurface *surface;
1752 DDSURFACEDESC surface_desc;
1753 IDirect3DDevice *device;
1754 IDirectDraw *ddraw;
1755 HWND window;
1756 HRESULT hr;
1758 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
1760 win_skip("DirectDrawCreateEx not available, skipping test.\n");
1761 return;
1764 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1765 0, 0, 640, 480, 0, 0, 0, 0);
1766 if (!(ddraw = create_ddraw()))
1768 skip("Failed to create a ddraw object, skipping test.\n");
1769 DestroyWindow(window);
1770 return;
1772 /* Try to create a D3D device to see if the ddraw implementation supports
1773 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
1774 * doesn't support e.g. the IDirect3DTexture interfaces. */
1775 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1777 skip("Failed to create a 3D device, skipping test.\n");
1778 IDirectDraw_Release(ddraw);
1779 DestroyWindow(window);
1780 return;
1782 IDirect3DDevice_Release(device);
1784 memset(&surface_desc, 0, sizeof(surface_desc));
1785 surface_desc.dwSize = sizeof(surface_desc);
1786 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1787 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1788 surface_desc.dwWidth = 512;
1789 surface_desc.dwHeight = 512;
1790 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1791 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1793 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface, tests, sizeof(tests) / sizeof(*tests));
1795 IDirectDrawSurface_Release(surface);
1796 IDirectDraw_Release(ddraw);
1797 DestroyWindow(window);
1800 static void test_device_qi(void)
1802 static const struct qi_test tests[] =
1804 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface, S_OK },
1805 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface, S_OK },
1806 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
1807 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1808 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
1809 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
1810 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
1811 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
1812 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
1813 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
1814 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
1815 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
1816 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
1817 {&IID_IDirect3DHALDevice, &IID_IDirectDrawSurface, S_OK },
1818 {&IID_IDirect3D7, NULL, E_INVALIDARG },
1819 {&IID_IDirect3D3, NULL, E_INVALIDARG },
1820 {&IID_IDirect3D2, NULL, E_INVALIDARG },
1821 {&IID_IDirect3D, NULL, E_INVALIDARG },
1822 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
1823 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
1824 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
1825 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
1826 {&IID_IDirectDraw, NULL, E_INVALIDARG },
1827 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
1828 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
1829 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
1830 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
1831 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
1832 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
1833 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
1834 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
1835 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
1836 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
1837 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
1838 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
1839 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
1843 IDirect3DDevice *device;
1844 IDirectDraw *ddraw;
1845 HWND window;
1847 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
1849 win_skip("DirectDrawCreateEx not available, skipping test.\n");
1850 return;
1853 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1854 0, 0, 640, 480, 0, 0, 0, 0);
1855 if (!(ddraw = create_ddraw()))
1857 skip("Failed to create a ddraw object, skipping test.\n");
1858 DestroyWindow(window);
1859 return;
1861 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1863 skip("Failed to create a 3D device, skipping test.\n");
1864 IDirectDraw_Release(ddraw);
1865 DestroyWindow(window);
1866 return;
1869 test_qi("device_qi", (IUnknown *)device, &IID_IDirectDrawSurface, tests, sizeof(tests) / sizeof(*tests));
1871 IDirect3DDevice_Release(device);
1872 IDirectDraw_Release(ddraw);
1873 DestroyWindow(window);
1876 static void test_wndproc(void)
1878 LONG_PTR proc, ddraw_proc;
1879 IDirectDraw *ddraw;
1880 WNDCLASSA wc = {0};
1881 HWND window;
1882 HRESULT hr;
1883 ULONG ref;
1885 static const UINT messages[] =
1887 WM_WINDOWPOSCHANGING,
1888 WM_MOVE,
1889 WM_SIZE,
1890 WM_WINDOWPOSCHANGING,
1891 WM_ACTIVATE,
1892 WM_SETFOCUS,
1896 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
1897 if (!(ddraw = create_ddraw()))
1899 skip("Failed to create a ddraw object, skipping test.\n");
1900 return;
1903 wc.lpfnWndProc = test_proc;
1904 wc.lpszClassName = "ddraw_test_wndproc_wc";
1905 ok(RegisterClassA(&wc), "Failed to register window class.\n");
1907 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
1908 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
1910 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1911 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1912 (LONG_PTR)test_proc, proc);
1913 expect_messages = messages;
1914 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1915 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1916 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
1917 expect_messages = NULL;
1918 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1919 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1920 (LONG_PTR)test_proc, proc);
1921 ref = IDirectDraw_Release(ddraw);
1922 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1923 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1924 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1925 (LONG_PTR)test_proc, proc);
1927 /* DDSCL_NORMAL doesn't. */
1928 ddraw = create_ddraw();
1929 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1930 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1931 (LONG_PTR)test_proc, proc);
1932 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
1933 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1934 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1935 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1936 (LONG_PTR)test_proc, proc);
1937 ref = IDirectDraw_Release(ddraw);
1938 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1939 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1940 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1941 (LONG_PTR)test_proc, proc);
1943 /* The original window proc is only restored by ddraw if the current
1944 * window proc matches the one ddraw set. This also affects switching
1945 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
1946 ddraw = create_ddraw();
1947 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1948 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1949 (LONG_PTR)test_proc, proc);
1950 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1951 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1952 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1953 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1954 (LONG_PTR)test_proc, proc);
1955 ddraw_proc = proc;
1956 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1957 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1958 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1959 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1960 (LONG_PTR)test_proc, proc);
1961 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1962 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1963 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
1964 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1965 (LONG_PTR)test_proc, proc);
1966 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1967 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1968 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1969 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
1970 (LONG_PTR)DefWindowProcA, proc);
1971 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1972 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1973 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc);
1974 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
1975 (LONG_PTR)DefWindowProcA, proc);
1976 ref = IDirectDraw_Release(ddraw);
1977 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1978 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1979 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1980 (LONG_PTR)test_proc, proc);
1982 ddraw = create_ddraw();
1983 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1984 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1985 (LONG_PTR)test_proc, proc);
1986 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1987 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1988 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
1989 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1990 (LONG_PTR)test_proc, proc);
1991 ref = IDirectDraw_Release(ddraw);
1992 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1993 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1994 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
1995 (LONG_PTR)DefWindowProcA, proc);
1997 fix_wndproc(window, (LONG_PTR)test_proc);
1998 expect_messages = NULL;
1999 DestroyWindow(window);
2000 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2003 static void test_window_style(void)
2005 LONG style, exstyle, tmp;
2006 RECT fullscreen_rect, r;
2007 IDirectDraw *ddraw;
2008 HWND window;
2009 HRESULT hr;
2010 ULONG ref;
2012 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2013 0, 0, 100, 100, 0, 0, 0, 0);
2014 if (!(ddraw = create_ddraw()))
2016 skip("Failed to create a ddraw object, skipping test.\n");
2017 DestroyWindow(window);
2018 return;
2021 style = GetWindowLongA(window, GWL_STYLE);
2022 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
2023 SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2025 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2026 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2028 tmp = GetWindowLongA(window, GWL_STYLE);
2029 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2030 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2031 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2033 GetWindowRect(window, &r);
2034 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2035 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2036 r.left, r.top, r.right, r.bottom);
2037 GetClientRect(window, &r);
2038 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2040 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2041 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2043 tmp = GetWindowLongA(window, GWL_STYLE);
2044 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2045 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2046 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2048 ref = IDirectDraw_Release(ddraw);
2049 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2051 DestroyWindow(window);
2054 static void test_redundant_mode_set(void)
2056 DDSURFACEDESC surface_desc = {0};
2057 IDirectDraw *ddraw;
2058 HWND window;
2059 HRESULT hr;
2060 RECT r, s;
2061 ULONG ref;
2063 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2064 0, 0, 100, 100, 0, 0, 0, 0);
2065 if (!(ddraw = create_ddraw()))
2067 skip("Failed to create a ddraw object, skipping test.\n");
2068 DestroyWindow(window);
2069 return;
2072 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2073 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2075 surface_desc.dwSize = sizeof(surface_desc);
2076 hr = IDirectDraw_GetDisplayMode(ddraw, &surface_desc);
2077 ok(SUCCEEDED(hr), "GetDipslayMode failed, hr %#x.\n", hr);
2079 hr = IDirectDraw_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2080 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount);
2081 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2083 GetWindowRect(window, &r);
2084 r.right /= 2;
2085 r.bottom /= 2;
2086 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
2087 GetWindowRect(window, &s);
2088 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2089 r.left, r.top, r.right, r.bottom,
2090 s.left, s.top, s.right, s.bottom);
2092 hr = IDirectDraw_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2093 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount);
2094 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2096 GetWindowRect(window, &s);
2097 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2098 r.left, r.top, r.right, r.bottom,
2099 s.left, s.top, s.right, s.bottom);
2101 ref = IDirectDraw_Release(ddraw);
2102 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2104 DestroyWindow(window);
2107 static SIZE screen_size;
2109 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2111 if (message == WM_SIZE)
2113 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2114 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2117 return test_proc(hwnd, message, wparam, lparam);
2120 static void test_coop_level_mode_set(void)
2122 IDirectDrawSurface *primary;
2123 RECT fullscreen_rect, r, s;
2124 IDirectDraw *ddraw;
2125 DDSURFACEDESC ddsd;
2126 WNDCLASSA wc = {0};
2127 HWND window;
2128 HRESULT hr;
2129 ULONG ref;
2131 static const UINT exclusive_messages[] =
2133 WM_WINDOWPOSCHANGING,
2134 WM_WINDOWPOSCHANGED,
2135 WM_SIZE,
2136 WM_DISPLAYCHANGE,
2140 static const UINT normal_messages[] =
2142 WM_DISPLAYCHANGE,
2146 if (!(ddraw = create_ddraw()))
2148 skip("Failed to create a ddraw object, skipping test.\n");
2149 return;
2152 wc.lpfnWndProc = mode_set_proc;
2153 wc.lpszClassName = "ddraw_test_wndproc_wc";
2154 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2156 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
2157 0, 0, 100, 100, 0, 0, 0, 0);
2159 SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2160 SetRect(&s, 0, 0, 640, 480);
2162 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2163 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2165 GetWindowRect(window, &r);
2166 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2167 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2168 r.left, r.top, r.right, r.bottom);
2170 memset(&ddsd, 0, sizeof(ddsd));
2171 ddsd.dwSize = sizeof(ddsd);
2172 ddsd.dwFlags = DDSD_CAPS;
2173 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2175 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2176 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2177 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2178 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2179 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2180 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2181 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2182 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2184 GetWindowRect(window, &r);
2185 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2186 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2187 r.left, r.top, r.right, r.bottom);
2189 expect_messages = exclusive_messages;
2190 screen_size.cx = 0;
2191 screen_size.cy = 0;
2193 hr = IDirectDraw_SetDisplayMode(ddraw, 640, 480, 32);
2194 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2196 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2197 expect_messages = NULL;
2198 ok(screen_size.cx == s.right && screen_size.cy == s.bottom,
2199 "Expected screen size %ux%u, got %ux%u.\n",
2200 s.right, s.bottom, screen_size.cx, screen_size.cy);
2202 GetWindowRect(window, &r);
2203 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2204 s.left, s.top, s.right, s.bottom,
2205 r.left, r.top, r.right, r.bottom);
2207 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2208 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2209 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2210 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2211 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2212 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2213 IDirectDrawSurface_Release(primary);
2215 memset(&ddsd, 0, sizeof(ddsd));
2216 ddsd.dwSize = sizeof(ddsd);
2217 ddsd.dwFlags = DDSD_CAPS;
2218 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2220 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2221 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2222 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2223 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2224 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2225 s.right - s.left, ddsd.dwWidth);
2226 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2227 s.bottom - s.top, ddsd.dwHeight);
2229 GetWindowRect(window, &r);
2230 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2231 s.left, s.top, s.right, s.bottom,
2232 r.left, r.top, r.right, r.bottom);
2234 expect_messages = exclusive_messages;
2235 screen_size.cx = 0;
2236 screen_size.cy = 0;
2238 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2239 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2241 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2242 expect_messages = NULL;
2243 ok(screen_size.cx == fullscreen_rect.right && screen_size.cy == fullscreen_rect.bottom,
2244 "Expected screen size %ux%u, got %ux%u.\n",
2245 fullscreen_rect.right, fullscreen_rect.bottom, screen_size.cx, screen_size.cy);
2247 GetWindowRect(window, &r);
2248 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2249 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2250 r.left, r.top, r.right, r.bottom);
2252 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2253 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2254 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2255 s.right - s.left, ddsd.dwWidth);
2256 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2257 s.bottom - s.top, ddsd.dwHeight);
2258 IDirectDrawSurface_Release(primary);
2260 memset(&ddsd, 0, sizeof(ddsd));
2261 ddsd.dwSize = sizeof(ddsd);
2262 ddsd.dwFlags = DDSD_CAPS;
2263 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2265 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2266 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2267 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2268 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2269 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2270 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2271 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2272 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2274 GetWindowRect(window, &r);
2275 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2276 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2277 r.left, r.top, r.right, r.bottom);
2279 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2280 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2282 GetWindowRect(window, &r);
2283 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2284 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2285 r.left, r.top, r.right, r.bottom);
2287 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2288 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2289 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2290 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2291 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2292 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2293 IDirectDrawSurface_Release(primary);
2295 memset(&ddsd, 0, sizeof(ddsd));
2296 ddsd.dwSize = sizeof(ddsd);
2297 ddsd.dwFlags = DDSD_CAPS;
2298 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2300 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2301 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2302 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2303 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2304 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2305 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2306 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2307 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2309 GetWindowRect(window, &r);
2310 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2311 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2312 r.left, r.top, r.right, r.bottom);
2314 expect_messages = normal_messages;
2315 screen_size.cx = 0;
2316 screen_size.cy = 0;
2318 hr = IDirectDraw_SetDisplayMode(ddraw, 640, 480, 32);
2319 ok(SUCCEEDED(hr) || broken(hr == DDERR_NOEXCLUSIVEMODE) /* NT4 testbot */,
2320 "SetDisplayMode failed, hr %#x.\n", hr);
2321 if (hr == DDERR_NOEXCLUSIVEMODE)
2323 win_skip("Broken SetDisplayMode(), skipping remaining tests.\n");
2324 IDirectDrawSurface_Release(primary);
2325 IDirectDraw_Release(ddraw);
2326 goto done;
2329 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2330 expect_messages = NULL;
2331 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2333 GetWindowRect(window, &r);
2334 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2335 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2336 r.left, r.top, r.right, r.bottom);
2338 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2339 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2340 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2341 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2342 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2343 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2344 IDirectDrawSurface_Release(primary);
2346 memset(&ddsd, 0, sizeof(ddsd));
2347 ddsd.dwSize = sizeof(ddsd);
2348 ddsd.dwFlags = DDSD_CAPS;
2349 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2351 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2352 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2353 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2354 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2355 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2356 s.right - s.left, ddsd.dwWidth);
2357 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2358 s.bottom - s.top, ddsd.dwHeight);
2360 GetWindowRect(window, &r);
2361 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2362 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2363 r.left, r.top, r.right, r.bottom);
2365 expect_messages = normal_messages;
2366 screen_size.cx = 0;
2367 screen_size.cy = 0;
2369 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2370 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2372 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2373 expect_messages = NULL;
2374 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2376 GetWindowRect(window, &r);
2377 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2378 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2379 r.left, r.top, r.right, r.bottom);
2381 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2382 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2383 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2384 s.right - s.left, ddsd.dwWidth);
2385 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2386 s.bottom - s.top, ddsd.dwHeight);
2387 IDirectDrawSurface_Release(primary);
2389 memset(&ddsd, 0, sizeof(ddsd));
2390 ddsd.dwSize = sizeof(ddsd);
2391 ddsd.dwFlags = DDSD_CAPS;
2392 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2394 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2395 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2396 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2397 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2398 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2399 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2400 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2401 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2403 GetWindowRect(window, &r);
2404 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2405 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2406 r.left, r.top, r.right, r.bottom);
2408 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
2409 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
2410 * not DDSCL_FULLSCREEN. */
2411 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2412 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2414 GetWindowRect(window, &r);
2415 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2416 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2417 r.left, r.top, r.right, r.bottom);
2419 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2420 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2421 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2422 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2423 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2424 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2425 IDirectDrawSurface_Release(primary);
2427 memset(&ddsd, 0, sizeof(ddsd));
2428 ddsd.dwSize = sizeof(ddsd);
2429 ddsd.dwFlags = DDSD_CAPS;
2430 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2432 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2433 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2434 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2435 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2436 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2437 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2438 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2439 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2441 GetWindowRect(window, &r);
2442 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2443 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2444 r.left, r.top, r.right, r.bottom);
2446 expect_messages = normal_messages;
2447 screen_size.cx = 0;
2448 screen_size.cy = 0;
2450 hr = IDirectDraw_SetDisplayMode(ddraw, 640, 480, 32);
2451 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2453 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2454 expect_messages = NULL;
2455 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2457 GetWindowRect(window, &r);
2458 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2459 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2460 r.left, r.top, r.right, r.bottom);
2462 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2463 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2464 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2465 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2466 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2467 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2468 IDirectDrawSurface_Release(primary);
2470 memset(&ddsd, 0, sizeof(ddsd));
2471 ddsd.dwSize = sizeof(ddsd);
2472 ddsd.dwFlags = DDSD_CAPS;
2473 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2475 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2476 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2477 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2478 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2479 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2480 s.right - s.left, ddsd.dwWidth);
2481 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2482 s.bottom - s.top, ddsd.dwHeight);
2484 GetWindowRect(window, &r);
2485 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2486 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2487 r.left, r.top, r.right, r.bottom);
2489 expect_messages = normal_messages;
2490 screen_size.cx = 0;
2491 screen_size.cy = 0;
2493 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2494 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2496 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2497 expect_messages = NULL;
2498 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2500 GetWindowRect(window, &r);
2501 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2502 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2503 r.left, r.top, r.right, r.bottom);
2505 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2506 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2507 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2508 s.right - s.left, ddsd.dwWidth);
2509 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2510 s.bottom - s.top, ddsd.dwHeight);
2511 IDirectDrawSurface_Release(primary);
2513 memset(&ddsd, 0, sizeof(ddsd));
2514 ddsd.dwSize = sizeof(ddsd);
2515 ddsd.dwFlags = DDSD_CAPS;
2516 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2518 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2519 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2520 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2521 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2522 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2523 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2524 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2525 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2526 IDirectDrawSurface_Release(primary);
2528 GetWindowRect(window, &r);
2529 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2530 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2531 r.left, r.top, r.right, r.bottom);
2533 /* Unlike ddraw2-7, changing from EXCLUSIVE to NORMAL does not restore the resolution */
2534 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2535 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2536 hr = IDirectDraw_SetDisplayMode(ddraw, 640, 480, 32);
2537 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2539 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2540 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2542 memset(&ddsd, 0, sizeof(ddsd));
2543 ddsd.dwSize = sizeof(ddsd);
2544 ddsd.dwFlags = DDSD_CAPS;
2545 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2547 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2548 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2549 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2550 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2551 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2552 s.right - s.left, ddsd.dwWidth);
2553 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2554 s.bottom - s.top, ddsd.dwHeight);
2555 IDirectDrawSurface_Release(primary);
2556 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2557 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2559 ref = IDirectDraw_Release(ddraw);
2560 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2562 GetWindowRect(window, &r);
2563 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2564 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2565 r.left, r.top, r.right, r.bottom);
2567 done:
2568 expect_messages = NULL;
2569 DestroyWindow(window);
2570 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2573 static void test_coop_level_mode_set_multi(void)
2575 IDirectDraw *ddraw1, *ddraw2;
2576 UINT orig_w, orig_h, w, h;
2577 HWND window;
2578 HRESULT hr;
2579 ULONG ref;
2581 if (!(ddraw1 = create_ddraw()))
2583 skip("Failed to create a ddraw object, skipping test.\n");
2584 return;
2587 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2588 0, 0, 100, 100, 0, 0, 0, 0);
2590 orig_w = GetSystemMetrics(SM_CXSCREEN);
2591 orig_h = GetSystemMetrics(SM_CYSCREEN);
2593 /* With just a single ddraw object, the display mode is restored on
2594 * release. */
2595 hr = IDirectDraw_SetDisplayMode(ddraw1, 800, 600, 32);
2596 ok(SUCCEEDED(hr) || broken(hr == DDERR_NOEXCLUSIVEMODE) /* NT4 testbot */,
2597 "SetDisplayMode failed, hr %#x.\n", hr);
2598 if (hr == DDERR_NOEXCLUSIVEMODE)
2600 win_skip("Broken SetDisplayMode(), skipping test.\n");
2601 IDirectDraw_Release(ddraw1);
2602 DestroyWindow(window);
2603 return;
2605 w = GetSystemMetrics(SM_CXSCREEN);
2606 ok(w == 800, "Got unexpected screen width %u.\n", w);
2607 h = GetSystemMetrics(SM_CYSCREEN);
2608 ok(h == 600, "Got unexpected screen height %u.\n", h);
2610 ref = IDirectDraw_Release(ddraw1);
2611 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2612 w = GetSystemMetrics(SM_CXSCREEN);
2613 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2614 h = GetSystemMetrics(SM_CYSCREEN);
2615 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2617 /* When there are multiple ddraw objects, the display mode is restored to
2618 * the initial mode, before the first SetDisplayMode() call. */
2619 ddraw1 = create_ddraw();
2620 hr = IDirectDraw_SetDisplayMode(ddraw1, 800, 600, 32);
2621 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2622 w = GetSystemMetrics(SM_CXSCREEN);
2623 ok(w == 800, "Got unexpected screen width %u.\n", w);
2624 h = GetSystemMetrics(SM_CYSCREEN);
2625 ok(h == 600, "Got unexpected screen height %u.\n", h);
2627 ddraw2 = create_ddraw();
2628 hr = IDirectDraw_SetDisplayMode(ddraw2, 640, 480, 32);
2629 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2630 w = GetSystemMetrics(SM_CXSCREEN);
2631 ok(w == 640, "Got unexpected screen width %u.\n", w);
2632 h = GetSystemMetrics(SM_CYSCREEN);
2633 ok(h == 480, "Got unexpected screen height %u.\n", h);
2635 ref = IDirectDraw_Release(ddraw2);
2636 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2637 w = GetSystemMetrics(SM_CXSCREEN);
2638 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2639 h = GetSystemMetrics(SM_CYSCREEN);
2640 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2642 ref = IDirectDraw_Release(ddraw1);
2643 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2644 w = GetSystemMetrics(SM_CXSCREEN);
2645 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2646 h = GetSystemMetrics(SM_CYSCREEN);
2647 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2649 /* Regardless of release ordering. */
2650 ddraw1 = create_ddraw();
2651 hr = IDirectDraw_SetDisplayMode(ddraw1, 800, 600, 32);
2652 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2653 w = GetSystemMetrics(SM_CXSCREEN);
2654 ok(w == 800, "Got unexpected screen width %u.\n", w);
2655 h = GetSystemMetrics(SM_CYSCREEN);
2656 ok(h == 600, "Got unexpected screen height %u.\n", h);
2658 ddraw2 = create_ddraw();
2659 hr = IDirectDraw_SetDisplayMode(ddraw2, 640, 480, 32);
2660 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2661 w = GetSystemMetrics(SM_CXSCREEN);
2662 ok(w == 640, "Got unexpected screen width %u.\n", w);
2663 h = GetSystemMetrics(SM_CYSCREEN);
2664 ok(h == 480, "Got unexpected screen height %u.\n", h);
2666 ref = IDirectDraw_Release(ddraw1);
2667 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2668 w = GetSystemMetrics(SM_CXSCREEN);
2669 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2670 h = GetSystemMetrics(SM_CYSCREEN);
2671 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2673 ref = IDirectDraw_Release(ddraw2);
2674 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2675 w = GetSystemMetrics(SM_CXSCREEN);
2676 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2677 h = GetSystemMetrics(SM_CYSCREEN);
2678 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2680 /* But only for ddraw objects that called SetDisplayMode(). */
2681 ddraw1 = create_ddraw();
2682 ddraw2 = create_ddraw();
2683 hr = IDirectDraw_SetDisplayMode(ddraw2, 640, 480, 32);
2684 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2685 w = GetSystemMetrics(SM_CXSCREEN);
2686 ok(w == 640, "Got unexpected screen width %u.\n", w);
2687 h = GetSystemMetrics(SM_CYSCREEN);
2688 ok(h == 480, "Got unexpected screen height %u.\n", h);
2690 ref = IDirectDraw_Release(ddraw1);
2691 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2692 w = GetSystemMetrics(SM_CXSCREEN);
2693 ok(w == 640, "Got unexpected screen width %u.\n", w);
2694 h = GetSystemMetrics(SM_CYSCREEN);
2695 ok(h == 480, "Got unexpected screen height %u.\n", h);
2697 ref = IDirectDraw_Release(ddraw2);
2698 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2699 w = GetSystemMetrics(SM_CXSCREEN);
2700 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2701 h = GetSystemMetrics(SM_CYSCREEN);
2702 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2704 /* If there's a ddraw object that's currently in exclusive mode, it blocks
2705 * restoring the display mode. */
2706 ddraw1 = create_ddraw();
2707 hr = IDirectDraw_SetDisplayMode(ddraw1, 800, 600, 32);
2708 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2709 w = GetSystemMetrics(SM_CXSCREEN);
2710 ok(w == 800, "Got unexpected screen width %u.\n", w);
2711 h = GetSystemMetrics(SM_CYSCREEN);
2712 ok(h == 600, "Got unexpected screen height %u.\n", h);
2714 ddraw2 = create_ddraw();
2715 hr = IDirectDraw_SetDisplayMode(ddraw2, 640, 480, 32);
2716 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2717 w = GetSystemMetrics(SM_CXSCREEN);
2718 ok(w == 640, "Got unexpected screen width %u.\n", w);
2719 h = GetSystemMetrics(SM_CYSCREEN);
2720 ok(h == 480, "Got unexpected screen height %u.\n", h);
2722 hr = IDirectDraw_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2723 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2725 ref = IDirectDraw_Release(ddraw1);
2726 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2727 w = GetSystemMetrics(SM_CXSCREEN);
2728 ok(w == 640, "Got unexpected screen width %u.\n", w);
2729 h = GetSystemMetrics(SM_CYSCREEN);
2730 ok(h == 480, "Got unexpected screen height %u.\n", h);
2732 ref = IDirectDraw_Release(ddraw2);
2733 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2734 w = GetSystemMetrics(SM_CXSCREEN);
2735 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2736 h = GetSystemMetrics(SM_CYSCREEN);
2737 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2739 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
2740 ddraw1 = create_ddraw();
2741 hr = IDirectDraw_SetDisplayMode(ddraw1, 800, 600, 32);
2742 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2743 w = GetSystemMetrics(SM_CXSCREEN);
2744 ok(w == 800, "Got unexpected screen width %u.\n", w);
2745 h = GetSystemMetrics(SM_CYSCREEN);
2746 ok(h == 600, "Got unexpected screen height %u.\n", h);
2748 hr = IDirectDraw_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2749 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2751 ddraw2 = create_ddraw();
2752 hr = IDirectDraw_SetDisplayMode(ddraw2, 640, 480, 32);
2753 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
2755 ref = IDirectDraw_Release(ddraw1);
2756 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2757 w = GetSystemMetrics(SM_CXSCREEN);
2758 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2759 h = GetSystemMetrics(SM_CYSCREEN);
2760 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2762 ref = IDirectDraw_Release(ddraw2);
2763 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2764 w = GetSystemMetrics(SM_CXSCREEN);
2765 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2766 h = GetSystemMetrics(SM_CYSCREEN);
2767 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2769 DestroyWindow(window);
2772 static void test_initialize(void)
2774 IDirectDraw *ddraw;
2775 IDirect3D *d3d;
2776 HRESULT hr;
2778 if (!(ddraw = create_ddraw()))
2780 skip("Failed to create a ddraw object, skipping test.\n");
2781 return;
2784 hr = IDirectDraw_Initialize(ddraw, NULL);
2785 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
2786 IDirectDraw_Release(ddraw);
2788 CoInitialize(NULL);
2789 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw, (void **)&ddraw);
2790 ok(SUCCEEDED(hr), "Failed to create IDirectDraw instance, hr %#x.\n", hr);
2791 hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d);
2792 if (SUCCEEDED(hr))
2794 /* IDirect3D_Initialize() just returns DDERR_ALREADYINITIALIZED. */
2795 hr = IDirect3D_Initialize(d3d, NULL);
2796 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
2797 IDirect3D_Release(d3d);
2799 else
2800 skip("D3D interface is not available, skipping test.\n");
2801 hr = IDirectDraw_Initialize(ddraw, NULL);
2802 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
2803 hr = IDirectDraw_Initialize(ddraw, NULL);
2804 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
2805 IDirectDraw_Release(ddraw);
2806 CoUninitialize();
2808 if (0) /* This crashes on the W2KPROSP4 testbot. */
2810 CoInitialize(NULL);
2811 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirect3D, (void **)&d3d);
2812 ok(hr == E_NOINTERFACE, "CoCreateInstance returned hr %#x, expected E_NOINTERFACE.\n", hr);
2813 CoUninitialize();
2817 static void test_coop_level_surf_create(void)
2819 IDirectDrawSurface *surface;
2820 IDirectDraw *ddraw;
2821 DDSURFACEDESC ddsd;
2822 HRESULT hr;
2824 if (!(ddraw = create_ddraw()))
2826 skip("Failed to create a ddraw object, skipping test.\n");
2827 return;
2830 memset(&ddsd, 0, sizeof(ddsd));
2831 ddsd.dwSize = sizeof(ddsd);
2832 ddsd.dwFlags = DDSD_CAPS;
2833 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2834 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
2835 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
2837 IDirectDraw_Release(ddraw);
2840 static void test_coop_level_multi_window(void)
2842 HWND window1, window2;
2843 IDirectDraw *ddraw;
2844 HRESULT hr;
2846 window1 = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
2847 0, 0, 640, 480, 0, 0, 0, 0);
2848 window2 = CreateWindowA("static", "ddraw_test2", WS_OVERLAPPEDWINDOW,
2849 0, 0, 640, 480, 0, 0, 0, 0);
2850 if (!(ddraw = create_ddraw()))
2852 skip("Failed to create a ddraw object, skipping test.\n");
2853 DestroyWindow(window2);
2854 DestroyWindow(window1);
2855 return;
2858 hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
2859 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2860 hr = IDirectDraw_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
2861 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2862 ok(IsWindow(window1), "Window 1 was destroyed.\n");
2863 ok(IsWindow(window2), "Window 2 was destroyed.\n");
2865 IDirectDraw_Release(ddraw);
2866 DestroyWindow(window2);
2867 DestroyWindow(window1);
2870 static void test_clear_rect_count(void)
2872 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
2873 IDirect3DMaterial *white, *red, *green, *blue;
2874 IDirect3DViewport *viewport;
2875 IDirect3DDevice *device;
2876 IDirectDrawSurface *rt;
2877 IDirectDraw *ddraw;
2878 D3DCOLOR color;
2879 HWND window;
2880 HRESULT hr;
2882 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2883 0, 0, 640, 480, 0, 0, 0, 0);
2884 if (!(ddraw = create_ddraw()))
2886 skip("Failed to create a ddraw object, skipping test.\n");
2887 DestroyWindow(window);
2888 return;
2890 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
2892 skip("Failed to create a 3D device, skipping test.\n");
2893 IDirectDraw_Release(ddraw);
2894 DestroyWindow(window);
2895 return;
2898 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
2899 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
2901 white = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
2902 red = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
2903 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
2904 blue = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
2905 viewport = create_viewport(device, 0, 0, 640, 480);
2907 viewport_set_background(device, viewport, white);
2908 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
2909 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2910 viewport_set_background(device, viewport, red);
2911 hr = IDirect3DViewport_Clear(viewport, 0, &clear_rect, D3DCLEAR_TARGET);
2912 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2913 viewport_set_background(device, viewport, green);
2914 hr = IDirect3DViewport_Clear(viewport, 0, NULL, D3DCLEAR_TARGET);
2915 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2916 viewport_set_background(device, viewport, blue);
2917 hr = IDirect3DViewport_Clear(viewport, 1, NULL, D3DCLEAR_TARGET);
2918 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2920 color = get_surface_color(rt, 320, 240);
2921 ok(compare_color(color, 0x00ffffff, 1), "Got unexpected color 0x%08x.\n", color);
2923 IDirectDrawSurface_Release(rt);
2924 destroy_viewport(device, viewport);
2925 destroy_material(white);
2926 destroy_material(red);
2927 destroy_material(green);
2928 destroy_material(blue);
2929 IDirect3DDevice_Release(device);
2930 IDirectDraw_Release(ddraw);
2931 DestroyWindow(window);
2934 static struct
2936 BOOL received;
2937 IDirectDraw *ddraw;
2938 HWND window;
2939 DWORD coop_level;
2940 } activateapp_testdata;
2942 static LRESULT CALLBACK activateapp_test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2944 if (message == WM_ACTIVATEAPP)
2946 if (activateapp_testdata.ddraw)
2948 HRESULT hr;
2949 activateapp_testdata.received = FALSE;
2950 hr = IDirectDraw_SetCooperativeLevel(activateapp_testdata.ddraw,
2951 activateapp_testdata.window, activateapp_testdata.coop_level);
2952 ok(SUCCEEDED(hr), "Recursive SetCooperativeLevel call failed, hr %#x.\n", hr);
2953 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP during recursive SetCooperativeLevel call.\n");
2955 activateapp_testdata.received = TRUE;
2958 return DefWindowProcA(hwnd, message, wparam, lparam);
2961 static void test_coop_level_activateapp(void)
2963 IDirectDraw *ddraw;
2964 HRESULT hr;
2965 HWND window;
2966 WNDCLASSA wc = {0};
2967 DDSURFACEDESC ddsd;
2968 IDirectDrawSurface *surface;
2970 if (!(ddraw = create_ddraw()))
2972 skip("Failed to create a ddraw object, skipping test.\n");
2973 return;
2976 wc.lpfnWndProc = activateapp_test_proc;
2977 wc.lpszClassName = "ddraw_test_wndproc_wc";
2978 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2980 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
2981 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
2983 /* Exclusive with window already active. */
2984 SetActiveWindow(window);
2985 activateapp_testdata.received = FALSE;
2986 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2987 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2988 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP although window was already active.\n");
2989 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
2990 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2992 /* Exclusive with window not active. */
2993 SetActiveWindow(NULL);
2994 activateapp_testdata.received = FALSE;
2995 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2996 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2997 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
2998 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
2999 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3001 /* Normal with window not active, then exclusive with the same window. */
3002 SetActiveWindow(NULL);
3003 activateapp_testdata.received = FALSE;
3004 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3005 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3006 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP when setting DDSCL_NORMAL.\n");
3007 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3008 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3009 /* Except in the first SetCooperativeLevel call, Windows XP randomly does not send
3010 * WM_ACTIVATEAPP. Windows 7 sends the message reliably. Mark the XP behavior broken. */
3011 ok(activateapp_testdata.received || broken(!activateapp_testdata.received),
3012 "Expected WM_ACTIVATEAPP, but did not receive it.\n");
3013 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3014 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3016 /* Recursive set of DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. */
3017 SetActiveWindow(NULL);
3018 activateapp_testdata.received = FALSE;
3019 activateapp_testdata.ddraw = ddraw;
3020 activateapp_testdata.window = window;
3021 activateapp_testdata.coop_level = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
3022 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3023 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3024 ok(activateapp_testdata.received || broken(!activateapp_testdata.received),
3025 "Expected WM_ACTIVATEAPP, but did not receive it.\n");
3026 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3027 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3029 /* The recursive call seems to have some bad effect on native ddraw, despite (apparently)
3030 * succeeding. Another switch to exclusive and back to normal is needed to release the
3031 * window properly. Without doing this, SetCooperativeLevel(EXCLUSIVE) will not send
3032 * WM_ACTIVATEAPP messages. */
3033 activateapp_testdata.ddraw = NULL;
3034 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3035 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3036 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3037 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3039 /* Setting DDSCL_NORMAL with recursive invocation. */
3040 SetActiveWindow(NULL);
3041 activateapp_testdata.received = FALSE;
3042 activateapp_testdata.ddraw = ddraw;
3043 activateapp_testdata.window = window;
3044 activateapp_testdata.coop_level = DDSCL_NORMAL;
3045 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3046 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3047 ok(activateapp_testdata.received || broken(!activateapp_testdata.received),
3048 "Expected WM_ACTIVATEAPP, but did not receive it.\n");
3050 /* DDraw is in exlusive mode now. */
3051 memset(&ddsd, 0, sizeof(ddsd));
3052 ddsd.dwSize = sizeof(ddsd);
3053 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
3054 ddsd.dwBackBufferCount = 1;
3055 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
3056 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
3057 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
3058 IDirectDrawSurface_Release(surface);
3060 /* Recover again, just to be sure. */
3061 activateapp_testdata.ddraw = NULL;
3062 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3063 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3064 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3065 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3067 DestroyWindow(window);
3068 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
3069 IDirectDraw_Release(ddraw);
3072 struct format_support_check
3074 const DDPIXELFORMAT *format;
3075 BOOL supported;
3078 static HRESULT WINAPI test_unsupported_formats_cb(DDSURFACEDESC *desc, void *ctx)
3080 struct format_support_check *format = ctx;
3082 if (!memcmp(format->format, &desc->ddpfPixelFormat, sizeof(*format->format)))
3084 format->supported = TRUE;
3085 return DDENUMRET_CANCEL;
3088 return DDENUMRET_OK;
3091 static void test_unsupported_formats(void)
3093 HRESULT hr;
3094 BOOL expect_success;
3095 HWND window;
3096 IDirectDraw *ddraw;
3097 IDirect3DDevice *device;
3098 IDirectDrawSurface *surface;
3099 DDSURFACEDESC ddsd;
3100 unsigned int i, j;
3101 DWORD expected_caps;
3102 static const struct
3104 const char *name;
3105 DDPIXELFORMAT fmt;
3107 formats[] =
3110 "D3DFMT_A8R8G8B8",
3112 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
3113 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
3117 "D3DFMT_P8",
3119 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
3120 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
3124 static const DWORD caps[] = {0, DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY};
3126 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3127 0, 0, 640, 480, 0, 0, 0, 0);
3128 if (!(ddraw = create_ddraw()))
3130 skip("Failed to create a ddraw object, skipping test.\n");
3131 DestroyWindow(window);
3132 return;
3134 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
3136 skip("Failed to create a 3D device, skipping test.\n");
3137 IDirectDraw_Release(ddraw);
3138 DestroyWindow(window);
3139 return;
3142 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
3144 struct format_support_check check = {&formats[i].fmt, FALSE};
3145 hr = IDirect3DDevice_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
3146 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
3148 for (j = 0; j < sizeof(caps) / sizeof(*caps); j++)
3150 memset(&ddsd, 0, sizeof(ddsd));
3151 ddsd.dwSize = sizeof(ddsd);
3152 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
3153 ddsd.ddpfPixelFormat = formats[i].fmt;
3154 ddsd.dwWidth = 4;
3155 ddsd.dwHeight = 4;
3156 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | caps[j];
3158 if (caps[j] & DDSCAPS_VIDEOMEMORY && !check.supported)
3159 expect_success = FALSE;
3160 else
3161 expect_success = TRUE;
3163 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
3164 ok(SUCCEEDED(hr) == expect_success,
3165 "Got unexpected hr %#x for format %s, caps %#x, expected %s.\n",
3166 hr, formats[i].name, caps[j], expect_success ? "success" : "failure");
3167 if (FAILED(hr))
3168 continue;
3170 memset(&ddsd, 0, sizeof(ddsd));
3171 ddsd.dwSize = sizeof(ddsd);
3172 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &ddsd);
3173 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3175 if (caps[j] & DDSCAPS_VIDEOMEMORY)
3176 expected_caps = DDSCAPS_VIDEOMEMORY;
3177 else if (caps[j] & DDSCAPS_SYSTEMMEMORY)
3178 expected_caps = DDSCAPS_SYSTEMMEMORY;
3179 else if (check.supported)
3180 expected_caps = DDSCAPS_VIDEOMEMORY;
3181 else
3182 expected_caps = DDSCAPS_SYSTEMMEMORY;
3184 ok(ddsd.ddsCaps.dwCaps & expected_caps,
3185 "Expected capability %#x, format %s, input cap %#x.\n",
3186 expected_caps, formats[i].name, caps[j]);
3188 IDirectDrawSurface_Release(surface);
3192 IDirect3DDevice_Release(device);
3193 IDirectDraw_Release(ddraw);
3194 DestroyWindow(window);
3197 static void test_rt_caps(void)
3199 PALETTEENTRY palette_entries[256];
3200 IDirectDrawPalette *palette;
3201 IDirectDraw *ddraw;
3202 DWORD z_depth = 0;
3203 IDirect3D *d3d;
3204 unsigned int i;
3205 ULONG refcount;
3206 HWND window;
3207 HRESULT hr;
3209 static const DDPIXELFORMAT p8_fmt =
3211 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
3212 {8}, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000},
3215 static const struct
3217 const DDPIXELFORMAT *pf;
3218 DWORD caps_in;
3219 DWORD caps_out;
3220 HRESULT create_device_hr;
3221 BOOL create_may_fail;
3223 test_data[] =
3226 NULL,
3227 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
3228 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3229 D3D_OK,
3230 FALSE,
3233 NULL,
3234 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
3235 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3236 D3D_OK,
3237 FALSE,
3240 NULL,
3241 DDSCAPS_OFFSCREENPLAIN,
3242 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3243 DDERR_INVALIDCAPS,
3244 FALSE,
3247 NULL,
3248 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3249 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3250 D3DERR_SURFACENOTINVIDMEM,
3251 FALSE,
3254 NULL,
3255 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3256 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3257 DDERR_INVALIDCAPS,
3258 FALSE,
3261 NULL,
3262 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
3263 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3264 D3D_OK,
3265 FALSE,
3268 NULL,
3269 DDSCAPS_3DDEVICE,
3270 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3271 D3D_OK,
3272 FALSE,
3275 NULL,
3277 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3278 DDERR_INVALIDCAPS,
3279 FALSE,
3282 NULL,
3283 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3284 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3285 D3DERR_SURFACENOTINVIDMEM,
3286 FALSE,
3289 NULL,
3290 DDSCAPS_SYSTEMMEMORY,
3291 DDSCAPS_SYSTEMMEMORY,
3292 DDERR_INVALIDCAPS,
3293 FALSE,
3296 &p8_fmt,
3298 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3299 DDERR_INVALIDCAPS,
3300 FALSE,
3303 &p8_fmt,
3304 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
3305 ~0U /* AMD r200 */ ,
3306 DDERR_NOPALETTEATTACHED,
3307 FALSE,
3310 &p8_fmt,
3311 DDSCAPS_OFFSCREENPLAIN,
3312 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3313 DDERR_INVALIDCAPS,
3314 FALSE,
3317 &p8_fmt,
3318 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3319 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
3320 DDERR_NOPALETTEATTACHED,
3321 FALSE,
3324 &p8_fmt,
3325 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3326 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3327 DDERR_INVALIDCAPS,
3328 FALSE,
3331 NULL,
3332 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
3333 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
3334 DDERR_INVALIDCAPS,
3335 TRUE /* AMD Evergreen */,
3338 NULL,
3339 DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
3340 ~0U /* AMD Evergreen */,
3341 DDERR_INVALIDCAPS,
3342 FALSE,
3345 NULL,
3346 DDSCAPS_ZBUFFER,
3347 ~0U /* AMD Evergreen */,
3348 DDERR_INVALIDCAPS,
3349 FALSE,
3352 NULL,
3353 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
3354 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
3355 DDERR_INVALIDCAPS,
3356 TRUE /* Nvidia Kepler */,
3359 NULL,
3360 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
3361 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
3362 DDERR_INVALIDCAPS,
3363 TRUE /* Nvidia Kepler */,
3367 if (!(ddraw = create_ddraw()))
3369 skip("Failed to create a ddraw object, skipping test.\n");
3370 return;
3373 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3374 0, 0, 640, 480, 0, 0, 0, 0);
3375 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3376 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3378 if (FAILED(hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d)))
3380 skip("D3D interface is not available, skipping test.\n");
3381 goto done;
3384 hr = IDirect3D_EnumDevices(d3d, enum_z_fmt, &z_depth);
3385 if (FAILED(hr) || !z_depth)
3387 skip("No depth buffer formats available, skipping test.\n");
3388 IDirect3D_Release(d3d);
3389 goto done;
3392 memset(palette_entries, 0, sizeof(palette_entries));
3393 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
3394 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
3396 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
3398 IDirectDrawSurface *surface;
3399 DDSURFACEDESC surface_desc;
3400 IDirect3DDevice *device;
3402 memset(&surface_desc, 0, sizeof(surface_desc));
3403 surface_desc.dwSize = sizeof(surface_desc);
3404 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3405 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
3406 if (test_data[i].pf)
3408 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
3409 surface_desc.ddpfPixelFormat = *test_data[i].pf;
3411 if (test_data[i].caps_in & DDSCAPS_ZBUFFER)
3413 surface_desc.dwFlags |= DDSD_ZBUFFERBITDEPTH;
3414 U2(surface_desc).dwZBufferBitDepth = z_depth;
3416 surface_desc.dwWidth = 640;
3417 surface_desc.dwHeight = 480;
3418 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
3419 ok(SUCCEEDED(hr) || broken(test_data[i].create_may_fail),
3420 "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
3421 i, test_data[i].caps_in, hr);
3422 if (FAILED(hr))
3423 continue;
3425 memset(&surface_desc, 0, sizeof(surface_desc));
3426 surface_desc.dwSize = sizeof(surface_desc);
3427 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
3428 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
3429 ok(test_data[i].caps_out == ~0U || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out,
3430 "Test %u: Got unexpected caps %#x, expected %#x.\n",
3431 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
3433 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DHALDevice, (void **)&device);
3434 ok(hr == test_data[i].create_device_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n",
3435 i, hr, test_data[i].create_device_hr);
3436 if (hr == DDERR_NOPALETTEATTACHED)
3438 hr = IDirectDrawSurface_SetPalette(surface, palette);
3439 ok(SUCCEEDED(hr), "Test %u: Failed to set palette, hr %#x.\n", i, hr);
3440 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DHALDevice, (void **)&device);
3441 if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
3442 ok(hr == DDERR_INVALIDPIXELFORMAT, "Test %u: Got unexpected hr %#x.\n", i, hr);
3443 else
3444 ok(hr == D3DERR_SURFACENOTINVIDMEM, "Test %u: Got unexpected hr %#x.\n", i, hr);
3446 if (SUCCEEDED(hr))
3448 refcount = IDirect3DDevice_Release(device);
3449 ok(refcount == 1, "Test %u: Got unexpected refcount %u.\n", i, refcount);
3452 refcount = IDirectDrawSurface_Release(surface);
3453 ok(refcount == 0, "Test %u: The surface was not properly freed, refcount %u.\n", i, refcount);
3456 IDirectDrawPalette_Release(palette);
3457 IDirect3D_Release(d3d);
3459 done:
3460 refcount = IDirectDraw_Release(ddraw);
3461 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
3462 DestroyWindow(window);
3465 static void test_primary_caps(void)
3467 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
3468 IDirectDrawSurface *surface;
3469 DDSURFACEDESC surface_desc;
3470 IDirectDraw *ddraw;
3471 unsigned int i;
3472 ULONG refcount;
3473 HWND window;
3474 HRESULT hr;
3476 static const struct
3478 DWORD coop_level;
3479 DWORD caps_in;
3480 DWORD back_buffer_count;
3481 HRESULT hr;
3482 DWORD caps_out;
3484 test_data[] =
3487 DDSCL_NORMAL,
3488 DDSCAPS_PRIMARYSURFACE,
3489 ~0u,
3490 DD_OK,
3491 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE,
3494 DDSCL_NORMAL,
3495 DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE,
3496 ~0u,
3497 DDERR_INVALIDCAPS,
3498 ~0u,
3501 DDSCL_NORMAL,
3502 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
3503 ~0u,
3504 DD_OK,
3505 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
3508 DDSCL_NORMAL,
3509 DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER,
3510 ~0u,
3511 DDERR_INVALIDCAPS,
3512 ~0u,
3515 DDSCL_NORMAL,
3516 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP,
3517 ~0u,
3518 DDERR_INVALIDCAPS,
3519 ~0u,
3522 DDSCL_NORMAL,
3523 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX,
3524 ~0u,
3525 DDERR_INVALIDCAPS,
3526 ~0u,
3529 DDSCL_NORMAL,
3530 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
3531 ~0u,
3532 DDERR_INVALIDCAPS,
3533 ~0u,
3536 DDSCL_NORMAL,
3537 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
3539 DDERR_INVALIDCAPS,
3540 ~0u,
3543 DDSCL_NORMAL,
3544 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
3546 DDERR_NOEXCLUSIVEMODE,
3547 ~0u,
3550 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
3551 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
3553 DDERR_INVALIDCAPS,
3554 ~0u,
3557 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
3558 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
3560 DD_OK,
3561 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX,
3564 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
3565 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER,
3567 DDERR_INVALIDCAPS,
3568 ~0u,
3571 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
3572 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_BACKBUFFER,
3574 DDERR_INVALIDCAPS,
3575 ~0u,
3579 if (!(ddraw = create_ddraw()))
3581 skip("Failed to create a ddraw object, skipping test.\n");
3582 return;
3585 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3586 0, 0, 640, 480, 0, 0, 0, 0);
3588 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
3590 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, test_data[i].coop_level);
3591 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3593 memset(&surface_desc, 0, sizeof(surface_desc));
3594 surface_desc.dwSize = sizeof(surface_desc);
3595 surface_desc.dwFlags = DDSD_CAPS;
3596 if (test_data[i].back_buffer_count != ~0u)
3597 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
3598 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
3599 surface_desc.dwBackBufferCount = test_data[i].back_buffer_count;
3600 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
3601 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
3602 if (FAILED(hr))
3603 continue;
3605 memset(&surface_desc, 0, sizeof(surface_desc));
3606 surface_desc.dwSize = sizeof(surface_desc);
3607 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
3608 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
3609 ok((surface_desc.ddsCaps.dwCaps & ~placement) == test_data[i].caps_out,
3610 "Test %u: Got unexpected caps %#x, expected %#x.\n",
3611 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
3613 IDirectDrawSurface_Release(surface);
3616 refcount = IDirectDraw_Release(ddraw);
3617 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
3618 DestroyWindow(window);
3621 static void test_surface_lock(void)
3623 IDirectDraw *ddraw;
3624 IDirect3D *d3d = NULL;
3625 IDirectDrawSurface *surface;
3626 HRESULT hr;
3627 HWND window;
3628 unsigned int i;
3629 DDSURFACEDESC ddsd;
3630 ULONG refcount;
3631 DWORD z_depth = 0;
3632 static const struct
3634 DWORD caps;
3635 const char *name;
3637 tests[] =
3640 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
3641 "videomemory offscreenplain"
3644 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
3645 "systemmemory offscreenplain"
3648 DDSCAPS_PRIMARYSURFACE,
3649 "primary"
3652 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
3653 "videomemory texture"
3656 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
3657 "systemmemory texture"
3660 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
3661 "render target"
3664 DDSCAPS_ZBUFFER,
3665 "Z buffer"
3669 if (!(ddraw = create_ddraw()))
3671 skip("Failed to create a ddraw object, skipping test.\n");
3672 return;
3675 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3676 0, 0, 640, 480, 0, 0, 0, 0);
3677 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3678 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3680 if (FAILED(hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d)))
3682 skip("D3D interface is not available, skipping test.\n");
3683 goto done;
3686 hr = IDirect3D_EnumDevices(d3d, enum_z_fmt, &z_depth);
3687 if (FAILED(hr) || !z_depth)
3689 skip("No depth buffer formats available, skipping test.\n");
3690 goto done;
3693 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
3695 memset(&ddsd, 0, sizeof(ddsd)),
3696 ddsd.dwSize = sizeof(ddsd);
3697 ddsd.dwFlags = DDSD_CAPS;
3698 if (!(tests[i].caps & DDSCAPS_PRIMARYSURFACE))
3700 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
3701 ddsd.dwWidth = 64;
3702 ddsd.dwHeight = 64;
3704 if (tests[i].caps & DDSCAPS_ZBUFFER)
3706 ddsd.dwFlags |= DDSD_ZBUFFERBITDEPTH;
3707 U2(ddsd).dwZBufferBitDepth = z_depth;
3709 ddsd.ddsCaps.dwCaps = tests[i].caps;
3711 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
3712 ok(SUCCEEDED(hr), "Failed to create surface, type %s, hr %#x.\n", tests[i].name, hr);
3714 memset(&ddsd, 0, sizeof(ddsd)),
3715 ddsd.dwSize = sizeof(ddsd);
3716 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
3717 ok(SUCCEEDED(hr), "Failed to lock surface, type %s, hr %#x.\n", tests[i].name, hr);
3718 if (SUCCEEDED(hr))
3720 hr = IDirectDrawSurface_Unlock(surface, NULL);
3721 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
3724 IDirectDrawSurface_Release(surface);
3728 done:
3729 if (d3d)
3730 IDirect3D_Release(d3d);
3731 refcount = IDirectDraw_Release(ddraw);
3732 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
3733 DestroyWindow(window);
3736 static void test_surface_discard(void)
3738 IDirectDraw *ddraw;
3739 HRESULT hr;
3740 HWND window;
3741 DDSURFACEDESC ddsd;
3742 IDirectDrawSurface *surface, *primary;
3743 void *addr;
3744 static const struct
3746 DWORD caps;
3747 BOOL discard;
3749 tests[] =
3751 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, TRUE},
3752 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, FALSE},
3753 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, TRUE},
3754 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, FALSE},
3756 unsigned int i;
3758 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3759 0, 0, 640, 480, 0, 0, 0, 0);
3760 if (!(ddraw = create_ddraw()))
3762 skip("Failed to create a ddraw object, skipping test.\n");
3763 DestroyWindow(window);
3764 return;
3766 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3767 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3769 memset(&ddsd, 0, sizeof(ddsd));
3770 ddsd.dwSize = sizeof(ddsd);
3771 ddsd.dwFlags = DDSD_CAPS;
3772 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3773 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
3775 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
3777 BOOL discarded;
3779 memset(&ddsd, 0, sizeof(ddsd));
3780 ddsd.dwSize = sizeof(ddsd);
3781 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3782 ddsd.ddsCaps.dwCaps = tests[i].caps;
3783 ddsd.dwWidth = 64;
3784 ddsd.dwHeight = 64;
3785 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
3786 if (FAILED(hr))
3788 skip("Failed to create surface, skipping.\n");
3789 continue;
3792 memset(&ddsd, 0, sizeof(ddsd));
3793 ddsd.dwSize = sizeof(ddsd);
3794 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
3795 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
3796 addr = ddsd.lpSurface;
3797 hr = IDirectDrawSurface_Unlock(surface, NULL);
3798 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
3800 memset(&ddsd, 0, sizeof(ddsd));
3801 ddsd.dwSize = sizeof(ddsd);
3802 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL);
3803 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
3804 discarded = ddsd.lpSurface != addr;
3805 hr = IDirectDrawSurface_Unlock(surface, NULL);
3806 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
3808 hr = IDirectDrawSurface_Blt(primary, NULL, surface, NULL, DDBLT_WAIT, NULL);
3809 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
3811 memset(&ddsd, 0, sizeof(ddsd));
3812 ddsd.dwSize = sizeof(ddsd);
3813 hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL);
3814 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
3815 discarded |= ddsd.lpSurface != addr;
3816 hr = IDirectDrawSurface_Unlock(surface, NULL);
3817 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
3819 IDirectDrawSurface_Release(surface);
3821 /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler,
3822 * AMD r500, evergreen). Windows XP, at least on AMD r200, never changes the pointer. */
3823 ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i);
3826 IDirectDrawSurface_Release(primary);
3827 IDirectDraw_Release(ddraw);
3828 DestroyWindow(window);
3831 static void test_flip(void)
3833 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
3834 IDirectDrawSurface *primary, *backbuffer1, *backbuffer2, *backbuffer3, *surface;
3835 DDSCAPS caps = {DDSCAPS_FLIP};
3836 DDSURFACEDESC surface_desc;
3837 BOOL sysmem_primary;
3838 IDirectDraw *ddraw;
3839 D3DCOLOR color;
3840 ULONG refcount;
3841 HWND window;
3842 DDBLTFX fx;
3843 HRESULT hr;
3845 if (!(ddraw = create_ddraw()))
3847 skip("Failed to create a ddraw object, skipping test.\n");
3848 return;
3851 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3852 0, 0, 640, 480, 0, 0, 0, 0);
3854 hr = IDirectDraw_SetDisplayMode(ddraw, 640, 480, 32);
3855 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3856 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3857 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3859 memset(&surface_desc, 0, sizeof(surface_desc));
3860 surface_desc.dwSize = sizeof(surface_desc);
3861 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
3862 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
3863 surface_desc.dwBackBufferCount = 3;
3864 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &primary, NULL);
3865 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
3867 memset(&surface_desc, 0, sizeof(surface_desc));
3868 surface_desc.dwSize = sizeof(surface_desc);
3869 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &surface_desc);
3870 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3871 ok((surface_desc.ddsCaps.dwCaps & ~placement)
3872 == (DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX),
3873 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
3874 sysmem_primary = surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
3876 hr = IDirectDrawSurface_GetAttachedSurface(primary, &caps, &backbuffer1);
3877 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
3878 memset(&surface_desc, 0, sizeof(surface_desc));
3879 surface_desc.dwSize = sizeof(surface_desc);
3880 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer1, &surface_desc);
3881 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3882 ok(!surface_desc.dwBackBufferCount, "Got unexpected back buffer count %u.\n", surface_desc.dwBackBufferCount);
3883 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_BACKBUFFER),
3884 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
3886 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer1, &caps, &backbuffer2);
3887 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
3888 memset(&surface_desc, 0, sizeof(surface_desc));
3889 surface_desc.dwSize = sizeof(surface_desc);
3890 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer2, &surface_desc);
3891 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3892 ok(!surface_desc.dwBackBufferCount, "Got unexpected back buffer count %u.\n", surface_desc.dwBackBufferCount);
3893 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX),
3894 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
3896 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer2, &caps, &backbuffer3);
3897 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
3898 memset(&surface_desc, 0, sizeof(surface_desc));
3899 surface_desc.dwSize = sizeof(surface_desc);
3900 hr = IDirectDrawSurface_GetSurfaceDesc(backbuffer3, &surface_desc);
3901 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3902 ok(!surface_desc.dwBackBufferCount, "Got unexpected back buffer count %u.\n", surface_desc.dwBackBufferCount);
3903 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX),
3904 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
3906 hr = IDirectDrawSurface_GetAttachedSurface(backbuffer3, &caps, &surface);
3907 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
3908 ok(surface == primary, "Got unexpected surface %p, expected %p.\n", surface, primary);
3909 IDirectDrawSurface_Release(surface);
3911 memset(&surface_desc, 0, sizeof(surface_desc));
3912 surface_desc.dwSize = sizeof(surface_desc);
3913 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3914 surface_desc.ddsCaps.dwCaps = 0;
3915 surface_desc.dwWidth = 640;
3916 surface_desc.dwHeight = 480;
3917 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
3918 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
3919 hr = IDirectDrawSurface_Flip(primary, surface, DDFLIP_WAIT);
3920 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
3921 IDirectDrawSurface_Release(surface);
3923 hr = IDirectDrawSurface_Flip(primary, primary, DDFLIP_WAIT);
3924 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
3925 hr = IDirectDrawSurface_Flip(backbuffer1, NULL, DDFLIP_WAIT);
3926 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
3927 hr = IDirectDrawSurface_Flip(backbuffer2, NULL, DDFLIP_WAIT);
3928 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
3929 hr = IDirectDrawSurface_Flip(backbuffer3, NULL, DDFLIP_WAIT);
3930 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
3932 memset(&fx, 0, sizeof(fx));
3933 fx.dwSize = sizeof(fx);
3934 U5(fx).dwFillColor = 0xffff0000;
3935 hr = IDirectDrawSurface_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3936 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3937 U5(fx).dwFillColor = 0xff00ff00;
3938 hr = IDirectDrawSurface_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3939 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3940 U5(fx).dwFillColor = 0xff0000ff;
3941 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3942 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3944 hr = IDirectDrawSurface_Flip(primary, NULL, DDFLIP_WAIT);
3945 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
3946 color = get_surface_color(backbuffer1, 320, 240);
3947 /* The testbot seems to just copy the contents of one surface to all the
3948 * others, instead of properly flipping. */
3949 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
3950 "Got unexpected color 0x%08x.\n", color);
3951 color = get_surface_color(backbuffer2, 320, 240);
3952 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
3953 U5(fx).dwFillColor = 0xffff0000;
3954 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3955 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3957 hr = IDirectDrawSurface_Flip(primary, NULL, DDFLIP_WAIT);
3958 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
3959 color = get_surface_color(backbuffer1, 320, 240);
3960 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
3961 "Got unexpected color 0x%08x.\n", color);
3962 color = get_surface_color(backbuffer2, 320, 240);
3963 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
3964 U5(fx).dwFillColor = 0xff00ff00;
3965 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3966 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3968 hr = IDirectDrawSurface_Flip(primary, NULL, DDFLIP_WAIT);
3969 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
3970 color = get_surface_color(backbuffer1, 320, 240);
3971 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
3972 "Got unexpected color 0x%08x.\n", color);
3973 color = get_surface_color(backbuffer2, 320, 240);
3974 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
3975 U5(fx).dwFillColor = 0xff0000ff;
3976 hr = IDirectDrawSurface_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3977 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3979 hr = IDirectDrawSurface_Flip(primary, backbuffer1, DDFLIP_WAIT);
3980 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
3981 color = get_surface_color(backbuffer2, 320, 240);
3982 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
3983 "Got unexpected color 0x%08x.\n", color);
3984 color = get_surface_color(backbuffer3, 320, 240);
3985 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
3986 U5(fx).dwFillColor = 0xffff0000;
3987 hr = IDirectDrawSurface_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3988 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
3990 hr = IDirectDrawSurface_Flip(primary, backbuffer2, DDFLIP_WAIT);
3991 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
3992 color = get_surface_color(backbuffer1, 320, 240);
3993 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
3994 color = get_surface_color(backbuffer3, 320, 240);
3995 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
3996 "Got unexpected color 0x%08x.\n", color);
3997 U5(fx).dwFillColor = 0xff00ff00;
3998 hr = IDirectDrawSurface_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
3999 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
4001 hr = IDirectDrawSurface_Flip(primary, backbuffer3, DDFLIP_WAIT);
4002 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
4003 color = get_surface_color(backbuffer1, 320, 240);
4004 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
4005 "Got unexpected color 0x%08x.\n", color);
4006 color = get_surface_color(backbuffer2, 320, 240);
4007 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
4009 IDirectDrawSurface_Release(backbuffer3);
4010 IDirectDrawSurface_Release(backbuffer2);
4011 IDirectDrawSurface_Release(backbuffer1);
4012 IDirectDrawSurface_Release(primary);
4013 refcount = IDirectDraw_Release(ddraw);
4014 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
4015 DestroyWindow(window);
4018 static void test_sysmem_overlay(void)
4020 IDirectDraw *ddraw;
4021 HWND window;
4022 HRESULT hr;
4023 DDSURFACEDESC ddsd;
4024 IDirectDrawSurface *surface;
4025 ULONG ref;
4027 if (!(ddraw = create_ddraw()))
4029 skip("Failed to create a ddraw object, skipping test.\n");
4030 return;
4033 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4034 0, 0, 640, 480, 0, 0, 0, 0);
4036 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4037 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4039 memset(&ddsd, 0, sizeof(ddsd));
4040 ddsd.dwSize = sizeof(ddsd);
4041 ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
4042 ddsd.dwWidth = 16;
4043 ddsd.dwHeight = 16;
4044 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OVERLAY;
4045 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
4046 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
4047 U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
4048 U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
4049 U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
4050 U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
4051 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
4052 ok(hr == DDERR_NOOVERLAYHW, "Got unexpected hr %#x.\n", hr);
4054 ref = IDirectDraw_Release(ddraw);
4055 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
4056 DestroyWindow(window);
4059 static void test_primary_palette(void)
4061 DDSCAPS surface_caps = {DDSCAPS_FLIP};
4062 IDirectDrawSurface *primary, *backbuffer;
4063 PALETTEENTRY palette_entries[256];
4064 IDirectDrawPalette *palette, *tmp;
4065 DDSURFACEDESC surface_desc;
4066 IDirectDraw *ddraw;
4067 DWORD palette_caps;
4068 ULONG refcount;
4069 HWND window;
4070 HRESULT hr;
4072 if (!(ddraw = create_ddraw()))
4074 skip("Failed to create a ddraw object, skipping test.\n");
4075 return;
4078 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4079 0, 0, 640, 480, 0, 0, 0, 0);
4080 hr = IDirectDraw_SetDisplayMode(ddraw, 640, 480, 8);
4081 if (hr == E_NOTIMPL)
4083 win_skip("changing display mode is not supported (8bpp)\n");
4084 IDirectDraw_Release(ddraw);
4085 DestroyWindow(window);
4086 return;
4088 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
4089 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4090 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4092 memset(&surface_desc, 0, sizeof(surface_desc));
4093 surface_desc.dwSize = sizeof(surface_desc);
4094 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
4095 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
4096 surface_desc.dwBackBufferCount = 1;
4097 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &primary, NULL);
4098 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4099 hr = IDirectDrawSurface_GetAttachedSurface(primary, &surface_caps, &backbuffer);
4100 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
4102 memset(palette_entries, 0, sizeof(palette_entries));
4103 hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_entries, &palette, NULL);
4104 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
4105 refcount = get_refcount((IUnknown *)palette);
4106 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
4108 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
4109 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
4110 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
4112 hr = IDirectDrawSurface_SetPalette(primary, palette);
4113 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
4114 refcount = get_refcount((IUnknown *)palette);
4115 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
4117 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
4118 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
4119 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE | DDPCAPS_ALLOW256),
4120 "Got unexpected palette caps %#x.\n", palette_caps);
4122 hr = IDirectDrawSurface_SetPalette(primary, NULL);
4123 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
4124 refcount = get_refcount((IUnknown *)palette);
4125 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
4127 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
4128 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
4129 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
4131 hr = IDirectDrawSurface_SetPalette(primary, palette);
4132 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
4133 refcount = get_refcount((IUnknown *)palette);
4134 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
4136 hr = IDirectDrawSurface_GetPalette(primary, &tmp);
4137 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
4138 ok(tmp == palette, "Got unexpected palette %p, expected %p.\n", tmp, palette);
4139 IDirectDrawPalette_Release(tmp);
4140 hr = IDirectDrawSurface_GetPalette(backbuffer, &tmp);
4141 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
4143 refcount = IDirectDrawPalette_Release(palette);
4144 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
4145 refcount = IDirectDrawPalette_Release(palette);
4146 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4148 /* Note that this only seems to work when the palette is attached to the
4149 * primary surface. When attached to a regular surface, attempting to get
4150 * the palette here will cause an access violation. */
4151 hr = IDirectDrawSurface_GetPalette(primary, &tmp);
4152 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
4154 refcount = IDirectDrawSurface_Release(backbuffer);
4155 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
4156 refcount = IDirectDrawSurface_Release(primary);
4157 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4158 refcount = IDirectDraw_Release(ddraw);
4159 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4160 DestroyWindow(window);
4163 static HRESULT WINAPI surface_counter(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
4165 UINT *surface_count = context;
4167 ++(*surface_count);
4168 IDirectDrawSurface_Release(surface);
4170 return DDENUMRET_OK;
4173 static void test_surface_attachment(void)
4175 IDirectDrawSurface *surface1, *surface2, *surface3, *surface4;
4176 DDSCAPS caps = {DDSCAPS_TEXTURE};
4177 DDSURFACEDESC surface_desc;
4178 IDirectDraw *ddraw;
4179 UINT surface_count;
4180 ULONG refcount;
4181 HWND window;
4182 HRESULT hr;
4184 if (!(ddraw = create_ddraw()))
4186 skip("Failed to create a ddraw object, skipping test.\n");
4187 return;
4190 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4191 0, 0, 640, 480, 0, 0, 0, 0);
4192 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4193 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4195 memset(&surface_desc, 0, sizeof(surface_desc));
4196 surface_desc.dwSize = sizeof(surface_desc);
4197 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
4198 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
4199 U2(surface_desc).dwMipMapCount = 3;
4200 surface_desc.dwWidth = 128;
4201 surface_desc.dwHeight = 128;
4202 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
4203 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4205 hr = IDirectDrawSurface_GetAttachedSurface(surface1, &caps, &surface2);
4206 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
4207 hr = IDirectDrawSurface_GetAttachedSurface(surface2, &caps, &surface3);
4208 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
4209 hr = IDirectDrawSurface_GetAttachedSurface(surface3, &caps, &surface4);
4210 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
4212 surface_count = 0;
4213 IDirectDrawSurface_EnumAttachedSurfaces(surface1, &surface_count, surface_counter);
4214 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
4215 surface_count = 0;
4216 IDirectDrawSurface_EnumAttachedSurfaces(surface2, &surface_count, surface_counter);
4217 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
4218 surface_count = 0;
4219 IDirectDrawSurface_EnumAttachedSurfaces(surface3, &surface_count, surface_counter);
4220 ok(!surface_count, "Got unexpected surface_count %u.\n", surface_count);
4222 memset(&surface_desc, 0, sizeof(surface_desc));
4223 surface_desc.dwSize = sizeof(surface_desc);
4224 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4225 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
4226 surface_desc.dwWidth = 16;
4227 surface_desc.dwHeight = 16;
4228 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
4229 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4231 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
4232 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4233 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
4234 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4235 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface4);
4236 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4237 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface3);
4238 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4239 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface4);
4240 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4241 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface2);
4242 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4244 IDirectDrawSurface_Release(surface4);
4246 memset(&surface_desc, 0, sizeof(surface_desc));
4247 surface_desc.dwSize = sizeof(surface_desc);
4248 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4249 surface_desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
4250 surface_desc.dwWidth = 16;
4251 surface_desc.dwHeight = 16;
4252 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
4253 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4255 if (SUCCEEDED(hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4)))
4257 skip("Running on refrast, skipping some tests.\n");
4258 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface4);
4259 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4261 else
4263 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4264 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
4265 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4266 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface4);
4267 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4268 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface3);
4269 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4270 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface4);
4271 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4272 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface2);
4273 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4276 IDirectDrawSurface_Release(surface4);
4277 IDirectDrawSurface_Release(surface3);
4278 IDirectDrawSurface_Release(surface2);
4279 IDirectDrawSurface_Release(surface1);
4281 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4282 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4284 /* Try a single primary and two offscreen plain surfaces. */
4285 memset(&surface_desc, 0, sizeof(surface_desc));
4286 surface_desc.dwSize = sizeof(surface_desc);
4287 surface_desc.dwFlags = DDSD_CAPS;
4288 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4289 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
4290 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4292 memset(&surface_desc, 0, sizeof(surface_desc));
4293 surface_desc.dwSize = sizeof(surface_desc);
4294 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4295 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4296 surface_desc.dwWidth = GetSystemMetrics(SM_CXSCREEN);
4297 surface_desc.dwHeight = GetSystemMetrics(SM_CYSCREEN);
4298 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
4299 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4301 memset(&surface_desc, 0, sizeof(surface_desc));
4302 surface_desc.dwSize = sizeof(surface_desc);
4303 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4304 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4305 surface_desc.dwWidth = GetSystemMetrics(SM_CXSCREEN);
4306 surface_desc.dwHeight = GetSystemMetrics(SM_CYSCREEN);
4307 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
4308 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4310 /* This one has a different size. */
4311 memset(&surface_desc, 0, sizeof(surface_desc));
4312 surface_desc.dwSize = sizeof(surface_desc);
4313 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4314 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4315 surface_desc.dwWidth = 128;
4316 surface_desc.dwHeight = 128;
4317 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
4318 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4320 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
4321 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4322 /* Try the reverse without detaching first. */
4323 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
4324 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
4325 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
4326 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4328 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
4329 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4330 /* Try to detach reversed. */
4331 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
4332 ok(hr == DDERR_CANNOTDETACHSURFACE, "Got unexpected hr %#x.\n", hr);
4333 hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface1);
4334 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4336 hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface3);
4337 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4338 hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface3);
4339 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4341 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
4342 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4343 hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
4344 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
4346 IDirectDrawSurface_Release(surface4);
4347 IDirectDrawSurface_Release(surface3);
4348 IDirectDrawSurface_Release(surface2);
4349 IDirectDrawSurface_Release(surface1);
4351 /* Test DeleteAttachedSurface() and automatic detachment of attached surfaces on release. */
4352 memset(&surface_desc, 0, sizeof(surface_desc));
4353 surface_desc.dwSize = sizeof(surface_desc);
4354 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
4355 surface_desc.dwWidth = 64;
4356 surface_desc.dwHeight = 64;
4357 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
4358 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
4359 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
4360 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 16;
4361 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0xf800;
4362 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x07e0;
4363 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x001f;
4364 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
4365 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4366 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
4367 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4369 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
4370 surface_desc.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
4371 U1(surface_desc.ddpfPixelFormat).dwZBufferBitDepth = 16;
4372 U3(surface_desc.ddpfPixelFormat).dwZBitMask = 0x0000ffff;
4373 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
4374 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4376 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
4377 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4378 refcount = get_refcount((IUnknown *)surface2);
4379 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
4380 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
4381 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
4383 /* Attaching while already attached to other surface. */
4384 hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface2);
4385 todo_wine ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4386 hr = IDirectDrawSurface_DeleteAttachedSurface(surface3, 0, surface2);
4387 todo_wine ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4388 IDirectDrawSurface_Release(surface3);
4390 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
4391 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
4392 refcount = get_refcount((IUnknown *)surface2);
4393 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
4395 /* Automatic detachment on release. */
4396 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
4397 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
4398 refcount = get_refcount((IUnknown *)surface2);
4399 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
4400 refcount = IDirectDrawSurface_Release(surface1);
4401 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4402 refcount = IDirectDrawSurface_Release(surface2);
4403 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4404 refcount = IDirectDraw_Release(ddraw);
4405 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
4406 DestroyWindow(window);
4409 static void test_pixel_format(void)
4411 HWND window, window2 = NULL;
4412 HDC hdc, hdc2 = NULL;
4413 HMODULE gl = NULL;
4414 int format, test_format;
4415 PIXELFORMATDESCRIPTOR pfd;
4416 IDirectDraw *ddraw = NULL;
4417 IDirectDrawClipper *clipper = NULL;
4418 DDSURFACEDESC ddsd;
4419 IDirectDrawSurface *primary = NULL;
4420 DDBLTFX fx;
4421 HRESULT hr;
4423 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
4424 100, 100, 160, 160, NULL, NULL, NULL, NULL);
4425 if (!window)
4427 skip("Failed to create window\n");
4428 return;
4431 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
4432 100, 100, 160, 160, NULL, NULL, NULL, NULL);
4434 hdc = GetDC(window);
4435 if (!hdc)
4437 skip("Failed to get DC\n");
4438 goto cleanup;
4441 if (window2)
4442 hdc2 = GetDC(window2);
4444 gl = LoadLibraryA("opengl32.dll");
4445 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
4447 format = GetPixelFormat(hdc);
4448 ok(format == 0, "new window has pixel format %d\n", format);
4450 ZeroMemory(&pfd, sizeof(pfd));
4451 pfd.nSize = sizeof(pfd);
4452 pfd.nVersion = 1;
4453 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
4454 pfd.iPixelType = PFD_TYPE_RGBA;
4455 pfd.iLayerType = PFD_MAIN_PLANE;
4456 format = ChoosePixelFormat(hdc, &pfd);
4457 if (format <= 0)
4459 skip("no pixel format available\n");
4460 goto cleanup;
4463 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
4465 skip("failed to set pixel format\n");
4466 goto cleanup;
4469 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
4471 skip("failed to set pixel format on second window\n");
4472 if (hdc2)
4474 ReleaseDC(window2, hdc2);
4475 hdc2 = NULL;
4479 ddraw = create_ddraw();
4480 if (!ddraw)
4482 skip("Failed to create ddraw object\n");
4483 goto cleanup;
4486 test_format = GetPixelFormat(hdc);
4487 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
4489 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4490 if (FAILED(hr))
4492 skip("Failed to set cooperative level, hr %#x.\n", hr);
4493 goto cleanup;
4496 test_format = GetPixelFormat(hdc);
4497 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
4499 if (hdc2)
4501 hr = IDirectDraw_CreateClipper(ddraw, 0, &clipper, NULL);
4502 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
4503 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window2);
4504 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
4506 test_format = GetPixelFormat(hdc);
4507 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
4509 test_format = GetPixelFormat(hdc2);
4510 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
4513 memset(&ddsd, 0, sizeof(ddsd));
4514 ddsd.dwSize = sizeof(ddsd);
4515 ddsd.dwFlags = DDSD_CAPS;
4516 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4518 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
4519 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
4521 test_format = GetPixelFormat(hdc);
4522 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
4524 if (hdc2)
4526 test_format = GetPixelFormat(hdc2);
4527 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
4530 if (clipper)
4532 hr = IDirectDrawSurface_SetClipper(primary, clipper);
4533 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
4535 test_format = GetPixelFormat(hdc);
4536 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
4538 test_format = GetPixelFormat(hdc2);
4539 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
4542 memset(&fx, 0, sizeof(fx));
4543 fx.dwSize = sizeof(fx);
4544 hr = IDirectDrawSurface_Blt(primary, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
4545 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
4547 test_format = GetPixelFormat(hdc);
4548 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
4550 if (hdc2)
4552 test_format = GetPixelFormat(hdc2);
4553 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
4556 cleanup:
4557 if (primary) IDirectDrawSurface_Release(primary);
4558 if (clipper) IDirectDrawClipper_Release(clipper);
4559 if (ddraw) IDirectDraw_Release(ddraw);
4560 if (gl) FreeLibrary(gl);
4561 if (hdc) ReleaseDC(window, hdc);
4562 if (hdc2) ReleaseDC(window2, hdc2);
4563 if (window) DestroyWindow(window);
4564 if (window2) DestroyWindow(window2);
4567 START_TEST(ddraw1)
4569 test_coop_level_create_device_window();
4570 test_clipper_blt();
4571 test_coop_level_d3d_state();
4572 test_surface_interface_mismatch();
4573 test_coop_level_threaded();
4574 test_viewport();
4575 test_zenable();
4576 test_ck_rgba();
4577 test_ck_default();
4578 test_ck_complex();
4579 test_surface_qi();
4580 test_device_qi();
4581 test_wndproc();
4582 test_window_style();
4583 test_redundant_mode_set();
4584 test_coop_level_mode_set();
4585 test_coop_level_mode_set_multi();
4586 test_initialize();
4587 test_coop_level_surf_create();
4588 test_coop_level_multi_window();
4589 test_clear_rect_count();
4590 test_coop_level_activateapp();
4591 test_unsupported_formats();
4592 test_rt_caps();
4593 test_primary_caps();
4594 test_surface_lock();
4595 test_surface_discard();
4596 test_flip();
4597 test_sysmem_overlay();
4598 test_primary_palette();
4599 test_surface_attachment();
4600 test_pixel_format();