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(void)
944 IDirect3DViewport *viewport, *another_vp;
945 IDirect3DViewport2 *viewport2;
946 IDirect3DViewport3 *viewport3;
947 IDirectDrawGammaControl *gamma;
949 IDirect3DDevice *device;
952 if (!(ddraw = create_ddraw()))
954 skip("Failed to create ddraw object, skipping test.\n");
957 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
958 0, 0, 640, 480, 0, 0, 0, 0);
959 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
961 skip("Failed to create D3D device, skipping test.\n");
962 IDirectDraw_Release(ddraw);
963 DestroyWindow(window);
967 hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d);
968 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
969 ref = get_refcount((IUnknown *) d3d);
970 ok(ref == 2, "IDirect3D refcount is %d\n", ref);
972 hr = IDirect3D_CreateViewport(d3d, &viewport, NULL);
973 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
974 ref = get_refcount((IUnknown *)viewport);
975 ok(ref == 1, "Initial IDirect3DViewport refcount is %u\n", ref);
976 ref = get_refcount((IUnknown *)d3d);
977 ok(ref == 2, "IDirect3D refcount is %u\n", ref);
979 /* E_FAIL return values are returned by Winetestbot Windows NT machines. While not supporting
980 * newer interfaces is legitimate for old ddraw versions, E_FAIL violates Microsoft's rules
981 * for QueryInterface, hence the broken() */
982 gamma = (IDirectDrawGammaControl *)0xdeadbeef;
983 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IDirectDrawGammaControl, (void **)&gamma);
984 ok(hr == E_NOINTERFACE || broken(hr == E_FAIL), "Got unexpected hr %#x.\n", hr);
985 ok(gamma == NULL, "Interface not set to NULL by failed QI call: %p\n", gamma);
986 if (SUCCEEDED(hr)) IDirectDrawGammaControl_Release(gamma);
987 /* NULL iid: Segfaults */
989 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IDirect3DViewport2, (void **)&viewport2);
990 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE || broken(hr == E_FAIL),
991 "Failed to QI IDirect3DViewport2, hr %#x.\n", hr);
994 ref = get_refcount((IUnknown *)viewport);
995 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
996 ref = get_refcount((IUnknown *)viewport2);
997 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
998 IDirect3DViewport2_Release(viewport2);
1002 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IDirect3DViewport3, (void **)&viewport3);
1003 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE || broken(hr == E_FAIL),
1004 "Failed to QI IDirect3DViewport3, hr %#x.\n", hr);
1007 ref = get_refcount((IUnknown *)viewport);
1008 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
1009 ref = get_refcount((IUnknown *)viewport3);
1010 ok(ref == 2, "IDirect3DViewport3 refcount is %u\n", ref);
1011 IDirect3DViewport3_Release(viewport3);
1014 hr = IDirect3DViewport_QueryInterface(viewport, &IID_IUnknown, (void **)&unknown);
1015 ok(SUCCEEDED(hr), "Failed to QI IUnknown, hr %#x.\n", hr);
1018 ref = get_refcount((IUnknown *)viewport);
1019 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
1020 ref = get_refcount(unknown);
1021 ok(ref == 2, "IUnknown refcount is %u\n", ref);
1022 IUnknown_Release(unknown);
1025 /* AddViewport(NULL): Segfault */
1026 hr = IDirect3DDevice_DeleteViewport(device, NULL);
1027 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1029 hr = IDirect3D_CreateViewport(d3d, &another_vp, NULL);
1030 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1032 hr = IDirect3DDevice_AddViewport(device, viewport);
1033 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1034 ref = get_refcount((IUnknown *) viewport);
1035 ok(ref == 2, "IDirect3DViewport refcount is %d\n", ref);
1036 hr = IDirect3DDevice_AddViewport(device, another_vp);
1037 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1038 ref = get_refcount((IUnknown *) another_vp);
1039 ok(ref == 2, "IDirect3DViewport refcount is %d\n", ref);
1041 hr = IDirect3DDevice_DeleteViewport(device, another_vp);
1042 ok(SUCCEEDED(hr), "Failed to delete viewport from device, hr %#x.\n", hr);
1043 ref = get_refcount((IUnknown *) another_vp);
1044 ok(ref == 1, "IDirect3DViewport refcount is %d\n", ref);
1046 IDirect3DDevice_Release(device);
1047 ref = get_refcount((IUnknown *) viewport);
1048 ok(ref == 1, "IDirect3DViewport refcount is %d\n", ref);
1050 IDirect3DViewport_Release(another_vp);
1051 IDirect3D_Release(d3d);
1052 IDirect3DViewport_Release(viewport);
1053 DestroyWindow(window);
1054 IDirectDraw_Release(ddraw);
1057 static void test_zenable(void)
1059 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1060 static D3DTLVERTEX tquad[] =
1062 {{ 0.0f}, {480.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1063 {{ 0.0f}, { 0.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1064 {{640.0f}, {480.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1065 {{640.0f}, { 0.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1067 IDirect3DExecuteBuffer *execute_buffer;
1068 D3DEXECUTEBUFFERDESC exec_desc;
1069 IDirect3DMaterial *background;
1070 IDirect3DViewport *viewport;
1071 IDirect3DDevice *device;
1072 IDirectDrawSurface *rt;
1082 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1083 0, 0, 640, 480, 0, 0, 0, 0);
1084 if (!(ddraw = create_ddraw()))
1086 skip("Failed to create ddraw object, skipping test.\n");
1087 DestroyWindow(window);
1090 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1092 skip("Failed to create D3D device, skipping test.\n");
1093 IDirectDraw_Release(ddraw);
1094 DestroyWindow(window);
1098 background = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
1099 viewport = create_viewport(device, 0, 0, 640, 480);
1100 viewport_set_background(device, viewport, background);
1102 memset(&exec_desc, 0, sizeof(exec_desc));
1103 exec_desc.dwSize = sizeof(exec_desc);
1104 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
1105 exec_desc.dwBufferSize = 1024;
1106 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
1108 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
1109 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
1110 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
1111 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
1112 memcpy(exec_desc.lpData, tquad, sizeof(tquad));
1113 ptr = ((BYTE *)exec_desc.lpData) + sizeof(tquad);
1114 emit_process_vertices(&ptr, 0, 4);
1115 emit_set_rs(&ptr, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1116 emit_tquad(&ptr, 0);
1118 inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
1119 inst_length -= sizeof(tquad);
1120 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
1121 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
1123 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1124 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1125 hr = IDirect3DDevice_BeginScene(device);
1126 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1127 set_execute_data(execute_buffer, 4, sizeof(tquad), inst_length);
1128 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1129 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1130 hr = IDirect3DDevice_EndScene(device);
1131 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1133 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
1134 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1135 for (i = 0; i < 4; ++i)
1137 for (j = 0; j < 4; ++j)
1139 x = 80 * ((2 * j) + 1);
1140 y = 60 * ((2 * i) + 1);
1141 color = get_surface_color(rt, x, y);
1142 ok(compare_color(color, 0x0000ff00, 1),
1143 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1146 IDirectDrawSurface_Release(rt);
1148 destroy_viewport(device, viewport);
1149 IDirect3DExecuteBuffer_Release(execute_buffer);
1150 destroy_material(background);
1151 IDirect3DDevice_Release(device);
1152 IDirectDraw_Release(ddraw);
1153 DestroyWindow(window);
1156 static void test_ck_rgba(void)
1158 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1159 static D3DTLVERTEX tquad[] =
1161 {{ 0.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1162 {{ 0.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1163 {{640.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1164 {{640.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1165 {{ 0.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1166 {{ 0.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1167 {{640.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1168 {{640.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1172 D3DCOLOR fill_color;
1180 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x000000ff},
1181 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x000000ff},
1182 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00},
1183 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00},
1184 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00807f00},
1185 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x0000ff00},
1186 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00},
1187 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00},
1190 IDirect3DExecuteBuffer *execute_buffer;
1191 D3DTEXTUREHANDLE texture_handle;
1192 D3DEXECUTEBUFFERDESC exec_desc;
1193 IDirect3DMaterial *background;
1194 IDirectDrawSurface *surface;
1195 IDirect3DViewport *viewport;
1196 DDSURFACEDESC surface_desc;
1197 IDirect3DTexture *texture;
1198 IDirect3DDevice *device;
1199 IDirectDrawSurface *rt;
1207 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1208 0, 0, 640, 480, 0, 0, 0, 0);
1209 if (!(ddraw = create_ddraw()))
1211 skip("Failed to create ddraw object, skipping test.\n");
1212 DestroyWindow(window);
1215 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1217 skip("Failed to create D3D device, skipping test.\n");
1218 IDirectDraw_Release(ddraw);
1219 DestroyWindow(window);
1223 background = create_diffuse_material(device, 1.0, 0.0f, 0.0f, 1.0f);
1224 viewport = create_viewport(device, 0, 0, 640, 480);
1225 viewport_set_background(device, viewport, background);
1227 memset(&surface_desc, 0, sizeof(surface_desc));
1228 surface_desc.dwSize = sizeof(surface_desc);
1229 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1230 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1231 surface_desc.dwWidth = 256;
1232 surface_desc.dwHeight = 256;
1233 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1234 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1235 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1236 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1237 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1238 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1239 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1240 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1241 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1242 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1243 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1244 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
1245 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1246 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
1247 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1248 IDirect3DTexture_Release(texture);
1250 memset(&exec_desc, 0, sizeof(exec_desc));
1251 exec_desc.dwSize = sizeof(exec_desc);
1252 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
1253 exec_desc.dwBufferSize = 1024;
1254 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
1255 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
1256 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
1258 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
1259 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1261 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
1263 UINT draw1_len, draw2_len;
1266 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
1267 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
1268 memcpy(exec_desc.lpData, tquad, sizeof(tquad));
1269 ptr = ((BYTE *)exec_desc.lpData) + sizeof(tquad);
1270 emit_process_vertices(&ptr, 0, 4);
1271 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1272 emit_set_rs(&ptr, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1273 emit_set_rs(&ptr, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1274 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1275 emit_set_rs(&ptr, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1276 emit_tquad(&ptr, 0);
1278 draw1_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - sizeof(tquad);
1279 emit_process_vertices(&ptr, 4, 4);
1280 emit_tquad(&ptr, 0);
1281 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1283 draw2_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw1_len;
1284 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
1285 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
1287 memset(&fx, 0, sizeof(fx));
1288 fx.dwSize = sizeof(fx);
1289 U5(fx).dwFillColor = tests[i].fill_color;
1290 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1291 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1293 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
1294 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1295 hr = IDirect3DDevice_BeginScene(device);
1296 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1297 set_execute_data(execute_buffer, 8, sizeof(tquad), draw1_len);
1298 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1299 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1300 hr = IDirect3DDevice_EndScene(device);
1301 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1303 color = get_surface_color(rt, 320, 240);
1305 todo_wine ok(compare_color(color, tests[i].result1, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1306 tests[i].result1, i, color);
1308 ok(compare_color(color, tests[i].result1, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1309 tests[i].result1, i, color);
1311 U5(fx).dwFillColor = 0xff0000ff;
1312 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1313 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1315 hr = IDirect3DDevice_BeginScene(device);
1316 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1317 set_execute_data(execute_buffer, 8, sizeof(tquad) + draw1_len, draw2_len);
1318 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1319 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1320 hr = IDirect3DDevice_EndScene(device);
1321 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1323 /* This tests that fragments that are masked out by the color key are
1324 * discarded, instead of just fully transparent. */
1325 color = get_surface_color(rt, 320, 240);
1327 todo_wine ok(compare_color(color, tests[i].result2, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1328 tests[i].result2, i, color);
1330 ok(compare_color(color, tests[i].result2, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1331 tests[i].result2, i, color);
1334 IDirectDrawSurface_Release(rt);
1335 IDirect3DExecuteBuffer_Release(execute_buffer);
1336 IDirectDrawSurface_Release(surface);
1337 destroy_viewport(device, viewport);
1338 destroy_material(background);
1339 IDirect3DDevice_Release(device);
1340 IDirectDraw_Release(ddraw);
1341 DestroyWindow(window);
1344 static void test_ck_default(void)
1346 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1347 static D3DTLVERTEX tquad[] =
1349 {{ 0.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1350 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1351 {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1352 {{640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1354 IDirect3DExecuteBuffer *execute_buffer;
1355 IDirectDrawSurface *surface, *rt;
1356 D3DTEXTUREHANDLE texture_handle;
1357 D3DEXECUTEBUFFERDESC exec_desc;
1358 IDirect3DMaterial *background;
1359 UINT draw1_offset, draw1_len;
1360 UINT draw2_offset, draw2_len;
1361 UINT draw3_offset, draw3_len;
1362 UINT draw4_offset, draw4_len;
1363 IDirect3DViewport *viewport;
1364 DDSURFACEDESC surface_desc;
1365 IDirect3DTexture *texture;
1366 IDirect3DDevice *device;
1374 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1375 0, 0, 640, 480, 0, 0, 0, 0);
1377 if (!(ddraw = create_ddraw()))
1379 skip("Failed to create ddraw object, skipping test.\n");
1380 DestroyWindow(window);
1383 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1385 skip("Failed to create D3D device, skipping test.\n");
1386 IDirectDraw_Release(ddraw);
1387 DestroyWindow(window);
1391 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
1392 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1394 background = create_diffuse_material(device, 0.0, 1.0f, 0.0f, 1.0f);
1395 viewport = create_viewport(device, 0, 0, 640, 480);
1396 viewport_set_background(device, viewport, background);
1398 memset(&surface_desc, 0, sizeof(surface_desc));
1399 surface_desc.dwSize = sizeof(surface_desc);
1400 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1401 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1402 surface_desc.dwWidth = 256;
1403 surface_desc.dwHeight = 256;
1404 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1405 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
1406 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1407 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1408 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1409 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1410 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
1411 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
1412 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1413 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1414 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture, (void **)&texture);
1415 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1416 hr = IDirect3DTexture_GetHandle(texture, device, &texture_handle);
1417 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1418 IDirect3DTexture_Release(texture);
1420 memset(&fx, 0, sizeof(fx));
1421 fx.dwSize = sizeof(fx);
1422 U5(fx).dwFillColor = 0x000000ff;
1423 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1424 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
1426 memset(&exec_desc, 0, sizeof(exec_desc));
1427 exec_desc.dwSize = sizeof(exec_desc);
1428 exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
1429 exec_desc.dwBufferSize = 1024;
1430 exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
1431 hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
1432 ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
1434 hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
1435 ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
1436 memcpy(exec_desc.lpData, tquad, sizeof(tquad));
1437 ptr = (BYTE *)exec_desc.lpData + sizeof(tquad);
1438 emit_process_vertices(&ptr, 0, 4);
1439 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1440 emit_tquad(&ptr, 0);
1442 draw1_offset = sizeof(tquad);
1443 draw1_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw1_offset;
1444 emit_process_vertices(&ptr, 0, 4);
1445 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, FALSE);
1446 emit_tquad(&ptr, 0);
1448 draw2_offset = draw1_offset + draw1_len;
1449 draw2_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw2_offset;
1450 emit_process_vertices(&ptr, 0, 4);
1451 emit_tquad(&ptr, 0);
1453 draw3_offset = draw2_offset + draw2_len;
1454 draw3_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw3_offset;
1455 emit_process_vertices(&ptr, 0, 4);
1456 emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
1457 emit_tquad(&ptr, 0);
1458 emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1460 draw4_offset = draw3_offset + draw3_len;
1461 draw4_len = (BYTE *)ptr - (BYTE *)exec_desc.lpData - draw4_offset;
1462 hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
1463 ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
1465 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1466 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1467 hr = IDirect3DDevice_BeginScene(device);
1468 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1469 set_execute_data(execute_buffer, 4, draw1_offset, draw1_len);
1470 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1471 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1472 hr = IDirect3DDevice_EndScene(device);
1473 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1474 color = get_surface_color(rt, 320, 240);
1475 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1477 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1478 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1479 hr = IDirect3DDevice_BeginScene(device);
1480 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1481 set_execute_data(execute_buffer, 4, draw2_offset, draw2_len);
1482 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1483 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1484 hr = IDirect3DDevice_EndScene(device);
1485 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1486 color = get_surface_color(rt, 320, 240);
1487 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1489 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1490 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1491 hr = IDirect3DDevice_BeginScene(device);
1492 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1493 set_execute_data(execute_buffer, 4, draw3_offset, draw3_len);
1494 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1495 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1496 hr = IDirect3DDevice_EndScene(device);
1497 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1498 color = get_surface_color(rt, 320, 240);
1499 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1501 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1502 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1503 hr = IDirect3DDevice_BeginScene(device);
1504 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1505 set_execute_data(execute_buffer, 4, draw4_offset, draw4_len);
1506 hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
1507 ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
1508 hr = IDirect3DDevice_EndScene(device);
1509 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1510 color = get_surface_color(rt, 320, 240);
1511 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1513 IDirect3DExecuteBuffer_Release(execute_buffer);
1514 IDirectDrawSurface_Release(surface);
1515 destroy_viewport(device, viewport);
1516 destroy_material(background);
1517 IDirectDrawSurface_Release(rt);
1518 IDirect3DDevice_Release(device);
1519 IDirectDraw_Release(ddraw);
1520 DestroyWindow(window);
1526 REFIID refcount_iid;
1530 static void test_qi(const char *test_name, IUnknown *base_iface,
1531 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
1533 ULONG refcount, expected_refcount;
1534 IUnknown *iface1, *iface2;
1538 for (i = 0; i < entry_count; ++i)
1540 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
1541 ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
1544 for (j = 0; j < entry_count; ++j)
1546 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
1547 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
1550 expected_refcount = 0;
1551 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
1552 ++expected_refcount;
1553 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
1554 ++expected_refcount;
1555 refcount = IUnknown_Release(iface2);
1556 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
1557 refcount, test_name, i, j, expected_refcount);
1561 expected_refcount = 0;
1562 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
1563 ++expected_refcount;
1564 refcount = IUnknown_Release(iface1);
1565 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
1566 refcount, test_name, i, expected_refcount);
1571 static void test_surface_qi(void)
1573 static const struct qi_test tests[] =
1575 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface, S_OK },
1576 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface, S_OK },
1577 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
1578 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1579 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
1580 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
1581 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
1582 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
1583 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
1584 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
1585 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
1586 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
1587 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
1588 {&IID_IDirect3D7, NULL, E_INVALIDARG },
1589 {&IID_IDirect3D3, NULL, E_INVALIDARG },
1590 {&IID_IDirect3D2, NULL, E_INVALIDARG },
1591 {&IID_IDirect3D, NULL, E_INVALIDARG },
1592 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
1593 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
1594 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
1595 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
1596 {&IID_IDirectDraw, NULL, E_INVALIDARG },
1597 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
1598 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
1599 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
1600 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
1601 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
1602 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
1603 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
1604 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
1605 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
1606 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
1607 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
1608 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
1609 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
1612 IDirectDrawSurface *surface;
1613 DDSURFACEDESC surface_desc;
1614 IDirect3DDevice *device;
1619 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
1621 win_skip("DirectDrawCreateEx not available, skipping test.\n");
1625 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1626 0, 0, 640, 480, 0, 0, 0, 0);
1627 if (!(ddraw = create_ddraw()))
1629 skip("Failed to create a ddraw object, skipping test.\n");
1630 DestroyWindow(window);
1633 /* Try to create a D3D device to see if the ddraw implementation supports
1634 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
1635 * doesn't support e.g. the IDirect3DTexture interfaces. */
1636 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1638 skip("Failed to create D3D device, skipping test.\n");
1639 IDirectDraw_Release(ddraw);
1640 DestroyWindow(window);
1643 IDirect3DDevice_Release(device);
1645 memset(&surface_desc, 0, sizeof(surface_desc));
1646 surface_desc.dwSize = sizeof(surface_desc);
1647 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1648 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1649 surface_desc.dwWidth = 512;
1650 surface_desc.dwHeight = 512;
1651 hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1652 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1654 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface, tests, sizeof(tests) / sizeof(*tests));
1656 IDirectDrawSurface_Release(surface);
1657 IDirectDraw_Release(ddraw);
1658 DestroyWindow(window);
1661 static void test_device_qi(void)
1663 static const struct qi_test tests[] =
1665 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface, S_OK },
1666 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface, S_OK },
1667 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
1668 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1669 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
1670 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
1671 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
1672 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
1673 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
1674 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
1675 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
1676 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
1677 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
1678 {&IID_IDirect3DHALDevice, &IID_IDirectDrawSurface, S_OK },
1679 {&IID_IDirect3D7, NULL, E_INVALIDARG },
1680 {&IID_IDirect3D3, NULL, E_INVALIDARG },
1681 {&IID_IDirect3D2, NULL, E_INVALIDARG },
1682 {&IID_IDirect3D, NULL, E_INVALIDARG },
1683 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
1684 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
1685 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
1686 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
1687 {&IID_IDirectDraw, NULL, E_INVALIDARG },
1688 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
1689 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
1690 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
1691 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
1692 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
1693 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
1694 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
1695 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
1696 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
1697 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
1698 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
1699 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
1700 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
1704 IDirect3DDevice *device;
1708 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
1710 win_skip("DirectDrawCreateEx not available, skipping test.\n");
1714 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1715 0, 0, 640, 480, 0, 0, 0, 0);
1716 if (!(ddraw = create_ddraw()))
1718 skip("Failed to create ddraw object, skipping test.\n");
1719 DestroyWindow(window);
1722 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1724 skip("Failed to create D3D device, skipping test.\n");
1725 IDirectDraw_Release(ddraw);
1726 DestroyWindow(window);
1730 test_qi("device_qi", (IUnknown *)device, &IID_IDirectDrawSurface, tests, sizeof(tests) / sizeof(*tests));
1732 IDirect3DDevice_Release(device);
1733 IDirectDraw_Release(ddraw);
1734 DestroyWindow(window);
1737 static void test_wndproc(void)
1739 LONG_PTR proc, ddraw_proc;
1746 static const UINT messages[] =
1748 WM_WINDOWPOSCHANGING,
1751 WM_WINDOWPOSCHANGING,
1757 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
1758 if (!(ddraw = create_ddraw()))
1760 skip("Failed to create IDirectDraw object, skipping tests.\n");
1764 wc.lpfnWndProc = test_proc;
1765 wc.lpszClassName = "ddraw_test_wndproc_wc";
1766 ok(RegisterClassA(&wc), "Failed to register window class.\n");
1768 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
1769 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
1771 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1772 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1773 (LONG_PTR)test_proc, proc);
1774 expect_messages = messages;
1775 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1776 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1777 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
1778 expect_messages = NULL;
1779 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1780 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1781 (LONG_PTR)test_proc, proc);
1782 ref = IDirectDraw_Release(ddraw);
1783 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1784 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1785 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1786 (LONG_PTR)test_proc, proc);
1788 /* DDSCL_NORMAL doesn't. */
1789 ddraw = create_ddraw();
1790 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1791 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1792 (LONG_PTR)test_proc, proc);
1793 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
1794 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1795 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1796 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1797 (LONG_PTR)test_proc, proc);
1798 ref = IDirectDraw_Release(ddraw);
1799 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1800 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1801 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1802 (LONG_PTR)test_proc, proc);
1804 /* The original window proc is only restored by ddraw if the current
1805 * window proc matches the one ddraw set. This also affects switching
1806 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
1807 ddraw = create_ddraw();
1808 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1809 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1810 (LONG_PTR)test_proc, proc);
1811 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1812 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1813 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1814 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1815 (LONG_PTR)test_proc, proc);
1817 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1818 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1819 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1820 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1821 (LONG_PTR)test_proc, proc);
1822 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1823 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1824 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
1825 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1826 (LONG_PTR)test_proc, proc);
1827 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1828 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1829 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1830 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
1831 (LONG_PTR)DefWindowProcA, proc);
1832 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1833 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1834 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc);
1835 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
1836 (LONG_PTR)DefWindowProcA, proc);
1837 ref = IDirectDraw_Release(ddraw);
1838 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1839 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1840 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1841 (LONG_PTR)test_proc, proc);
1843 ddraw = create_ddraw();
1844 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1845 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1846 (LONG_PTR)test_proc, proc);
1847 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1848 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1849 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
1850 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1851 (LONG_PTR)test_proc, proc);
1852 ref = IDirectDraw_Release(ddraw);
1853 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1854 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1855 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
1856 (LONG_PTR)DefWindowProcA, proc);
1858 fix_wndproc(window, (LONG_PTR)test_proc);
1859 expect_messages = NULL;
1860 DestroyWindow(window);
1861 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
1864 static void test_window_style(void)
1866 LONG style, exstyle, tmp;
1867 RECT fullscreen_rect, r;
1873 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1874 0, 0, 100, 100, 0, 0, 0, 0);
1875 if (!(ddraw = create_ddraw()))
1877 skip("Failed to create a ddraw object, skipping test.\n");
1878 DestroyWindow(window);
1882 style = GetWindowLongA(window, GWL_STYLE);
1883 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
1884 SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
1886 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1887 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1889 tmp = GetWindowLongA(window, GWL_STYLE);
1890 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
1891 tmp = GetWindowLongA(window, GWL_EXSTYLE);
1892 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
1894 GetWindowRect(window, &r);
1895 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
1896 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
1897 r.left, r.top, r.right, r.bottom);
1898 GetClientRect(window, &r);
1899 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
1901 ref = IDirectDraw_Release(ddraw);
1902 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1904 DestroyWindow(window);
1907 static void test_redundant_mode_set(void)
1909 DDSURFACEDESC surface_desc = {0};
1916 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1917 0, 0, 100, 100, 0, 0, 0, 0);
1918 if (!(ddraw = create_ddraw()))
1920 skip("Failed to create a ddraw object, skipping test.\n");
1921 DestroyWindow(window);
1925 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1926 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1928 surface_desc.dwSize = sizeof(surface_desc);
1929 hr = IDirectDraw_GetDisplayMode(ddraw, &surface_desc);
1930 ok(SUCCEEDED(hr), "GetDipslayMode failed, hr %#x.\n", hr);
1932 hr = IDirectDraw_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
1933 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount);
1934 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
1936 GetWindowRect(window, &r);
1939 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
1940 GetWindowRect(window, &s);
1941 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
1942 r.left, r.top, r.right, r.bottom,
1943 s.left, s.top, s.right, s.bottom);
1945 hr = IDirectDraw_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
1946 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount);
1947 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
1949 GetWindowRect(window, &s);
1950 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
1951 r.left, r.top, r.right, r.bottom,
1952 s.left, s.top, s.right, s.bottom);
1954 ref = IDirectDraw_Release(ddraw);
1955 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1957 DestroyWindow(window);
1960 static SIZE screen_size;
1962 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
1964 if (message == WM_SIZE)
1966 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
1967 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
1970 return test_proc(hwnd, message, wparam, lparam);
1973 static void test_coop_level_mode_set(void)
1975 IDirectDrawSurface *primary;
1976 RECT fullscreen_rect, r, s;
1984 static const UINT exclusive_messages[] =
1986 WM_WINDOWPOSCHANGING,
1987 WM_WINDOWPOSCHANGED,
1993 static const UINT normal_messages[] =
1999 if (!(ddraw = create_ddraw()))
2001 skip("Failed to create a ddraw object, skipping test.\n");
2005 wc.lpfnWndProc = mode_set_proc;
2006 wc.lpszClassName = "ddraw_test_wndproc_wc";
2007 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2009 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
2010 0, 0, 100, 100, 0, 0, 0, 0);
2012 SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2013 SetRect(&s, 0, 0, 640, 480);
2015 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2016 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2018 GetWindowRect(window, &r);
2019 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2020 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2021 r.left, r.top, r.right, r.bottom);
2023 memset(&ddsd, 0, sizeof(ddsd));
2024 ddsd.dwSize = sizeof(ddsd);
2025 ddsd.dwFlags = DDSD_CAPS;
2026 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2028 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2029 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2030 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2031 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2032 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2033 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2034 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2035 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2037 GetWindowRect(window, &r);
2038 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2039 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2040 r.left, r.top, r.right, r.bottom);
2042 expect_messages = exclusive_messages;
2046 hr = IDirectDraw_SetDisplayMode(ddraw, 640, 480, 32);
2047 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2049 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2050 expect_messages = NULL;
2051 ok(screen_size.cx == s.right && screen_size.cy == s.bottom,
2052 "Expected screen size %ux%u, got %ux%u.\n",
2053 s.right, s.bottom, screen_size.cx, screen_size.cy);
2055 GetWindowRect(window, &r);
2056 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2057 s.left, s.top, s.right, s.bottom,
2058 r.left, r.top, r.right, r.bottom);
2060 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2061 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2062 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2063 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2064 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2065 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2066 IDirectDrawSurface_Release(primary);
2068 memset(&ddsd, 0, sizeof(ddsd));
2069 ddsd.dwSize = sizeof(ddsd);
2070 ddsd.dwFlags = DDSD_CAPS;
2071 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2073 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2074 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2075 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2076 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2077 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2078 s.right - s.left, ddsd.dwWidth);
2079 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2080 s.bottom - s.top, ddsd.dwHeight);
2082 GetWindowRect(window, &r);
2083 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2084 s.left, s.top, s.right, s.bottom,
2085 r.left, r.top, r.right, r.bottom);
2087 expect_messages = exclusive_messages;
2091 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2092 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2094 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2095 expect_messages = NULL;
2096 ok(screen_size.cx == fullscreen_rect.right && screen_size.cy == fullscreen_rect.bottom,
2097 "Expected screen size %ux%u, got %ux%u.\n",
2098 fullscreen_rect.right, fullscreen_rect.bottom, screen_size.cx, screen_size.cy);
2100 GetWindowRect(window, &r);
2101 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2102 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2103 r.left, r.top, r.right, r.bottom);
2105 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2106 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2107 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2108 s.right - s.left, ddsd.dwWidth);
2109 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2110 s.bottom - s.top, ddsd.dwHeight);
2111 IDirectDrawSurface_Release(primary);
2113 memset(&ddsd, 0, sizeof(ddsd));
2114 ddsd.dwSize = sizeof(ddsd);
2115 ddsd.dwFlags = DDSD_CAPS;
2116 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2118 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2119 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2120 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2121 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2122 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2123 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2124 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2125 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2127 GetWindowRect(window, &r);
2128 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2129 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2130 r.left, r.top, r.right, r.bottom);
2132 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2133 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2135 GetWindowRect(window, &r);
2136 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2137 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2138 r.left, r.top, r.right, r.bottom);
2140 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2141 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2142 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2143 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2144 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2145 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2146 IDirectDrawSurface_Release(primary);
2148 memset(&ddsd, 0, sizeof(ddsd));
2149 ddsd.dwSize = sizeof(ddsd);
2150 ddsd.dwFlags = DDSD_CAPS;
2151 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2153 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2154 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2155 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2156 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2157 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2158 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2159 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2160 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2162 GetWindowRect(window, &r);
2163 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2164 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2165 r.left, r.top, r.right, r.bottom);
2167 expect_messages = normal_messages;
2171 hr = IDirectDraw_SetDisplayMode(ddraw, 640, 480, 32);
2172 ok(SUCCEEDED(hr) || broken(hr == DDERR_NOEXCLUSIVEMODE) /* NT4 testbot */,
2173 "SetDipslayMode failed, hr %#x.\n", hr);
2174 if (hr == DDERR_NOEXCLUSIVEMODE)
2176 win_skip("Broken SetDisplayMode(), skipping remaining tests.\n");
2177 IDirectDrawSurface_Release(primary);
2178 IDirectDraw_Release(ddraw);
2182 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2183 expect_messages = NULL;
2184 ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2186 GetWindowRect(window, &r);
2187 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2188 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2189 r.left, r.top, r.right, r.bottom);
2191 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2192 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2193 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2194 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2195 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2196 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2197 IDirectDrawSurface_Release(primary);
2199 memset(&ddsd, 0, sizeof(ddsd));
2200 ddsd.dwSize = sizeof(ddsd);
2201 ddsd.dwFlags = DDSD_CAPS;
2202 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2204 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2205 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2206 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2207 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2208 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2209 s.right - s.left, ddsd.dwWidth);
2210 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2211 s.bottom - s.top, ddsd.dwHeight);
2213 GetWindowRect(window, &r);
2214 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2215 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2216 r.left, r.top, r.right, r.bottom);
2218 expect_messages = normal_messages;
2222 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2223 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2225 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2226 expect_messages = NULL;
2227 ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2229 GetWindowRect(window, &r);
2230 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2231 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2232 r.left, r.top, r.right, r.bottom);
2234 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2235 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2236 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2237 s.right - s.left, ddsd.dwWidth);
2238 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2239 s.bottom - s.top, ddsd.dwHeight);
2240 IDirectDrawSurface_Release(primary);
2242 memset(&ddsd, 0, sizeof(ddsd));
2243 ddsd.dwSize = sizeof(ddsd);
2244 ddsd.dwFlags = DDSD_CAPS;
2245 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2247 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2248 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2249 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2250 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2251 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2252 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2253 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2254 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2256 GetWindowRect(window, &r);
2257 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2258 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2259 r.left, r.top, r.right, r.bottom);
2261 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
2262 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
2263 * not DDSCL_FULLSCREEN. */
2264 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2265 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2267 GetWindowRect(window, &r);
2268 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2269 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2270 r.left, r.top, r.right, r.bottom);
2272 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2273 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2274 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2275 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2276 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2277 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2278 IDirectDrawSurface_Release(primary);
2280 memset(&ddsd, 0, sizeof(ddsd));
2281 ddsd.dwSize = sizeof(ddsd);
2282 ddsd.dwFlags = DDSD_CAPS;
2283 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2285 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2286 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2287 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2288 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2289 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2290 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2291 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2292 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2294 GetWindowRect(window, &r);
2295 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2296 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2297 r.left, r.top, r.right, r.bottom);
2299 expect_messages = normal_messages;
2303 hr = IDirectDraw_SetDisplayMode(ddraw, 640, 480, 32);
2304 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2306 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2307 expect_messages = NULL;
2308 ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2310 GetWindowRect(window, &r);
2311 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2312 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2313 r.left, r.top, r.right, r.bottom);
2315 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2316 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2317 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2318 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2319 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2320 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2321 IDirectDrawSurface_Release(primary);
2323 memset(&ddsd, 0, sizeof(ddsd));
2324 ddsd.dwSize = sizeof(ddsd);
2325 ddsd.dwFlags = DDSD_CAPS;
2326 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2328 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2329 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2330 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2331 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2332 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2333 s.right - s.left, ddsd.dwWidth);
2334 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2335 s.bottom - s.top, ddsd.dwHeight);
2337 GetWindowRect(window, &r);
2338 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2339 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2340 r.left, r.top, r.right, r.bottom);
2342 expect_messages = normal_messages;
2346 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2347 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2349 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2350 expect_messages = NULL;
2351 ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2353 GetWindowRect(window, &r);
2354 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2355 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2356 r.left, r.top, r.right, r.bottom);
2358 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2359 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2360 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2361 s.right - s.left, ddsd.dwWidth);
2362 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2363 s.bottom - s.top, ddsd.dwHeight);
2364 IDirectDrawSurface_Release(primary);
2366 memset(&ddsd, 0, sizeof(ddsd));
2367 ddsd.dwSize = sizeof(ddsd);
2368 ddsd.dwFlags = DDSD_CAPS;
2369 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2371 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2372 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2373 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2374 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2375 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2376 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2377 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2378 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2379 IDirectDrawSurface_Release(primary);
2381 GetWindowRect(window, &r);
2382 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2383 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2384 r.left, r.top, r.right, r.bottom);
2386 ref = IDirectDraw_Release(ddraw);
2387 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2389 GetWindowRect(window, &r);
2390 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2391 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2392 r.left, r.top, r.right, r.bottom);
2395 expect_messages = NULL;
2396 DestroyWindow(window);
2397 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2400 static void test_coop_level_mode_set_multi(void)
2402 IDirectDraw *ddraw1, *ddraw2;
2403 UINT orig_w, orig_h, w, h;
2408 if (!(ddraw1 = create_ddraw()))
2410 skip("Failed to create a ddraw object, skipping test.\n");
2414 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2415 0, 0, 100, 100, 0, 0, 0, 0);
2417 orig_w = GetSystemMetrics(SM_CXSCREEN);
2418 orig_h = GetSystemMetrics(SM_CYSCREEN);
2420 /* With just a single ddraw object, the display mode is restored on
2422 hr = IDirectDraw_SetDisplayMode(ddraw1, 800, 600, 32);
2423 ok(SUCCEEDED(hr) || broken(hr == DDERR_NOEXCLUSIVEMODE) /* NT4 testbot */,
2424 "SetDipslayMode failed, hr %#x.\n", hr);
2425 if (hr == DDERR_NOEXCLUSIVEMODE)
2427 win_skip("Broken SetDisplayMode(), skipping test.\n");
2428 IDirectDraw_Release(ddraw1);
2429 DestroyWindow(window);
2432 w = GetSystemMetrics(SM_CXSCREEN);
2433 ok(w == 800, "Got unexpected screen width %u.\n", w);
2434 h = GetSystemMetrics(SM_CYSCREEN);
2435 ok(h == 600, "Got unexpected screen height %u.\n", h);
2437 ref = IDirectDraw_Release(ddraw1);
2438 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2439 w = GetSystemMetrics(SM_CXSCREEN);
2440 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2441 h = GetSystemMetrics(SM_CYSCREEN);
2442 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2444 /* When there are multiple ddraw objects, the display mode is restored to
2445 * the initial mode, before the first SetDisplayMode() call. */
2446 ddraw1 = create_ddraw();
2447 hr = IDirectDraw_SetDisplayMode(ddraw1, 800, 600, 32);
2448 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2449 w = GetSystemMetrics(SM_CXSCREEN);
2450 ok(w == 800, "Got unexpected screen width %u.\n", w);
2451 h = GetSystemMetrics(SM_CYSCREEN);
2452 ok(h == 600, "Got unexpected screen height %u.\n", h);
2454 ddraw2 = create_ddraw();
2455 hr = IDirectDraw_SetDisplayMode(ddraw2, 640, 480, 32);
2456 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2457 w = GetSystemMetrics(SM_CXSCREEN);
2458 ok(w == 640, "Got unexpected screen width %u.\n", w);
2459 h = GetSystemMetrics(SM_CYSCREEN);
2460 ok(h == 480, "Got unexpected screen height %u.\n", h);
2462 ref = IDirectDraw_Release(ddraw2);
2463 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2464 w = GetSystemMetrics(SM_CXSCREEN);
2465 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2466 h = GetSystemMetrics(SM_CYSCREEN);
2467 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2469 ref = IDirectDraw_Release(ddraw1);
2470 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2471 w = GetSystemMetrics(SM_CXSCREEN);
2472 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2473 h = GetSystemMetrics(SM_CYSCREEN);
2474 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2476 /* Regardless of release ordering. */
2477 ddraw1 = create_ddraw();
2478 hr = IDirectDraw_SetDisplayMode(ddraw1, 800, 600, 32);
2479 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2480 w = GetSystemMetrics(SM_CXSCREEN);
2481 ok(w == 800, "Got unexpected screen width %u.\n", w);
2482 h = GetSystemMetrics(SM_CYSCREEN);
2483 ok(h == 600, "Got unexpected screen height %u.\n", h);
2485 ddraw2 = create_ddraw();
2486 hr = IDirectDraw_SetDisplayMode(ddraw2, 640, 480, 32);
2487 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2488 w = GetSystemMetrics(SM_CXSCREEN);
2489 ok(w == 640, "Got unexpected screen width %u.\n", w);
2490 h = GetSystemMetrics(SM_CYSCREEN);
2491 ok(h == 480, "Got unexpected screen height %u.\n", h);
2493 ref = IDirectDraw_Release(ddraw1);
2494 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2495 w = GetSystemMetrics(SM_CXSCREEN);
2496 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2497 h = GetSystemMetrics(SM_CYSCREEN);
2498 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2500 ref = IDirectDraw_Release(ddraw2);
2501 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2502 w = GetSystemMetrics(SM_CXSCREEN);
2503 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2504 h = GetSystemMetrics(SM_CYSCREEN);
2505 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2507 /* But only for ddraw objects that called SetDisplayMode(). */
2508 ddraw1 = create_ddraw();
2509 ddraw2 = create_ddraw();
2510 hr = IDirectDraw_SetDisplayMode(ddraw2, 640, 480, 32);
2511 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2512 w = GetSystemMetrics(SM_CXSCREEN);
2513 ok(w == 640, "Got unexpected screen width %u.\n", w);
2514 h = GetSystemMetrics(SM_CYSCREEN);
2515 ok(h == 480, "Got unexpected screen height %u.\n", h);
2517 ref = IDirectDraw_Release(ddraw1);
2518 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2519 w = GetSystemMetrics(SM_CXSCREEN);
2520 ok(w == 640, "Got unexpected screen width %u.\n", w);
2521 h = GetSystemMetrics(SM_CYSCREEN);
2522 ok(h == 480, "Got unexpected screen height %u.\n", h);
2524 ref = IDirectDraw_Release(ddraw2);
2525 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2526 w = GetSystemMetrics(SM_CXSCREEN);
2527 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2528 h = GetSystemMetrics(SM_CYSCREEN);
2529 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2531 /* If there's a ddraw object that's currently in exclusive mode, it blocks
2532 * restoring the display mode. */
2533 ddraw1 = create_ddraw();
2534 hr = IDirectDraw_SetDisplayMode(ddraw1, 800, 600, 32);
2535 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2536 w = GetSystemMetrics(SM_CXSCREEN);
2537 ok(w == 800, "Got unexpected screen width %u.\n", w);
2538 h = GetSystemMetrics(SM_CYSCREEN);
2539 ok(h == 600, "Got unexpected screen height %u.\n", h);
2541 ddraw2 = create_ddraw();
2542 hr = IDirectDraw_SetDisplayMode(ddraw2, 640, 480, 32);
2543 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2544 w = GetSystemMetrics(SM_CXSCREEN);
2545 ok(w == 640, "Got unexpected screen width %u.\n", w);
2546 h = GetSystemMetrics(SM_CYSCREEN);
2547 ok(h == 480, "Got unexpected screen height %u.\n", h);
2549 hr = IDirectDraw_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2550 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2552 ref = IDirectDraw_Release(ddraw1);
2553 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2554 w = GetSystemMetrics(SM_CXSCREEN);
2555 ok(w == 640, "Got unexpected screen width %u.\n", w);
2556 h = GetSystemMetrics(SM_CYSCREEN);
2557 ok(h == 480, "Got unexpected screen height %u.\n", h);
2559 ref = IDirectDraw_Release(ddraw2);
2560 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2561 w = GetSystemMetrics(SM_CXSCREEN);
2562 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2563 h = GetSystemMetrics(SM_CYSCREEN);
2564 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2566 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
2567 ddraw1 = create_ddraw();
2568 hr = IDirectDraw_SetDisplayMode(ddraw1, 800, 600, 32);
2569 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2570 w = GetSystemMetrics(SM_CXSCREEN);
2571 ok(w == 800, "Got unexpected screen width %u.\n", w);
2572 h = GetSystemMetrics(SM_CYSCREEN);
2573 ok(h == 600, "Got unexpected screen height %u.\n", h);
2575 hr = IDirectDraw_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2576 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2578 ddraw2 = create_ddraw();
2579 hr = IDirectDraw_SetDisplayMode(ddraw2, 640, 480, 32);
2580 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
2582 ref = IDirectDraw_Release(ddraw1);
2583 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2584 w = GetSystemMetrics(SM_CXSCREEN);
2585 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2586 h = GetSystemMetrics(SM_CYSCREEN);
2587 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2589 ref = IDirectDraw_Release(ddraw2);
2590 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2591 w = GetSystemMetrics(SM_CXSCREEN);
2592 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2593 h = GetSystemMetrics(SM_CYSCREEN);
2594 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2596 DestroyWindow(window);
2599 static void test_initialize(void)
2605 if (!(ddraw = create_ddraw()))
2607 skip("Failed to create a ddraw object, skipping test.\n");
2611 hr = IDirectDraw_Initialize(ddraw, NULL);
2612 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
2613 IDirectDraw_Release(ddraw);
2616 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw, (void **)&ddraw);
2617 ok(SUCCEEDED(hr), "Failed to create IDirectDraw instance, hr %#x.\n", hr);
2618 hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d);
2621 /* IDirect3D_Initialize() just returns DDERR_ALREADYINITIALIZED. */
2622 hr = IDirect3D_Initialize(d3d, NULL);
2623 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
2624 IDirect3D_Release(d3d);
2626 else skip("Failed to query IDirect3D interface, skipping tests.\n");
2627 hr = IDirectDraw_Initialize(ddraw, NULL);
2628 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
2629 hr = IDirectDraw_Initialize(ddraw, NULL);
2630 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
2631 IDirectDraw_Release(ddraw);
2634 if (0) /* This crashes on the W2KPROSP4 testbot. */
2637 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirect3D, (void **)&d3d);
2638 ok(hr == E_NOINTERFACE, "CoCreateInstance returned hr %#x, expected E_NOINTERFACE.\n", hr);
2643 static void test_coop_level_surf_create(void)
2645 IDirectDrawSurface *surface;
2650 if (!(ddraw = create_ddraw()))
2652 skip("Failed to create a ddraw object, skipping test.\n");
2656 memset(&ddsd, 0, sizeof(ddsd));
2657 ddsd.dwSize = sizeof(ddsd);
2658 ddsd.dwFlags = DDSD_CAPS;
2659 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2660 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
2661 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
2663 IDirectDraw_Release(ddraw);
2666 static void test_coop_level_multi_window(void)
2668 HWND window1, window2;
2672 window1 = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
2673 0, 0, 640, 480, 0, 0, 0, 0);
2674 window2 = CreateWindowA("static", "ddraw_test2", WS_OVERLAPPEDWINDOW,
2675 0, 0, 640, 480, 0, 0, 0, 0);
2676 if (!(ddraw = create_ddraw()))
2678 skip("Failed to create a ddraw object, skipping test.\n");
2679 DestroyWindow(window2);
2680 DestroyWindow(window1);
2684 hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
2685 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2686 hr = IDirectDraw_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
2687 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2688 ok(IsWindow(window1), "Window 1 was destroyed.\n");
2689 ok(IsWindow(window2), "Window 2 was destroyed.\n");
2691 IDirectDraw_Release(ddraw);
2692 DestroyWindow(window2);
2693 DestroyWindow(window1);
2696 static void test_clear_rect_count(void)
2698 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
2699 IDirect3DMaterial *white, *red, *green, *blue;
2700 IDirect3DViewport *viewport;
2701 IDirect3DDevice *device;
2702 IDirectDrawSurface *rt;
2708 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2709 0, 0, 640, 480, 0, 0, 0, 0);
2710 if (!(ddraw = create_ddraw()))
2712 skip("Failed to create ddraw object, skipping test.\n");
2713 DestroyWindow(window);
2716 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
2718 skip("Failed to create D3D device, skipping test.\n");
2719 IDirectDraw_Release(ddraw);
2720 DestroyWindow(window);
2724 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
2725 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
2727 white = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
2728 red = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
2729 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
2730 blue = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
2731 viewport = create_viewport(device, 0, 0, 640, 480);
2733 viewport_set_background(device, viewport, white);
2734 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
2735 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2736 viewport_set_background(device, viewport, red);
2737 hr = IDirect3DViewport_Clear(viewport, 0, &clear_rect, D3DCLEAR_TARGET);
2738 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2739 viewport_set_background(device, viewport, green);
2740 hr = IDirect3DViewport_Clear(viewport, 0, NULL, D3DCLEAR_TARGET);
2741 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2742 viewport_set_background(device, viewport, blue);
2743 hr = IDirect3DViewport_Clear(viewport, 1, NULL, D3DCLEAR_TARGET);
2744 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2746 color = get_surface_color(rt, 320, 240);
2747 ok(compare_color(color, 0x00ffffff, 1), "Got unexpected color 0x%08x.\n", color);
2749 IDirectDrawSurface_Release(rt);
2750 destroy_viewport(device, viewport);
2751 destroy_material(white);
2752 destroy_material(red);
2753 destroy_material(green);
2754 destroy_material(blue);
2755 IDirect3DDevice_Release(device);
2756 IDirectDraw_Release(ddraw);
2757 DestroyWindow(window);
2762 test_coop_level_create_device_window();
2764 test_coop_level_d3d_state();
2765 test_surface_interface_mismatch();
2766 test_coop_level_threaded();
2774 test_window_style();
2775 test_redundant_mode_set();
2776 test_coop_level_mode_set();
2777 test_coop_level_mode_set_multi();
2779 test_coop_level_surf_create();
2780 test_coop_level_multi_window();
2781 test_clear_rect_count();