2 * Copyright 2011 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "wine/test.h"
33 struct create_window_thread_param
36 HANDLE window_created;
37 HANDLE destroy_window;
41 static BOOL compare_float(float f, float g, unsigned int ulps)
51 if (abs(x - y) > ulps)
57 static BOOL compare_vec4(struct vec4 *vec, float x, float y, float z, float w, unsigned int ulps)
59 return compare_float(vec->x, x, ulps)
60 && compare_float(vec->y, y, ulps)
61 && compare_float(vec->z, z, ulps)
62 && compare_float(vec->w, w, ulps);
65 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
67 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
69 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
71 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
73 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
77 static DWORD WINAPI create_window_thread_proc(void *param)
79 struct create_window_thread_param *p = param;
83 p->window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
84 0, 0, 640, 480, 0, 0, 0, 0);
85 ret = SetEvent(p->window_created);
86 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
92 while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
93 DispatchMessage(&msg);
94 res = WaitForSingleObject(p->destroy_window, 100);
95 if (res == WAIT_OBJECT_0)
97 if (res != WAIT_TIMEOUT)
99 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
104 DestroyWindow(p->window);
109 static void create_window_thread(struct create_window_thread_param *p)
113 p->window_created = CreateEvent(NULL, FALSE, FALSE, NULL);
114 ok(!!p->window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
115 p->destroy_window = CreateEvent(NULL, FALSE, FALSE, NULL);
116 ok(!!p->destroy_window, "CreateEvent failed, last error %#x.\n", GetLastError());
117 p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
118 ok(!!p->thread, "Failed to create thread, last error %#x.\n", GetLastError());
119 res = WaitForSingleObject(p->window_created, INFINITE);
120 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
123 static void destroy_window_thread(struct create_window_thread_param *p)
125 SetEvent(p->destroy_window);
126 WaitForSingleObject(p->thread, INFINITE);
127 CloseHandle(p->destroy_window);
128 CloseHandle(p->window_created);
129 CloseHandle(p->thread);
132 static D3DCOLOR get_surface_color(IDirectDrawSurface4 *surface, UINT x, UINT y)
134 RECT rect = {x, y, x + 1, y + 1};
135 DDSURFACEDESC2 surface_desc;
139 memset(&surface_desc, 0, sizeof(surface_desc));
140 surface_desc.dwSize = sizeof(surface_desc);
142 hr = IDirectDrawSurface4_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
143 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
147 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
149 hr = IDirectDrawSurface4_Unlock(surface, &rect);
150 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
155 static HRESULT CALLBACK enum_z_fmt(DDPIXELFORMAT *format, void *ctx)
157 DDPIXELFORMAT *z_fmt = ctx;
159 if (U1(*format).dwZBufferBitDepth > U1(*z_fmt).dwZBufferBitDepth)
165 static IDirectDraw4 *create_ddraw(void)
167 IDirectDraw4 *ddraw4;
171 if (FAILED(DirectDrawCreate(NULL, &ddraw1, NULL)))
174 hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw4, (void **)&ddraw4);
175 IDirectDraw_Release(ddraw1);
182 static IDirect3DDevice3 *create_device(HWND window, DWORD coop_level)
184 IDirectDrawSurface4 *surface, *ds;
185 IDirect3DDevice3 *device = NULL;
186 DDSURFACEDESC2 surface_desc;
187 IDirectDraw4 *ddraw4;
192 if (!(ddraw4 = create_ddraw()))
195 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, coop_level);
196 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
198 memset(&surface_desc, 0, sizeof(surface_desc));
199 surface_desc.dwSize = sizeof(surface_desc);
200 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
201 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
202 surface_desc.dwWidth = 640;
203 surface_desc.dwHeight = 480;
205 hr = IDirectDraw4_CreateSurface(ddraw4, &surface_desc, &surface, NULL);
206 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
208 if (coop_level & DDSCL_NORMAL)
210 IDirectDrawClipper *clipper;
212 hr = IDirectDraw4_CreateClipper(ddraw4, 0, &clipper, NULL);
213 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
214 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
215 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
216 hr = IDirectDrawSurface4_SetClipper(surface, clipper);
217 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\n", hr);
218 IDirectDrawClipper_Release(clipper);
221 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirect3D3, (void **)&d3d3);
222 IDirectDraw4_Release(ddraw4);
225 IDirectDrawSurface4_Release(surface);
229 memset(&z_fmt, 0, sizeof(z_fmt));
230 hr = IDirect3D3_EnumZBufferFormats(d3d3, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
231 if (FAILED(hr) || !z_fmt.dwSize)
233 IDirect3D3_Release(d3d3);
234 IDirectDrawSurface4_Release(surface);
238 memset(&surface_desc, 0, sizeof(surface_desc));
239 surface_desc.dwSize = sizeof(surface_desc);
240 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
241 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
242 U4(surface_desc).ddpfPixelFormat = z_fmt;
243 surface_desc.dwWidth = 640;
244 surface_desc.dwHeight = 480;
245 hr = IDirectDraw4_CreateSurface(ddraw4, &surface_desc, &ds, NULL);
246 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
249 IDirect3D3_Release(d3d3);
250 IDirectDrawSurface4_Release(surface);
254 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
255 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
256 IDirectDrawSurface4_Release(ds);
259 IDirect3D3_Release(d3d3);
260 IDirectDrawSurface4_Release(surface);
264 hr = IDirect3D3_CreateDevice(d3d3, &IID_IDirect3DHALDevice, surface, &device, NULL);
265 IDirect3D3_Release(d3d3);
266 IDirectDrawSurface4_Release(surface);
273 static void test_process_vertices(void)
275 IDirect3DVertexBuffer *src_vb, *dst_vb;
276 IDirect3DViewport3 *viewport;
277 D3DVERTEXBUFFERDESC vb_desc;
278 IDirect3DDevice3 *device;
279 struct vec3 *src_data;
280 struct vec4 *dst_data;
287 static D3DMATRIX identity =
289 1.0f, 0.0f, 0.0f, 0.0f,
290 0.0f, 1.0f, 0.0f, 0.0f,
291 0.0f, 0.0f, 1.0f, 0.0f,
292 0.0f, 0.0f, 0.0f, 1.0f,
294 static D3DMATRIX projection =
296 1.0f, 0.0f, 0.0f, 0.0f,
297 0.0f, 1.0f, 0.0f, 0.0f,
298 0.0f, 0.0f, 1.0f, 0.0f,
299 6.0f, 7.0f, 8.0f, 1.0f,
302 window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
303 0, 0, 640, 480, 0, 0, 0, 0);
304 if (!(device = create_device(window, DDSCL_NORMAL)))
306 skip("Failed to create a 3D device, skipping test.\n");
307 DestroyWindow(window);
311 hr = IDirect3DDevice3_GetDirect3D(device, &d3d3);
312 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
314 memset(&vb_desc, 0, sizeof(vb_desc));
315 vb_desc.dwSize = sizeof(vb_desc);
316 vb_desc.dwFVF = D3DFVF_XYZ;
317 vb_desc.dwNumVertices = 3;
318 hr = IDirect3D3_CreateVertexBuffer(d3d3, &vb_desc, &src_vb, 0, NULL);
319 ok(SUCCEEDED(hr), "Failed to create source vertex buffer, hr %#x.\n", hr);
321 hr = IDirect3DVertexBuffer_Lock(src_vb, DDLOCK_WRITEONLY, (void **)&src_data, NULL);
322 ok(SUCCEEDED(hr), "Failed to lock source vertex buffer, hr %#x.\n", hr);
323 src_data[0].x = -1.0f;
324 src_data[0].y = -1.0f;
325 src_data[0].z = -1.0f;
326 src_data[1].x = 0.0f;
327 src_data[1].y = 0.0f;
328 src_data[1].z = 0.0f;
329 src_data[2].x = 1.0f;
330 src_data[2].y = 1.0f;
331 src_data[2].z = 1.0f;
332 hr = IDirect3DVertexBuffer_Unlock(src_vb);
333 ok(SUCCEEDED(hr), "Failed to unlock source vertex buffer, hr %#x.\n", hr);
335 memset(&vb_desc, 0, sizeof(vb_desc));
336 vb_desc.dwSize = sizeof(vb_desc);
337 vb_desc.dwFVF = D3DFVF_XYZRHW;
338 vb_desc.dwNumVertices = 3;
339 hr = IDirect3D3_CreateVertexBuffer(d3d3, &vb_desc, &dst_vb, 0, NULL);
340 ok(SUCCEEDED(hr), "Failed to create destination vertex buffer, hr %#x.\n", hr);
342 hr = IDirect3D3_CreateViewport(d3d3, &viewport, NULL);
343 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
344 hr = IDirect3DDevice3_AddViewport(device, viewport);
345 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
346 vp2.dwSize = sizeof(vp2);
353 vp2.dvClipWidth = 4.0f;
354 vp2.dvClipHeight = 5.0f;
357 hr = IDirect3DViewport3_SetViewport2(viewport, &vp2);
358 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
359 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
360 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
362 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &identity);
363 ok(SUCCEEDED(hr), "Failed to set world transformation, hr %#x.\n", hr);
364 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &identity);
365 ok(SUCCEEDED(hr), "Failed to set view transformation, hr %#x.\n", hr);
366 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &identity);
367 ok(SUCCEEDED(hr), "Failed to set projection transformation, hr %#x.\n", hr);
369 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
370 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
372 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
373 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
374 ok(compare_vec4(&dst_data[0], -6.500e+1f, +1.800e+2f, +2.000e-1f, +1.000e+0f, 4096),
375 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
376 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
377 ok(compare_vec4(&dst_data[1], -4.000e+1f, +1.400e+2f, +4.000e-1f, +1.000e+0f, 4096),
378 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
379 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
380 ok(compare_vec4(&dst_data[2], -1.500e+1f, +1.000e+2f, +6.000e-1f, +1.000e+0f, 4096),
381 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
382 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
383 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
384 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
386 hr = IDirect3DDevice3_MultiplyTransform(device, D3DTRANSFORMSTATE_PROJECTION, &projection);
387 ok(SUCCEEDED(hr), "Failed to set projection transformation, hr %#x.\n", hr);
389 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
390 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
392 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
393 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
394 ok(compare_vec4(&dst_data[0], +8.500e+1f, -1.000e+2f, +1.800e+0f, +1.000e+0f, 4096),
395 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
396 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
397 ok(compare_vec4(&dst_data[1], +1.100e+2f, -1.400e+2f, +2.000e+0f, +1.000e+0f, 4096),
398 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
399 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
400 ok(compare_vec4(&dst_data[2], +1.350e+2f, -1.800e+2f, +2.200e+0f, +1.000e+0f, 4096),
401 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
402 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
403 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
404 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
406 vp2.dwSize = sizeof(vp2);
413 vp2.dvClipWidth = 2.0f;
414 vp2.dvClipHeight = 4.0f;
417 hr = IDirect3DViewport3_SetViewport2(viewport, &vp2);
418 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
420 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
421 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
423 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
424 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
425 ok(compare_vec4(&dst_data[0], +7.500e+1f, +4.000e+1f, -8.000e-1f, +1.000e+0f, 4096),
426 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
427 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
428 ok(compare_vec4(&dst_data[1], +1.200e+2f, +2.000e+1f, -1.000e+0f, +1.000e+0f, 4096),
429 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
430 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
431 ok(compare_vec4(&dst_data[2], +1.650e+2f, +0.000e+0f, -1.200e+0f, +1.000e+0f, 4096),
432 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
433 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
434 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
435 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
437 vp1.dwSize = sizeof(vp1);
448 hr = IDirect3DViewport3_SetViewport(viewport, &vp1);
449 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
451 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
452 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
454 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
455 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
456 ok(compare_vec4(&dst_data[0], +1.100e+2f, +6.800e+1f, +7.000e+0f, +1.000e+0f, 4096),
457 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
458 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
459 ok(compare_vec4(&dst_data[1], +1.170e+2f, +6.600e+1f, +8.000e+0f, +1.000e+0f, 4096),
460 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
461 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
462 ok(compare_vec4(&dst_data[2], +1.240e+2f, +6.400e+1f, +9.000e+0f, +1.000e+0f, 4096),
463 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
464 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
465 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
466 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
468 hr = IDirect3DDevice3_DeleteViewport(device, viewport);
469 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
471 IDirect3DVertexBuffer_Release(dst_vb);
472 IDirect3DVertexBuffer_Release(src_vb);
473 IDirect3DViewport3_Release(viewport);
474 IDirect3D3_Release(d3d3);
475 IDirect3DDevice3_Release(device);
476 DestroyWindow(window);
479 static void test_coop_level_create_device_window(void)
481 HWND focus_window, device_window;
485 focus_window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
486 0, 0, 640, 480, 0, 0, 0, 0);
487 if (!(ddraw = create_ddraw()))
489 skip("Failed to create a ddraw object, skipping test.\n");
490 DestroyWindow(focus_window);
494 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
495 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
496 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
497 ok(!device_window, "Unexpected device window found.\n");
498 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
499 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
500 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
501 ok(!device_window, "Unexpected device window found.\n");
502 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
503 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
504 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
505 ok(!device_window, "Unexpected device window found.\n");
506 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
507 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
508 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
509 ok(!device_window, "Unexpected device window found.\n");
510 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
511 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
512 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
513 ok(!device_window, "Unexpected device window found.\n");
515 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
516 if (broken(hr == DDERR_INVALIDPARAMS))
518 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
519 IDirectDraw4_Release(ddraw);
520 DestroyWindow(focus_window);
524 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
525 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
526 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
527 ok(!device_window, "Unexpected device window found.\n");
528 hr = IDirectDraw4_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
529 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
530 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
531 ok(!device_window, "Unexpected device window found.\n");
533 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
534 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
535 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
536 ok(!device_window, "Unexpected device window found.\n");
537 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
538 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
539 ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
540 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
541 ok(!!device_window, "Device window not found.\n");
543 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
544 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
545 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
546 ok(!device_window, "Unexpected device window found.\n");
547 hr = IDirectDraw4_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
548 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
549 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
550 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
551 ok(!!device_window, "Device window not found.\n");
553 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
554 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
555 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
556 ok(!device_window, "Unexpected device window found.\n");
557 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
558 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
559 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
560 ok(!device_window, "Unexpected device window found.\n");
561 hr = IDirectDraw4_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
562 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
563 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
564 ok(!device_window, "Unexpected device window found.\n");
565 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
566 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
567 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
568 ok(!!device_window, "Device window not found.\n");
570 IDirectDraw4_Release(ddraw);
571 DestroyWindow(focus_window);
574 static void test_clipper_blt(void)
576 IDirectDrawSurface4 *src_surface, *dst_surface;
577 RECT client_rect, src_rect, *rect;
578 IDirectDrawClipper *clipper;
579 DDSURFACEDESC2 surface_desc;
580 unsigned int i, j, x, y;
591 static const DWORD src_data[] =
593 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
594 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
595 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
597 static const D3DCOLOR expected1[] =
599 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
600 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
601 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
602 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
604 static const D3DCOLOR expected2[] =
606 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
607 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
608 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
609 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
612 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
613 10, 10, 640, 480, 0, 0, 0, 0);
614 ShowWindow(window, SW_SHOW);
615 if (!(ddraw = create_ddraw()))
617 skip("Failed to create a ddraw object, skipping test.\n");
618 DestroyWindow(window);
622 ret = GetClientRect(window, &client_rect);
623 ok(ret, "Failed to get client rect.\n");
624 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
625 ok(ret, "Failed to map client rect.\n");
627 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
628 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
630 hr = IDirectDraw4_CreateClipper(ddraw, 0, &clipper, NULL);
631 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
632 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
633 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
634 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
635 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
636 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
637 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
638 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
639 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
640 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
641 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
642 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
643 ok(rgn_data->rdh.nCount == 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
644 ok(rgn_data->rdh.nRgnSize == 16, "Got unexpected region size %u.\n", rgn_data->rdh.nRgnSize);
645 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
646 "Got unexpected bounding rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
647 rgn_data->rdh.rcBound.left, rgn_data->rdh.rcBound.top,
648 rgn_data->rdh.rcBound.right, rgn_data->rdh.rcBound.bottom,
649 client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
650 rect = (RECT *)&rgn_data->Buffer[0];
651 ok(EqualRect(rect, &client_rect),
652 "Got unexpected clip rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
653 rect->left, rect->top, rect->right, rect->bottom,
654 client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
655 HeapFree(GetProcessHeap(), 0, rgn_data);
657 r1 = CreateRectRgn(0, 0, 320, 240);
658 ok(!!r1, "Failed to create region.\n");
659 r2 = CreateRectRgn(320, 240, 640, 480);
660 ok(!!r2, "Failed to create region.\n");
661 CombineRgn(r1, r1, r2, RGN_OR);
662 ret = GetRegionData(r1, 0, NULL);
663 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
664 ret = GetRegionData(r1, ret, rgn_data);
665 ok(!!ret, "Failed to get region data.\n");
670 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
671 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
672 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
673 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
674 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
675 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
677 HeapFree(GetProcessHeap(), 0, rgn_data);
679 memset(&surface_desc, 0, sizeof(surface_desc));
680 surface_desc.dwSize = sizeof(surface_desc);
681 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
682 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
683 surface_desc.dwWidth = 640;
684 surface_desc.dwHeight = 480;
685 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
686 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
687 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
688 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
689 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
690 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
692 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
693 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
694 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
695 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
697 memset(&fx, 0, sizeof(fx));
698 fx.dwSize = sizeof(fx);
699 hr = IDirectDrawSurface4_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
700 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
701 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
702 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
704 hr = IDirectDrawSurface4_Lock(src_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
705 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
706 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
707 ptr = surface_desc.lpSurface;
708 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
709 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
710 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
711 hr = IDirectDrawSurface4_Unlock(src_surface, NULL);
712 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
714 hr = IDirectDrawSurface4_SetClipper(dst_surface, clipper);
715 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
717 SetRect(&src_rect, 1, 1, 5, 2);
718 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
719 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
720 for (i = 0; i < 4; ++i)
722 for (j = 0; j < 4; ++j)
724 x = 80 * ((2 * j) + 1);
725 y = 60 * ((2 * i) + 1);
726 color = get_surface_color(dst_surface, x, y);
727 ok(compare_color(color, expected1[i * 4 + j], 1),
728 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
732 U5(fx).dwFillColor = 0xff0000ff;
733 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
734 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
735 for (i = 0; i < 4; ++i)
737 for (j = 0; j < 4; ++j)
739 x = 80 * ((2 * j) + 1);
740 y = 60 * ((2 * i) + 1);
741 color = get_surface_color(dst_surface, x, y);
742 ok(compare_color(color, expected2[i * 4 + j], 1),
743 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
747 hr = IDirectDrawSurface4_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
748 ok(hr == DDERR_BLTFASTCANTCLIP, "Got unexpected hr %#x.\n", hr);
750 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
751 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
752 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
753 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
754 DestroyWindow(window);
755 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
756 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
757 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
758 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
759 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
760 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
761 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
762 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
763 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
764 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
765 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
766 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
768 IDirectDrawSurface4_Release(dst_surface);
769 IDirectDrawSurface4_Release(src_surface);
770 IDirectDrawClipper_Release(clipper);
771 IDirectDraw4_Release(ddraw);
774 static void test_coop_level_d3d_state(void)
776 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
777 IDirectDrawSurface4 *rt, *surface;
778 IDirect3DViewport3 *viewport;
779 IDirect3DDevice3 *device;
788 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
789 0, 0, 640, 480, 0, 0, 0, 0);
790 if (!(device = create_device(window, DDSCL_NORMAL)))
792 skip("Failed to create D3D device, skipping test.\n");
793 DestroyWindow(window);
797 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
798 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
800 hr = IDirect3D3_CreateViewport(d3d, &viewport, NULL);
801 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
802 hr = IDirect3DDevice3_AddViewport(device, viewport);
803 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
804 memset(&vp, 0, sizeof(vp));
805 vp.dwSize = sizeof(vp);
812 vp.dvClipWidth = 2.0f;
813 vp.dvClipHeight = 2.0f;
816 hr = IDirect3DViewport3_SetViewport2(viewport, &vp);
817 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
819 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
820 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
821 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
822 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
823 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
824 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
825 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
826 ok(!value, "Got unexpected alpha blend enable state %#x.\n", value);
827 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
828 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
829 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
830 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
831 color = get_surface_color(rt, 320, 240);
832 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
834 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
835 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
836 IDirect3D3_Release(d3d);
837 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
838 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
839 hr = IDirectDrawSurface4_IsLost(rt);
840 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
841 hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
842 ok(SUCCEEDED(hr), "Failed to restore surfaces, hr %#x.\n", hr);
843 IDirectDraw4_Release(ddraw);
845 hr = IDirect3DDevice3_GetRenderTarget(device, &surface);
846 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
847 ok(surface == rt, "Got unexpected surface %p.\n", surface);
848 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
849 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
850 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
851 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
852 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
853 ok(!!value, "Got unexpected alpha blend enable state %#x.\n", value);
854 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
855 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
856 color = get_surface_color(rt, 320, 240);
857 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
859 hr = IDirect3DDevice3_DeleteViewport(device, viewport);
860 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
861 IDirect3DViewport3_Release(viewport);
862 IDirectDrawSurface4_Release(surface);
863 IDirectDrawSurface4_Release(rt);
864 IDirect3DDevice3_Release(device);
865 DestroyWindow(window);
868 static void test_surface_interface_mismatch(void)
870 IDirectDraw4 *ddraw = NULL;
871 IDirect3D3 *d3d = NULL;
872 IDirectDrawSurface4 *surface = NULL, *ds;
873 IDirectDrawSurface3 *surface3 = NULL;
874 IDirect3DDevice3 *device = NULL;
875 IDirect3DViewport3 *viewport = NULL;
876 DDSURFACEDESC2 surface_desc;
883 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
885 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
886 0, 0, 640, 480, 0, 0, 0, 0);
888 if (!(ddraw = create_ddraw()))
890 skip("Failed to create a ddraw object, skipping test.\n");
894 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
895 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
897 memset(&surface_desc, 0, sizeof(surface_desc));
898 surface_desc.dwSize = sizeof(surface_desc);
899 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
900 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
901 surface_desc.dwWidth = 640;
902 surface_desc.dwHeight = 480;
904 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
905 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
907 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
908 ok(SUCCEEDED(hr), "Failed to QI IDirectDrawSurface3, hr %#x.\n", hr);
910 hr = IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d);
913 skip("Failed to get the IDirect3D7 interface, skipping test.\n");
917 memset(&z_fmt, 0, sizeof(z_fmt));
918 hr = IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
919 if (FAILED(hr) || !z_fmt.dwSize)
921 skip("No depth buffer formats available, skipping test.\n");
925 memset(&surface_desc, 0, sizeof(surface_desc));
926 surface_desc.dwSize = sizeof(surface_desc);
927 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
928 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
929 U4(surface_desc).ddpfPixelFormat = z_fmt;
930 surface_desc.dwWidth = 640;
931 surface_desc.dwHeight = 480;
932 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &ds, NULL);
933 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
937 /* Using a different surface interface version still works */
938 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
939 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
940 refcount = IDirectDrawSurface4_Release(ds);
941 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
946 hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, (IDirectDrawSurface4 *)surface3, &device, NULL);
947 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
951 hr = IDirect3D3_CreateViewport(d3d, &viewport, NULL);
952 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
953 hr = IDirect3DDevice3_AddViewport(device, viewport);
954 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
955 memset(&vp, 0, sizeof(vp));
956 vp.dwSize = sizeof(vp);
963 vp.dvClipWidth = 2.0f;
964 vp.dvClipHeight = 2.0f;
967 hr = IDirect3DViewport3_SetViewport2(viewport, &vp);
968 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
970 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
971 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
972 color = get_surface_color(surface, 320, 240);
973 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
978 IDirect3DDevice2_DeleteViewport(device, viewport);
979 IDirect3DViewport2_Release(viewport);
981 if (surface3) IDirectDrawSurface3_Release(surface3);
982 if (surface) IDirectDrawSurface4_Release(surface);
983 if (device) IDirect3DDevice3_Release(device);
984 if (d3d) IDirect3D3_Release(d3d);
985 if (ddraw) IDirectDraw4_Release(ddraw);
986 DestroyWindow(window);
989 static void test_coop_level_threaded(void)
991 struct create_window_thread_param p;
995 if (!(ddraw = create_ddraw()))
997 skip("Failed to create a ddraw object, skipping test.\n");
1000 create_window_thread(&p);
1002 hr = IDirectDraw4_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1003 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1005 IDirectDraw4_Release(ddraw);
1006 destroy_window_thread(&p);
1009 static IDirectDrawSurface4 *get_depth_stencil(IDirect3DDevice3 *device)
1011 IDirectDrawSurface4 *rt, *ret;
1012 DDSCAPS2 caps = {DDSCAPS_ZBUFFER, 0, 0, 0};
1015 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1016 ok(SUCCEEDED(hr), "Failed to get the render target, hr %#x.\n", hr);
1017 hr = IDirectDrawSurface4_GetAttachedSurface(rt, &caps, &ret);
1018 ok(SUCCEEDED(hr) || hr == DDERR_NOTFOUND, "Failed to get the z buffer, hr %#x.\n", hr);
1019 IDirectDrawSurface4_Release(rt);
1023 static void test_depth_blit(void)
1032 { -1.0, 1.0, 0.50f, 0xff00ff00},
1033 { 1.0, 1.0, 0.50f, 0xff00ff00},
1034 { -1.0, -1.0, 0.50f, 0xff00ff00},
1035 { 1.0, -1.0, 0.50f, 0xff00ff00},
1037 static const D3DCOLOR expected_colors[4][4] =
1039 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1040 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1041 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1042 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1044 DDSURFACEDESC2 ddsd_new, ddsd_existing;
1046 IDirect3DDevice3 *device;
1047 IDirectDrawSurface4 *ds1, *ds2, *ds3, *rt;
1048 IDirect3DViewport3 *viewport;
1049 D3DVIEWPORT2 vp_data;
1050 RECT src_rect, dst_rect;
1055 IDirectDraw4 *ddraw;
1060 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1061 0, 0, 640, 480, 0, 0, 0, 0);
1062 if (!(device = create_device(window, DDSCL_NORMAL)))
1064 skip("Failed to create D3D device, skipping test.\n");
1065 DestroyWindow(window);
1069 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1070 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
1071 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1072 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
1073 hr = IDirect3D3_CreateViewport(d3d, &viewport, NULL);
1074 ok(SUCCEEDED(hr), "Failed to create a viewport, hr %#x.\n", hr);
1075 IDirect3D3_Release(d3d);
1077 ds1 = get_depth_stencil(device);
1079 memset(&ddsd_new, 0, sizeof(ddsd_new));
1080 ddsd_new.dwSize = sizeof(ddsd_new);
1081 memset(&ddsd_existing, 0, sizeof(ddsd_existing));
1082 ddsd_existing.dwSize = sizeof(ddsd_existing);
1083 hr = IDirectDrawSurface4_GetSurfaceDesc(ds1, &ddsd_existing);
1084 ddsd_new.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1085 ddsd_new.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1086 ddsd_new.dwWidth = ddsd_existing.dwWidth;
1087 ddsd_new.dwHeight = ddsd_existing.dwHeight;
1088 U4(ddsd_new).ddpfPixelFormat = U4(ddsd_existing).ddpfPixelFormat;
1089 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd_new, &ds2, NULL);
1090 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
1091 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd_new, &ds3, NULL);
1092 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
1093 IDirectDraw4_Release(ddraw);
1095 hr = IDirect3DDevice3_AddViewport(device, viewport);
1096 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1097 memset(&vp_data, 0, sizeof(vp_data));
1098 vp_data.dwSize = sizeof(vp_data);
1099 vp_data.dwWidth = ddsd_existing.dwWidth;
1100 vp_data.dwHeight = ddsd_existing.dwHeight;
1101 vp_data.dvMaxZ = 1.0;
1102 vp_data.dvClipX = -1.0f;
1103 vp_data.dvClipWidth = 2.0f;
1104 vp_data.dvClipY = 1.0f;
1105 vp_data.dvClipHeight = 2.0f;
1106 hr = IDirect3DViewport3_SetViewport2(viewport, &vp_data);
1107 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
1108 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
1109 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
1111 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
1112 ok(SUCCEEDED(hr), "Failed to enable z testing, hr %#x.\n", hr);
1113 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
1114 ok(SUCCEEDED(hr), "Failed to set the z function, hr %#x.\n", hr);
1115 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
1116 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
1118 U1(d3drect).x1 = U2(d3drect).y1 = 0;
1119 U3(d3drect).x2 = vp_data.dwWidth; U4(d3drect).y2 = vp_data.dwHeight;
1120 hr = IDirect3DViewport3_Clear2(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
1121 ok(SUCCEEDED(hr), "Failed to clear the z buffer, hr %#x.\n", hr);
1124 SetRect(&src_rect, 0, 0, 320, 240);
1125 SetRect(&dst_rect, 0, 0, 320, 240);
1126 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1127 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1128 /* Different locations. */
1129 SetRect(&src_rect, 0, 0, 320, 240);
1130 SetRect(&dst_rect, 320, 240, 640, 480);
1131 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1132 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1134 SetRect(&src_rect, 0, 0, 320, 240);
1135 SetRect(&dst_rect, 0, 0, 640, 480);
1136 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1137 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1139 SetRect(&src_rect, 0, 480, 640, 0);
1140 SetRect(&dst_rect, 0, 0, 640, 480);
1141 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1142 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1143 SetRect(&src_rect, 0, 0, 640, 480);
1144 SetRect(&dst_rect, 0, 480, 640, 0);
1145 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1146 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1147 /* Full, explicit. */
1148 SetRect(&src_rect, 0, 0, 640, 480);
1149 SetRect(&dst_rect, 0, 0, 640, 480);
1150 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1151 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1152 /* Depth -> color blit: Succeeds on Win7 + Radeon HD 5700, fails on WinXP + Radeon X1600 */
1154 /* Depth blit inside a BeginScene / EndScene pair */
1155 hr = IDirect3DDevice3_BeginScene(device);
1156 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
1157 /* From the current depth stencil */
1158 hr = IDirectDrawSurface4_Blt(ds2, NULL, ds1, NULL, DDBLT_WAIT, NULL);
1159 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1160 /* To the current depth stencil */
1161 hr = IDirectDrawSurface4_Blt(ds1, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1162 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1163 /* Between unbound surfaces */
1164 hr = IDirectDrawSurface4_Blt(ds3, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1165 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1166 hr = IDirect3DDevice3_EndScene(device);
1167 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1169 /* Avoid changing the depth stencil, it doesn't work properly on Windows.
1170 * Instead use DDBLT_DEPTHFILL to clear the depth stencil. Unfortunately
1171 * drivers disagree on the meaning of dwFillDepth. Only 0 seems to produce
1172 * a reliable result(z = 0.0) */
1173 memset(&fx, 0, sizeof(fx));
1174 fx.dwSize = sizeof(fx);
1175 hr = IDirectDrawSurface4_Blt(ds2, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
1176 ok(SUCCEEDED(hr), "Failed to clear the source z buffer, hr %#x.\n", hr);
1178 hr = IDirect3DViewport3_Clear2(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET, 0xffff0000, 1.0f, 0);
1179 ok(SUCCEEDED(hr), "Failed to clear the color and z buffers, hr %#x.\n", hr);
1180 SetRect(&dst_rect, 0, 0, 320, 240);
1181 hr = IDirectDrawSurface4_Blt(ds1, &dst_rect, ds2, NULL, DDBLT_WAIT, NULL);
1182 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1183 IDirectDrawSurface4_Release(ds3);
1184 IDirectDrawSurface4_Release(ds2);
1185 IDirectDrawSurface4_Release(ds1);
1187 hr = IDirect3DDevice3_BeginScene(device);
1188 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
1189 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
1191 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1192 hr = IDirect3DDevice3_EndScene(device);
1193 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1195 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1196 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1197 for (i = 0; i < 4; ++i)
1199 for (j = 0; j < 4; ++j)
1201 unsigned int x = 80 * ((2 * j) + 1);
1202 unsigned int y = 60 * ((2 * i) + 1);
1203 color = get_surface_color(rt, x, y);
1204 ok(compare_color(color, expected_colors[i][j], 1),
1205 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
1208 IDirectDrawSurface4_Release(rt);
1210 hr = IDirect3DDevice3_DeleteViewport(device, viewport);
1211 ok(SUCCEEDED(hr), "Failed to delete viewport from device, hr %#x.\n", hr);
1212 IDirect3DViewport3_Release(viewport);
1213 IDirect3DDevice3_Release(device);
1214 DestroyWindow(window);
1219 test_process_vertices();
1220 test_coop_level_create_device_window();
1222 test_coop_level_d3d_state();
1223 test_surface_interface_mismatch();
1224 test_coop_level_threaded();