ole32/tests: Check function pointer.
[wine.git] / dlls / ddraw / tests / ddraw4.c
blob742bd3f3c309ca3143947918ab5102c011f35f86
1 /*
2 * Copyright 2011-2012 Henri Verbeet for CodeWeavers
3 * Copyright 2012-2013 Stefan Dösinger for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define COBJMACROS
21 #include "wine/test.h"
22 #include <limits.h>
23 #include "d3d.h"
25 struct vec2
27 float x, y;
30 struct vec3
32 float x, y, z;
35 struct vec4
37 float x, y, z, w;
40 struct create_window_thread_param
42 HWND window;
43 HANDLE window_created;
44 HANDLE destroy_window;
45 HANDLE thread;
48 static BOOL compare_float(float f, float g, unsigned int ulps)
50 int x = *(int *)&f;
51 int y = *(int *)&g;
53 if (x < 0)
54 x = INT_MIN - x;
55 if (y < 0)
56 y = INT_MIN - y;
58 if (abs(x - y) > ulps)
59 return FALSE;
61 return TRUE;
64 static BOOL compare_vec4(struct vec4 *vec, float x, float y, float z, float w, unsigned int ulps)
66 return compare_float(vec->x, x, ulps)
67 && compare_float(vec->y, y, ulps)
68 && compare_float(vec->z, z, ulps)
69 && compare_float(vec->w, w, ulps);
72 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
74 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
75 c1 >>= 8; c2 >>= 8;
76 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
77 c1 >>= 8; c2 >>= 8;
78 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
79 c1 >>= 8; c2 >>= 8;
80 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
81 return TRUE;
84 static DWORD WINAPI create_window_thread_proc(void *param)
86 struct create_window_thread_param *p = param;
87 DWORD res;
88 BOOL ret;
90 p->window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
91 0, 0, 640, 480, 0, 0, 0, 0);
92 ret = SetEvent(p->window_created);
93 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
95 for (;;)
97 MSG msg;
99 while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
100 DispatchMessage(&msg);
101 res = WaitForSingleObject(p->destroy_window, 100);
102 if (res == WAIT_OBJECT_0)
103 break;
104 if (res != WAIT_TIMEOUT)
106 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
107 break;
111 DestroyWindow(p->window);
113 return 0;
116 static void create_window_thread(struct create_window_thread_param *p)
118 DWORD res, tid;
120 p->window_created = CreateEvent(NULL, FALSE, FALSE, NULL);
121 ok(!!p->window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
122 p->destroy_window = CreateEvent(NULL, FALSE, FALSE, NULL);
123 ok(!!p->destroy_window, "CreateEvent failed, last error %#x.\n", GetLastError());
124 p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
125 ok(!!p->thread, "Failed to create thread, last error %#x.\n", GetLastError());
126 res = WaitForSingleObject(p->window_created, INFINITE);
127 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
130 static void destroy_window_thread(struct create_window_thread_param *p)
132 SetEvent(p->destroy_window);
133 WaitForSingleObject(p->thread, INFINITE);
134 CloseHandle(p->destroy_window);
135 CloseHandle(p->window_created);
136 CloseHandle(p->thread);
139 static IDirectDrawSurface4 *get_depth_stencil(IDirect3DDevice3 *device)
141 IDirectDrawSurface4 *rt, *ret;
142 DDSCAPS2 caps = {DDSCAPS_ZBUFFER, 0, 0, 0};
143 HRESULT hr;
145 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
146 ok(SUCCEEDED(hr), "Failed to get the render target, hr %#x.\n", hr);
147 hr = IDirectDrawSurface4_GetAttachedSurface(rt, &caps, &ret);
148 ok(SUCCEEDED(hr) || hr == DDERR_NOTFOUND, "Failed to get the z buffer, hr %#x.\n", hr);
149 IDirectDrawSurface4_Release(rt);
150 return ret;
153 static D3DCOLOR get_surface_color(IDirectDrawSurface4 *surface, UINT x, UINT y)
155 RECT rect = {x, y, x + 1, y + 1};
156 DDSURFACEDESC2 surface_desc;
157 D3DCOLOR color;
158 HRESULT hr;
160 memset(&surface_desc, 0, sizeof(surface_desc));
161 surface_desc.dwSize = sizeof(surface_desc);
163 hr = IDirectDrawSurface4_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
164 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
165 if (FAILED(hr))
166 return 0xdeadbeef;
168 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
170 hr = IDirectDrawSurface4_Unlock(surface, &rect);
171 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
173 return color;
176 static HRESULT CALLBACK enum_z_fmt(DDPIXELFORMAT *format, void *ctx)
178 DDPIXELFORMAT *z_fmt = ctx;
180 if (U1(*format).dwZBufferBitDepth > U1(*z_fmt).dwZBufferBitDepth)
181 *z_fmt = *format;
183 return DDENUMRET_OK;
186 static IDirectDraw4 *create_ddraw(void)
188 IDirectDraw4 *ddraw4;
189 IDirectDraw *ddraw1;
190 HRESULT hr;
192 if (FAILED(DirectDrawCreate(NULL, &ddraw1, NULL)))
193 return NULL;
195 hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw4, (void **)&ddraw4);
196 IDirectDraw_Release(ddraw1);
197 if (FAILED(hr))
198 return NULL;
200 return ddraw4;
203 static IDirect3DDevice3 *create_device(HWND window, DWORD coop_level)
205 IDirectDrawSurface4 *surface, *ds;
206 IDirect3DDevice3 *device = NULL;
207 DDSURFACEDESC2 surface_desc;
208 IDirectDraw4 *ddraw4;
209 DDPIXELFORMAT z_fmt;
210 IDirect3D3 *d3d3;
211 HRESULT hr;
213 if (!(ddraw4 = create_ddraw()))
214 return NULL;
216 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, coop_level);
217 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
219 memset(&surface_desc, 0, sizeof(surface_desc));
220 surface_desc.dwSize = sizeof(surface_desc);
221 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
222 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
223 surface_desc.dwWidth = 640;
224 surface_desc.dwHeight = 480;
226 hr = IDirectDraw4_CreateSurface(ddraw4, &surface_desc, &surface, NULL);
227 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
229 if (coop_level & DDSCL_NORMAL)
231 IDirectDrawClipper *clipper;
233 hr = IDirectDraw4_CreateClipper(ddraw4, 0, &clipper, NULL);
234 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
235 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
236 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
237 hr = IDirectDrawSurface4_SetClipper(surface, clipper);
238 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\n", hr);
239 IDirectDrawClipper_Release(clipper);
242 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirect3D3, (void **)&d3d3);
243 IDirectDraw4_Release(ddraw4);
244 if (FAILED(hr))
246 IDirectDrawSurface4_Release(surface);
247 return NULL;
250 memset(&z_fmt, 0, sizeof(z_fmt));
251 hr = IDirect3D3_EnumZBufferFormats(d3d3, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
252 if (FAILED(hr) || !z_fmt.dwSize)
254 IDirect3D3_Release(d3d3);
255 IDirectDrawSurface4_Release(surface);
256 return NULL;
259 memset(&surface_desc, 0, sizeof(surface_desc));
260 surface_desc.dwSize = sizeof(surface_desc);
261 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
262 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
263 U4(surface_desc).ddpfPixelFormat = z_fmt;
264 surface_desc.dwWidth = 640;
265 surface_desc.dwHeight = 480;
266 hr = IDirectDraw4_CreateSurface(ddraw4, &surface_desc, &ds, NULL);
267 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
268 if (FAILED(hr))
270 IDirect3D3_Release(d3d3);
271 IDirectDrawSurface4_Release(surface);
272 return NULL;
275 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
276 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
277 IDirectDrawSurface4_Release(ds);
278 if (FAILED(hr))
280 IDirect3D3_Release(d3d3);
281 IDirectDrawSurface4_Release(surface);
282 return NULL;
285 hr = IDirect3D3_CreateDevice(d3d3, &IID_IDirect3DHALDevice, surface, &device, NULL);
286 IDirect3D3_Release(d3d3);
287 IDirectDrawSurface4_Release(surface);
288 if (FAILED(hr))
289 return NULL;
291 return device;
294 static IDirect3DViewport3 *create_viewport(IDirect3DDevice3 *device, UINT x, UINT y, UINT w, UINT h)
296 IDirect3DViewport3 *viewport;
297 D3DVIEWPORT2 vp;
298 IDirect3D3 *d3d;
299 HRESULT hr;
301 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
302 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
303 hr = IDirect3D3_CreateViewport(d3d, &viewport, NULL);
304 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
305 hr = IDirect3DDevice3_AddViewport(device, viewport);
306 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
307 memset(&vp, 0, sizeof(vp));
308 vp.dwSize = sizeof(vp);
309 vp.dwX = x;
310 vp.dwY = y;
311 vp.dwWidth = w;
312 vp.dwHeight = h;
313 vp.dvClipX = -1.0f;
314 vp.dvClipY = 1.0f;
315 vp.dvClipWidth = 2.0f;
316 vp.dvClipHeight = 2.0f;
317 vp.dvMinZ = 0.0f;
318 vp.dvMaxZ = 1.0f;
319 hr = IDirect3DViewport3_SetViewport2(viewport, &vp);
320 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
321 IDirect3D3_Release(d3d);
323 return viewport;
326 static void destroy_viewport(IDirect3DDevice3 *device, IDirect3DViewport3 *viewport)
328 HRESULT hr;
330 hr = IDirect3DDevice3_DeleteViewport(device, viewport);
331 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
332 IDirect3DViewport3_Release(viewport);
335 static const UINT *expect_messages;
337 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
339 if (expect_messages && message == *expect_messages)
340 ++expect_messages;
342 return DefWindowProcA(hwnd, message, wparam, lparam);
345 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
346 * interface. This prevents subsequent SetCooperativeLevel() calls on a
347 * different window from failing with DDERR_HWNDALREADYSET. */
348 static void fix_wndproc(HWND window, LONG_PTR proc)
350 IDirectDraw4 *ddraw;
351 HRESULT hr;
353 if (!(ddraw = create_ddraw()))
354 return;
356 SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
357 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
358 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
359 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
360 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
362 IDirectDraw4_Release(ddraw);
365 static void test_process_vertices(void)
367 IDirect3DVertexBuffer *src_vb, *dst_vb;
368 IDirect3DViewport3 *viewport;
369 D3DVERTEXBUFFERDESC vb_desc;
370 IDirect3DDevice3 *device;
371 struct vec3 *src_data;
372 struct vec4 *dst_data;
373 IDirect3D3 *d3d3;
374 D3DVIEWPORT2 vp2;
375 D3DVIEWPORT vp1;
376 HWND window;
377 HRESULT hr;
379 static D3DMATRIX identity =
381 1.0f, 0.0f, 0.0f, 0.0f,
382 0.0f, 1.0f, 0.0f, 0.0f,
383 0.0f, 0.0f, 1.0f, 0.0f,
384 0.0f, 0.0f, 0.0f, 1.0f,
386 static D3DMATRIX projection =
388 1.0f, 0.0f, 0.0f, 0.0f,
389 0.0f, 1.0f, 0.0f, 0.0f,
390 0.0f, 0.0f, 1.0f, 0.0f,
391 6.0f, 7.0f, 8.0f, 1.0f,
394 window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
395 0, 0, 640, 480, 0, 0, 0, 0);
396 if (!(device = create_device(window, DDSCL_NORMAL)))
398 skip("Failed to create a 3D device, skipping test.\n");
399 DestroyWindow(window);
400 return;
403 hr = IDirect3DDevice3_GetDirect3D(device, &d3d3);
404 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
406 memset(&vb_desc, 0, sizeof(vb_desc));
407 vb_desc.dwSize = sizeof(vb_desc);
408 vb_desc.dwFVF = D3DFVF_XYZ;
409 vb_desc.dwNumVertices = 3;
410 hr = IDirect3D3_CreateVertexBuffer(d3d3, &vb_desc, &src_vb, 0, NULL);
411 ok(SUCCEEDED(hr), "Failed to create source vertex buffer, hr %#x.\n", hr);
413 hr = IDirect3DVertexBuffer_Lock(src_vb, DDLOCK_WRITEONLY, (void **)&src_data, NULL);
414 ok(SUCCEEDED(hr), "Failed to lock source vertex buffer, hr %#x.\n", hr);
415 src_data[0].x = -1.0f;
416 src_data[0].y = -1.0f;
417 src_data[0].z = -1.0f;
418 src_data[1].x = 0.0f;
419 src_data[1].y = 0.0f;
420 src_data[1].z = 0.0f;
421 src_data[2].x = 1.0f;
422 src_data[2].y = 1.0f;
423 src_data[2].z = 1.0f;
424 hr = IDirect3DVertexBuffer_Unlock(src_vb);
425 ok(SUCCEEDED(hr), "Failed to unlock source vertex buffer, hr %#x.\n", hr);
427 memset(&vb_desc, 0, sizeof(vb_desc));
428 vb_desc.dwSize = sizeof(vb_desc);
429 vb_desc.dwFVF = D3DFVF_XYZRHW;
430 vb_desc.dwNumVertices = 3;
431 hr = IDirect3D3_CreateVertexBuffer(d3d3, &vb_desc, &dst_vb, 0, NULL);
432 ok(SUCCEEDED(hr), "Failed to create destination vertex buffer, hr %#x.\n", hr);
434 hr = IDirect3D3_CreateViewport(d3d3, &viewport, NULL);
435 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
436 hr = IDirect3DDevice3_AddViewport(device, viewport);
437 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
438 vp2.dwSize = sizeof(vp2);
439 vp2.dwX = 10;
440 vp2.dwY = 20;
441 vp2.dwWidth = 100;
442 vp2.dwHeight = 200;
443 vp2.dvClipX = 2.0f;
444 vp2.dvClipY = 3.0f;
445 vp2.dvClipWidth = 4.0f;
446 vp2.dvClipHeight = 5.0f;
447 vp2.dvMinZ = -2.0f;
448 vp2.dvMaxZ = 3.0f;
449 hr = IDirect3DViewport3_SetViewport2(viewport, &vp2);
450 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
451 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
452 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
454 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &identity);
455 ok(SUCCEEDED(hr), "Failed to set world transformation, hr %#x.\n", hr);
456 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &identity);
457 ok(SUCCEEDED(hr), "Failed to set view transformation, hr %#x.\n", hr);
458 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &identity);
459 ok(SUCCEEDED(hr), "Failed to set projection transformation, hr %#x.\n", hr);
461 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
462 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
464 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
465 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
466 ok(compare_vec4(&dst_data[0], -6.500e+1f, +1.800e+2f, +2.000e-1f, +1.000e+0f, 4096),
467 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
468 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
469 ok(compare_vec4(&dst_data[1], -4.000e+1f, +1.400e+2f, +4.000e-1f, +1.000e+0f, 4096),
470 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
471 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
472 ok(compare_vec4(&dst_data[2], -1.500e+1f, +1.000e+2f, +6.000e-1f, +1.000e+0f, 4096),
473 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
474 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
475 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
476 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
478 hr = IDirect3DDevice3_MultiplyTransform(device, D3DTRANSFORMSTATE_PROJECTION, &projection);
479 ok(SUCCEEDED(hr), "Failed to set projection transformation, hr %#x.\n", hr);
481 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
482 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
484 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
485 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
486 ok(compare_vec4(&dst_data[0], +8.500e+1f, -1.000e+2f, +1.800e+0f, +1.000e+0f, 4096),
487 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
488 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
489 ok(compare_vec4(&dst_data[1], +1.100e+2f, -1.400e+2f, +2.000e+0f, +1.000e+0f, 4096),
490 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
491 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
492 ok(compare_vec4(&dst_data[2], +1.350e+2f, -1.800e+2f, +2.200e+0f, +1.000e+0f, 4096),
493 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
494 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
495 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
496 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
498 vp2.dwSize = sizeof(vp2);
499 vp2.dwX = 30;
500 vp2.dwY = 40;
501 vp2.dwWidth = 90;
502 vp2.dwHeight = 80;
503 vp2.dvClipX = 4.0f;
504 vp2.dvClipY = 6.0f;
505 vp2.dvClipWidth = 2.0f;
506 vp2.dvClipHeight = 4.0f;
507 vp2.dvMinZ = 3.0f;
508 vp2.dvMaxZ = -2.0f;
509 hr = IDirect3DViewport3_SetViewport2(viewport, &vp2);
510 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
512 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
513 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
515 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
516 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
517 ok(compare_vec4(&dst_data[0], +7.500e+1f, +4.000e+1f, -8.000e-1f, +1.000e+0f, 4096),
518 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
519 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
520 ok(compare_vec4(&dst_data[1], +1.200e+2f, +2.000e+1f, -1.000e+0f, +1.000e+0f, 4096),
521 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
522 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
523 ok(compare_vec4(&dst_data[2], +1.650e+2f, +0.000e+0f, -1.200e+0f, +1.000e+0f, 4096),
524 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
525 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
526 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
527 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
529 vp1.dwSize = sizeof(vp1);
530 vp1.dwX = 30;
531 vp1.dwY = 40;
532 vp1.dwWidth = 90;
533 vp1.dwHeight = 80;
534 vp1.dvScaleX = 7.0f;
535 vp1.dvScaleY = 2.0f;
536 vp1.dvMaxX = 6.0f;
537 vp1.dvMaxY = 10.0f;
538 vp1.dvMinZ = -2.0f;
539 vp1.dvMaxZ = 3.0f;
540 hr = IDirect3DViewport3_SetViewport(viewport, &vp1);
541 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
543 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
544 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
546 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
547 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
548 ok(compare_vec4(&dst_data[0], +1.100e+2f, +6.800e+1f, +7.000e+0f, +1.000e+0f, 4096),
549 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
550 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
551 ok(compare_vec4(&dst_data[1], +1.170e+2f, +6.600e+1f, +8.000e+0f, +1.000e+0f, 4096),
552 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
553 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
554 ok(compare_vec4(&dst_data[2], +1.240e+2f, +6.400e+1f, +9.000e+0f, +1.000e+0f, 4096),
555 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
556 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
557 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
558 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
560 hr = IDirect3DDevice3_DeleteViewport(device, viewport);
561 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
563 IDirect3DVertexBuffer_Release(dst_vb);
564 IDirect3DVertexBuffer_Release(src_vb);
565 IDirect3DViewport3_Release(viewport);
566 IDirect3D3_Release(d3d3);
567 IDirect3DDevice3_Release(device);
568 DestroyWindow(window);
571 static void test_coop_level_create_device_window(void)
573 HWND focus_window, device_window;
574 IDirectDraw4 *ddraw;
575 HRESULT hr;
577 focus_window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
578 0, 0, 640, 480, 0, 0, 0, 0);
579 if (!(ddraw = create_ddraw()))
581 skip("Failed to create a ddraw object, skipping test.\n");
582 DestroyWindow(focus_window);
583 return;
586 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
587 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
588 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
589 ok(!device_window, "Unexpected device window found.\n");
590 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
591 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
592 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
593 ok(!device_window, "Unexpected device window found.\n");
594 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
595 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
596 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
597 ok(!device_window, "Unexpected device window found.\n");
598 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
599 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
600 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
601 ok(!device_window, "Unexpected device window found.\n");
602 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
603 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
604 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
605 ok(!device_window, "Unexpected device window found.\n");
607 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
608 if (broken(hr == DDERR_INVALIDPARAMS))
610 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
611 IDirectDraw4_Release(ddraw);
612 DestroyWindow(focus_window);
613 return;
616 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
617 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
618 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
619 ok(!device_window, "Unexpected device window found.\n");
620 hr = IDirectDraw4_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
621 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
622 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
623 ok(!device_window, "Unexpected device window found.\n");
625 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
626 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
627 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
628 ok(!device_window, "Unexpected device window found.\n");
629 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
630 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
631 ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
632 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
633 ok(!!device_window, "Device window not found.\n");
635 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
636 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
637 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
638 ok(!device_window, "Unexpected device window found.\n");
639 hr = IDirectDraw4_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
640 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
641 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
642 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
643 ok(!!device_window, "Device window not found.\n");
645 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
646 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
647 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
648 ok(!device_window, "Unexpected device window found.\n");
649 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
650 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
651 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
652 ok(!device_window, "Unexpected device window found.\n");
653 hr = IDirectDraw4_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
654 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
655 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
656 ok(!device_window, "Unexpected device window found.\n");
657 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
658 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
659 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
660 ok(!!device_window, "Device window not found.\n");
662 IDirectDraw4_Release(ddraw);
663 DestroyWindow(focus_window);
666 static void test_clipper_blt(void)
668 IDirectDrawSurface4 *src_surface, *dst_surface;
669 RECT client_rect, src_rect;
670 IDirectDrawClipper *clipper;
671 DDSURFACEDESC2 surface_desc;
672 unsigned int i, j, x, y;
673 IDirectDraw4 *ddraw;
674 RGNDATA *rgn_data;
675 D3DCOLOR color;
676 HRGN r1, r2;
677 HWND window;
678 DDBLTFX fx;
679 HRESULT hr;
680 DWORD *ptr;
681 DWORD ret;
683 static const DWORD src_data[] =
685 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
686 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
687 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
689 static const D3DCOLOR expected1[] =
691 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
692 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
693 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
694 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
696 static const D3DCOLOR expected2[] =
698 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
699 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
700 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
701 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
704 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
705 10, 10, 640, 480, 0, 0, 0, 0);
706 ShowWindow(window, SW_SHOW);
707 if (!(ddraw = create_ddraw()))
709 skip("Failed to create a ddraw object, skipping test.\n");
710 DestroyWindow(window);
711 return;
714 ret = GetClientRect(window, &client_rect);
715 ok(ret, "Failed to get client rect.\n");
716 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
717 ok(ret, "Failed to map client rect.\n");
719 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
720 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
722 hr = IDirectDraw4_CreateClipper(ddraw, 0, &clipper, NULL);
723 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
724 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
725 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
726 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
727 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
728 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
729 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
730 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
731 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
732 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
733 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
734 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
735 ok(rgn_data->rdh.nCount >= 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
736 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
737 "Got unexpected bounding rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
738 rgn_data->rdh.rcBound.left, rgn_data->rdh.rcBound.top,
739 rgn_data->rdh.rcBound.right, rgn_data->rdh.rcBound.bottom,
740 client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
741 HeapFree(GetProcessHeap(), 0, rgn_data);
743 r1 = CreateRectRgn(0, 0, 320, 240);
744 ok(!!r1, "Failed to create region.\n");
745 r2 = CreateRectRgn(320, 240, 640, 480);
746 ok(!!r2, "Failed to create region.\n");
747 CombineRgn(r1, r1, r2, RGN_OR);
748 ret = GetRegionData(r1, 0, NULL);
749 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
750 ret = GetRegionData(r1, ret, rgn_data);
751 ok(!!ret, "Failed to get region data.\n");
753 DeleteObject(r2);
754 DeleteObject(r1);
756 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
757 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
758 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
759 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
760 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
761 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
763 HeapFree(GetProcessHeap(), 0, rgn_data);
765 memset(&surface_desc, 0, sizeof(surface_desc));
766 surface_desc.dwSize = sizeof(surface_desc);
767 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
768 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
769 surface_desc.dwWidth = 640;
770 surface_desc.dwHeight = 480;
771 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
772 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
773 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
774 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
775 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
776 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
778 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
779 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
780 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
781 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
783 memset(&fx, 0, sizeof(fx));
784 fx.dwSize = sizeof(fx);
785 hr = IDirectDrawSurface4_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
786 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
787 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
788 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
790 hr = IDirectDrawSurface4_Lock(src_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
791 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
792 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
793 ptr = surface_desc.lpSurface;
794 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
795 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
796 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
797 hr = IDirectDrawSurface4_Unlock(src_surface, NULL);
798 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
800 hr = IDirectDrawSurface4_SetClipper(dst_surface, clipper);
801 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
803 SetRect(&src_rect, 1, 1, 5, 2);
804 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
805 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
806 for (i = 0; i < 4; ++i)
808 for (j = 0; j < 4; ++j)
810 x = 80 * ((2 * j) + 1);
811 y = 60 * ((2 * i) + 1);
812 color = get_surface_color(dst_surface, x, y);
813 ok(compare_color(color, expected1[i * 4 + j], 1),
814 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
818 U5(fx).dwFillColor = 0xff0000ff;
819 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
820 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
821 for (i = 0; i < 4; ++i)
823 for (j = 0; j < 4; ++j)
825 x = 80 * ((2 * j) + 1);
826 y = 60 * ((2 * i) + 1);
827 color = get_surface_color(dst_surface, x, y);
828 ok(compare_color(color, expected2[i * 4 + j], 1),
829 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
833 hr = IDirectDrawSurface4_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
834 ok(hr == DDERR_BLTFASTCANTCLIP, "Got unexpected hr %#x.\n", hr);
836 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
837 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
838 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
839 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
840 DestroyWindow(window);
841 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
842 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
843 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
844 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
845 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
846 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
847 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
848 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
849 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
850 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
851 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
852 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
854 IDirectDrawSurface4_Release(dst_surface);
855 IDirectDrawSurface4_Release(src_surface);
856 IDirectDrawClipper_Release(clipper);
857 IDirectDraw4_Release(ddraw);
860 static void test_coop_level_d3d_state(void)
862 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
863 IDirectDrawSurface4 *rt, *surface;
864 IDirect3DViewport3 *viewport;
865 IDirect3DDevice3 *device;
866 IDirectDraw4 *ddraw;
867 IDirect3D3 *d3d;
868 D3DCOLOR color;
869 DWORD value;
870 HWND window;
871 HRESULT hr;
873 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
874 0, 0, 640, 480, 0, 0, 0, 0);
875 if (!(device = create_device(window, DDSCL_NORMAL)))
877 skip("Failed to create D3D device, skipping test.\n");
878 DestroyWindow(window);
879 return;
882 viewport = create_viewport(device, 0, 0, 640, 480);
884 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
885 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
886 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
887 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
888 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
889 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
890 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
891 ok(!value, "Got unexpected alpha blend enable state %#x.\n", value);
892 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
893 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
894 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
895 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
896 color = get_surface_color(rt, 320, 240);
897 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
899 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
900 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
901 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
902 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
903 IDirect3D3_Release(d3d);
904 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
905 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
906 hr = IDirectDrawSurface4_IsLost(rt);
907 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
908 hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
909 ok(SUCCEEDED(hr), "Failed to restore surfaces, hr %#x.\n", hr);
910 IDirectDraw4_Release(ddraw);
912 hr = IDirect3DDevice3_GetRenderTarget(device, &surface);
913 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
914 ok(surface == rt, "Got unexpected surface %p.\n", surface);
915 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
916 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
917 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
918 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
919 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
920 ok(!!value, "Got unexpected alpha blend enable state %#x.\n", value);
921 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
922 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
923 color = get_surface_color(rt, 320, 240);
924 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
926 destroy_viewport(device, viewport);
927 IDirectDrawSurface4_Release(surface);
928 IDirectDrawSurface4_Release(rt);
929 IDirect3DDevice3_Release(device);
930 DestroyWindow(window);
933 static void test_surface_interface_mismatch(void)
935 IDirectDraw4 *ddraw = NULL;
936 IDirect3D3 *d3d = NULL;
937 IDirectDrawSurface4 *surface = NULL, *ds;
938 IDirectDrawSurface3 *surface3 = NULL;
939 IDirect3DDevice3 *device = NULL;
940 IDirect3DViewport3 *viewport = NULL;
941 DDSURFACEDESC2 surface_desc;
942 DDPIXELFORMAT z_fmt;
943 ULONG refcount;
944 HRESULT hr;
945 D3DCOLOR color;
946 HWND window;
947 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
949 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
950 0, 0, 640, 480, 0, 0, 0, 0);
952 if (!(ddraw = create_ddraw()))
954 skip("Failed to create a ddraw object, skipping test.\n");
955 goto cleanup;
958 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
959 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
961 memset(&surface_desc, 0, sizeof(surface_desc));
962 surface_desc.dwSize = sizeof(surface_desc);
963 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
964 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
965 surface_desc.dwWidth = 640;
966 surface_desc.dwHeight = 480;
968 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
969 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
971 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
972 ok(SUCCEEDED(hr), "Failed to QI IDirectDrawSurface3, hr %#x.\n", hr);
974 hr = IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d);
975 if (FAILED(hr))
977 skip("Failed to get the IDirect3D7 interface, skipping test.\n");
978 goto cleanup;
981 memset(&z_fmt, 0, sizeof(z_fmt));
982 hr = IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
983 if (FAILED(hr) || !z_fmt.dwSize)
985 skip("No depth buffer formats available, skipping test.\n");
986 goto cleanup;
989 memset(&surface_desc, 0, sizeof(surface_desc));
990 surface_desc.dwSize = sizeof(surface_desc);
991 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
992 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
993 U4(surface_desc).ddpfPixelFormat = z_fmt;
994 surface_desc.dwWidth = 640;
995 surface_desc.dwHeight = 480;
996 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &ds, NULL);
997 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
998 if (FAILED(hr))
999 goto cleanup;
1001 /* Using a different surface interface version still works */
1002 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
1003 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
1004 refcount = IDirectDrawSurface4_Release(ds);
1005 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
1006 if (FAILED(hr))
1007 goto cleanup;
1009 /* Here too */
1010 hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, (IDirectDrawSurface4 *)surface3, &device, NULL);
1011 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
1012 if (FAILED(hr))
1013 goto cleanup;
1015 viewport = create_viewport(device, 0, 0, 640, 480);
1017 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
1018 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1019 color = get_surface_color(surface, 320, 240);
1020 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1022 cleanup:
1023 if (viewport)
1024 destroy_viewport(device, viewport);
1025 if (surface3) IDirectDrawSurface3_Release(surface3);
1026 if (surface) IDirectDrawSurface4_Release(surface);
1027 if (device) IDirect3DDevice3_Release(device);
1028 if (d3d) IDirect3D3_Release(d3d);
1029 if (ddraw) IDirectDraw4_Release(ddraw);
1030 DestroyWindow(window);
1033 static void test_coop_level_threaded(void)
1035 struct create_window_thread_param p;
1036 IDirectDraw4 *ddraw;
1037 HRESULT hr;
1039 if (!(ddraw = create_ddraw()))
1041 skip("Failed to create a ddraw object, skipping test.\n");
1042 return;
1044 create_window_thread(&p);
1046 hr = IDirectDraw4_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1047 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1049 IDirectDraw4_Release(ddraw);
1050 destroy_window_thread(&p);
1053 static void test_depth_blit(void)
1055 static struct
1057 float x, y, z;
1058 DWORD color;
1060 quad1[] =
1062 { -1.0, 1.0, 0.50f, 0xff00ff00},
1063 { 1.0, 1.0, 0.50f, 0xff00ff00},
1064 { -1.0, -1.0, 0.50f, 0xff00ff00},
1065 { 1.0, -1.0, 0.50f, 0xff00ff00},
1067 static const D3DCOLOR expected_colors[4][4] =
1069 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1070 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1071 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1072 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1074 DDSURFACEDESC2 ddsd_new, ddsd_existing;
1076 IDirect3DDevice3 *device;
1077 IDirectDrawSurface4 *ds1, *ds2, *ds3, *rt;
1078 IDirect3DViewport3 *viewport;
1079 RECT src_rect, dst_rect;
1080 unsigned int i, j;
1081 D3DCOLOR color;
1082 HRESULT hr;
1083 IDirect3D3 *d3d;
1084 IDirectDraw4 *ddraw;
1085 DDBLTFX fx;
1086 HWND window;
1087 D3DRECT d3drect;
1089 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1090 0, 0, 640, 480, 0, 0, 0, 0);
1091 if (!(device = create_device(window, DDSCL_NORMAL)))
1093 skip("Failed to create D3D device, skipping test.\n");
1094 DestroyWindow(window);
1095 return;
1098 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1099 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
1100 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1101 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
1102 IDirect3D3_Release(d3d);
1104 ds1 = get_depth_stencil(device);
1106 memset(&ddsd_new, 0, sizeof(ddsd_new));
1107 ddsd_new.dwSize = sizeof(ddsd_new);
1108 memset(&ddsd_existing, 0, sizeof(ddsd_existing));
1109 ddsd_existing.dwSize = sizeof(ddsd_existing);
1110 hr = IDirectDrawSurface4_GetSurfaceDesc(ds1, &ddsd_existing);
1111 ddsd_new.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1112 ddsd_new.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1113 ddsd_new.dwWidth = ddsd_existing.dwWidth;
1114 ddsd_new.dwHeight = ddsd_existing.dwHeight;
1115 U4(ddsd_new).ddpfPixelFormat = U4(ddsd_existing).ddpfPixelFormat;
1116 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd_new, &ds2, NULL);
1117 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
1118 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd_new, &ds3, NULL);
1119 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
1120 IDirectDraw4_Release(ddraw);
1122 viewport = create_viewport(device, 0, 0, ddsd_existing.dwWidth, ddsd_existing.dwHeight);
1123 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
1124 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
1126 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
1127 ok(SUCCEEDED(hr), "Failed to enable z testing, hr %#x.\n", hr);
1128 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
1129 ok(SUCCEEDED(hr), "Failed to set the z function, hr %#x.\n", hr);
1130 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
1131 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
1133 U1(d3drect).x1 = U2(d3drect).y1 = 0;
1134 U3(d3drect).x2 = ddsd_existing.dwWidth; U4(d3drect).y2 = ddsd_existing.dwHeight;
1135 hr = IDirect3DViewport3_Clear2(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
1136 ok(SUCCEEDED(hr), "Failed to clear the z buffer, hr %#x.\n", hr);
1138 /* Partial blit. */
1139 SetRect(&src_rect, 0, 0, 320, 240);
1140 SetRect(&dst_rect, 0, 0, 320, 240);
1141 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1142 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1143 /* Different locations. */
1144 SetRect(&src_rect, 0, 0, 320, 240);
1145 SetRect(&dst_rect, 320, 240, 640, 480);
1146 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1147 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1148 /* Streched. */
1149 SetRect(&src_rect, 0, 0, 320, 240);
1150 SetRect(&dst_rect, 0, 0, 640, 480);
1151 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1152 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1153 /* Flipped. */
1154 SetRect(&src_rect, 0, 480, 640, 0);
1155 SetRect(&dst_rect, 0, 0, 640, 480);
1156 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1157 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1158 SetRect(&src_rect, 0, 0, 640, 480);
1159 SetRect(&dst_rect, 0, 480, 640, 0);
1160 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1161 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1162 /* Full, explicit. */
1163 SetRect(&src_rect, 0, 0, 640, 480);
1164 SetRect(&dst_rect, 0, 0, 640, 480);
1165 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1166 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1167 /* Depth -> color blit: Succeeds on Win7 + Radeon HD 5700, fails on WinXP + Radeon X1600 */
1169 /* Depth blit inside a BeginScene / EndScene pair */
1170 hr = IDirect3DDevice3_BeginScene(device);
1171 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
1172 /* From the current depth stencil */
1173 hr = IDirectDrawSurface4_Blt(ds2, NULL, ds1, NULL, DDBLT_WAIT, NULL);
1174 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1175 /* To the current depth stencil */
1176 hr = IDirectDrawSurface4_Blt(ds1, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1177 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1178 /* Between unbound surfaces */
1179 hr = IDirectDrawSurface4_Blt(ds3, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1180 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1181 hr = IDirect3DDevice3_EndScene(device);
1182 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1184 /* Avoid changing the depth stencil, it doesn't work properly on Windows.
1185 * Instead use DDBLT_DEPTHFILL to clear the depth stencil. Unfortunately
1186 * drivers disagree on the meaning of dwFillDepth. Only 0 seems to produce
1187 * a reliable result(z = 0.0) */
1188 memset(&fx, 0, sizeof(fx));
1189 fx.dwSize = sizeof(fx);
1190 hr = IDirectDrawSurface4_Blt(ds2, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
1191 ok(SUCCEEDED(hr), "Failed to clear the source z buffer, hr %#x.\n", hr);
1193 hr = IDirect3DViewport3_Clear2(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET, 0xffff0000, 1.0f, 0);
1194 ok(SUCCEEDED(hr), "Failed to clear the color and z buffers, hr %#x.\n", hr);
1195 SetRect(&dst_rect, 0, 0, 320, 240);
1196 hr = IDirectDrawSurface4_Blt(ds1, &dst_rect, ds2, NULL, DDBLT_WAIT, NULL);
1197 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1198 IDirectDrawSurface4_Release(ds3);
1199 IDirectDrawSurface4_Release(ds2);
1200 IDirectDrawSurface4_Release(ds1);
1202 hr = IDirect3DDevice3_BeginScene(device);
1203 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
1204 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
1205 quad1, 4, 0);
1206 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1207 hr = IDirect3DDevice3_EndScene(device);
1208 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1210 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1211 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1212 for (i = 0; i < 4; ++i)
1214 for (j = 0; j < 4; ++j)
1216 unsigned int x = 80 * ((2 * j) + 1);
1217 unsigned int y = 60 * ((2 * i) + 1);
1218 color = get_surface_color(rt, x, y);
1219 ok(compare_color(color, expected_colors[i][j], 1),
1220 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
1223 IDirectDrawSurface4_Release(rt);
1225 destroy_viewport(device, viewport);
1226 IDirect3DDevice3_Release(device);
1227 DestroyWindow(window);
1230 static void test_texture_load_ckey(void)
1232 IDirectDraw4 *ddraw;
1233 IDirectDrawSurface4 *src;
1234 IDirectDrawSurface4 *dst;
1235 IDirect3DTexture2 *src_tex;
1236 IDirect3DTexture2 *dst_tex;
1237 DDSURFACEDESC2 ddsd;
1238 HRESULT hr;
1239 DDCOLORKEY ckey;
1241 if (!(ddraw = create_ddraw()))
1243 skip("Failed to create ddraw object, skipping test.\n");
1244 return;
1246 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
1247 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1249 memset(&ddsd, 0, sizeof(ddsd));
1250 ddsd.dwSize = sizeof(ddsd);
1251 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
1252 ddsd.dwHeight = 128;
1253 ddsd.dwWidth = 128;
1254 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
1255 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &src, NULL);
1256 ok(SUCCEEDED(hr), "Failed to create source texture, hr %#x.\n", hr);
1257 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1258 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &dst, NULL);
1259 ok(SUCCEEDED(hr), "Failed to create destination texture, hr %#x.\n", hr);
1261 hr = IDirectDrawSurface4_QueryInterface(src, &IID_IDirect3DTexture2, (void **)&src_tex);
1262 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get Direct3DTexture2 interface, hr %#x.\n", hr);
1263 if (FAILED(hr))
1265 /* 64 bit ddraw does not support d3d */
1266 skip("Could not get Direct3DTexture2 interface, skipping texture::Load color keying tests.\n");
1267 IDirectDrawSurface4_Release(dst);
1268 IDirectDrawSurface4_Release(src);
1269 IDirectDraw4_Release(ddraw);
1270 return;
1272 hr = IDirectDrawSurface4_QueryInterface(dst, &IID_IDirect3DTexture2, (void **)&dst_tex);
1273 ok(SUCCEEDED(hr), "Failed to get Direct3DTexture2 interface, hr %#x.\n", hr);
1275 /* No surface has a color key */
1276 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1277 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1278 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0xdeadbeef;
1279 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1280 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1281 ok(ckey.dwColorSpaceLowValue == 0xdeadbeef, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1282 ok(ckey.dwColorSpaceHighValue == 0xdeadbeef, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1284 /* Source surface has a color key */
1285 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
1286 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
1287 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1288 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1289 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1290 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1291 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1292 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1293 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1295 /* Both surfaces have a color key: Dest ckey is overwritten */
1296 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x000000ff;
1297 hr = IDirectDrawSurface4_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1298 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1299 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1300 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1301 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1302 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1303 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1304 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1306 /* Only the destination has a color key: It is not deleted */
1307 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, NULL);
1308 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1309 hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
1310 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1311 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1312 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1313 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1314 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1315 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1316 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1318 IDirect3DTexture2_Release(dst_tex);
1319 IDirect3DTexture2_Release(src_tex);
1320 IDirectDrawSurface4_Release(dst);
1321 IDirectDrawSurface4_Release(src);
1322 IDirectDraw4_Release(ddraw);
1325 static ULONG get_refcount(IUnknown *test_iface)
1327 IUnknown_AddRef(test_iface);
1328 return IUnknown_Release(test_iface);
1331 static void test_viewport(void)
1333 IDirectDraw4 *ddraw;
1334 IDirect3D3 *d3d;
1335 HRESULT hr, old_d3d_ref;
1336 ULONG ref;
1337 IDirect3DViewport *viewport;
1338 IDirect3DViewport2 *viewport2;
1339 IDirect3DViewport3 *viewport3, *another_vp, *test_vp;
1340 IDirectDrawGammaControl *gamma;
1341 IUnknown *unknown;
1342 HWND window;
1343 IDirect3DDevice3 *device;
1345 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1346 0, 0, 640, 480, 0, 0, 0, 0);
1347 if (!(device = create_device(window, DDSCL_NORMAL)))
1349 skip("Failed to create D3D device, skipping test.\n");
1350 DestroyWindow(window);
1351 return;
1353 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1354 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
1355 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1356 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
1357 old_d3d_ref = get_refcount((IUnknown *) d3d);
1359 hr = IDirect3D3_CreateViewport(d3d, &viewport3, NULL);
1360 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1361 ref = get_refcount((IUnknown *)viewport3);
1362 ok(ref == 1, "Initial IDirect3DViewport3 refcount is %u\n", ref);
1363 ref = get_refcount((IUnknown *)d3d);
1364 ok(ref == old_d3d_ref, "IDirect3D3 refcount is %u\n", ref);
1366 gamma = (IDirectDrawGammaControl *)0xdeadbeef;
1367 hr = IDirect3DViewport2_QueryInterface(viewport3, &IID_IDirectDrawGammaControl, (void **)&gamma);
1368 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
1369 ok(gamma == NULL, "Interface not set to NULL by failed QI call: %p\n", gamma);
1370 if (SUCCEEDED(hr)) IDirectDrawGammaControl_Release(gamma);
1371 /* NULL iid: Segfaults */
1373 hr = IDirect3DViewport3_QueryInterface(viewport3, &IID_IDirect3DViewport, (void **)&viewport);
1374 ok(SUCCEEDED(hr), "Failed to QI IDirect3DViewport, hr %#x.\n", hr);
1375 if (viewport)
1377 ref = get_refcount((IUnknown *)viewport);
1378 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
1379 ref = get_refcount((IUnknown *)viewport3);
1380 ok(ref == 2, "IDirect3DViewport3 refcount is %u\n", ref);
1381 IDirect3DViewport_Release(viewport);
1382 viewport = NULL;
1385 hr = IDirect3DViewport3_QueryInterface(viewport3, &IID_IDirect3DViewport3, (void **)&viewport2);
1386 ok(SUCCEEDED(hr), "Failed to QI IDirect3DViewport3, hr %#x.\n", hr);
1387 if (viewport2)
1389 ref = get_refcount((IUnknown *)viewport2);
1390 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
1391 ref = get_refcount((IUnknown *)viewport3);
1392 ok(ref == 2, "IDirect3DViewport3 refcount is %u\n", ref);
1393 IDirect3DViewport3_Release(viewport2);
1396 hr = IDirect3DViewport3_QueryInterface(viewport3, &IID_IUnknown, (void **)&unknown);
1397 ok(SUCCEEDED(hr), "Failed to QI IUnknown, hr %#x.\n", hr);
1398 if (unknown)
1400 ref = get_refcount((IUnknown *)viewport3);
1401 ok(ref == 2, "IDirect3DViewport3 refcount is %u\n", ref);
1402 ref = get_refcount(unknown);
1403 ok(ref == 2, "IUnknown refcount is %u\n", ref);
1404 IUnknown_Release(unknown);
1407 /* AddViewport(NULL): Segfault */
1408 hr = IDirect3DDevice3_DeleteViewport(device, NULL);
1409 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1410 hr = IDirect3DDevice3_GetCurrentViewport(device, NULL);
1411 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1413 hr = IDirect3D3_CreateViewport(d3d, &another_vp, NULL);
1414 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1416 /* Setting a viewport not in the viewport list fails */
1417 hr = IDirect3DDevice3_SetCurrentViewport(device, another_vp);
1418 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
1420 hr = IDirect3DDevice3_AddViewport(device, viewport3);
1421 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1422 ref = get_refcount((IUnknown *) viewport3);
1423 ok(ref == 2, "viewport3 refcount is %d\n", ref);
1424 hr = IDirect3DDevice3_AddViewport(device, another_vp);
1425 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1426 ref = get_refcount((IUnknown *) another_vp);
1427 ok(ref == 2, "another_vp refcount is %d\n", ref);
1429 test_vp = (IDirect3DViewport3 *) 0xbaadc0de;
1430 hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
1431 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1432 ok(test_vp == (IDirect3DViewport3 *) 0xbaadc0de, "Got unexpected pointer %p\n", test_vp);
1434 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport3);
1435 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1436 ref = get_refcount((IUnknown *) viewport3);
1437 ok(ref == 3, "viewport3 refcount is %d\n", ref);
1438 ref = get_refcount((IUnknown *) device);
1439 ok(ref == 1, "device refcount is %d\n", ref);
1441 test_vp = NULL;
1442 hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
1443 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1444 ok(test_vp == viewport3, "Got unexpected viewport %p\n", test_vp);
1445 ref = get_refcount((IUnknown *) viewport3);
1446 ok(ref == 4, "viewport3 refcount is %d\n", ref);
1447 if(test_vp) IDirect3DViewport3_Release(test_vp);
1449 /* GetCurrentViewport with a viewport set and NULL input param: Segfault */
1451 /* Cannot set the viewport to NULL */
1452 hr = IDirect3DDevice3_SetCurrentViewport(device, NULL);
1453 ok(hr == DDERR_INVALIDPARAMS, "Failed to set viewport to NULL, hr %#x.\n", hr);
1454 test_vp = NULL;
1455 hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
1456 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1457 ok(test_vp == viewport3, "Got unexpected viewport %p\n", test_vp);
1458 if(test_vp) IDirect3DViewport3_Release(test_vp);
1460 /* SetCurrentViewport properly releases the old viewport's reference */
1461 hr = IDirect3DDevice3_SetCurrentViewport(device, another_vp);
1462 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1463 ref = get_refcount((IUnknown *) viewport3);
1464 ok(ref == 2, "viewport3 refcount is %d\n", ref);
1465 ref = get_refcount((IUnknown *) another_vp);
1466 ok(ref == 3, "another_vp refcount is %d\n", ref);
1468 /* Unlike device2::DeleteViewport, device3::DeleteViewport releases the
1469 * reference held by SetCurrentViewport */
1470 hr = IDirect3DDevice3_DeleteViewport(device, another_vp);
1471 ok(SUCCEEDED(hr), "Failed to delete viewport from device, hr %#x.\n", hr);
1472 ref = get_refcount((IUnknown *) another_vp);
1473 ok(ref == 1, "another_vp refcount is %d\n", ref);
1475 /* GetCurrentViewport still fails */
1476 test_vp = NULL;
1477 hr = IDirect3DDevice3_GetCurrentViewport(device, &test_vp);
1478 ok(hr == D3DERR_NOCURRENTVIEWPORT, "Got unexpected hr %#x.\n", hr);
1479 ok(test_vp == NULL, "Got unexpected viewport %p\n", test_vp);
1480 if(test_vp) IDirect3DViewport3_Release(test_vp);
1482 /* Setting a different viewport doesn't have any surprises now */
1483 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport3);
1484 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1485 ref = get_refcount((IUnknown *) viewport3);
1486 ok(ref == 3, "viewport3 refcount is %d\n", ref);
1487 ref = get_refcount((IUnknown *) another_vp);
1488 ok(ref == 1, "another_vp refcount is %d\n", ref);
1490 /* Destroying the device removes the viewport and releases the reference */
1491 IDirect3DDevice3_Release(device);
1492 ref = get_refcount((IUnknown *) viewport3);
1493 ok(ref == 1, "viewport3 refcount is %d\n", ref);
1495 ref = IDirect3DViewport3_Release(another_vp);
1496 ok(ref == 0, "Got unexpected ref %d\n", ref);
1497 ref = IDirect3DViewport3_Release(viewport3);
1498 ok(ref == 0, "Got unexpected ref %d\n", ref);
1499 IDirect3D3_Release(d3d);
1500 DestroyWindow(window);
1501 IDirectDraw4_Release(ddraw);
1504 static void test_zenable(void)
1506 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1507 static struct
1509 struct vec4 position;
1510 D3DCOLOR diffuse;
1512 tquad[] =
1514 {{ 0.0f, 480.0f, -0.5f, 1.0f}, 0xff00ff00},
1515 {{ 0.0f, 0.0f, -0.5f, 1.0f}, 0xff00ff00},
1516 {{640.0f, 480.0f, 1.5f, 1.0f}, 0xff00ff00},
1517 {{640.0f, 0.0f, 1.5f, 1.0f}, 0xff00ff00},
1519 IDirect3DViewport3 *viewport;
1520 IDirect3DDevice3 *device;
1521 IDirectDrawSurface4 *rt;
1522 D3DCOLOR color;
1523 HWND window;
1524 HRESULT hr;
1525 UINT x, y;
1526 UINT i, j;
1528 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1529 0, 0, 640, 480, 0, 0, 0, 0);
1530 if (!(device = create_device(window, DDSCL_NORMAL)))
1532 skip("Failed to create D3D device, skipping test.\n");
1533 DestroyWindow(window);
1534 return;
1537 viewport = create_viewport(device, 0, 0, 640, 480);
1538 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
1539 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1541 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1542 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
1544 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 0.0f, 0);
1545 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1546 hr = IDirect3DDevice3_BeginScene(device);
1547 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1548 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_DIFFUSE, tquad, 4, 0);
1549 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1550 hr = IDirect3DDevice3_EndScene(device);
1551 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1553 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1554 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1555 for (i = 0; i < 4; ++i)
1557 for (j = 0; j < 4; ++j)
1559 x = 80 * ((2 * j) + 1);
1560 y = 60 * ((2 * i) + 1);
1561 color = get_surface_color(rt, x, y);
1562 ok(compare_color(color, 0x0000ff00, 1),
1563 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1566 IDirectDrawSurface4_Release(rt);
1568 destroy_viewport(device, viewport);
1569 IDirect3DDevice3_Release(device);
1570 DestroyWindow(window);
1573 static void test_ck_rgba(void)
1575 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1576 static struct
1578 struct vec4 position;
1579 struct vec2 texcoord;
1581 tquad[] =
1583 {{ 0.0f, 480.0f, 0.25f, 1.0f}, {0.0f, 0.0f}},
1584 {{ 0.0f, 0.0f, 0.25f, 1.0f}, {0.0f, 1.0f}},
1585 {{640.0f, 480.0f, 0.25f, 1.0f}, {1.0f, 0.0f}},
1586 {{640.0f, 0.0f, 0.25f, 1.0f}, {1.0f, 1.0f}},
1587 {{ 0.0f, 480.0f, 0.75f, 1.0f}, {0.0f, 0.0f}},
1588 {{ 0.0f, 0.0f, 0.75f, 1.0f}, {0.0f, 1.0f}},
1589 {{640.0f, 480.0f, 0.75f, 1.0f}, {1.0f, 0.0f}},
1590 {{640.0f, 0.0f, 0.75f, 1.0f}, {1.0f, 1.0f}},
1592 static const struct
1594 D3DCOLOR fill_color;
1595 BOOL color_key;
1596 BOOL blend;
1597 D3DCOLOR result1;
1598 D3DCOLOR result2;
1600 tests[] =
1602 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x000000ff},
1603 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x000000ff},
1604 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00},
1605 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00},
1606 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00807f00},
1607 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x0000ff00},
1608 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00},
1609 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00},
1612 IDirectDrawSurface4 *surface;
1613 IDirect3DViewport3 *viewport;
1614 DDSURFACEDESC2 surface_desc;
1615 IDirect3DTexture2 *texture;
1616 IDirect3DDevice3 *device;
1617 IDirectDrawSurface4 *rt;
1618 IDirectDraw4 *ddraw;
1619 IDirect3D3 *d3d;
1620 D3DCOLOR color;
1621 HWND window;
1622 DDBLTFX fx;
1623 HRESULT hr;
1624 UINT i;
1626 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1627 0, 0, 640, 480, 0, 0, 0, 0);
1628 if (!(device = create_device(window, DDSCL_NORMAL)))
1630 skip("Failed to create D3D device, skipping test.\n");
1631 DestroyWindow(window);
1632 return;
1635 viewport = create_viewport(device, 0, 0, 640, 480);
1636 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
1637 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1639 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1640 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1641 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1642 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1643 IDirect3D3_Release(d3d);
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 | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1648 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1649 surface_desc.dwWidth = 256;
1650 surface_desc.dwHeight = 256;
1651 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1652 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1653 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1654 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1655 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1656 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1657 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1658 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1659 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1660 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1661 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1662 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
1663 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1665 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
1666 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1667 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1668 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1669 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1670 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1672 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1673 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1675 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
1677 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1678 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1679 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1680 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1682 memset(&fx, 0, sizeof(fx));
1683 fx.dwSize = sizeof(fx);
1684 U5(fx).dwFillColor = tests[i].fill_color;
1685 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1686 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1688 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect,
1689 D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 1.0f, 0);
1690 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1691 hr = IDirect3DDevice3_BeginScene(device);
1692 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1693 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1694 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1695 hr = IDirect3DDevice3_EndScene(device);
1696 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1698 color = get_surface_color(rt, 320, 240);
1699 if (i == 2)
1700 todo_wine ok(compare_color(color, tests[i].result1, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1701 tests[i].result1, i, color);
1702 else
1703 ok(compare_color(color, tests[i].result1, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1704 tests[i].result1, i, color);
1706 U5(fx).dwFillColor = 0xff0000ff;
1707 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1708 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1710 hr = IDirect3DDevice3_BeginScene(device);
1711 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1712 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[4], 4, 0);
1713 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1714 hr = IDirect3DDevice3_EndScene(device);
1715 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1717 /* This tests that fragments that are masked out by the color key are
1718 * discarded, instead of just fully transparent. */
1719 color = get_surface_color(rt, 320, 240);
1720 if (i == 2)
1721 todo_wine ok(compare_color(color, tests[i].result2, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1722 tests[i].result2, i, color);
1723 else
1724 ok(compare_color(color, tests[i].result2, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1725 tests[i].result2, i, color);
1728 IDirectDrawSurface4_Release(rt);
1729 IDirect3DTexture2_Release(texture);
1730 IDirectDrawSurface4_Release(surface);
1731 destroy_viewport(device, viewport);
1732 IDirectDraw4_Release(ddraw);
1733 IDirect3DDevice3_Release(device);
1734 DestroyWindow(window);
1737 static void test_ck_default(void)
1739 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1740 static struct
1742 struct vec4 position;
1743 struct vec2 texcoord;
1745 tquad[] =
1747 {{ 0.0f, 480.0f, 0.0f, 1.0f}, {0.0f, 0.0f}},
1748 {{ 0.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 1.0f}},
1749 {{640.0f, 480.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
1750 {{640.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
1752 IDirectDrawSurface4 *surface, *rt;
1753 IDirect3DViewport3 *viewport;
1754 DDSURFACEDESC2 surface_desc;
1755 IDirect3DTexture2 *texture;
1756 IDirect3DDevice3 *device;
1757 IDirectDraw4 *ddraw;
1758 IDirect3D3 *d3d;
1759 D3DCOLOR color;
1760 DWORD value;
1761 HWND window;
1762 DDBLTFX fx;
1763 HRESULT hr;
1765 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1766 0, 0, 640, 480, 0, 0, 0, 0);
1768 if (!(device = create_device(window, DDSCL_NORMAL)))
1770 skip("Failed to create D3D device, skipping test.\n");
1771 DestroyWindow(window);
1772 return;
1775 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1776 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1777 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1778 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1779 IDirect3D3_Release(d3d);
1781 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1782 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1784 viewport = create_viewport(device, 0, 0, 640, 480);
1785 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
1786 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1788 memset(&surface_desc, 0, sizeof(surface_desc));
1789 surface_desc.dwSize = sizeof(surface_desc);
1790 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1791 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1792 surface_desc.dwWidth = 256;
1793 surface_desc.dwHeight = 256;
1794 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1795 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
1796 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1797 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1798 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1799 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1800 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
1801 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
1802 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1803 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1804 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
1805 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1806 hr = IDirect3DDevice3_SetTexture(device, 0, texture);
1807 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1809 memset(&fx, 0, sizeof(fx));
1810 fx.dwSize = sizeof(fx);
1811 U5(fx).dwFillColor = 0x000000ff;
1812 hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1813 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
1815 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
1816 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1817 hr = IDirect3DDevice3_BeginScene(device);
1818 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1819 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1820 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1821 ok(!value, "Got unexpected color keying state %#x.\n", value);
1822 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1823 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1824 hr = IDirect3DDevice3_EndScene(device);
1825 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1826 color = get_surface_color(rt, 320, 240);
1827 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1829 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
1830 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1831 hr = IDirect3DDevice3_BeginScene(device);
1832 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1833 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
1834 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1835 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1836 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1837 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1838 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1839 ok(!!value, "Got unexpected color keying state %#x.\n", value);
1840 hr = IDirect3DDevice3_EndScene(device);
1841 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1842 color = get_surface_color(rt, 320, 240);
1843 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1845 IDirect3DTexture_Release(texture);
1846 IDirectDrawSurface4_Release(surface);
1847 destroy_viewport(device, viewport);
1848 IDirectDrawSurface4_Release(rt);
1849 IDirect3DDevice3_Release(device);
1850 IDirectDraw4_Release(ddraw);
1851 DestroyWindow(window);
1854 struct qi_test
1856 REFIID iid;
1857 REFIID refcount_iid;
1858 HRESULT hr;
1861 static void test_qi(const char *test_name, IUnknown *base_iface,
1862 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
1864 ULONG refcount, expected_refcount;
1865 IUnknown *iface1, *iface2;
1866 HRESULT hr;
1867 UINT i, j;
1869 for (i = 0; i < entry_count; ++i)
1871 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
1872 ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
1873 if (SUCCEEDED(hr))
1875 for (j = 0; j < entry_count; ++j)
1877 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
1878 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
1879 if (SUCCEEDED(hr))
1881 expected_refcount = 0;
1882 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
1883 ++expected_refcount;
1884 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
1885 ++expected_refcount;
1886 refcount = IUnknown_Release(iface2);
1887 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
1888 refcount, test_name, i, j, expected_refcount);
1892 expected_refcount = 0;
1893 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
1894 ++expected_refcount;
1895 refcount = IUnknown_Release(iface1);
1896 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
1897 refcount, test_name, i, expected_refcount);
1902 static void test_surface_qi(void)
1904 static const struct qi_test tests[] =
1906 {&IID_IDirect3DTexture2, &IID_IDirectDrawSurface4, S_OK },
1907 {&IID_IDirect3DTexture, &IID_IDirectDrawSurface4, S_OK },
1908 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
1909 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1910 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
1911 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
1912 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
1913 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
1914 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
1915 {&IID_IDirect3DDevice7, NULL, E_INVALIDARG },
1916 {&IID_IDirect3DDevice3, NULL, E_INVALIDARG },
1917 {&IID_IDirect3DDevice2, NULL, E_INVALIDARG },
1918 {&IID_IDirect3DDevice, NULL, E_INVALIDARG },
1919 {&IID_IDirect3D7, NULL, E_INVALIDARG },
1920 {&IID_IDirect3D3, NULL, E_INVALIDARG },
1921 {&IID_IDirect3D2, NULL, E_INVALIDARG },
1922 {&IID_IDirect3D, NULL, E_INVALIDARG },
1923 {&IID_IDirectDraw7, NULL, E_INVALIDARG },
1924 {&IID_IDirectDraw4, NULL, E_INVALIDARG },
1925 {&IID_IDirectDraw3, NULL, E_INVALIDARG },
1926 {&IID_IDirectDraw2, NULL, E_INVALIDARG },
1927 {&IID_IDirectDraw, NULL, E_INVALIDARG },
1928 {&IID_IDirect3DLight, NULL, E_INVALIDARG },
1929 {&IID_IDirect3DMaterial, NULL, E_INVALIDARG },
1930 {&IID_IDirect3DMaterial2, NULL, E_INVALIDARG },
1931 {&IID_IDirect3DMaterial3, NULL, E_INVALIDARG },
1932 {&IID_IDirect3DExecuteBuffer, NULL, E_INVALIDARG },
1933 {&IID_IDirect3DViewport, NULL, E_INVALIDARG },
1934 {&IID_IDirect3DViewport2, NULL, E_INVALIDARG },
1935 {&IID_IDirect3DViewport3, NULL, E_INVALIDARG },
1936 {&IID_IDirect3DVertexBuffer, NULL, E_INVALIDARG },
1937 {&IID_IDirect3DVertexBuffer7, NULL, E_INVALIDARG },
1938 {&IID_IDirectDrawPalette, NULL, E_INVALIDARG },
1939 {&IID_IDirectDrawClipper, NULL, E_INVALIDARG },
1940 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
1943 IDirectDrawSurface4 *surface;
1944 DDSURFACEDESC2 surface_desc;
1945 IDirect3DDevice3 *device;
1946 IDirectDraw4 *ddraw;
1947 HWND window;
1948 HRESULT hr;
1950 if (!GetProcAddress(GetModuleHandleA("ddraw.dll"), "DirectDrawCreateEx"))
1952 win_skip("DirectDrawCreateEx not available, skipping test.\n");
1953 return;
1956 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1957 0, 0, 640, 480, 0, 0, 0, 0);
1958 /* Try to create a D3D device to see if the ddraw implementation supports
1959 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
1960 * doesn't support e.g. the IDirect3DTexture interfaces. */
1961 if (!(device = create_device(window, DDSCL_NORMAL)))
1963 skip("Failed to create D3D device, skipping test.\n");
1964 DestroyWindow(window);
1965 return;
1967 IDirect3DDevice_Release(device);
1968 if (!(ddraw = create_ddraw()))
1970 skip("Failed to create a ddraw object, skipping test.\n");
1971 DestroyWindow(window);
1972 return;
1974 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1975 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1977 memset(&surface_desc, 0, sizeof(surface_desc));
1978 surface_desc.dwSize = sizeof(surface_desc);
1979 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1980 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1981 surface_desc.dwWidth = 512;
1982 surface_desc.dwHeight = 512;
1983 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1984 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1986 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface4, tests, sizeof(tests) / sizeof(*tests));
1988 IDirectDrawSurface4_Release(surface);
1989 IDirectDraw4_Release(ddraw);
1990 DestroyWindow(window);
1993 static void test_device_qi(void)
1995 static const struct qi_test tests[] =
1997 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
1998 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
1999 {&IID_IDirectDrawGammaControl, NULL, E_NOINTERFACE},
2000 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2001 {&IID_IDirectDrawSurface7, NULL, E_NOINTERFACE},
2002 {&IID_IDirectDrawSurface4, NULL, E_NOINTERFACE},
2003 {&IID_IDirectDrawSurface3, NULL, E_NOINTERFACE},
2004 {&IID_IDirectDrawSurface2, NULL, E_NOINTERFACE},
2005 {&IID_IDirectDrawSurface, NULL, E_NOINTERFACE},
2006 {&IID_IDirect3DDevice7, NULL, E_NOINTERFACE},
2007 {&IID_IDirect3DDevice3, &IID_IDirect3DDevice3, S_OK },
2008 {&IID_IDirect3DDevice2, &IID_IDirect3DDevice3, S_OK },
2009 {&IID_IDirect3DDevice, &IID_IDirect3DDevice3, S_OK },
2010 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
2011 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
2012 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
2013 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
2014 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
2015 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
2016 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
2017 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
2018 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
2019 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
2020 {&IID_IDirect3D, NULL, E_NOINTERFACE},
2021 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
2022 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
2023 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
2024 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
2025 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
2026 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
2027 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
2028 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
2029 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
2030 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
2031 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
2032 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
2033 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
2034 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
2035 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
2036 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
2037 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
2038 {&IID_IUnknown, &IID_IDirect3DDevice3, S_OK },
2041 IDirect3DDevice3 *device;
2042 HWND window;
2044 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2045 0, 0, 640, 480, 0, 0, 0, 0);
2046 if (!(device = create_device(window, DDSCL_NORMAL)))
2048 skip("Failed to create D3D device, skipping test.\n");
2049 DestroyWindow(window);
2050 return;
2053 test_qi("device_qi", (IUnknown *)device, &IID_IDirect3DDevice3, tests, sizeof(tests) / sizeof(*tests));
2055 IDirect3DDevice3_Release(device);
2056 DestroyWindow(window);
2059 static void test_wndproc(void)
2061 LONG_PTR proc, ddraw_proc;
2062 IDirectDraw4 *ddraw;
2063 WNDCLASSA wc = {0};
2064 HWND window;
2065 HRESULT hr;
2066 ULONG ref;
2068 static const UINT messages[] =
2070 WM_WINDOWPOSCHANGING,
2071 WM_MOVE,
2072 WM_SIZE,
2073 WM_WINDOWPOSCHANGING,
2074 WM_ACTIVATE,
2075 WM_SETFOCUS,
2079 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
2080 if (!(ddraw = create_ddraw()))
2082 skip("Failed to create IDirectDraw4 object, skipping tests.\n");
2083 return;
2086 wc.lpfnWndProc = test_proc;
2087 wc.lpszClassName = "ddraw_test_wndproc_wc";
2088 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2090 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
2091 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
2093 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2094 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2095 (LONG_PTR)test_proc, proc);
2096 expect_messages = messages;
2097 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2098 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2099 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2100 expect_messages = NULL;
2101 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2102 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2103 (LONG_PTR)test_proc, proc);
2104 ref = IDirectDraw4_Release(ddraw);
2105 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2106 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2107 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2108 (LONG_PTR)test_proc, proc);
2110 /* DDSCL_NORMAL doesn't. */
2111 ddraw = create_ddraw();
2112 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2113 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2114 (LONG_PTR)test_proc, proc);
2115 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2116 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2117 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2118 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2119 (LONG_PTR)test_proc, proc);
2120 ref = IDirectDraw4_Release(ddraw);
2121 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2122 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2123 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2124 (LONG_PTR)test_proc, proc);
2126 /* The original window proc is only restored by ddraw if the current
2127 * window proc matches the one ddraw set. This also affects switching
2128 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
2129 ddraw = create_ddraw();
2130 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2131 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2132 (LONG_PTR)test_proc, proc);
2133 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2134 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2135 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2136 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2137 (LONG_PTR)test_proc, proc);
2138 ddraw_proc = proc;
2139 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2140 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2141 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2142 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2143 (LONG_PTR)test_proc, proc);
2144 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2145 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2146 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2147 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2148 (LONG_PTR)test_proc, proc);
2149 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2150 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2151 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2152 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2153 (LONG_PTR)DefWindowProcA, proc);
2154 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2155 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2156 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc);
2157 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2158 (LONG_PTR)DefWindowProcA, proc);
2159 ref = IDirectDraw4_Release(ddraw);
2160 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2161 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2162 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2163 (LONG_PTR)test_proc, proc);
2165 ddraw = create_ddraw();
2166 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2167 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2168 (LONG_PTR)test_proc, proc);
2169 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2170 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2171 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2172 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2173 (LONG_PTR)test_proc, proc);
2174 ref = IDirectDraw4_Release(ddraw);
2175 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2176 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2177 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2178 (LONG_PTR)DefWindowProcA, proc);
2180 fix_wndproc(window, (LONG_PTR)test_proc);
2181 expect_messages = NULL;
2182 DestroyWindow(window);
2183 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2186 static void test_window_style(void)
2188 LONG style, exstyle, tmp;
2189 RECT fullscreen_rect, r;
2190 IDirectDraw4 *ddraw;
2191 HWND window;
2192 HRESULT hr;
2193 ULONG ref;
2195 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2196 0, 0, 100, 100, 0, 0, 0, 0);
2197 if (!(ddraw = create_ddraw()))
2199 skip("Failed to create a ddraw object, skipping test.\n");
2200 DestroyWindow(window);
2201 return;
2204 style = GetWindowLongA(window, GWL_STYLE);
2205 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
2206 SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2208 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2209 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2211 tmp = GetWindowLongA(window, GWL_STYLE);
2212 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2213 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2214 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2216 GetWindowRect(window, &r);
2217 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2218 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2219 r.left, r.top, r.right, r.bottom);
2220 GetClientRect(window, &r);
2221 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2223 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2224 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2226 tmp = GetWindowLongA(window, GWL_STYLE);
2227 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2228 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2229 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2231 ref = IDirectDraw4_Release(ddraw);
2232 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2234 DestroyWindow(window);
2237 static void test_redundant_mode_set(void)
2239 DDSURFACEDESC2 surface_desc = {0};
2240 IDirectDraw4 *ddraw;
2241 HWND window;
2242 HRESULT hr;
2243 RECT r, s;
2244 ULONG ref;
2246 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2247 0, 0, 100, 100, 0, 0, 0, 0);
2248 if (!(ddraw = create_ddraw()))
2250 skip("Failed to create a ddraw object, skipping test.\n");
2251 DestroyWindow(window);
2252 return;
2255 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2256 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2258 surface_desc.dwSize = sizeof(surface_desc);
2259 hr = IDirectDraw4_GetDisplayMode(ddraw, &surface_desc);
2260 ok(SUCCEEDED(hr), "GetDipslayMode failed, hr %#x.\n", hr);
2262 hr = IDirectDraw4_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2263 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
2264 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2266 GetWindowRect(window, &r);
2267 r.right /= 2;
2268 r.bottom /= 2;
2269 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
2270 GetWindowRect(window, &s);
2271 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2272 r.left, r.top, r.right, r.bottom,
2273 s.left, s.top, s.right, s.bottom);
2275 hr = IDirectDraw4_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2276 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
2277 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2279 GetWindowRect(window, &s);
2280 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2281 r.left, r.top, r.right, r.bottom,
2282 s.left, s.top, s.right, s.bottom);
2284 ref = IDirectDraw4_Release(ddraw);
2285 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2287 DestroyWindow(window);
2290 static SIZE screen_size;
2292 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2294 if (message == WM_SIZE)
2296 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2297 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2300 return test_proc(hwnd, message, wparam, lparam);
2303 static void test_coop_level_mode_set(void)
2305 IDirectDrawSurface4 *primary;
2306 RECT fullscreen_rect, r, s;
2307 IDirectDraw4 *ddraw;
2308 DDSURFACEDESC2 ddsd;
2309 WNDCLASSA wc = {0};
2310 HWND window;
2311 HRESULT hr;
2312 ULONG ref;
2314 static const UINT exclusive_messages[] =
2316 WM_WINDOWPOSCHANGING,
2317 WM_WINDOWPOSCHANGED,
2318 WM_SIZE,
2319 WM_DISPLAYCHANGE,
2323 static const UINT normal_messages[] =
2325 WM_DISPLAYCHANGE,
2329 if (!(ddraw = create_ddraw()))
2331 skip("Failed to create a ddraw object, skipping test.\n");
2332 return;
2335 wc.lpfnWndProc = mode_set_proc;
2336 wc.lpszClassName = "ddraw_test_wndproc_wc";
2337 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2339 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
2340 0, 0, 100, 100, 0, 0, 0, 0);
2342 SetRect(&fullscreen_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2343 SetRect(&s, 0, 0, 640, 480);
2345 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2346 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2348 GetWindowRect(window, &r);
2349 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2350 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2351 r.left, r.top, r.right, r.bottom);
2353 memset(&ddsd, 0, sizeof(ddsd));
2354 ddsd.dwSize = sizeof(ddsd);
2355 ddsd.dwFlags = DDSD_CAPS;
2356 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2358 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2359 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2360 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2361 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2362 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2363 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2364 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2365 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2367 GetWindowRect(window, &r);
2368 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2369 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2370 r.left, r.top, r.right, r.bottom);
2372 expect_messages = exclusive_messages;
2373 screen_size.cx = 0;
2374 screen_size.cy = 0;
2376 hr = IDirectDraw4_SetDisplayMode(ddraw, 640, 480, 32, 0, 0);
2377 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2379 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2380 expect_messages = NULL;
2381 ok(screen_size.cx == s.right && screen_size.cy == s.bottom,
2382 "Expected screen size %ux%u, got %ux%u.\n",
2383 s.right, s.bottom, screen_size.cx, screen_size.cy);
2385 GetWindowRect(window, &r);
2386 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2387 s.left, s.top, s.right, s.bottom,
2388 r.left, r.top, r.right, r.bottom);
2390 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2391 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2392 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2393 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2394 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2395 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2396 IDirectDrawSurface4_Release(primary);
2398 memset(&ddsd, 0, sizeof(ddsd));
2399 ddsd.dwSize = sizeof(ddsd);
2400 ddsd.dwFlags = DDSD_CAPS;
2401 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2403 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2404 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2405 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2406 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2407 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2408 s.right - s.left, ddsd.dwWidth);
2409 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2410 s.bottom - s.top, ddsd.dwHeight);
2412 GetWindowRect(window, &r);
2413 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2414 s.left, s.top, s.right, s.bottom,
2415 r.left, r.top, r.right, r.bottom);
2417 expect_messages = exclusive_messages;
2418 screen_size.cx = 0;
2419 screen_size.cy = 0;
2421 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2422 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2424 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2425 expect_messages = NULL;
2426 ok(screen_size.cx == fullscreen_rect.right && screen_size.cy == fullscreen_rect.bottom,
2427 "Expected screen size %ux%u, got %ux%u.\n",
2428 fullscreen_rect.right, fullscreen_rect.bottom, screen_size.cx, screen_size.cy);
2430 GetWindowRect(window, &r);
2431 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2432 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2433 r.left, r.top, r.right, r.bottom);
2435 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2436 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2437 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2438 s.right - s.left, ddsd.dwWidth);
2439 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2440 s.bottom - s.top, ddsd.dwHeight);
2441 IDirectDrawSurface4_Release(primary);
2443 memset(&ddsd, 0, sizeof(ddsd));
2444 ddsd.dwSize = sizeof(ddsd);
2445 ddsd.dwFlags = DDSD_CAPS;
2446 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2448 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2449 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2450 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2451 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2452 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2453 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2454 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2455 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2457 GetWindowRect(window, &r);
2458 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2459 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2460 r.left, r.top, r.right, r.bottom);
2462 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2463 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2465 GetWindowRect(window, &r);
2466 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2467 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2468 r.left, r.top, r.right, r.bottom);
2470 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2471 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2472 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2473 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2474 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2475 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2476 IDirectDrawSurface4_Release(primary);
2478 memset(&ddsd, 0, sizeof(ddsd));
2479 ddsd.dwSize = sizeof(ddsd);
2480 ddsd.dwFlags = DDSD_CAPS;
2481 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2483 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2484 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2485 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2486 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2487 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2488 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2489 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2490 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2492 GetWindowRect(window, &r);
2493 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2494 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2495 r.left, r.top, r.right, r.bottom);
2497 expect_messages = normal_messages;
2498 screen_size.cx = 0;
2499 screen_size.cy = 0;
2501 hr = IDirectDraw4_SetDisplayMode(ddraw, 640, 480, 32, 0, 0);
2502 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2504 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2505 expect_messages = NULL;
2506 ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2508 GetWindowRect(window, &r);
2509 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2510 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2511 r.left, r.top, r.right, r.bottom);
2513 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2514 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2515 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2516 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2517 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2518 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2519 IDirectDrawSurface4_Release(primary);
2521 memset(&ddsd, 0, sizeof(ddsd));
2522 ddsd.dwSize = sizeof(ddsd);
2523 ddsd.dwFlags = DDSD_CAPS;
2524 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2526 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2527 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2528 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2529 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2530 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2531 s.right - s.left, ddsd.dwWidth);
2532 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2533 s.bottom - s.top, ddsd.dwHeight);
2535 GetWindowRect(window, &r);
2536 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2537 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2538 r.left, r.top, r.right, r.bottom);
2540 expect_messages = normal_messages;
2541 screen_size.cx = 0;
2542 screen_size.cy = 0;
2544 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2545 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2547 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2548 expect_messages = NULL;
2549 ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2551 GetWindowRect(window, &r);
2552 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2553 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2554 r.left, r.top, r.right, r.bottom);
2556 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2557 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2558 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2559 s.right - s.left, ddsd.dwWidth);
2560 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2561 s.bottom - s.top, ddsd.dwHeight);
2562 IDirectDrawSurface4_Release(primary);
2564 memset(&ddsd, 0, sizeof(ddsd));
2565 ddsd.dwSize = sizeof(ddsd);
2566 ddsd.dwFlags = DDSD_CAPS;
2567 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2569 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2570 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2571 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2572 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2573 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2574 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2575 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2576 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2578 GetWindowRect(window, &r);
2579 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2580 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2581 r.left, r.top, r.right, r.bottom);
2583 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
2584 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
2585 * not DDSCL_FULLSCREEN. */
2586 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2587 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2589 GetWindowRect(window, &r);
2590 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2591 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2592 r.left, r.top, r.right, r.bottom);
2594 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2595 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2596 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2597 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2598 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2599 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2600 IDirectDrawSurface4_Release(primary);
2602 memset(&ddsd, 0, sizeof(ddsd));
2603 ddsd.dwSize = sizeof(ddsd);
2604 ddsd.dwFlags = DDSD_CAPS;
2605 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2607 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2608 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2609 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2610 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2611 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2612 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2613 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2614 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2616 GetWindowRect(window, &r);
2617 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2618 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2619 r.left, r.top, r.right, r.bottom);
2621 expect_messages = normal_messages;
2622 screen_size.cx = 0;
2623 screen_size.cy = 0;
2625 hr = IDirectDraw4_SetDisplayMode(ddraw, 640, 480, 32, 0, 0);
2626 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2628 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2629 expect_messages = NULL;
2630 ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2632 GetWindowRect(window, &r);
2633 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2634 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2635 r.left, r.top, r.right, r.bottom);
2637 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2638 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2639 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2640 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2641 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2642 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2643 IDirectDrawSurface4_Release(primary);
2645 memset(&ddsd, 0, sizeof(ddsd));
2646 ddsd.dwSize = sizeof(ddsd);
2647 ddsd.dwFlags = DDSD_CAPS;
2648 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2650 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2651 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2652 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2653 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2654 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2655 s.right - s.left, ddsd.dwWidth);
2656 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2657 s.bottom - s.top, ddsd.dwHeight);
2659 GetWindowRect(window, &r);
2660 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2661 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2662 r.left, r.top, r.right, r.bottom);
2664 expect_messages = normal_messages;
2665 screen_size.cx = 0;
2666 screen_size.cy = 0;
2668 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2669 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2671 ok(!*expect_messages, "Expected message %#x, but didn't receive it.\n", *expect_messages);
2672 expect_messages = NULL;
2673 ok(!screen_size.cx && !screen_size.cy, "Got unxpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2675 GetWindowRect(window, &r);
2676 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2677 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2678 r.left, r.top, r.right, r.bottom);
2680 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2681 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2682 ok(ddsd.dwWidth == s.right - s.left, "Expected surface width %u, got %u.\n",
2683 s.right - s.left, ddsd.dwWidth);
2684 ok(ddsd.dwHeight == s.bottom - s.top, "Expected surface height %u, got %u.\n",
2685 s.bottom - s.top, ddsd.dwHeight);
2686 IDirectDrawSurface4_Release(primary);
2688 memset(&ddsd, 0, sizeof(ddsd));
2689 ddsd.dwSize = sizeof(ddsd);
2690 ddsd.dwFlags = DDSD_CAPS;
2691 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2693 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &primary, NULL);
2694 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2695 hr = IDirectDrawSurface4_GetSurfaceDesc(primary, &ddsd);
2696 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2697 ok(ddsd.dwWidth == fullscreen_rect.right - fullscreen_rect.left, "Expected surface width %u, got %u.\n",
2698 fullscreen_rect.right - fullscreen_rect.left, ddsd.dwWidth);
2699 ok(ddsd.dwHeight == fullscreen_rect.bottom - fullscreen_rect.top, "Expected surface height %u, got %u.\n",
2700 fullscreen_rect.bottom - fullscreen_rect.top, ddsd.dwHeight);
2701 IDirectDrawSurface4_Release(primary);
2703 GetWindowRect(window, &r);
2704 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2705 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2706 r.left, r.top, r.right, r.bottom);
2708 ref = IDirectDraw4_Release(ddraw);
2709 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2711 GetWindowRect(window, &r);
2712 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2713 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2714 r.left, r.top, r.right, r.bottom);
2716 expect_messages = NULL;
2717 DestroyWindow(window);
2718 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2721 static void test_coop_level_mode_set_multi(void)
2723 IDirectDraw4 *ddraw1, *ddraw2;
2724 UINT orig_w, orig_h, w, h;
2725 HWND window;
2726 HRESULT hr;
2727 ULONG ref;
2729 if (!(ddraw1 = create_ddraw()))
2731 skip("Failed to create a ddraw object, skipping test.\n");
2732 return;
2735 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2736 0, 0, 100, 100, 0, 0, 0, 0);
2738 orig_w = GetSystemMetrics(SM_CXSCREEN);
2739 orig_h = GetSystemMetrics(SM_CYSCREEN);
2741 /* With just a single ddraw object, the display mode is restored on
2742 * release. */
2743 hr = IDirectDraw4_SetDisplayMode(ddraw1, 800, 600, 32, 0, 0);
2744 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2745 w = GetSystemMetrics(SM_CXSCREEN);
2746 ok(w == 800, "Got unexpected screen width %u.\n", w);
2747 h = GetSystemMetrics(SM_CYSCREEN);
2748 ok(h == 600, "Got unexpected screen height %u.\n", h);
2750 ref = IDirectDraw4_Release(ddraw1);
2751 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2752 w = GetSystemMetrics(SM_CXSCREEN);
2753 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2754 h = GetSystemMetrics(SM_CYSCREEN);
2755 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2757 /* When there are multiple ddraw objects, the display mode is restored to
2758 * the initial mode, before the first SetDisplayMode() call. */
2759 ddraw1 = create_ddraw();
2760 hr = IDirectDraw4_SetDisplayMode(ddraw1, 800, 600, 32, 0, 0);
2761 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2762 w = GetSystemMetrics(SM_CXSCREEN);
2763 ok(w == 800, "Got unexpected screen width %u.\n", w);
2764 h = GetSystemMetrics(SM_CYSCREEN);
2765 ok(h == 600, "Got unexpected screen height %u.\n", h);
2767 ddraw2 = create_ddraw();
2768 hr = IDirectDraw4_SetDisplayMode(ddraw2, 640, 480, 32, 0, 0);
2769 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2770 w = GetSystemMetrics(SM_CXSCREEN);
2771 ok(w == 640, "Got unexpected screen width %u.\n", w);
2772 h = GetSystemMetrics(SM_CYSCREEN);
2773 ok(h == 480, "Got unexpected screen height %u.\n", h);
2775 ref = IDirectDraw4_Release(ddraw2);
2776 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2777 w = GetSystemMetrics(SM_CXSCREEN);
2778 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2779 h = GetSystemMetrics(SM_CYSCREEN);
2780 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2782 ref = IDirectDraw4_Release(ddraw1);
2783 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2784 w = GetSystemMetrics(SM_CXSCREEN);
2785 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2786 h = GetSystemMetrics(SM_CYSCREEN);
2787 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2789 /* Regardless of release ordering. */
2790 ddraw1 = create_ddraw();
2791 hr = IDirectDraw4_SetDisplayMode(ddraw1, 800, 600, 32, 0, 0);
2792 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2793 w = GetSystemMetrics(SM_CXSCREEN);
2794 ok(w == 800, "Got unexpected screen width %u.\n", w);
2795 h = GetSystemMetrics(SM_CYSCREEN);
2796 ok(h == 600, "Got unexpected screen height %u.\n", h);
2798 ddraw2 = create_ddraw();
2799 hr = IDirectDraw4_SetDisplayMode(ddraw2, 640, 480, 32, 0, 0);
2800 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2801 w = GetSystemMetrics(SM_CXSCREEN);
2802 ok(w == 640, "Got unexpected screen width %u.\n", w);
2803 h = GetSystemMetrics(SM_CYSCREEN);
2804 ok(h == 480, "Got unexpected screen height %u.\n", h);
2806 ref = IDirectDraw4_Release(ddraw1);
2807 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2808 w = GetSystemMetrics(SM_CXSCREEN);
2809 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2810 h = GetSystemMetrics(SM_CYSCREEN);
2811 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2813 ref = IDirectDraw4_Release(ddraw2);
2814 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2815 w = GetSystemMetrics(SM_CXSCREEN);
2816 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2817 h = GetSystemMetrics(SM_CYSCREEN);
2818 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2820 /* But only for ddraw objects that called SetDisplayMode(). */
2821 ddraw1 = create_ddraw();
2822 ddraw2 = create_ddraw();
2823 hr = IDirectDraw4_SetDisplayMode(ddraw2, 640, 480, 32, 0, 0);
2824 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2825 w = GetSystemMetrics(SM_CXSCREEN);
2826 ok(w == 640, "Got unexpected screen width %u.\n", w);
2827 h = GetSystemMetrics(SM_CYSCREEN);
2828 ok(h == 480, "Got unexpected screen height %u.\n", h);
2830 ref = IDirectDraw4_Release(ddraw1);
2831 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2832 w = GetSystemMetrics(SM_CXSCREEN);
2833 ok(w == 640, "Got unexpected screen width %u.\n", w);
2834 h = GetSystemMetrics(SM_CYSCREEN);
2835 ok(h == 480, "Got unexpected screen height %u.\n", h);
2837 ref = IDirectDraw4_Release(ddraw2);
2838 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2839 w = GetSystemMetrics(SM_CXSCREEN);
2840 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2841 h = GetSystemMetrics(SM_CYSCREEN);
2842 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2844 /* If there's a ddraw object that's currently in exclusive mode, it blocks
2845 * restoring the display mode. */
2846 ddraw1 = create_ddraw();
2847 hr = IDirectDraw4_SetDisplayMode(ddraw1, 800, 600, 32, 0, 0);
2848 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2849 w = GetSystemMetrics(SM_CXSCREEN);
2850 ok(w == 800, "Got unexpected screen width %u.\n", w);
2851 h = GetSystemMetrics(SM_CYSCREEN);
2852 ok(h == 600, "Got unexpected screen height %u.\n", h);
2854 ddraw2 = create_ddraw();
2855 hr = IDirectDraw4_SetDisplayMode(ddraw2, 640, 480, 32, 0, 0);
2856 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2857 w = GetSystemMetrics(SM_CXSCREEN);
2858 ok(w == 640, "Got unexpected screen width %u.\n", w);
2859 h = GetSystemMetrics(SM_CYSCREEN);
2860 ok(h == 480, "Got unexpected screen height %u.\n", h);
2862 hr = IDirectDraw4_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2863 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2865 ref = IDirectDraw4_Release(ddraw1);
2866 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2867 w = GetSystemMetrics(SM_CXSCREEN);
2868 ok(w == 640, "Got unexpected screen width %u.\n", w);
2869 h = GetSystemMetrics(SM_CYSCREEN);
2870 ok(h == 480, "Got unexpected screen height %u.\n", h);
2872 ref = IDirectDraw4_Release(ddraw2);
2873 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2874 w = GetSystemMetrics(SM_CXSCREEN);
2875 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2876 h = GetSystemMetrics(SM_CYSCREEN);
2877 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2879 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
2880 ddraw1 = create_ddraw();
2881 hr = IDirectDraw4_SetDisplayMode(ddraw1, 800, 600, 32, 0, 0);
2882 ok(SUCCEEDED(hr), "SetDipslayMode failed, hr %#x.\n", hr);
2883 w = GetSystemMetrics(SM_CXSCREEN);
2884 ok(w == 800, "Got unexpected screen width %u.\n", w);
2885 h = GetSystemMetrics(SM_CYSCREEN);
2886 ok(h == 600, "Got unexpected screen height %u.\n", h);
2888 hr = IDirectDraw4_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2889 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2891 ddraw2 = create_ddraw();
2892 hr = IDirectDraw4_SetDisplayMode(ddraw2, 640, 480, 32, 0, 0);
2893 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
2895 ref = IDirectDraw4_Release(ddraw1);
2896 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2897 w = GetSystemMetrics(SM_CXSCREEN);
2898 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2899 h = GetSystemMetrics(SM_CYSCREEN);
2900 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2902 ref = IDirectDraw4_Release(ddraw2);
2903 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2904 w = GetSystemMetrics(SM_CXSCREEN);
2905 ok(w == orig_w, "Got unexpected screen width %u.\n", w);
2906 h = GetSystemMetrics(SM_CYSCREEN);
2907 ok(h == orig_h, "Got unexpected screen height %u.\n", h);
2909 DestroyWindow(window);
2912 static void test_initialize(void)
2914 IDirectDraw4 *ddraw;
2915 HRESULT hr;
2917 if (!(ddraw = create_ddraw()))
2919 skip("Failed to create a ddraw object, skipping test.\n");
2920 return;
2923 hr = IDirectDraw4_Initialize(ddraw, NULL);
2924 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
2925 IDirectDraw4_Release(ddraw);
2927 CoInitialize(NULL);
2928 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw4, (void **)&ddraw);
2929 ok(SUCCEEDED(hr), "Failed to create IDirectDraw4 instance, hr %#x.\n", hr);
2930 hr = IDirectDraw4_Initialize(ddraw, NULL);
2931 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
2932 hr = IDirectDraw4_Initialize(ddraw, NULL);
2933 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
2934 IDirectDraw4_Release(ddraw);
2935 CoUninitialize();
2938 static void test_coop_level_surf_create(void)
2940 IDirectDrawSurface4 *surface;
2941 IDirectDraw4 *ddraw;
2942 DDSURFACEDESC2 ddsd;
2943 HRESULT hr;
2945 if (!(ddraw = create_ddraw()))
2947 skip("Failed to create a ddraw object, skipping test.\n");
2948 return;
2951 memset(&ddsd, 0, sizeof(ddsd));
2952 ddsd.dwSize = sizeof(ddsd);
2953 ddsd.dwFlags = DDSD_CAPS;
2954 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2955 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL);
2956 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
2958 IDirectDraw4_Release(ddraw);
2961 static void test_vb_discard(void)
2963 static const struct vec4 quad[] =
2965 { 0.0f, 480.0f, 0.0f, 1.0f},
2966 { 0.0f, 0.0f, 0.0f, 1.0f},
2967 {640.0f, 480.0f, 0.0f, 1.0f},
2968 {640.0f, 0.0f, 0.0f, 1.0f},
2971 IDirect3DDevice3 *device;
2972 IDirect3D3 *d3d;
2973 IDirect3DVertexBuffer *buffer;
2974 HWND window;
2975 HRESULT hr;
2976 D3DVERTEXBUFFERDESC desc;
2977 BYTE *data;
2978 static const unsigned int vbsize = 16;
2979 unsigned int i;
2981 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2982 0, 0, 640, 480, 0, 0, 0, 0);
2984 if (!(device = create_device(window, DDSCL_NORMAL)))
2986 skip("Failed to create D3D device, skipping test.\n");
2987 DestroyWindow(window);
2988 return;
2991 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
2992 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
2994 memset(&desc, 0, sizeof(desc));
2995 desc.dwSize = sizeof(desc);
2996 desc.dwCaps = D3DVBCAPS_WRITEONLY;
2997 desc.dwFVF = D3DFVF_XYZRHW;
2998 desc.dwNumVertices = vbsize;
2999 hr = IDirect3D3_CreateVertexBuffer(d3d, &desc, &buffer, 0, NULL);
3000 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
3002 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3003 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3004 memcpy(data, quad, sizeof(quad));
3005 hr = IDirect3DVertexBuffer_Unlock(buffer);
3006 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3008 hr = IDirect3DDevice3_BeginScene(device);
3009 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3010 hr = IDirect3DDevice3_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
3011 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3012 hr = IDirect3DDevice3_EndScene(device);
3013 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3015 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3016 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3017 memset(data, 0xaa, sizeof(struct vec4) * vbsize);
3018 hr = IDirect3DVertexBuffer_Unlock(buffer);
3019 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3021 hr = IDirect3DVertexBuffer_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3022 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3023 for (i = 0; i < sizeof(struct vec4) * vbsize; i++)
3025 if (data[i] != 0xaa)
3027 ok(FALSE, "Vertex buffer data byte %u is 0x%02x, expected 0xaa\n", i, data[i]);
3028 break;
3031 hr = IDirect3DVertexBuffer_Unlock(buffer);
3032 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3034 IDirect3DVertexBuffer_Release(buffer);
3035 IDirect3D3_Release(d3d);
3036 IDirect3DDevice3_Release(device);
3037 DestroyWindow(window);
3040 static void test_coop_level_multi_window(void)
3042 HWND window1, window2;
3043 IDirectDraw4 *ddraw;
3044 HRESULT hr;
3046 window1 = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
3047 0, 0, 640, 480, 0, 0, 0, 0);
3048 window2 = CreateWindowA("static", "ddraw_test2", WS_OVERLAPPEDWINDOW,
3049 0, 0, 640, 480, 0, 0, 0, 0);
3050 if (!(ddraw = create_ddraw()))
3052 skip("Failed to create a ddraw object, skipping test.\n");
3053 DestroyWindow(window2);
3054 DestroyWindow(window1);
3055 return;
3058 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
3059 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3060 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3061 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3062 ok(IsWindow(window1), "Window 1 was destroyed.\n");
3063 ok(IsWindow(window2), "Window 2 was destroyed.\n");
3065 IDirectDraw4_Release(ddraw);
3066 DestroyWindow(window2);
3067 DestroyWindow(window1);
3070 static void test_draw_strided(void)
3072 static struct vec3 position[] =
3074 {-1.0, -1.0, 0.0},
3075 {-1.0, 1.0, 0.0},
3076 { 1.0, 1.0, 0.0},
3077 { 1.0, -1.0, 0.0},
3079 static DWORD diffuse[] =
3081 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
3083 static WORD indices[] =
3085 0, 1, 2, 2, 3, 0
3088 IDirectDrawSurface4 *rt;
3089 IDirect3DDevice3 *device;
3090 D3DCOLOR color;
3091 HWND window;
3092 HRESULT hr;
3093 D3DDRAWPRIMITIVESTRIDEDDATA strided;
3094 IDirect3DViewport3 *viewport;
3095 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
3097 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3098 0, 0, 640, 480, 0, 0, 0, 0);
3100 if (!(device = create_device(window, DDSCL_NORMAL)))
3102 skip("Failed to create D3D device, skipping test.\n");
3103 DestroyWindow(window);
3104 return;
3107 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
3108 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3109 viewport = create_viewport(device, 0, 0, 640, 480);
3110 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
3111 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
3112 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
3113 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
3115 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
3116 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
3117 hr = IDirect3DDevice3_BeginScene(device);
3118 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3120 memset(&strided, 0x55, sizeof(strided));
3121 strided.position.lpvData = position;
3122 strided.position.dwStride = sizeof(*position);
3123 strided.diffuse.lpvData = diffuse;
3124 strided.diffuse.dwStride = sizeof(*diffuse);
3125 hr = IDirect3DDevice3_DrawIndexedPrimitiveStrided(device, D3DPT_TRIANGLELIST, D3DFVF_XYZ | D3DFVF_DIFFUSE,
3126 &strided, 4, indices, 6, 0);
3127 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3129 hr = IDirect3DDevice3_EndScene(device);
3130 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3132 color = get_surface_color(rt, 320, 240);
3133 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
3135 IDirect3DViewport3_Release(viewport);
3136 IDirectDrawSurface4_Release(rt);
3137 IDirect3DDevice3_Release(device);
3138 DestroyWindow(window);
3141 static void test_clear_rect_count(void)
3143 IDirectDrawSurface4 *rt;
3144 IDirect3DDevice3 *device;
3145 D3DCOLOR color;
3146 HWND window;
3147 HRESULT hr;
3148 IDirect3DViewport3 *viewport;
3149 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
3151 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3152 0, 0, 640, 480, 0, 0, 0, 0);
3153 if (!(device = create_device(window, DDSCL_NORMAL)))
3155 skip("Failed to create D3D device, skipping test.\n");
3156 DestroyWindow(window);
3157 return;
3160 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
3161 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3163 viewport = create_viewport(device, 0, 0, 640, 480);
3164 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
3165 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
3166 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x00ffffff, 0.0f, 0);
3167 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
3168 hr = IDirect3DViewport3_Clear2(viewport, 0, &clear_rect, D3DCLEAR_TARGET, 0x00ff0000, 0.0f, 0);
3169 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
3170 hr = IDirect3DViewport3_Clear2(viewport, 0, NULL, D3DCLEAR_TARGET, 0x0000ff00, 0.0f, 0);
3171 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
3172 hr = IDirect3DViewport3_Clear2(viewport, 1, NULL, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0);
3173 ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
3175 color = get_surface_color(rt, 320, 240);
3176 ok(compare_color(color, 0x00ffffff, 1), "Got unexpected color 0x%08x.\n", color);
3178 IDirect3DViewport3_Release(viewport);
3179 IDirectDrawSurface4_Release(rt);
3180 IDirect3DDevice3_Release(device);
3181 DestroyWindow(window);
3184 START_TEST(ddraw4)
3186 test_process_vertices();
3187 test_coop_level_create_device_window();
3188 test_clipper_blt();
3189 test_coop_level_d3d_state();
3190 test_surface_interface_mismatch();
3191 test_coop_level_threaded();
3192 test_depth_blit();
3193 test_texture_load_ckey();
3194 test_viewport();
3195 test_zenable();
3196 test_ck_rgba();
3197 test_ck_default();
3198 test_surface_qi();
3199 test_device_qi();
3200 test_wndproc();
3201 test_window_style();
3202 test_redundant_mode_set();
3203 test_coop_level_mode_set();
3204 test_coop_level_mode_set_multi();
3205 test_initialize();
3206 test_coop_level_surf_create();
3207 test_vb_discard();
3208 test_coop_level_multi_window();
3209 test_draw_strided();
3210 test_clear_rect_count();