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 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1902 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1904 tmp = GetWindowLongA(window, GWL_STYLE);
1905 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
1906 tmp = GetWindowLongA(window, GWL_EXSTYLE);
1907 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
1909 ref = IDirectDraw_Release(ddraw);
1910 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1912 DestroyWindow(window);
1915 static void test_redundant_mode_set(void)
1917 DDSURFACEDESC surface_desc = {0};
1924 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1925 0, 0, 100, 100, 0, 0, 0, 0);
1926 if (!(ddraw = create_ddraw()))
1928 skip("Failed to create a ddraw object, skipping test.\n");
1929 DestroyWindow(window);
1933 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1934 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1936 surface_desc.dwSize = sizeof(surface_desc);
1937 hr = IDirectDraw_GetDisplayMode(ddraw, &surface_desc);
1938 ok(SUCCEEDED(hr), "GetDipslayMode failed, hr %#x.\n", hr);
1940 hr = IDirectDraw_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
1941 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount);
1942 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
1944 GetWindowRect(window, &r);
1947 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
1948 GetWindowRect(window, &s);
1949 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
1950 r.left, r.top, r.right, r.bottom,
1951 s.left, s.top, s.right, s.bottom);
1953 hr = IDirectDraw_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
1954 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount);
1955 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
1957 GetWindowRect(window, &s);
1958 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
1959 r.left, r.top, r.right, r.bottom,
1960 s.left, s.top, s.right, s.bottom);
1962 ref = IDirectDraw_Release(ddraw);
1963 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1965 DestroyWindow(window);
1968 static SIZE screen_size;
1970 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
1972 if (message == WM_SIZE)
1974 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
1975 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
1978 return test_proc(hwnd, message, wparam, lparam);
1981 static void test_coop_level_mode_set(void)
1983 IDirectDrawSurface *primary;
1984 RECT fullscreen_rect, r, s;
1992 static const UINT exclusive_messages[] =
1994 WM_WINDOWPOSCHANGING,
1995 WM_WINDOWPOSCHANGED,
2001 static const UINT normal_messages[] =
2007 if (!(ddraw = create_ddraw()))
2009 skip("Failed to create a ddraw object, skipping test.\n");
2013 wc.lpfnWndProc = mode_set_proc;
2014 wc.lpszClassName = "ddraw_test_wndproc_wc";
2015 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2017 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
2018 0, 0, 100, 100, 0, 0, 0, 0);
2020 SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2021 SetRect(&s, 0, 0, 640, 480);
2023 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2024 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2026 GetWindowRect(window, &r);
2027 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2028 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2029 r.left, r.top, r.right, r.bottom);
2031 memset(&ddsd, 0, sizeof(ddsd));
2032 ddsd.dwSize = sizeof(ddsd);
2033 ddsd.dwFlags = DDSD_CAPS;
2034 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2036 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2037 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2038 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2039 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2040 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2041 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2042 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2043 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2045 GetWindowRect(window, &r);
2046 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2047 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2048 r.left, r.top, r.right, r.bottom);
2050 expect_messages = exclusive_messages;
2054 hr = IDirectDraw_SetDisplayMode(ddraw, 640, 480, 32);
2055 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2057 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2058 expect_messages = NULL;
2059 ok(screen_size.cx == s.right && screen_size.cy == s.bottom,
2060 "Expected screen size %ux%u, got %ux%u.\n",
2061 s.right, s.bottom, screen_size.cx, screen_size.cy);
2063 GetWindowRect(window, &r);
2064 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2065 s.left, s.top, s.right, s.bottom,
2066 r.left, r.top, r.right, r.bottom);
2068 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2069 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2070 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2071 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2072 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2073 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2074 IDirectDrawSurface_Release(primary);
2076 memset(&ddsd, 0, sizeof(ddsd));
2077 ddsd.dwSize = sizeof(ddsd);
2078 ddsd.dwFlags = DDSD_CAPS;
2079 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2081 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2082 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2083 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2084 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2085 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2086 s.right - s.left, ddsd.dwWidth);
2087 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2088 s.bottom - s.top, ddsd.dwHeight);
2090 GetWindowRect(window, &r);
2091 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2092 s.left, s.top, s.right, s.bottom,
2093 r.left, r.top, r.right, r.bottom);
2095 expect_messages = exclusive_messages;
2099 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2100 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2102 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2103 expect_messages = NULL;
2104 ok(screen_size.cx == fullscreen_rect.right && screen_size.cy == fullscreen_rect.bottom,
2105 "Expected screen size %ux%u, got %ux%u.\n",
2106 fullscreen_rect.right, fullscreen_rect.bottom, screen_size.cx, screen_size.cy);
2108 GetWindowRect(window, &r);
2109 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2110 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2111 r.left, r.top, r.right, r.bottom);
2113 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2114 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2115 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2116 s.right - s.left, ddsd.dwWidth);
2117 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2118 s.bottom - s.top, ddsd.dwHeight);
2119 IDirectDrawSurface_Release(primary);
2121 memset(&ddsd, 0, sizeof(ddsd));
2122 ddsd.dwSize = sizeof(ddsd);
2123 ddsd.dwFlags = DDSD_CAPS;
2124 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2126 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2127 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2128 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2129 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2130 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2131 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2132 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2133 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
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 = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2141 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2143 GetWindowRect(window, &r);
2144 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2145 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2146 r.left, r.top, r.right, r.bottom);
2148 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2149 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2150 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2151 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2152 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2153 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2154 IDirectDrawSurface_Release(primary);
2156 memset(&ddsd, 0, sizeof(ddsd));
2157 ddsd.dwSize = sizeof(ddsd);
2158 ddsd.dwFlags = DDSD_CAPS;
2159 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2161 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2162 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2163 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2164 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2165 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2166 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2167 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2168 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2170 GetWindowRect(window, &r);
2171 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2172 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2173 r.left, r.top, r.right, r.bottom);
2175 expect_messages = normal_messages;
2179 hr = IDirectDraw_SetDisplayMode(ddraw, 640, 480, 32);
2180 ok(SUCCEEDED(hr) || broken(hr == DDERR_NOEXCLUSIVEMODE) /* NT4 testbot */,
2181 "SetDipslayMode failed, hr %#x.\n", hr);
2182 if (hr == DDERR_NOEXCLUSIVEMODE)
2184 win_skip("Broken SetDisplayMode(), skipping remaining tests.\n");
2185 IDirectDrawSurface_Release(primary);
2186 IDirectDraw_Release(ddraw);
2190 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2191 expect_messages = NULL;
2192 ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2194 GetWindowRect(window, &r);
2195 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2196 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2197 r.left, r.top, r.right, r.bottom);
2199 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2200 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2201 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2202 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2203 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2204 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2205 IDirectDrawSurface_Release(primary);
2207 memset(&ddsd, 0, sizeof(ddsd));
2208 ddsd.dwSize = sizeof(ddsd);
2209 ddsd.dwFlags = DDSD_CAPS;
2210 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2212 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2213 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2214 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2215 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2216 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2217 s.right - s.left, ddsd.dwWidth);
2218 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2219 s.bottom - s.top, ddsd.dwHeight);
2221 GetWindowRect(window, &r);
2222 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2223 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2224 r.left, r.top, r.right, r.bottom);
2226 expect_messages = normal_messages;
2230 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2231 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2233 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2234 expect_messages = NULL;
2235 ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2237 GetWindowRect(window, &r);
2238 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2239 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2240 r.left, r.top, r.right, r.bottom);
2242 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2243 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2244 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2245 s.right - s.left, ddsd.dwWidth);
2246 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2247 s.bottom - s.top, ddsd.dwHeight);
2248 IDirectDrawSurface_Release(primary);
2250 memset(&ddsd, 0, sizeof(ddsd));
2251 ddsd.dwSize = sizeof(ddsd);
2252 ddsd.dwFlags = DDSD_CAPS;
2253 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2255 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2256 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2257 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2258 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2259 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2260 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2261 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2262 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2264 GetWindowRect(window, &r);
2265 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2266 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2267 r.left, r.top, r.right, r.bottom);
2269 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
2270 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
2271 * not DDSCL_FULLSCREEN. */
2272 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2273 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2275 GetWindowRect(window, &r);
2276 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2277 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2278 r.left, r.top, r.right, r.bottom);
2280 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2281 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2282 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2283 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2284 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2285 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2286 IDirectDrawSurface_Release(primary);
2288 memset(&ddsd, 0, sizeof(ddsd));
2289 ddsd.dwSize = sizeof(ddsd);
2290 ddsd.dwFlags = DDSD_CAPS;
2291 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2293 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2294 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2295 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2296 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2297 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2298 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2299 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2300 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2302 GetWindowRect(window, &r);
2303 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2304 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2305 r.left, r.top, r.right, r.bottom);
2307 expect_messages = normal_messages;
2311 hr = IDirectDraw_SetDisplayMode(ddraw, 640, 480, 32);
2312 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2314 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2315 expect_messages = NULL;
2316 ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2318 GetWindowRect(window, &r);
2319 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2320 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2321 r.left, r.top, r.right, r.bottom);
2323 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2324 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2325 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2326 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2327 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2328 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2329 IDirectDrawSurface_Release(primary);
2331 memset(&ddsd, 0, sizeof(ddsd));
2332 ddsd.dwSize = sizeof(ddsd);
2333 ddsd.dwFlags = DDSD_CAPS;
2334 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2336 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2337 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2338 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2339 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2340 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2341 s.right - s.left, ddsd.dwWidth);
2342 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2343 s.bottom - s.top, ddsd.dwHeight);
2345 GetWindowRect(window, &r);
2346 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2347 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2348 r.left, r.top, r.right, r.bottom);
2350 expect_messages = normal_messages;
2354 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2355 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2357 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2358 expect_messages = NULL;
2359 ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2361 GetWindowRect(window, &r);
2362 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2363 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2364 r.left, r.top, r.right, r.bottom);
2366 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2367 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2368 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2369 s.right - s.left, ddsd.dwWidth);
2370 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2371 s.bottom - s.top, ddsd.dwHeight);
2372 IDirectDrawSurface_Release(primary);
2374 memset(&ddsd, 0, sizeof(ddsd));
2375 ddsd.dwSize = sizeof(ddsd);
2376 ddsd.dwFlags = DDSD_CAPS;
2377 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2379 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL);
2380 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2381 hr = IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd);
2382 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2383 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2384 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2385 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2386 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2387 IDirectDrawSurface_Release(primary);
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);
2394 ref = IDirectDraw_Release(ddraw);
2395 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2397 GetWindowRect(window, &r);
2398 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2399 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2400 r.left, r.top, r.right, r.bottom);
2403 expect_messages = NULL;
2404 DestroyWindow(window);
2405 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2408 static void test_coop_level_mode_set_multi(void)
2410 IDirectDraw *ddraw1, *ddraw2;
2411 UINT orig_w, orig_h, w, h;
2416 if (!(ddraw1 = create_ddraw()))
2418 skip("Failed to create a ddraw object, skipping test.\n");
2422 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2423 0, 0, 100, 100, 0, 0, 0, 0);
2425 orig_w = GetSystemMetrics(SM_CXSCREEN);
2426 orig_h = GetSystemMetrics(SM_CYSCREEN);
2428 /* With just a single ddraw object, the display mode is restored on
2430 hr = IDirectDraw_SetDisplayMode(ddraw1, 800, 600, 32);
2431 ok(SUCCEEDED(hr) || broken(hr == DDERR_NOEXCLUSIVEMODE) /* NT4 testbot */,
2432 "SetDipslayMode failed, hr %#x.\n", hr);
2433 if (hr == DDERR_NOEXCLUSIVEMODE)
2435 win_skip("Broken SetDisplayMode(), skipping test.\n");
2436 IDirectDraw_Release(ddraw1);
2437 DestroyWindow(window);
2440 w = GetSystemMetrics(SM_CXSCREEN);
2441 ok(w == 800, "Got unexpected screen width %u.\n", w);
2442 h = GetSystemMetrics(SM_CYSCREEN);
2443 ok(h == 600, "Got unexpected screen height %u.\n", h);
2445 ref = IDirectDraw_Release(ddraw1);
2446 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2447 w = GetSystemMetrics(SM_CXSCREEN);
2448 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2449 h = GetSystemMetrics(SM_CYSCREEN);
2450 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2452 /* When there are multiple ddraw objects, the display mode is restored to
2453 * the initial mode, before the first SetDisplayMode() call. */
2454 ddraw1 = create_ddraw();
2455 hr = IDirectDraw_SetDisplayMode(ddraw1, 800, 600, 32);
2456 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2457 w = GetSystemMetrics(SM_CXSCREEN);
2458 ok(w == 800, "Got unexpected screen width %u.\n", w);
2459 h = GetSystemMetrics(SM_CYSCREEN);
2460 ok(h == 600, "Got unexpected screen height %u.\n", h);
2462 ddraw2 = create_ddraw();
2463 hr = IDirectDraw_SetDisplayMode(ddraw2, 640, 480, 32);
2464 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2465 w = GetSystemMetrics(SM_CXSCREEN);
2466 ok(w == 640, "Got unexpected screen width %u.\n", w);
2467 h = GetSystemMetrics(SM_CYSCREEN);
2468 ok(h == 480, "Got unexpected screen height %u.\n", h);
2470 ref = IDirectDraw_Release(ddraw2);
2471 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2472 w = GetSystemMetrics(SM_CXSCREEN);
2473 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2474 h = GetSystemMetrics(SM_CYSCREEN);
2475 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2477 ref = IDirectDraw_Release(ddraw1);
2478 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2479 w = GetSystemMetrics(SM_CXSCREEN);
2480 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2481 h = GetSystemMetrics(SM_CYSCREEN);
2482 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2484 /* Regardless of release ordering. */
2485 ddraw1 = create_ddraw();
2486 hr = IDirectDraw_SetDisplayMode(ddraw1, 800, 600, 32);
2487 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2488 w = GetSystemMetrics(SM_CXSCREEN);
2489 ok(w == 800, "Got unexpected screen width %u.\n", w);
2490 h = GetSystemMetrics(SM_CYSCREEN);
2491 ok(h == 600, "Got unexpected screen height %u.\n", h);
2493 ddraw2 = create_ddraw();
2494 hr = IDirectDraw_SetDisplayMode(ddraw2, 640, 480, 32);
2495 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2496 w = GetSystemMetrics(SM_CXSCREEN);
2497 ok(w == 640, "Got unexpected screen width %u.\n", w);
2498 h = GetSystemMetrics(SM_CYSCREEN);
2499 ok(h == 480, "Got unexpected screen height %u.\n", h);
2501 ref = IDirectDraw_Release(ddraw1);
2502 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2503 w = GetSystemMetrics(SM_CXSCREEN);
2504 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2505 h = GetSystemMetrics(SM_CYSCREEN);
2506 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2508 ref = IDirectDraw_Release(ddraw2);
2509 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2510 w = GetSystemMetrics(SM_CXSCREEN);
2511 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2512 h = GetSystemMetrics(SM_CYSCREEN);
2513 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2515 /* But only for ddraw objects that called SetDisplayMode(). */
2516 ddraw1 = create_ddraw();
2517 ddraw2 = create_ddraw();
2518 hr = IDirectDraw_SetDisplayMode(ddraw2, 640, 480, 32);
2519 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2520 w = GetSystemMetrics(SM_CXSCREEN);
2521 ok(w == 640, "Got unexpected screen width %u.\n", w);
2522 h = GetSystemMetrics(SM_CYSCREEN);
2523 ok(h == 480, "Got unexpected screen height %u.\n", h);
2525 ref = IDirectDraw_Release(ddraw1);
2526 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2527 w = GetSystemMetrics(SM_CXSCREEN);
2528 ok(w == 640, "Got unexpected screen width %u.\n", w);
2529 h = GetSystemMetrics(SM_CYSCREEN);
2530 ok(h == 480, "Got unexpected screen height %u.\n", h);
2532 ref = IDirectDraw_Release(ddraw2);
2533 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2534 w = GetSystemMetrics(SM_CXSCREEN);
2535 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2536 h = GetSystemMetrics(SM_CYSCREEN);
2537 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2539 /* If there's a ddraw object that's currently in exclusive mode, it blocks
2540 * restoring the display mode. */
2541 ddraw1 = create_ddraw();
2542 hr = IDirectDraw_SetDisplayMode(ddraw1, 800, 600, 32);
2543 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2544 w = GetSystemMetrics(SM_CXSCREEN);
2545 ok(w == 800, "Got unexpected screen width %u.\n", w);
2546 h = GetSystemMetrics(SM_CYSCREEN);
2547 ok(h == 600, "Got unexpected screen height %u.\n", h);
2549 ddraw2 = create_ddraw();
2550 hr = IDirectDraw_SetDisplayMode(ddraw2, 640, 480, 32);
2551 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2552 w = GetSystemMetrics(SM_CXSCREEN);
2553 ok(w == 640, "Got unexpected screen width %u.\n", w);
2554 h = GetSystemMetrics(SM_CYSCREEN);
2555 ok(h == 480, "Got unexpected screen height %u.\n", h);
2557 hr = IDirectDraw_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2558 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2560 ref = IDirectDraw_Release(ddraw1);
2561 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2562 w = GetSystemMetrics(SM_CXSCREEN);
2563 ok(w == 640, "Got unexpected screen width %u.\n", w);
2564 h = GetSystemMetrics(SM_CYSCREEN);
2565 ok(h == 480, "Got unexpected screen height %u.\n", h);
2567 ref = IDirectDraw_Release(ddraw2);
2568 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2569 w = GetSystemMetrics(SM_CXSCREEN);
2570 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2571 h = GetSystemMetrics(SM_CYSCREEN);
2572 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2574 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
2575 ddraw1 = create_ddraw();
2576 hr = IDirectDraw_SetDisplayMode(ddraw1, 800, 600, 32);
2577 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2578 w = GetSystemMetrics(SM_CXSCREEN);
2579 ok(w == 800, "Got unexpected screen width %u.\n", w);
2580 h = GetSystemMetrics(SM_CYSCREEN);
2581 ok(h == 600, "Got unexpected screen height %u.\n", h);
2583 hr = IDirectDraw_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2584 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2586 ddraw2 = create_ddraw();
2587 hr = IDirectDraw_SetDisplayMode(ddraw2, 640, 480, 32);
2588 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
2590 ref = IDirectDraw_Release(ddraw1);
2591 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2592 w = GetSystemMetrics(SM_CXSCREEN);
2593 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2594 h = GetSystemMetrics(SM_CYSCREEN);
2595 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2597 ref = IDirectDraw_Release(ddraw2);
2598 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2599 w = GetSystemMetrics(SM_CXSCREEN);
2600 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2601 h = GetSystemMetrics(SM_CYSCREEN);
2602 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2604 DestroyWindow(window);
2607 static void test_initialize(void)
2613 if (!(ddraw = create_ddraw()))
2615 skip("Failed to create a ddraw object, skipping test.\n");
2619 hr = IDirectDraw_Initialize(ddraw, NULL);
2620 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
2621 IDirectDraw_Release(ddraw);
2624 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw, (void **)&ddraw);
2625 ok(SUCCEEDED(hr), "Failed to create IDirectDraw instance, hr %#x.\n", hr);
2626 hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d);
2629 /* IDirect3D_Initialize() just returns DDERR_ALREADYINITIALIZED. */
2630 hr = IDirect3D_Initialize(d3d, NULL);
2631 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
2632 IDirect3D_Release(d3d);
2634 else skip("Failed to query IDirect3D interface, skipping tests.\n");
2635 hr = IDirectDraw_Initialize(ddraw, NULL);
2636 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
2637 hr = IDirectDraw_Initialize(ddraw, NULL);
2638 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
2639 IDirectDraw_Release(ddraw);
2642 if (0) /* This crashes on the W2KPROSP4 testbot. */
2645 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirect3D, (void **)&d3d);
2646 ok(hr == E_NOINTERFACE, "CoCreateInstance returned hr %#x, expected E_NOINTERFACE.\n", hr);
2651 static void test_coop_level_surf_create(void)
2653 IDirectDrawSurface *surface;
2658 if (!(ddraw = create_ddraw()))
2660 skip("Failed to create a ddraw object, skipping test.\n");
2664 memset(&ddsd, 0, sizeof(ddsd));
2665 ddsd.dwSize = sizeof(ddsd);
2666 ddsd.dwFlags = DDSD_CAPS;
2667 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2668 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
2669 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
2671 IDirectDraw_Release(ddraw);
2674 static void test_coop_level_multi_window(void)
2676 HWND window1, window2;
2680 window1 = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
2681 0, 0, 640, 480, 0, 0, 0, 0);
2682 window2 = CreateWindowA("static", "ddraw_test2", WS_OVERLAPPEDWINDOW,
2683 0, 0, 640, 480, 0, 0, 0, 0);
2684 if (!(ddraw = create_ddraw()))
2686 skip("Failed to create a ddraw object, skipping test.\n");
2687 DestroyWindow(window2);
2688 DestroyWindow(window1);
2692 hr = IDirectDraw_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
2693 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2694 hr = IDirectDraw_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
2695 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2696 ok(IsWindow(window1), "Window 1 was destroyed.\n");
2697 ok(IsWindow(window2), "Window 2 was destroyed.\n");
2699 IDirectDraw_Release(ddraw);
2700 DestroyWindow(window2);
2701 DestroyWindow(window1);
2704 static void test_clear_rect_count(void)
2706 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
2707 IDirect3DMaterial *white, *red, *green, *blue;
2708 IDirect3DViewport *viewport;
2709 IDirect3DDevice *device;
2710 IDirectDrawSurface *rt;
2716 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2717 0, 0, 640, 480, 0, 0, 0, 0);
2718 if (!(ddraw = create_ddraw()))
2720 skip("Failed to create ddraw object, skipping test.\n");
2721 DestroyWindow(window);
2724 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
2726 skip("Failed to create D3D device, skipping test.\n");
2727 IDirectDraw_Release(ddraw);
2728 DestroyWindow(window);
2732 hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
2733 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
2735 white = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
2736 red = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
2737 green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
2738 blue = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
2739 viewport = create_viewport(device, 0, 0, 640, 480);
2741 viewport_set_background(device, viewport, white);
2742 hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
2743 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2744 viewport_set_background(device, viewport, red);
2745 hr = IDirect3DViewport_Clear(viewport, 0, &clear_rect, D3DCLEAR_TARGET);
2746 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2747 viewport_set_background(device, viewport, green);
2748 hr = IDirect3DViewport_Clear(viewport, 0, NULL, D3DCLEAR_TARGET);
2749 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2750 viewport_set_background(device, viewport, blue);
2751 hr = IDirect3DViewport_Clear(viewport, 1, NULL, D3DCLEAR_TARGET);
2752 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
2754 color = get_surface_color(rt, 320, 240);
2755 ok(compare_color(color, 0x00ffffff, 1), "Got unexpected color 0x%08x.\n", color);
2757 IDirectDrawSurface_Release(rt);
2758 destroy_viewport(device, viewport);
2759 destroy_material(white);
2760 destroy_material(red);
2761 destroy_material(green);
2762 destroy_material(blue);
2763 IDirect3DDevice_Release(device);
2764 IDirectDraw_Release(ddraw);
2765 DestroyWindow(window);
2770 test_coop_level_create_device_window();
2772 test_coop_level_d3d_state();
2773 test_surface_interface_mismatch();
2774 test_coop_level_threaded();
2782 test_window_style();
2783 test_redundant_mode_set();
2784 test_coop_level_mode_set();
2785 test_coop_level_mode_set_multi();
2787 test_coop_level_surf_create();
2788 test_coop_level_multi_window();
2789 test_clear_rect_count();