2 * Copyright 2011-2012 Henri Verbeet for CodeWeavers
3 * Copyright 2012-2013 Stefan Dösinger for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "wine/test.h"
24 struct create_window_thread_param
27 HANDLE window_created;
28 HANDLE destroy_window;
32 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
34 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
36 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
38 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
40 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
44 static DWORD WINAPI create_window_thread_proc(void *param)
46 struct create_window_thread_param *p = param;
50 p->window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
51 0, 0, 640, 480, 0, 0, 0, 0);
52 ret = SetEvent(p->window_created);
53 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
59 while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
60 DispatchMessage(&msg);
61 res = WaitForSingleObject(p->destroy_window, 100);
62 if (res == WAIT_OBJECT_0)
64 if (res != WAIT_TIMEOUT)
66 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
71 DestroyWindow(p->window);
76 static void create_window_thread(struct create_window_thread_param *p)
80 p->window_created = CreateEvent(NULL, FALSE, FALSE, NULL);
81 ok(!!p->window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
82 p->destroy_window = CreateEvent(NULL, FALSE, FALSE, NULL);
83 ok(!!p->destroy_window, "CreateEvent failed, last error %#x.\n", GetLastError());
84 p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
85 ok(!!p->thread, "Failed to create thread, last error %#x.\n", GetLastError());
86 res = WaitForSingleObject(p->window_created, INFINITE);
87 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
90 static void destroy_window_thread(struct create_window_thread_param *p)
92 SetEvent(p->destroy_window);
93 WaitForSingleObject(p->thread, INFINITE);
94 CloseHandle(p->destroy_window);
95 CloseHandle(p->window_created);
96 CloseHandle(p->thread);
99 static D3DCOLOR get_surface_color(IDirectDrawSurface *surface, UINT x, UINT y)
101 RECT rect = {x, y, x + 1, y + 1};
102 DDSURFACEDESC surface_desc;
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);
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);
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);
131 pv->dwFlags = D3DPROCESSVERTICES_COPY;
132 pv->wStart = base_idx;
134 pv->dwCount = vertex_count;
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);
149 U1(*rs).drstRenderStateType = state;
150 U2(*rs).dwArg[0] = value;
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);
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;
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;
179 static void emit_end(void **ptr)
181 D3DINSTRUCTION *inst = *ptr;
183 inst->bOpcode = D3DOP_EXIT;
190 static void set_execute_data(IDirect3DExecuteBuffer *execute_buffer, UINT vertex_count, UINT offset, UINT len)
192 D3DEXECUTEDATA exec_data;
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)
214 else if (hal_desc->dwDeviceZBufferBitDepth & DDBD_24)
216 else if (hal_desc->dwDeviceZBufferBitDepth & DDBD_16)
222 static IDirectDraw *create_ddraw(void)
226 if (FAILED(DirectDrawCreate(NULL, &ddraw, NULL)))
232 static IDirect3DDevice *create_device(IDirectDraw *ddraw, HWND window, DWORD coop_level)
234 IDirectDrawSurface *surface, *ds;
235 IDirect3DDevice *device = NULL;
236 DDSURFACEDESC surface_desc;
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);
270 IDirectDrawSurface_Release(surface);
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);
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);
294 IDirectDrawSurface_Release(surface);
298 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
299 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
300 IDirectDrawSurface_Release(ds);
303 IDirectDrawSurface_Release(surface);
307 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DHALDevice, (void **)&device);
308 IDirectDrawSurface_Release(surface);
315 static IDirect3DViewport *create_viewport(IDirect3DDevice *device, UINT x, UINT y, UINT w, UINT h)
317 IDirect3DViewport *viewport;
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);
334 vp.dvScaleX = (float)w / 2.0f;
335 vp.dvScaleY = (float)h / 2.0f;
340 hr = IDirect3DViewport_SetViewport(viewport, &vp);
341 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
342 IDirect3D_Release(d3d);
347 static void viewport_set_background(IDirect3DDevice *device, IDirect3DViewport *viewport,
348 IDirect3DMaterial *material)
350 D3DMATERIALHANDLE material_handle;
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)
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;
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);
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)
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)
415 if (!(ddraw = create_ddraw()))
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);
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;
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);
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);
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;
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);
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");
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;
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 ddraw object, skipping test.\n");
749 DestroyWindow(window);
752 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
754 skip("Failed to create D3D device, skipping test.\n");
755 IDirectDraw_Release(ddraw);
756 DestroyWindow(window);
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;
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");
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);
846 skip("Failed to get the IDirectDrawSurface3 interface, skipping test.\n");
850 hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d);
853 skip("Failed to get the IDirect3D interface, skipping test.\n");
857 hr = IDirect3D_EnumDevices(d3d, enum_z_fmt, &z_depth);
858 if (FAILED(hr) || !z_depth)
860 skip("No depth buffer formats available, skipping test.\n");
864 memset(&surface_desc, 0, sizeof(surface_desc));
865 surface_desc.dwSize = sizeof(surface_desc);
866 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
867 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
868 U2(surface_desc).dwZBufferBitDepth = z_depth;
869 surface_desc.dwWidth = 640;
870 surface_desc.dwHeight = 480;
871 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &ds, NULL);
872 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
876 /* Using a different surface interface version still works */
877 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
878 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
879 refcount = IDirectDrawSurface_Release(ds);
880 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
885 hr = IDirectDrawSurface3_QueryInterface(surface3, &IID_IDirect3DHALDevice, (void **)&device);
886 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
890 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
891 viewport = create_viewport(device, 0, 0, 640, 480);
892 viewport_set_background(device, viewport, background);
894 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
895 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
896 color = get_surface_color(surface, 320, 240);
897 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
901 destroy_viewport(device, viewport);
903 destroy_material(background);
904 if (surface3) IDirectDrawSurface3_Release(surface3);
905 if (surface) IDirectDrawSurface_Release(surface);
906 if (device) IDirect3DDevice_Release(device);
907 if (d3d) IDirect3D_Release(d3d);
908 if (ddraw) IDirectDraw_Release(ddraw);
909 DestroyWindow(window);
912 static void test_coop_level_threaded(void)
914 struct create_window_thread_param p;
918 if (!(ddraw = create_ddraw()))
920 skip("Failed to create a ddraw object, skipping test.\n");
923 create_window_thread(&p);
925 hr = IDirectDraw_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
926 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
928 IDirectDraw_Release(ddraw);
929 destroy_window_thread(&p);
932 static ULONG get_refcount(IUnknown *test_iface)
934 IUnknown_AddRef(test_iface);
935 return IUnknown_Release(test_iface);
938 static void test_viewport_interfaces(void)
944 IDirect3DViewport *viewport;
945 IDirect3DViewport2 *viewport2;
946 IDirect3DViewport3 *viewport3;
947 IDirectDrawGammaControl *gamma;
950 if (!(ddraw = create_ddraw()))
952 skip("Failed to create ddraw object, skipping test.\n");
955 hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d);
956 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get d3d interface, hr %#x.\n", hr);
959 skip("Direct3D not available, skipping tests\n");
960 IDirectDraw_Release(ddraw);
963 ref = get_refcount((IUnknown *)d3d);
964 ok(ref == 2, "IDirect3D refcount is %d\n", ref);
966 hr = IDirect3D_CreateViewport(d3d, &viewport, NULL);
967 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
968 ref = get_refcount((IUnknown *)viewport);
969 ok(ref == 1, "Initial IDirect3DViewport refcount is %u\n", ref);
970 ref = get_refcount((IUnknown *)d3d);
971 ok(ref == 2, "IDirect3D refcount is %u\n", ref);
973 /* E_FAIL return values are returned by Winetestbot Windows NT machines. While not supporting
974 * newer interfaces is legitimate for old ddraw versions, E_FAIL violates Microsoft's rules
975 * for QueryInterface, hence the broken() */
976 gamma = (IDirectDrawGammaControl *)0xdeadbeef;
977 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IDirectDrawGammaControl, (void **)&gamma);
978 ok(hr == E_NOINTERFACE || broken(hr == E_FAIL), "Got unexpected hr %#x.\n", hr);
979 ok(gamma == NULL, "Interface not set to NULL by failed QI call: %p\n", gamma);
980 if (SUCCEEDED(hr)) IDirectDrawGammaControl_Release(gamma);
981 /* NULL iid: Segfaults */
983 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IDirect3DViewport2, (void **)&viewport2);
984 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE || broken(hr == E_FAIL),
985 "Failed to QI IDirect3DViewport2, hr %#x.\n", hr);
988 ref = get_refcount((IUnknown *)viewport);
989 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
990 ref = get_refcount((IUnknown *)viewport2);
991 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
992 IDirect3DViewport2_Release(viewport2);
996 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IDirect3DViewport3, (void **)&viewport3);
997 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE || broken(hr == E_FAIL),
998 "Failed to QI IDirect3DViewport3, hr %#x.\n", hr);
1001 ref = get_refcount((IUnknown *)viewport);
1002 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
1003 ref = get_refcount((IUnknown *)viewport3);
1004 ok(ref == 2, "IDirect3DViewport3 refcount is %u\n", ref);
1005 IDirect3DViewport3_Release(viewport3);
1008 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IUnknown, (void **)&unknown);
1009 ok(SUCCEEDED(hr), "Failed to QI IUnknown, hr %#x.\n", hr);
1012 ref = get_refcount((IUnknown *)viewport);
1013 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
1014 ref = get_refcount(unknown);
1015 ok(ref == 2, "IUnknown refcount is %u\n", ref);
1016 IUnknown_Release(unknown);
1019 IDirect3DViewport_Release(viewport);
1020 IDirect3D_Release(d3d);
1021 IDirectDraw_Release(ddraw);
1024 static void test_zenable(void)
1026 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1027 static D3DTLVERTEX tquad[] =
1029 {{ 0.0f}, {480.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1030 {{ 0.0f}, { 0.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1031 {{640.0f}, {480.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1032 {{640.0f}, { 0.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1034 IDirect3DExecuteBuffer *execute_buffer;
1035 D3DEXECUTEBUFFERDESC exec_desc;
1036 IDirect3DMaterial *background;
1037 IDirect3DViewport *viewport;
1038 IDirect3DDevice *device;
1039 IDirectDrawSurface *rt;
1049 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1050 0, 0, 640, 480, 0, 0, 0, 0);
1051 if (!(ddraw = create_ddraw()))
1053 skip("Failed to create ddraw object, skipping test.\n");
1054 DestroyWindow(window);
1057 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1059 skip("Failed to create D3D device, skipping test.\n");
1060 IDirectDraw_Release(ddraw);
1061 DestroyWindow(window);
1065 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1066 viewport = create_viewport(device, 0, 0, 640, 480);
1067 viewport_set_background(device, viewport, background);
1069 memset(&exec_desc, 0, sizeof(exec_desc));
1070 exec_desc.dwSize = sizeof(exec_desc);
1071 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
1072 exec_desc.dwBufferSize = 1024;
1073 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
1075 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
1076 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
1077 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
1078 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
1079 memcpy(exec_desc.lpData, tquad, sizeof(tquad));
1080 ptr = ((BYTE *)exec_desc.lpData) + sizeof(tquad);
1081 emit_process_vertices(&ptr, 0, 4);
1082 emit_set_rs(&ptr, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1083 emit_tquad(&ptr, 0);
1085 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
1086 inst_length -= sizeof(tquad);
1087 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
1088 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
1090 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1091 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1092 hr = IDirect3DDevice_BeginScene(device);
1093 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1094 set_execute_data(execute_buffer, 4, sizeof(tquad), inst_length);
1095 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1096 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1097 hr = IDirect3DDevice_EndScene(device);
1098 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1100 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
1101 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1102 for (i = 0; i < 4; ++i)
1104 for (j = 0; j < 4; ++j)
1106 x = 80 * ((2 * j) + 1);
1107 y = 60 * ((2 * i) + 1);
1108 color = get_surface_color(rt, x, y);
1109 ok(compare_color(color, 0x0000ff00, 1),
1110 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1113 IDirectDrawSurface_Release(rt);
1115 destroy_viewport(device, viewport);
1116 IDirect3DExecuteBuffer_Release(execute_buffer);
1117 destroy_material(background);
1118 IDirect3DDevice_Release(device);
1119 IDirectDraw_Release(ddraw);
1120 DestroyWindow(window);
1123 static void test_ck_rgba(void)
1125 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1126 static D3DTLVERTEX tquad[] =
1128 {{ 0.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1129 {{ 0.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1130 {{640.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1131 {{640.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1132 {{ 0.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1133 {{ 0.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1134 {{640.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1135 {{640.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1139 D3DCOLOR fill_color;
1147 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x000000ff},
1148 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x000000ff},
1149 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00},
1150 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00},
1151 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00807f00},
1152 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x0000ff00},
1153 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00},
1154 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00},
1157 IDirect3DExecuteBuffer *execute_buffer;
1158 D3DTEXTUREHANDLE texture_handle;
1159 D3DEXECUTEBUFFERDESC exec_desc;
1160 IDirect3DMaterial *background;
1161 IDirectDrawSurface *surface;
1162 IDirect3DViewport *viewport;
1163 DDSURFACEDESC surface_desc;
1164 IDirect3DTexture *texture;
1165 IDirect3DDevice *device;
1166 IDirectDrawSurface *rt;
1174 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1175 0, 0, 640, 480, 0, 0, 0, 0);
1176 if (!(ddraw = create_ddraw()))
1178 skip("Failed to create ddraw object, skipping test.\n");
1179 DestroyWindow(window);
1182 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1184 skip("Failed to create D3D device, skipping test.\n");
1185 IDirectDraw_Release(ddraw);
1186 DestroyWindow(window);
1190 background = create_diffuse_material(device, 1.0, 0.0f, 0.0f, 1.0f);
1191 viewport = create_viewport(device, 0, 0, 640, 480);
1192 viewport_set_background(device, viewport, background);
1194 memset(&surface_desc, 0, sizeof(surface_desc));
1195 surface_desc.dwSize = sizeof(surface_desc);
1196 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1197 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1198 surface_desc.dwWidth = 256;
1199 surface_desc.dwHeight = 256;
1200 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1201 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1202 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1203 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1204 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1205 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1206 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1207 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1208 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1209 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1210 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1211 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
1212 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1213 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
1214 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1215 IDirect3DTexture_Release(texture);
1217 memset(&exec_desc, 0, sizeof(exec_desc));
1218 exec_desc.dwSize = sizeof(exec_desc);
1219 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
1220 exec_desc.dwBufferSize = 1024;
1221 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
1222 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
1223 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
1225 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
1226 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1228 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
1230 UINT draw1_len, draw2_len;
1233 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
1234 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
1235 memcpy(exec_desc.lpData, tquad, sizeof(tquad));
1236 ptr = ((BYTE *)exec_desc.lpData) + sizeof(tquad);
1237 emit_process_vertices(&ptr, 0, 4);
1238 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1239 emit_set_rs(&ptr, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1240 emit_set_rs(&ptr, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1241 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1242 emit_set_rs(&ptr, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1243 emit_tquad(&ptr, 0);
1245 draw1_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - sizeof(tquad);
1246 emit_process_vertices(&ptr, 4, 4);
1247 emit_tquad(&ptr, 0);
1248 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1250 draw2_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw1_len;
1251 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
1252 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
1254 memset(&fx, 0, sizeof(fx));
1255 fx.dwSize = sizeof(fx);
1256 U5(fx).dwFillColor = tests[i].fill_color;
1257 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1258 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1260 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
1261 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1262 hr = IDirect3DDevice_BeginScene(device);
1263 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1264 set_execute_data(execute_buffer, 8, sizeof(tquad), draw1_len);
1265 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1266 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1267 hr = IDirect3DDevice_EndScene(device);
1268 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1270 color = get_surface_color(rt, 320, 240);
1272 todo_wine ok(compare_color(color, tests[i].result1, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1273 tests[i].result1, i, color);
1275 ok(compare_color(color, tests[i].result1, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1276 tests[i].result1, i, color);
1278 U5(fx).dwFillColor = 0xff0000ff;
1279 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1280 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1282 hr = IDirect3DDevice_BeginScene(device);
1283 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1284 set_execute_data(execute_buffer, 8, sizeof(tquad) + draw1_len, draw2_len);
1285 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1286 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1287 hr = IDirect3DDevice_EndScene(device);
1288 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1290 /* This tests that fragments that are masked out by the color key are
1291 * discarded, instead of just fully transparent. */
1292 color = get_surface_color(rt, 320, 240);
1294 todo_wine ok(compare_color(color, tests[i].result2, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1295 tests[i].result2, i, color);
1297 ok(compare_color(color, tests[i].result2, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1298 tests[i].result2, i, color);
1301 IDirectDrawSurface_Release(rt);
1302 IDirect3DExecuteBuffer_Release(execute_buffer);
1303 IDirectDrawSurface_Release(surface);
1304 destroy_viewport(device, viewport);
1305 destroy_material(background);
1306 IDirect3DDevice_Release(device);
1307 IDirectDraw_Release(ddraw);
1308 DestroyWindow(window);
1311 static void test_ck_default(void)
1313 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1314 static D3DTLVERTEX tquad[] =
1316 {{ 0.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1317 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1318 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1319 {{640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1321 IDirect3DExecuteBuffer *execute_buffer;
1322 IDirectDrawSurface *surface, *rt;
1323 D3DTEXTUREHANDLE texture_handle;
1324 D3DEXECUTEBUFFERDESC exec_desc;
1325 IDirect3DMaterial *background;
1326 UINT draw1_offset, draw1_len;
1327 UINT draw2_offset, draw2_len;
1328 UINT draw3_offset, draw3_len;
1329 UINT draw4_offset, draw4_len;
1330 IDirect3DViewport *viewport;
1331 DDSURFACEDESC surface_desc;
1332 IDirect3DTexture *texture;
1333 IDirect3DDevice *device;
1341 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1342 0, 0, 640, 480, 0, 0, 0, 0);
1344 if (!(ddraw = create_ddraw()))
1346 skip("Failed to create ddraw object, skipping test.\n");
1347 DestroyWindow(window);
1350 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1352 skip("Failed to create D3D device, skipping test.\n");
1353 IDirectDraw_Release(ddraw);
1354 DestroyWindow(window);
1358 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
1359 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1361 background = create_diffuse_material(device, 0.0, 1.0f, 0.0f, 1.0f);
1362 viewport = create_viewport(device, 0, 0, 640, 480);
1363 viewport_set_background(device, viewport, background);
1365 memset(&surface_desc, 0, sizeof(surface_desc));
1366 surface_desc.dwSize = sizeof(surface_desc);
1367 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1368 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1369 surface_desc.dwWidth = 256;
1370 surface_desc.dwHeight = 256;
1371 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1372 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
1373 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1374 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1375 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1376 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1377 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
1378 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
1379 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1380 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1381 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
1382 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1383 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
1384 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1385 IDirect3DTexture_Release(texture);
1387 memset(&fx, 0, sizeof(fx));
1388 fx.dwSize = sizeof(fx);
1389 U5(fx).dwFillColor = 0x000000ff;
1390 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1391 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
1393 memset(&exec_desc, 0, sizeof(exec_desc));
1394 exec_desc.dwSize = sizeof(exec_desc);
1395 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
1396 exec_desc.dwBufferSize = 1024;
1397 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
1398 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
1399 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
1401 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
1402 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
1403 memcpy(exec_desc.lpData, tquad, sizeof(tquad));
1404 ptr = (BYTE *)exec_desc.lpData + sizeof(tquad);
1405 emit_process_vertices(&ptr, 0, 4);
1406 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1407 emit_tquad(&ptr, 0);
1409 draw1_offset = sizeof(tquad);
1410 draw1_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw1_offset;
1411 emit_process_vertices(&ptr, 0, 4);
1412 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, FALSE);
1413 emit_tquad(&ptr, 0);
1415 draw2_offset = draw1_offset + draw1_len;
1416 draw2_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw2_offset;
1417 emit_process_vertices(&ptr, 0, 4);
1418 emit_tquad(&ptr, 0);
1420 draw3_offset = draw2_offset + draw2_len;
1421 draw3_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw3_offset;
1422 emit_process_vertices(&ptr, 0, 4);
1423 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
1424 emit_tquad(&ptr, 0);
1425 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1427 draw4_offset = draw3_offset + draw3_len;
1428 draw4_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw4_offset;
1429 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
1430 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
1432 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1433 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1434 hr = IDirect3DDevice_BeginScene(device);
1435 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1436 set_execute_data(execute_buffer, 4, draw1_offset, draw1_len);
1437 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1438 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1439 hr = IDirect3DDevice_EndScene(device);
1440 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1441 color = get_surface_color(rt, 320, 240);
1442 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1444 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1445 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1446 hr = IDirect3DDevice_BeginScene(device);
1447 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1448 set_execute_data(execute_buffer, 4, draw2_offset, draw2_len);
1449 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1450 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1451 hr = IDirect3DDevice_EndScene(device);
1452 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1453 color = get_surface_color(rt, 320, 240);
1454 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1456 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1457 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1458 hr = IDirect3DDevice_BeginScene(device);
1459 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1460 set_execute_data(execute_buffer, 4, draw3_offset, draw3_len);
1461 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1462 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1463 hr = IDirect3DDevice_EndScene(device);
1464 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1465 color = get_surface_color(rt, 320, 240);
1466 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1468 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1469 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1470 hr = IDirect3DDevice_BeginScene(device);
1471 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1472 set_execute_data(execute_buffer, 4, draw4_offset, draw4_len);
1473 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1474 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1475 hr = IDirect3DDevice_EndScene(device);
1476 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1477 color = get_surface_color(rt, 320, 240);
1478 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1480 IDirect3DExecuteBuffer_Release(execute_buffer);
1481 IDirectDrawSurface_Release(surface);
1482 destroy_viewport(device, viewport);
1483 destroy_material(background);
1484 IDirectDrawSurface_Release(rt);
1485 IDirect3DDevice_Release(device);
1486 IDirectDraw_Release(ddraw);
1487 DestroyWindow(window);
1493 REFIID refcount_iid;
1497 static void test_qi(const char *test_name, IUnknown *base_iface,
1498 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
1500 ULONG refcount, expected_refcount;
1501 IUnknown *iface1, *iface2;
1505 for (i = 0; i < entry_count; ++i)
1507 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
1508 ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
1511 for (j = 0; j < entry_count; ++j)
1513 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
1514 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
1517 expected_refcount = 0;
1518 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
1519 ++expected_refcount;
1520 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
1521 ++expected_refcount;
1522 refcount = IUnknown_Release(iface2);
1523 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
1524 refcount, test_name, i, j, expected_refcount);
1528 expected_refcount = 0;
1529 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
1530 ++expected_refcount;
1531 refcount = IUnknown_Release(iface1);
1532 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
1533 refcount, test_name, i, expected_refcount);
1538 static void test_surface_qi(void)
1540 static const struct qi_test tests[] =
1542 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface, S_OK },
1543 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface, S_OK },
1544 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
1545 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1546 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
1547 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
1548 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
1549 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
1550 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
1551 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
1552 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
1553 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
1554 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
1555 {&IID_IDirect3D7, NULL, E_INVALIDARG },
1556 {&IID_IDirect3D3, NULL, E_INVALIDARG },
1557 {&IID_IDirect3D2, NULL, E_INVALIDARG },
1558 {&IID_IDirect3D, NULL, E_INVALIDARG },
1559 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
1560 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
1561 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
1562 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
1563 {&IID_IDirectDraw, NULL, E_INVALIDARG },
1564 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
1565 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
1566 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
1567 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
1568 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
1569 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
1570 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
1571 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
1572 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
1573 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
1574 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
1575 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
1576 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
1579 IDirectDrawSurface *surface;
1580 DDSURFACEDESC surface_desc;
1581 IDirect3DDevice *device;
1586 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
1588 win_skip("DirectDrawCreateEx not available, skipping test.\n");
1592 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1593 0, 0, 640, 480, 0, 0, 0, 0);
1594 if (!(ddraw = create_ddraw()))
1596 skip("Failed to create a ddraw object, skipping test.\n");
1597 DestroyWindow(window);
1600 /* Try to create a D3D device to see if the ddraw implementation supports
1601 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
1602 * doesn't support e.g. the IDirect3DTexture interfaces. */
1603 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1605 skip("Failed to create D3D device, skipping test.\n");
1606 IDirectDraw_Release(ddraw);
1607 DestroyWindow(window);
1610 IDirect3DDevice_Release(device);
1612 memset(&surface_desc, 0, sizeof(surface_desc));
1613 surface_desc.dwSize = sizeof(surface_desc);
1614 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1615 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1616 surface_desc.dwWidth = 512;
1617 surface_desc.dwHeight = 512;
1618 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1619 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1621 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface, tests, sizeof(tests) / sizeof(*tests));
1623 IDirectDrawSurface_Release(surface);
1624 IDirectDraw_Release(ddraw);
1625 DestroyWindow(window);
1628 static void test_device_qi(void)
1630 static const struct qi_test tests[] =
1632 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface, S_OK },
1633 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface, S_OK },
1634 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
1635 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1636 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
1637 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
1638 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
1639 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
1640 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
1641 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
1642 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
1643 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
1644 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
1645 {&IID_IDirect3DHALDevice, &IID_IDirectDrawSurface, S_OK },
1646 {&IID_IDirect3D7, NULL, E_INVALIDARG },
1647 {&IID_IDirect3D3, NULL, E_INVALIDARG },
1648 {&IID_IDirect3D2, NULL, E_INVALIDARG },
1649 {&IID_IDirect3D, NULL, E_INVALIDARG },
1650 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
1651 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
1652 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
1653 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
1654 {&IID_IDirectDraw, NULL, E_INVALIDARG },
1655 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
1656 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
1657 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
1658 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
1659 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
1660 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
1661 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
1662 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
1663 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
1664 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
1665 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
1666 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
1667 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
1671 IDirect3DDevice *device;
1675 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
1677 win_skip("DirectDrawCreateEx not available, skipping test.\n");
1681 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1682 0, 0, 640, 480, 0, 0, 0, 0);
1683 if (!(ddraw = create_ddraw()))
1685 skip("Failed to create ddraw object, skipping test.\n");
1686 DestroyWindow(window);
1689 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1691 skip("Failed to create D3D device, skipping test.\n");
1692 IDirectDraw_Release(ddraw);
1693 DestroyWindow(window);
1697 test_qi("device_qi", (IUnknown *)device, &IID_IDirectDrawSurface, tests, sizeof(tests) / sizeof(*tests));
1699 IDirect3DDevice_Release(device);
1700 IDirectDraw_Release(ddraw);
1701 DestroyWindow(window);
1704 static void test_wndproc(void)
1706 LONG_PTR proc, ddraw_proc;
1713 static const UINT messages[] =
1715 WM_WINDOWPOSCHANGING,
1718 WM_WINDOWPOSCHANGING,
1724 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
1725 if (!(ddraw = create_ddraw()))
1727 skip("Failed to create IDirectDraw object, skipping tests.\n");
1731 wc.lpfnWndProc = test_proc;
1732 wc.lpszClassName = "ddraw_test_wndproc_wc";
1733 ok(RegisterClassA(&wc), "Failed to register window class.\n");
1735 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
1736 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
1738 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1739 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1740 (LONG_PTR)test_proc, proc);
1741 expect_messages = messages;
1742 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1743 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1744 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
1745 expect_messages = NULL;
1746 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1747 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1748 (LONG_PTR)test_proc, proc);
1749 ref = IDirectDraw_Release(ddraw);
1750 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1751 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1752 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1753 (LONG_PTR)test_proc, proc);
1755 /* DDSCL_NORMAL doesn't. */
1756 ddraw = create_ddraw();
1757 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1758 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1759 (LONG_PTR)test_proc, proc);
1760 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
1761 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1762 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1763 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1764 (LONG_PTR)test_proc, proc);
1765 ref = IDirectDraw_Release(ddraw);
1766 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1767 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1768 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1769 (LONG_PTR)test_proc, proc);
1771 /* The original window proc is only restored by ddraw if the current
1772 * window proc matches the one ddraw set. This also affects switching
1773 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
1774 ddraw = create_ddraw();
1775 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1776 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1777 (LONG_PTR)test_proc, proc);
1778 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1779 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1780 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1781 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1782 (LONG_PTR)test_proc, proc);
1784 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1785 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1786 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1787 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1788 (LONG_PTR)test_proc, proc);
1789 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1790 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1791 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
1792 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1793 (LONG_PTR)test_proc, proc);
1794 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1795 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1796 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1797 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
1798 (LONG_PTR)DefWindowProcA, proc);
1799 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1800 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1801 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc);
1802 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
1803 (LONG_PTR)DefWindowProcA, proc);
1804 ref = IDirectDraw_Release(ddraw);
1805 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1806 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1807 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1808 (LONG_PTR)test_proc, proc);
1810 ddraw = create_ddraw();
1811 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1812 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1813 (LONG_PTR)test_proc, proc);
1814 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1815 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1816 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
1817 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1818 (LONG_PTR)test_proc, proc);
1819 ref = IDirectDraw_Release(ddraw);
1820 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1821 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1822 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
1823 (LONG_PTR)DefWindowProcA, proc);
1825 fix_wndproc(window, (LONG_PTR)test_proc);
1826 expect_messages = NULL;
1827 DestroyWindow(window);
1828 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
1831 static void test_window_style(void)
1833 LONG style, exstyle, tmp;
1834 RECT fullscreen_rect, r;
1840 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1841 0, 0, 100, 100, 0, 0, 0, 0);
1842 if (!(ddraw = create_ddraw()))
1844 skip("Failed to create a ddraw object, skipping test.\n");
1845 DestroyWindow(window);
1849 style = GetWindowLongA(window, GWL_STYLE);
1850 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
1851 SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
1853 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1854 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1856 tmp = GetWindowLongA(window, GWL_STYLE);
1857 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
1858 tmp = GetWindowLongA(window, GWL_EXSTYLE);
1859 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
1861 GetWindowRect(window, &r);
1862 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
1863 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
1864 r.left, r.top, r.right, r.bottom);
1865 GetClientRect(window, &r);
1866 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
1868 ref = IDirectDraw_Release(ddraw);
1869 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1871 DestroyWindow(window);
1874 static void test_redundant_mode_set(void)
1876 DDSURFACEDESC surface_desc = {0};
1883 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1884 0, 0, 100, 100, 0, 0, 0, 0);
1885 if (!(ddraw = create_ddraw()))
1887 skip("Failed to create a ddraw object, skipping test.\n");
1888 DestroyWindow(window);
1892 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1893 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1895 surface_desc.dwSize = sizeof(surface_desc);
1896 hr = IDirectDraw_GetDisplayMode(ddraw, &surface_desc);
1897 ok(SUCCEEDED(hr), "GetDipslayMode failed, hr %#x.\n", hr);
1899 hr = IDirectDraw_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
1900 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount);
1901 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
1903 GetWindowRect(window, &r);
1906 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
1907 GetWindowRect(window, &s);
1908 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
1909 r.left, r.top, r.right, r.bottom,
1910 s.left, s.top, s.right, s.bottom);
1912 hr = IDirectDraw_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
1913 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount);
1914 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
1916 GetWindowRect(window, &s);
1917 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
1918 r.left, r.top, r.right, r.bottom,
1919 s.left, s.top, s.right, s.bottom);
1921 ref = IDirectDraw_Release(ddraw);
1922 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1924 DestroyWindow(window);
1927 static SIZE screen_size;
1929 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
1931 if (message == WM_SIZE)
1933 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
1934 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
1937 return test_proc(hwnd, message, wparam, lparam);
1940 static void test_coop_level_mode_set(void)
1942 IDirectDrawSurface *primary;
1943 RECT fullscreen_rect, r, s;
1951 static const UINT exclusive_messages[] =
1953 WM_WINDOWPOSCHANGING,
1954 WM_WINDOWPOSCHANGED,
1960 static const UINT normal_messages[] =
1966 if (!(ddraw = create_ddraw()))
1968 skip("Failed to create a ddraw object, skipping test.\n");
1972 wc.lpfnWndProc = mode_set_proc;
1973 wc.lpszClassName = "ddraw_test_wndproc_wc";
1974 ok(RegisterClassA(&wc), "Failed to register window class.\n");
1976 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
1977 0, 0, 100, 100, 0, 0, 0, 0);
1979 SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
1980 SetRect(&s, 0, 0, 640, 480);
1982 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1983 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1985 GetWindowRect(window, &r);
1986 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
1987 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
1988 r.left, r.top, r.right, r.bottom);
1990 memset(&ddsd, 0, sizeof(ddsd));
1991 ddsd.dwSize = sizeof(ddsd);
1992 ddsd.dwFlags = DDSD_CAPS;
1993 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
1995 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
1996 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
1997 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
1998 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
1999 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2000 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2001 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2002 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2004 GetWindowRect(window, &r);
2005 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2006 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2007 r.left, r.top, r.right, r.bottom);
2009 expect_messages = exclusive_messages;
2013 hr = IDirectDraw_SetDisplayMode(ddraw, 640, 480, 32);
2014 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2016 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2017 expect_messages = NULL;
2018 ok(screen_size.cx == s.right && screen_size.cy == s.bottom,
2019 "Expected screen size %ux%u, got %ux%u.\n",
2020 s.right, s.bottom, screen_size.cx, screen_size.cy);
2022 GetWindowRect(window, &r);
2023 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2024 s.left, s.top, s.right, s.bottom,
2025 r.left, r.top, r.right, r.bottom);
2027 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2028 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2029 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2030 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2031 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2032 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2033 IDirectDrawSurface_Release(primary);
2035 memset(&ddsd, 0, sizeof(ddsd));
2036 ddsd.dwSize = sizeof(ddsd);
2037 ddsd.dwFlags = DDSD_CAPS;
2038 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2040 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2041 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2042 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2043 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2044 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2045 s.right - s.left, ddsd.dwWidth);
2046 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2047 s.bottom - s.top, ddsd.dwHeight);
2049 GetWindowRect(window, &r);
2050 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2051 s.left, s.top, s.right, s.bottom,
2052 r.left, r.top, r.right, r.bottom);
2054 expect_messages = exclusive_messages;
2058 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2059 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2061 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2062 expect_messages = NULL;
2063 ok(screen_size.cx == fullscreen_rect.right && screen_size.cy == fullscreen_rect.bottom,
2064 "Expected screen size %ux%u, got %ux%u.\n",
2065 fullscreen_rect.right, fullscreen_rect.bottom, screen_size.cx, screen_size.cy);
2067 GetWindowRect(window, &r);
2068 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2069 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2070 r.left, r.top, r.right, r.bottom);
2072 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2073 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2074 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2075 s.right - s.left, ddsd.dwWidth);
2076 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2077 s.bottom - s.top, ddsd.dwHeight);
2078 IDirectDrawSurface_Release(primary);
2080 memset(&ddsd, 0, sizeof(ddsd));
2081 ddsd.dwSize = sizeof(ddsd);
2082 ddsd.dwFlags = DDSD_CAPS;
2083 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2085 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2086 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2087 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2088 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2089 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2090 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2091 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2092 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2094 GetWindowRect(window, &r);
2095 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2096 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2097 r.left, r.top, r.right, r.bottom);
2099 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2100 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2102 GetWindowRect(window, &r);
2103 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2104 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2105 r.left, r.top, r.right, r.bottom);
2107 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2108 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2109 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2110 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2111 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2112 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2113 IDirectDrawSurface_Release(primary);
2115 memset(&ddsd, 0, sizeof(ddsd));
2116 ddsd.dwSize = sizeof(ddsd);
2117 ddsd.dwFlags = DDSD_CAPS;
2118 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2120 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2121 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2122 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2123 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2124 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2125 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2126 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2127 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2129 GetWindowRect(window, &r);
2130 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2131 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2132 r.left, r.top, r.right, r.bottom);
2134 expect_messages = normal_messages;
2138 hr = IDirectDraw_SetDisplayMode(ddraw, 640, 480, 32);
2139 ok(SUCCEEDED(hr) || broken(hr == DDERR_NOEXCLUSIVEMODE) /* NT4 testbot */,
2140 "SetDipslayMode failed, hr %#x.\n", hr);
2141 if (hr == DDERR_NOEXCLUSIVEMODE)
2143 win_skip("Broken SetDisplayMode(), skipping remaining tests.\n");
2144 IDirectDrawSurface_Release(primary);
2145 IDirectDraw_Release(ddraw);
2149 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2150 expect_messages = NULL;
2151 ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2153 GetWindowRect(window, &r);
2154 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2155 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2156 r.left, r.top, r.right, r.bottom);
2158 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2159 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2160 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2161 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2162 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2163 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2164 IDirectDrawSurface_Release(primary);
2166 memset(&ddsd, 0, sizeof(ddsd));
2167 ddsd.dwSize = sizeof(ddsd);
2168 ddsd.dwFlags = DDSD_CAPS;
2169 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2171 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2172 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2173 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2174 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2175 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2176 s.right - s.left, ddsd.dwWidth);
2177 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2178 s.bottom - s.top, ddsd.dwHeight);
2180 GetWindowRect(window, &r);
2181 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2182 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2183 r.left, r.top, r.right, r.bottom);
2185 expect_messages = normal_messages;
2189 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2190 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2192 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2193 expect_messages = NULL;
2194 ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2196 GetWindowRect(window, &r);
2197 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2198 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2199 r.left, r.top, r.right, r.bottom);
2201 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2202 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2203 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2204 s.right - s.left, ddsd.dwWidth);
2205 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2206 s.bottom - s.top, ddsd.dwHeight);
2207 IDirectDrawSurface_Release(primary);
2209 memset(&ddsd, 0, sizeof(ddsd));
2210 ddsd.dwSize = sizeof(ddsd);
2211 ddsd.dwFlags = DDSD_CAPS;
2212 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2214 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2215 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2216 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2217 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2218 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2219 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2220 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2221 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2223 GetWindowRect(window, &r);
2224 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2225 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2226 r.left, r.top, r.right, r.bottom);
2228 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
2229 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
2230 * not DDSCL_FULLSCREEN. */
2231 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2232 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2234 GetWindowRect(window, &r);
2235 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2236 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2237 r.left, r.top, r.right, r.bottom);
2239 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2240 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2241 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2242 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2243 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2244 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2245 IDirectDrawSurface_Release(primary);
2247 memset(&ddsd, 0, sizeof(ddsd));
2248 ddsd.dwSize = sizeof(ddsd);
2249 ddsd.dwFlags = DDSD_CAPS;
2250 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2252 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2253 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2254 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2255 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2256 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2257 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2258 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2259 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2261 GetWindowRect(window, &r);
2262 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2263 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2264 r.left, r.top, r.right, r.bottom);
2266 expect_messages = normal_messages;
2270 hr = IDirectDraw_SetDisplayMode(ddraw, 640, 480, 32);
2271 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2273 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2274 expect_messages = NULL;
2275 ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2277 GetWindowRect(window, &r);
2278 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2279 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2280 r.left, r.top, r.right, r.bottom);
2282 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2283 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2284 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2285 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2286 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2287 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2288 IDirectDrawSurface_Release(primary);
2290 memset(&ddsd, 0, sizeof(ddsd));
2291 ddsd.dwSize = sizeof(ddsd);
2292 ddsd.dwFlags = DDSD_CAPS;
2293 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2295 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2296 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2297 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2298 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2299 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2300 s.right - s.left, ddsd.dwWidth);
2301 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2302 s.bottom - s.top, ddsd.dwHeight);
2304 GetWindowRect(window, &r);
2305 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2306 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2307 r.left, r.top, r.right, r.bottom);
2309 expect_messages = normal_messages;
2313 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2314 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2316 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2317 expect_messages = NULL;
2318 ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2320 GetWindowRect(window, &r);
2321 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2322 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2323 r.left, r.top, r.right, r.bottom);
2325 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2326 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2327 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2328 s.right - s.left, ddsd.dwWidth);
2329 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2330 s.bottom - s.top, ddsd.dwHeight);
2331 IDirectDrawSurface_Release(primary);
2333 memset(&ddsd, 0, sizeof(ddsd));
2334 ddsd.dwSize = sizeof(ddsd);
2335 ddsd.dwFlags = DDSD_CAPS;
2336 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2338 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2339 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2340 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2341 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2342 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2343 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2344 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2345 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2346 IDirectDrawSurface_Release(primary);
2348 GetWindowRect(window, &r);
2349 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2350 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2351 r.left, r.top, r.right, r.bottom);
2353 ref = IDirectDraw_Release(ddraw);
2354 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2356 GetWindowRect(window, &r);
2357 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2358 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2359 r.left, r.top, r.right, r.bottom);
2362 expect_messages = NULL;
2363 DestroyWindow(window);
2364 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2367 static void test_coop_level_mode_set_multi(void)
2369 IDirectDraw *ddraw1, *ddraw2;
2370 UINT orig_w, orig_h, w, h;
2375 if (!(ddraw1 = create_ddraw()))
2377 skip("Failed to create a ddraw object, skipping test.\n");
2381 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2382 0, 0, 100, 100, 0, 0, 0, 0);
2384 orig_w = GetSystemMetrics(SM_CXSCREEN);
2385 orig_h = GetSystemMetrics(SM_CYSCREEN);
2387 /* With just a single ddraw object, the display mode is restored on
2389 hr = IDirectDraw_SetDisplayMode(ddraw1, 800, 600, 32);
2390 ok(SUCCEEDED(hr) || broken(hr == DDERR_NOEXCLUSIVEMODE) /* NT4 testbot */,
2391 "SetDipslayMode failed, hr %#x.\n", hr);
2392 if (hr == DDERR_NOEXCLUSIVEMODE)
2394 win_skip("Broken SetDisplayMode(), skipping test.\n");
2395 IDirectDraw_Release(ddraw1);
2396 DestroyWindow(window);
2399 w = GetSystemMetrics(SM_CXSCREEN);
2400 ok(w == 800, "Got unexpected screen width %u.\n", w);
2401 h = GetSystemMetrics(SM_CYSCREEN);
2402 ok(h == 600, "Got unexpected screen height %u.\n", h);
2404 ref = IDirectDraw_Release(ddraw1);
2405 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2406 w = GetSystemMetrics(SM_CXSCREEN);
2407 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2408 h = GetSystemMetrics(SM_CYSCREEN);
2409 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2411 /* When there are multiple ddraw objects, the display mode is restored to
2412 * the initial mode, before the first SetDisplayMode() call. */
2413 ddraw1 = create_ddraw();
2414 hr = IDirectDraw_SetDisplayMode(ddraw1, 800, 600, 32);
2415 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2416 w = GetSystemMetrics(SM_CXSCREEN);
2417 ok(w == 800, "Got unexpected screen width %u.\n", w);
2418 h = GetSystemMetrics(SM_CYSCREEN);
2419 ok(h == 600, "Got unexpected screen height %u.\n", h);
2421 ddraw2 = create_ddraw();
2422 hr = IDirectDraw_SetDisplayMode(ddraw2, 640, 480, 32);
2423 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2424 w = GetSystemMetrics(SM_CXSCREEN);
2425 ok(w == 640, "Got unexpected screen width %u.\n", w);
2426 h = GetSystemMetrics(SM_CYSCREEN);
2427 ok(h == 480, "Got unexpected screen height %u.\n", h);
2429 ref = IDirectDraw_Release(ddraw2);
2430 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2431 w = GetSystemMetrics(SM_CXSCREEN);
2432 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2433 h = GetSystemMetrics(SM_CYSCREEN);
2434 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2436 ref = IDirectDraw_Release(ddraw1);
2437 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2438 w = GetSystemMetrics(SM_CXSCREEN);
2439 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2440 h = GetSystemMetrics(SM_CYSCREEN);
2441 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2443 /* Regardless of release ordering. */
2444 ddraw1 = create_ddraw();
2445 hr = IDirectDraw_SetDisplayMode(ddraw1, 800, 600, 32);
2446 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2447 w = GetSystemMetrics(SM_CXSCREEN);
2448 ok(w == 800, "Got unexpected screen width %u.\n", w);
2449 h = GetSystemMetrics(SM_CYSCREEN);
2450 ok(h == 600, "Got unexpected screen height %u.\n", h);
2452 ddraw2 = create_ddraw();
2453 hr = IDirectDraw_SetDisplayMode(ddraw2, 640, 480, 32);
2454 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2455 w = GetSystemMetrics(SM_CXSCREEN);
2456 ok(w == 640, "Got unexpected screen width %u.\n", w);
2457 h = GetSystemMetrics(SM_CYSCREEN);
2458 ok(h == 480, "Got unexpected screen height %u.\n", h);
2460 ref = IDirectDraw_Release(ddraw1);
2461 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2462 w = GetSystemMetrics(SM_CXSCREEN);
2463 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2464 h = GetSystemMetrics(SM_CYSCREEN);
2465 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2467 ref = IDirectDraw_Release(ddraw2);
2468 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2469 w = GetSystemMetrics(SM_CXSCREEN);
2470 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2471 h = GetSystemMetrics(SM_CYSCREEN);
2472 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2474 /* But only for ddraw objects that called SetDisplayMode(). */
2475 ddraw1 = create_ddraw();
2476 ddraw2 = create_ddraw();
2477 hr = IDirectDraw_SetDisplayMode(ddraw2, 640, 480, 32);
2478 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2479 w = GetSystemMetrics(SM_CXSCREEN);
2480 ok(w == 640, "Got unexpected screen width %u.\n", w);
2481 h = GetSystemMetrics(SM_CYSCREEN);
2482 ok(h == 480, "Got unexpected screen height %u.\n", h);
2484 ref = IDirectDraw_Release(ddraw1);
2485 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2486 w = GetSystemMetrics(SM_CXSCREEN);
2487 ok(w == 640, "Got unexpected screen width %u.\n", w);
2488 h = GetSystemMetrics(SM_CYSCREEN);
2489 ok(h == 480, "Got unexpected screen height %u.\n", h);
2491 ref = IDirectDraw_Release(ddraw2);
2492 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2493 w = GetSystemMetrics(SM_CXSCREEN);
2494 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2495 h = GetSystemMetrics(SM_CYSCREEN);
2496 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2498 /* If there's a ddraw object that's currently in exclusive mode, it blocks
2499 * restoring the display mode. */
2500 ddraw1 = create_ddraw();
2501 hr = IDirectDraw_SetDisplayMode(ddraw1, 800, 600, 32);
2502 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2503 w = GetSystemMetrics(SM_CXSCREEN);
2504 ok(w == 800, "Got unexpected screen width %u.\n", w);
2505 h = GetSystemMetrics(SM_CYSCREEN);
2506 ok(h == 600, "Got unexpected screen height %u.\n", h);
2508 ddraw2 = create_ddraw();
2509 hr = IDirectDraw_SetDisplayMode(ddraw2, 640, 480, 32);
2510 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2511 w = GetSystemMetrics(SM_CXSCREEN);
2512 ok(w == 640, "Got unexpected screen width %u.\n", w);
2513 h = GetSystemMetrics(SM_CYSCREEN);
2514 ok(h == 480, "Got unexpected screen height %u.\n", h);
2516 hr = IDirectDraw_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2517 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2519 ref = IDirectDraw_Release(ddraw1);
2520 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2521 w = GetSystemMetrics(SM_CXSCREEN);
2522 ok(w == 640, "Got unexpected screen width %u.\n", w);
2523 h = GetSystemMetrics(SM_CYSCREEN);
2524 ok(h == 480, "Got unexpected screen height %u.\n", h);
2526 ref = IDirectDraw_Release(ddraw2);
2527 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2528 w = GetSystemMetrics(SM_CXSCREEN);
2529 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2530 h = GetSystemMetrics(SM_CYSCREEN);
2531 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2533 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
2534 ddraw1 = create_ddraw();
2535 hr = IDirectDraw_SetDisplayMode(ddraw1, 800, 600, 32);
2536 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2537 w = GetSystemMetrics(SM_CXSCREEN);
2538 ok(w == 800, "Got unexpected screen width %u.\n", w);
2539 h = GetSystemMetrics(SM_CYSCREEN);
2540 ok(h == 600, "Got unexpected screen height %u.\n", h);
2542 hr = IDirectDraw_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2543 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2545 ddraw2 = create_ddraw();
2546 hr = IDirectDraw_SetDisplayMode(ddraw2, 640, 480, 32);
2547 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
2549 ref = IDirectDraw_Release(ddraw1);
2550 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2551 w = GetSystemMetrics(SM_CXSCREEN);
2552 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2553 h = GetSystemMetrics(SM_CYSCREEN);
2554 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2556 ref = IDirectDraw_Release(ddraw2);
2557 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2558 w = GetSystemMetrics(SM_CXSCREEN);
2559 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2560 h = GetSystemMetrics(SM_CYSCREEN);
2561 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2563 DestroyWindow(window);
2566 static void test_initialize(void)
2572 if (!(ddraw = create_ddraw()))
2574 skip("Failed to create a ddraw object, skipping test.\n");
2578 hr = IDirectDraw_Initialize(ddraw, NULL);
2579 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
2580 IDirectDraw_Release(ddraw);
2583 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw, (void **)&ddraw);
2584 ok(SUCCEEDED(hr), "Failed to create IDirectDraw instance, hr %#x.\n", hr);
2585 hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d);
2588 /* IDirect3D_Initialize() just returns DDERR_ALREADYINITIALIZED. */
2589 hr = IDirect3D_Initialize(d3d, NULL);
2590 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
2591 IDirect3D_Release(d3d);
2593 else skip("Failed to query IDirect3D interface, skipping tests.\n");
2594 hr = IDirectDraw_Initialize(ddraw, NULL);
2595 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
2596 hr = IDirectDraw_Initialize(ddraw, NULL);
2597 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
2598 IDirectDraw_Release(ddraw);
2601 if (0) /* This crashes on the W2KPROSP4 testbot. */
2604 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirect3D, (void **)&d3d);
2605 ok(hr == E_NOINTERFACE, "CoCreateInstance returned hr %#x, expected E_NOINTERFACE.\n", hr);
2610 static void test_coop_level_surf_create(void)
2612 IDirectDrawSurface *surface;
2617 if (!(ddraw = create_ddraw()))
2619 skip("Failed to create a ddraw object, skipping test.\n");
2623 memset(&ddsd, 0, sizeof(ddsd));
2624 ddsd.dwSize = sizeof(ddsd);
2625 ddsd.dwFlags = DDSD_CAPS;
2626 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2627 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
2628 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
2630 IDirectDraw_Release(ddraw);
2633 static void test_coop_level_multi_window(void)
2635 HWND window1, window2;
2639 window1 = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
2640 0, 0, 640, 480, 0, 0, 0, 0);
2641 window2 = CreateWindowA("static", "ddraw_test2", WS_OVERLAPPEDWINDOW,
2642 0, 0, 640, 480, 0, 0, 0, 0);
2643 if (!(ddraw = create_ddraw()))
2645 skip("Failed to create a ddraw object, skipping test.\n");
2646 DestroyWindow(window2);
2647 DestroyWindow(window1);
2651 hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
2652 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2653 hr = IDirectDraw_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
2654 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2655 ok(IsWindow(window1), "Window 1 was destroyed.\n");
2656 ok(IsWindow(window2), "Window 2 was destroyed.\n");
2658 IDirectDraw_Release(ddraw);
2659 DestroyWindow(window2);
2660 DestroyWindow(window1);
2663 static void test_clear_rect_count(void)
2665 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
2666 IDirect3DMaterial *white, *red, *green, *blue;
2667 IDirect3DViewport *viewport;
2668 IDirect3DDevice *device;
2669 IDirectDrawSurface *rt;
2675 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2676 0, 0, 640, 480, 0, 0, 0, 0);
2677 if (!(ddraw = create_ddraw()))
2679 skip("Failed to create ddraw object, skipping test.\n");
2680 DestroyWindow(window);
2683 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
2685 skip("Failed to create D3D device, skipping test.\n");
2686 IDirectDraw_Release(ddraw);
2687 DestroyWindow(window);
2691 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
2692 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
2694 white = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
2695 red = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
2696 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
2697 blue = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
2698 viewport = create_viewport(device, 0, 0, 640, 480);
2700 viewport_set_background(device, viewport, white);
2701 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
2702 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2703 viewport_set_background(device, viewport, red);
2704 hr = IDirect3DViewport_Clear(viewport, 0, &clear_rect, D3DCLEAR_TARGET);
2705 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2706 viewport_set_background(device, viewport, green);
2707 hr = IDirect3DViewport_Clear(viewport, 0, NULL, D3DCLEAR_TARGET);
2708 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2709 viewport_set_background(device, viewport, blue);
2710 hr = IDirect3DViewport_Clear(viewport, 1, NULL, D3DCLEAR_TARGET);
2711 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2713 color = get_surface_color(rt, 320, 240);
2714 ok(compare_color(color, 0x00ffffff, 1), "Got unexpected color 0x%08x.\n", color);
2716 IDirectDrawSurface_Release(rt);
2717 destroy_viewport(device, viewport);
2718 destroy_material(white);
2719 destroy_material(red);
2720 destroy_material(green);
2721 destroy_material(blue);
2722 IDirect3DDevice_Release(device);
2723 IDirectDraw_Release(ddraw);
2724 DestroyWindow(window);
2729 test_coop_level_create_device_window();
2731 test_coop_level_d3d_state();
2732 test_surface_interface_mismatch();
2733 test_coop_level_threaded();
2734 test_viewport_interfaces();
2741 test_window_style();
2742 test_redundant_mode_set();
2743 test_coop_level_mode_set();
2744 test_coop_level_mode_set_multi();
2746 test_coop_level_surf_create();
2747 test_coop_level_multi_window();
2748 test_clear_rect_count();