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
20 #include "wine/test.h"
34 struct create_window_thread_param
37 HANDLE window_created;
38 HANDLE destroy_window;
42 static BOOL compare_float(float f, float g, unsigned int ulps)
52 if (abs(x - y) > ulps)
58 static BOOL compare_vec4(struct vec4 *vec, float x, float y, float z, float w, unsigned int ulps)
60 return compare_float(vec->x, x, ulps)
61 && compare_float(vec->y, y, ulps)
62 && compare_float(vec->z, z, ulps)
63 && compare_float(vec->w, w, ulps);
66 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
68 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
70 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
72 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
74 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
78 static DWORD WINAPI create_window_thread_proc(void *param)
80 struct create_window_thread_param *p = param;
84 p->window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
85 0, 0, 640, 480, 0, 0, 0, 0);
86 ret = SetEvent(p->window_created);
87 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
93 while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
94 DispatchMessage(&msg);
95 res = WaitForSingleObject(p->destroy_window, 100);
96 if (res == WAIT_OBJECT_0)
98 if (res != WAIT_TIMEOUT)
100 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
105 DestroyWindow(p->window);
110 static void create_window_thread(struct create_window_thread_param *p)
114 p->window_created = CreateEvent(NULL, FALSE, FALSE, NULL);
115 ok(!!p->window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
116 p->destroy_window = CreateEvent(NULL, FALSE, FALSE, NULL);
117 ok(!!p->destroy_window, "CreateEvent failed, last error %#x.\n", GetLastError());
118 p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
119 ok(!!p->thread, "Failed to create thread, last error %#x.\n", GetLastError());
120 res = WaitForSingleObject(p->window_created, INFINITE);
121 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
124 static void destroy_window_thread(struct create_window_thread_param *p)
126 SetEvent(p->destroy_window);
127 WaitForSingleObject(p->thread, INFINITE);
128 CloseHandle(p->destroy_window);
129 CloseHandle(p->window_created);
130 CloseHandle(p->thread);
133 static IDirectDrawSurface4 *get_depth_stencil(IDirect3DDevice3 *device)
135 IDirectDrawSurface4 *rt, *ret;
136 DDSCAPS2 caps = {DDSCAPS_ZBUFFER, 0, 0, 0};
139 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
140 ok(SUCCEEDED(hr), "Failed to get the render target, hr %#x.\n", hr);
141 hr = IDirectDrawSurface4_GetAttachedSurface(rt, &caps, &ret);
142 ok(SUCCEEDED(hr) || hr == DDERR_NOTFOUND, "Failed to get the z buffer, hr %#x.\n", hr);
143 IDirectDrawSurface4_Release(rt);
147 static D3DCOLOR get_surface_color(IDirectDrawSurface4 *surface, UINT x, UINT y)
149 RECT rect = {x, y, x + 1, y + 1};
150 DDSURFACEDESC2 surface_desc;
154 memset(&surface_desc, 0, sizeof(surface_desc));
155 surface_desc.dwSize = sizeof(surface_desc);
157 hr = IDirectDrawSurface4_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
158 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
162 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
164 hr = IDirectDrawSurface4_Unlock(surface, &rect);
165 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
170 static HRESULT CALLBACK enum_z_fmt(DDPIXELFORMAT *format, void *ctx)
172 DDPIXELFORMAT *z_fmt = ctx;
174 if (U1(*format).dwZBufferBitDepth > U1(*z_fmt).dwZBufferBitDepth)
180 static IDirectDraw4 *create_ddraw(void)
182 IDirectDraw4 *ddraw4;
186 if (FAILED(DirectDrawCreate(NULL, &ddraw1, NULL)))
189 hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw4, (void **)&ddraw4);
190 IDirectDraw_Release(ddraw1);
197 static IDirect3DDevice3 *create_device(HWND window, DWORD coop_level)
199 IDirectDrawSurface4 *surface, *ds;
200 IDirect3DDevice3 *device = NULL;
201 DDSURFACEDESC2 surface_desc;
202 IDirectDraw4 *ddraw4;
207 if (!(ddraw4 = create_ddraw()))
210 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, coop_level);
211 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
213 memset(&surface_desc, 0, sizeof(surface_desc));
214 surface_desc.dwSize = sizeof(surface_desc);
215 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
216 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
217 surface_desc.dwWidth = 640;
218 surface_desc.dwHeight = 480;
220 hr = IDirectDraw4_CreateSurface(ddraw4, &surface_desc, &surface, NULL);
221 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
223 if (coop_level & DDSCL_NORMAL)
225 IDirectDrawClipper *clipper;
227 hr = IDirectDraw4_CreateClipper(ddraw4, 0, &clipper, NULL);
228 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
229 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
230 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
231 hr = IDirectDrawSurface4_SetClipper(surface, clipper);
232 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\n", hr);
233 IDirectDrawClipper_Release(clipper);
236 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirect3D3, (void **)&d3d3);
237 IDirectDraw4_Release(ddraw4);
240 IDirectDrawSurface4_Release(surface);
244 memset(&z_fmt, 0, sizeof(z_fmt));
245 hr = IDirect3D3_EnumZBufferFormats(d3d3, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
246 if (FAILED(hr) || !z_fmt.dwSize)
248 IDirect3D3_Release(d3d3);
249 IDirectDrawSurface4_Release(surface);
253 memset(&surface_desc, 0, sizeof(surface_desc));
254 surface_desc.dwSize = sizeof(surface_desc);
255 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
256 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
257 U4(surface_desc).ddpfPixelFormat = z_fmt;
258 surface_desc.dwWidth = 640;
259 surface_desc.dwHeight = 480;
260 hr = IDirectDraw4_CreateSurface(ddraw4, &surface_desc, &ds, NULL);
261 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
264 IDirect3D3_Release(d3d3);
265 IDirectDrawSurface4_Release(surface);
269 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
270 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
271 IDirectDrawSurface4_Release(ds);
274 IDirect3D3_Release(d3d3);
275 IDirectDrawSurface4_Release(surface);
279 hr = IDirect3D3_CreateDevice(d3d3, &IID_IDirect3DHALDevice, surface, &device, NULL);
280 IDirect3D3_Release(d3d3);
281 IDirectDrawSurface4_Release(surface);
288 static void test_process_vertices(void)
290 IDirect3DVertexBuffer *src_vb, *dst_vb;
291 IDirect3DViewport3 *viewport;
292 D3DVERTEXBUFFERDESC vb_desc;
293 IDirect3DDevice3 *device;
294 struct vec3 *src_data;
295 struct vec4 *dst_data;
302 static D3DMATRIX identity =
304 1.0f, 0.0f, 0.0f, 0.0f,
305 0.0f, 1.0f, 0.0f, 0.0f,
306 0.0f, 0.0f, 1.0f, 0.0f,
307 0.0f, 0.0f, 0.0f, 1.0f,
309 static D3DMATRIX projection =
311 1.0f, 0.0f, 0.0f, 0.0f,
312 0.0f, 1.0f, 0.0f, 0.0f,
313 0.0f, 0.0f, 1.0f, 0.0f,
314 6.0f, 7.0f, 8.0f, 1.0f,
317 window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
318 0, 0, 640, 480, 0, 0, 0, 0);
319 if (!(device = create_device(window, DDSCL_NORMAL)))
321 skip("Failed to create a 3D device, skipping test.\n");
322 DestroyWindow(window);
326 hr = IDirect3DDevice3_GetDirect3D(device, &d3d3);
327 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
329 memset(&vb_desc, 0, sizeof(vb_desc));
330 vb_desc.dwSize = sizeof(vb_desc);
331 vb_desc.dwFVF = D3DFVF_XYZ;
332 vb_desc.dwNumVertices = 3;
333 hr = IDirect3D3_CreateVertexBuffer(d3d3, &vb_desc, &src_vb, 0, NULL);
334 ok(SUCCEEDED(hr), "Failed to create source vertex buffer, hr %#x.\n", hr);
336 hr = IDirect3DVertexBuffer_Lock(src_vb, DDLOCK_WRITEONLY, (void **)&src_data, NULL);
337 ok(SUCCEEDED(hr), "Failed to lock source vertex buffer, hr %#x.\n", hr);
338 src_data[0].x = -1.0f;
339 src_data[0].y = -1.0f;
340 src_data[0].z = -1.0f;
341 src_data[1].x = 0.0f;
342 src_data[1].y = 0.0f;
343 src_data[1].z = 0.0f;
344 src_data[2].x = 1.0f;
345 src_data[2].y = 1.0f;
346 src_data[2].z = 1.0f;
347 hr = IDirect3DVertexBuffer_Unlock(src_vb);
348 ok(SUCCEEDED(hr), "Failed to unlock source vertex buffer, hr %#x.\n", hr);
350 memset(&vb_desc, 0, sizeof(vb_desc));
351 vb_desc.dwSize = sizeof(vb_desc);
352 vb_desc.dwFVF = D3DFVF_XYZRHW;
353 vb_desc.dwNumVertices = 3;
354 hr = IDirect3D3_CreateVertexBuffer(d3d3, &vb_desc, &dst_vb, 0, NULL);
355 ok(SUCCEEDED(hr), "Failed to create destination vertex buffer, hr %#x.\n", hr);
357 hr = IDirect3D3_CreateViewport(d3d3, &viewport, NULL);
358 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
359 hr = IDirect3DDevice3_AddViewport(device, viewport);
360 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
361 vp2.dwSize = sizeof(vp2);
368 vp2.dvClipWidth = 4.0f;
369 vp2.dvClipHeight = 5.0f;
372 hr = IDirect3DViewport3_SetViewport2(viewport, &vp2);
373 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
374 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
375 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
377 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &identity);
378 ok(SUCCEEDED(hr), "Failed to set world transformation, hr %#x.\n", hr);
379 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &identity);
380 ok(SUCCEEDED(hr), "Failed to set view transformation, hr %#x.\n", hr);
381 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &identity);
382 ok(SUCCEEDED(hr), "Failed to set projection transformation, hr %#x.\n", hr);
384 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
385 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
387 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
388 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
389 ok(compare_vec4(&dst_data[0], -6.500e+1f, +1.800e+2f, +2.000e-1f, +1.000e+0f, 4096),
390 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
391 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
392 ok(compare_vec4(&dst_data[1], -4.000e+1f, +1.400e+2f, +4.000e-1f, +1.000e+0f, 4096),
393 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
394 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
395 ok(compare_vec4(&dst_data[2], -1.500e+1f, +1.000e+2f, +6.000e-1f, +1.000e+0f, 4096),
396 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
397 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
398 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
399 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
401 hr = IDirect3DDevice3_MultiplyTransform(device, D3DTRANSFORMSTATE_PROJECTION, &projection);
402 ok(SUCCEEDED(hr), "Failed to set projection transformation, hr %#x.\n", hr);
404 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
405 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
407 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
408 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
409 ok(compare_vec4(&dst_data[0], +8.500e+1f, -1.000e+2f, +1.800e+0f, +1.000e+0f, 4096),
410 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
411 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
412 ok(compare_vec4(&dst_data[1], +1.100e+2f, -1.400e+2f, +2.000e+0f, +1.000e+0f, 4096),
413 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
414 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
415 ok(compare_vec4(&dst_data[2], +1.350e+2f, -1.800e+2f, +2.200e+0f, +1.000e+0f, 4096),
416 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
417 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
418 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
419 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
421 vp2.dwSize = sizeof(vp2);
428 vp2.dvClipWidth = 2.0f;
429 vp2.dvClipHeight = 4.0f;
432 hr = IDirect3DViewport3_SetViewport2(viewport, &vp2);
433 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
435 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
436 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
438 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
439 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
440 ok(compare_vec4(&dst_data[0], +7.500e+1f, +4.000e+1f, -8.000e-1f, +1.000e+0f, 4096),
441 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
442 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
443 ok(compare_vec4(&dst_data[1], +1.200e+2f, +2.000e+1f, -1.000e+0f, +1.000e+0f, 4096),
444 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
445 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
446 ok(compare_vec4(&dst_data[2], +1.650e+2f, +0.000e+0f, -1.200e+0f, +1.000e+0f, 4096),
447 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
448 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
449 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
450 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
452 vp1.dwSize = sizeof(vp1);
463 hr = IDirect3DViewport3_SetViewport(viewport, &vp1);
464 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
466 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
467 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
469 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
470 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
471 ok(compare_vec4(&dst_data[0], +1.100e+2f, +6.800e+1f, +7.000e+0f, +1.000e+0f, 4096),
472 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
473 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
474 ok(compare_vec4(&dst_data[1], +1.170e+2f, +6.600e+1f, +8.000e+0f, +1.000e+0f, 4096),
475 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
476 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
477 ok(compare_vec4(&dst_data[2], +1.240e+2f, +6.400e+1f, +9.000e+0f, +1.000e+0f, 4096),
478 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
479 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
480 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
481 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
483 hr = IDirect3DDevice3_DeleteViewport(device, viewport);
484 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
486 IDirect3DVertexBuffer_Release(dst_vb);
487 IDirect3DVertexBuffer_Release(src_vb);
488 IDirect3DViewport3_Release(viewport);
489 IDirect3D3_Release(d3d3);
490 IDirect3DDevice3_Release(device);
491 DestroyWindow(window);
494 static void test_coop_level_create_device_window(void)
496 HWND focus_window, device_window;
500 focus_window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
501 0, 0, 640, 480, 0, 0, 0, 0);
502 if (!(ddraw = create_ddraw()))
504 skip("Failed to create a ddraw object, skipping test.\n");
505 DestroyWindow(focus_window);
509 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
510 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
511 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
512 ok(!device_window, "Unexpected device window found.\n");
513 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
514 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
515 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
516 ok(!device_window, "Unexpected device window found.\n");
517 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
518 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
519 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
520 ok(!device_window, "Unexpected device window found.\n");
521 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
522 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
523 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
524 ok(!device_window, "Unexpected device window found.\n");
525 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
526 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
527 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
528 ok(!device_window, "Unexpected device window found.\n");
530 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
531 if (broken(hr == DDERR_INVALIDPARAMS))
533 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
534 IDirectDraw4_Release(ddraw);
535 DestroyWindow(focus_window);
539 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
540 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
541 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
542 ok(!device_window, "Unexpected device window found.\n");
543 hr = IDirectDraw4_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
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");
548 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
549 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
550 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
551 ok(!device_window, "Unexpected device window found.\n");
552 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
553 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
554 ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
555 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
556 ok(!!device_window, "Device window not found.\n");
558 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
559 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
560 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
561 ok(!device_window, "Unexpected device window found.\n");
562 hr = IDirectDraw4_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
563 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
564 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
565 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
566 ok(!!device_window, "Device window not found.\n");
568 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
569 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
570 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
571 ok(!device_window, "Unexpected device window found.\n");
572 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
573 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
574 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
575 ok(!device_window, "Unexpected device window found.\n");
576 hr = IDirectDraw4_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
577 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
578 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
579 ok(!device_window, "Unexpected device window found.\n");
580 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
581 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
582 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
583 ok(!!device_window, "Device window not found.\n");
585 IDirectDraw4_Release(ddraw);
586 DestroyWindow(focus_window);
589 static void test_clipper_blt(void)
591 IDirectDrawSurface4 *src_surface, *dst_surface;
592 RECT client_rect, src_rect, *rect;
593 IDirectDrawClipper *clipper;
594 DDSURFACEDESC2 surface_desc;
595 unsigned int i, j, x, y;
606 static const DWORD src_data[] =
608 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
609 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
610 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
612 static const D3DCOLOR expected1[] =
614 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
615 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
616 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
617 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
619 static const D3DCOLOR expected2[] =
621 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
622 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
623 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
624 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
627 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
628 10, 10, 640, 480, 0, 0, 0, 0);
629 ShowWindow(window, SW_SHOW);
630 if (!(ddraw = create_ddraw()))
632 skip("Failed to create a ddraw object, skipping test.\n");
633 DestroyWindow(window);
637 ret = GetClientRect(window, &client_rect);
638 ok(ret, "Failed to get client rect.\n");
639 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
640 ok(ret, "Failed to map client rect.\n");
642 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
643 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
645 hr = IDirectDraw4_CreateClipper(ddraw, 0, &clipper, NULL);
646 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
647 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
648 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
649 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
650 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
651 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
652 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
653 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
654 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
655 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
656 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
657 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
658 ok(rgn_data->rdh.nCount == 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
659 ok(rgn_data->rdh.nRgnSize == 16, "Got unexpected region size %u.\n", rgn_data->rdh.nRgnSize);
660 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
661 "Got unexpected bounding rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
662 rgn_data->rdh.rcBound.left, rgn_data->rdh.rcBound.top,
663 rgn_data->rdh.rcBound.right, rgn_data->rdh.rcBound.bottom,
664 client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
665 rect = (RECT *)&rgn_data->Buffer[0];
666 ok(EqualRect(rect, &client_rect),
667 "Got unexpected clip rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
668 rect->left, rect->top, rect->right, rect->bottom,
669 client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
670 HeapFree(GetProcessHeap(), 0, rgn_data);
672 r1 = CreateRectRgn(0, 0, 320, 240);
673 ok(!!r1, "Failed to create region.\n");
674 r2 = CreateRectRgn(320, 240, 640, 480);
675 ok(!!r2, "Failed to create region.\n");
676 CombineRgn(r1, r1, r2, RGN_OR);
677 ret = GetRegionData(r1, 0, NULL);
678 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
679 ret = GetRegionData(r1, ret, rgn_data);
680 ok(!!ret, "Failed to get region data.\n");
685 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
686 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
687 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
688 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
689 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
690 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
692 HeapFree(GetProcessHeap(), 0, rgn_data);
694 memset(&surface_desc, 0, sizeof(surface_desc));
695 surface_desc.dwSize = sizeof(surface_desc);
696 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
697 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
698 surface_desc.dwWidth = 640;
699 surface_desc.dwHeight = 480;
700 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
701 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
702 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
703 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
704 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
705 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
707 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
708 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
709 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
710 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
712 memset(&fx, 0, sizeof(fx));
713 fx.dwSize = sizeof(fx);
714 hr = IDirectDrawSurface4_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
715 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
716 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
717 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
719 hr = IDirectDrawSurface4_Lock(src_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
720 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
721 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
722 ptr = surface_desc.lpSurface;
723 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
724 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
725 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
726 hr = IDirectDrawSurface4_Unlock(src_surface, NULL);
727 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
729 hr = IDirectDrawSurface4_SetClipper(dst_surface, clipper);
730 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
732 SetRect(&src_rect, 1, 1, 5, 2);
733 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
734 ok(SUCCEEDED(hr), "Failed to blit, 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, expected1[i * 4 + j], 1),
743 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
747 U5(fx).dwFillColor = 0xff0000ff;
748 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
749 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
750 for (i = 0; i < 4; ++i)
752 for (j = 0; j < 4; ++j)
754 x = 80 * ((2 * j) + 1);
755 y = 60 * ((2 * i) + 1);
756 color = get_surface_color(dst_surface, x, y);
757 ok(compare_color(color, expected2[i * 4 + j], 1),
758 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
762 hr = IDirectDrawSurface4_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
763 ok(hr == DDERR_BLTFASTCANTCLIP, "Got unexpected hr %#x.\n", hr);
765 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
766 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
767 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
768 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
769 DestroyWindow(window);
770 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
771 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
772 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
773 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
774 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
775 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
776 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
777 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
778 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
779 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
780 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
781 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
783 IDirectDrawSurface4_Release(dst_surface);
784 IDirectDrawSurface4_Release(src_surface);
785 IDirectDrawClipper_Release(clipper);
786 IDirectDraw4_Release(ddraw);
789 static void test_coop_level_d3d_state(void)
791 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
792 IDirectDrawSurface4 *rt, *surface;
793 IDirect3DViewport3 *viewport;
794 IDirect3DDevice3 *device;
803 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
804 0, 0, 640, 480, 0, 0, 0, 0);
805 if (!(device = create_device(window, DDSCL_NORMAL)))
807 skip("Failed to create D3D device, skipping test.\n");
808 DestroyWindow(window);
812 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
813 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
815 hr = IDirect3D3_CreateViewport(d3d, &viewport, NULL);
816 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
817 hr = IDirect3DDevice3_AddViewport(device, viewport);
818 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
819 memset(&vp, 0, sizeof(vp));
820 vp.dwSize = sizeof(vp);
827 vp.dvClipWidth = 2.0f;
828 vp.dvClipHeight = 2.0f;
831 hr = IDirect3DViewport3_SetViewport2(viewport, &vp);
832 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
834 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
835 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
836 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
837 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
838 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
839 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
840 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
841 ok(!value, "Got unexpected alpha blend enable state %#x.\n", value);
842 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
843 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
844 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
845 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
846 color = get_surface_color(rt, 320, 240);
847 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
849 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
850 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
851 IDirect3D3_Release(d3d);
852 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
853 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
854 hr = IDirectDrawSurface4_IsLost(rt);
855 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
856 hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
857 ok(SUCCEEDED(hr), "Failed to restore surfaces, hr %#x.\n", hr);
858 IDirectDraw4_Release(ddraw);
860 hr = IDirect3DDevice3_GetRenderTarget(device, &surface);
861 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
862 ok(surface == rt, "Got unexpected surface %p.\n", surface);
863 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
864 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
865 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
866 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
867 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
868 ok(!!value, "Got unexpected alpha blend enable state %#x.\n", value);
869 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
870 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
871 color = get_surface_color(rt, 320, 240);
872 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
874 hr = IDirect3DDevice3_DeleteViewport(device, viewport);
875 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
876 IDirect3DViewport3_Release(viewport);
877 IDirectDrawSurface4_Release(surface);
878 IDirectDrawSurface4_Release(rt);
879 IDirect3DDevice3_Release(device);
880 DestroyWindow(window);
883 static void test_surface_interface_mismatch(void)
885 IDirectDraw4 *ddraw = NULL;
886 IDirect3D3 *d3d = NULL;
887 IDirectDrawSurface4 *surface = NULL, *ds;
888 IDirectDrawSurface3 *surface3 = NULL;
889 IDirect3DDevice3 *device = NULL;
890 IDirect3DViewport3 *viewport = NULL;
891 DDSURFACEDESC2 surface_desc;
898 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
900 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
901 0, 0, 640, 480, 0, 0, 0, 0);
903 if (!(ddraw = create_ddraw()))
905 skip("Failed to create a ddraw object, skipping test.\n");
909 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
910 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
912 memset(&surface_desc, 0, sizeof(surface_desc));
913 surface_desc.dwSize = sizeof(surface_desc);
914 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
915 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
916 surface_desc.dwWidth = 640;
917 surface_desc.dwHeight = 480;
919 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
920 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
922 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
923 ok(SUCCEEDED(hr), "Failed to QI IDirectDrawSurface3, hr %#x.\n", hr);
925 hr = IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d);
928 skip("Failed to get the IDirect3D7 interface, skipping test.\n");
932 memset(&z_fmt, 0, sizeof(z_fmt));
933 hr = IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
934 if (FAILED(hr) || !z_fmt.dwSize)
936 skip("No depth buffer formats available, skipping test.\n");
940 memset(&surface_desc, 0, sizeof(surface_desc));
941 surface_desc.dwSize = sizeof(surface_desc);
942 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
943 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
944 U4(surface_desc).ddpfPixelFormat = z_fmt;
945 surface_desc.dwWidth = 640;
946 surface_desc.dwHeight = 480;
947 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &ds, NULL);
948 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
952 /* Using a different surface interface version still works */
953 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
954 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
955 refcount = IDirectDrawSurface4_Release(ds);
956 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
961 hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, (IDirectDrawSurface4 *)surface3, &device, NULL);
962 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
966 hr = IDirect3D3_CreateViewport(d3d, &viewport, NULL);
967 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
968 hr = IDirect3DDevice3_AddViewport(device, viewport);
969 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
970 memset(&vp, 0, sizeof(vp));
971 vp.dwSize = sizeof(vp);
978 vp.dvClipWidth = 2.0f;
979 vp.dvClipHeight = 2.0f;
982 hr = IDirect3DViewport3_SetViewport2(viewport, &vp);
983 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
985 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
986 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
987 color = get_surface_color(surface, 320, 240);
988 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
993 IDirect3DDevice3_DeleteViewport(device, viewport);
994 IDirect3DViewport3_Release(viewport);
996 if (surface3) IDirectDrawSurface3_Release(surface3);
997 if (surface) IDirectDrawSurface4_Release(surface);
998 if (device) IDirect3DDevice3_Release(device);
999 if (d3d) IDirect3D3_Release(d3d);
1000 if (ddraw) IDirectDraw4_Release(ddraw);
1001 DestroyWindow(window);
1004 static void test_coop_level_threaded(void)
1006 struct create_window_thread_param p;
1007 IDirectDraw4 *ddraw;
1010 if (!(ddraw = create_ddraw()))
1012 skip("Failed to create a ddraw object, skipping test.\n");
1015 create_window_thread(&p);
1017 hr = IDirectDraw4_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1018 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1020 IDirectDraw4_Release(ddraw);
1021 destroy_window_thread(&p);
1024 static void test_depth_blit(void)
1033 { -1.0, 1.0, 0.50f, 0xff00ff00},
1034 { 1.0, 1.0, 0.50f, 0xff00ff00},
1035 { -1.0, -1.0, 0.50f, 0xff00ff00},
1036 { 1.0, -1.0, 0.50f, 0xff00ff00},
1038 static const D3DCOLOR expected_colors[4][4] =
1040 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1041 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1042 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1043 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1045 DDSURFACEDESC2 ddsd_new, ddsd_existing;
1047 IDirect3DDevice3 *device;
1048 IDirectDrawSurface4 *ds1, *ds2, *ds3, *rt;
1049 IDirect3DViewport3 *viewport;
1050 D3DVIEWPORT2 vp_data;
1051 RECT src_rect, dst_rect;
1056 IDirectDraw4 *ddraw;
1061 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1062 0, 0, 640, 480, 0, 0, 0, 0);
1063 if (!(device = create_device(window, DDSCL_NORMAL)))
1065 skip("Failed to create D3D device, skipping test.\n");
1066 DestroyWindow(window);
1070 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
1071 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
1072 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
1073 ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
1074 hr = IDirect3D3_CreateViewport(d3d, &viewport, NULL);
1075 ok(SUCCEEDED(hr), "Failed to create a viewport, hr %#x.\n", hr);
1076 IDirect3D3_Release(d3d);
1078 ds1 = get_depth_stencil(device);
1080 memset(&ddsd_new, 0, sizeof(ddsd_new));
1081 ddsd_new.dwSize = sizeof(ddsd_new);
1082 memset(&ddsd_existing, 0, sizeof(ddsd_existing));
1083 ddsd_existing.dwSize = sizeof(ddsd_existing);
1084 hr = IDirectDrawSurface4_GetSurfaceDesc(ds1, &ddsd_existing);
1085 ddsd_new.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1086 ddsd_new.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1087 ddsd_new.dwWidth = ddsd_existing.dwWidth;
1088 ddsd_new.dwHeight = ddsd_existing.dwHeight;
1089 U4(ddsd_new).ddpfPixelFormat = U4(ddsd_existing).ddpfPixelFormat;
1090 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd_new, &ds2, NULL);
1091 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
1092 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd_new, &ds3, NULL);
1093 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
1094 IDirectDraw4_Release(ddraw);
1096 hr = IDirect3DDevice3_AddViewport(device, viewport);
1097 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
1098 memset(&vp_data, 0, sizeof(vp_data));
1099 vp_data.dwSize = sizeof(vp_data);
1100 vp_data.dwWidth = ddsd_existing.dwWidth;
1101 vp_data.dwHeight = ddsd_existing.dwHeight;
1102 vp_data.dvMaxZ = 1.0;
1103 vp_data.dvClipX = -1.0f;
1104 vp_data.dvClipWidth = 2.0f;
1105 vp_data.dvClipY = 1.0f;
1106 vp_data.dvClipHeight = 2.0f;
1107 hr = IDirect3DViewport3_SetViewport2(viewport, &vp_data);
1108 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
1109 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
1110 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
1112 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
1113 ok(SUCCEEDED(hr), "Failed to enable z testing, hr %#x.\n", hr);
1114 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
1115 ok(SUCCEEDED(hr), "Failed to set the z function, hr %#x.\n", hr);
1116 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
1117 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
1119 U1(d3drect).x1 = U2(d3drect).y1 = 0;
1120 U3(d3drect).x2 = vp_data.dwWidth; U4(d3drect).y2 = vp_data.dwHeight;
1121 hr = IDirect3DViewport3_Clear2(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
1122 ok(SUCCEEDED(hr), "Failed to clear the z buffer, hr %#x.\n", hr);
1125 SetRect(&src_rect, 0, 0, 320, 240);
1126 SetRect(&dst_rect, 0, 0, 320, 240);
1127 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1128 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1129 /* Different locations. */
1130 SetRect(&src_rect, 0, 0, 320, 240);
1131 SetRect(&dst_rect, 320, 240, 640, 480);
1132 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1133 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1135 SetRect(&src_rect, 0, 0, 320, 240);
1136 SetRect(&dst_rect, 0, 0, 640, 480);
1137 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1138 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1140 SetRect(&src_rect, 0, 480, 640, 0);
1141 SetRect(&dst_rect, 0, 0, 640, 480);
1142 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1143 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1144 SetRect(&src_rect, 0, 0, 640, 480);
1145 SetRect(&dst_rect, 0, 480, 640, 0);
1146 hr = IDirectDrawSurface4_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1147 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1148 /* Full, explicit. */
1149 SetRect(&src_rect, 0, 0, 640, 480);
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 /* Depth -> color blit: Succeeds on Win7 + Radeon HD 5700, fails on WinXP + Radeon X1600 */
1155 /* Depth blit inside a BeginScene / EndScene pair */
1156 hr = IDirect3DDevice3_BeginScene(device);
1157 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
1158 /* From the current depth stencil */
1159 hr = IDirectDrawSurface4_Blt(ds2, NULL, ds1, NULL, DDBLT_WAIT, NULL);
1160 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1161 /* To the current depth stencil */
1162 hr = IDirectDrawSurface4_Blt(ds1, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1163 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1164 /* Between unbound surfaces */
1165 hr = IDirectDrawSurface4_Blt(ds3, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1166 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1167 hr = IDirect3DDevice3_EndScene(device);
1168 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1170 /* Avoid changing the depth stencil, it doesn't work properly on Windows.
1171 * Instead use DDBLT_DEPTHFILL to clear the depth stencil. Unfortunately
1172 * drivers disagree on the meaning of dwFillDepth. Only 0 seems to produce
1173 * a reliable result(z = 0.0) */
1174 memset(&fx, 0, sizeof(fx));
1175 fx.dwSize = sizeof(fx);
1176 hr = IDirectDrawSurface4_Blt(ds2, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
1177 ok(SUCCEEDED(hr), "Failed to clear the source z buffer, hr %#x.\n", hr);
1179 hr = IDirect3DViewport3_Clear2(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET, 0xffff0000, 1.0f, 0);
1180 ok(SUCCEEDED(hr), "Failed to clear the color and z buffers, hr %#x.\n", hr);
1181 SetRect(&dst_rect, 0, 0, 320, 240);
1182 hr = IDirectDrawSurface4_Blt(ds1, &dst_rect, ds2, NULL, DDBLT_WAIT, NULL);
1183 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1184 IDirectDrawSurface4_Release(ds3);
1185 IDirectDrawSurface4_Release(ds2);
1186 IDirectDrawSurface4_Release(ds1);
1188 hr = IDirect3DDevice3_BeginScene(device);
1189 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
1190 hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
1192 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1193 hr = IDirect3DDevice3_EndScene(device);
1194 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1196 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1197 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1198 for (i = 0; i < 4; ++i)
1200 for (j = 0; j < 4; ++j)
1202 unsigned int x = 80 * ((2 * j) + 1);
1203 unsigned int y = 60 * ((2 * i) + 1);
1204 color = get_surface_color(rt, x, y);
1205 ok(compare_color(color, expected_colors[i][j], 1),
1206 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
1209 IDirectDrawSurface4_Release(rt);
1211 hr = IDirect3DDevice3_DeleteViewport(device, viewport);
1212 ok(SUCCEEDED(hr), "Failed to delete viewport from device, hr %#x.\n", hr);
1213 IDirect3DViewport3_Release(viewport);
1214 IDirect3DDevice3_Release(device);
1215 DestroyWindow(window);
1218 static void test_texture_load_ckey(void)
1220 IDirectDraw4 *ddraw;
1221 IDirectDrawSurface4 *src;
1222 IDirectDrawSurface4 *dst;
1223 IDirect3DTexture2 *src_tex;
1224 IDirect3DTexture2 *dst_tex;
1225 DDSURFACEDESC2 ddsd;
1229 if (!(ddraw = create_ddraw()))
1231 skip("Failed to create ddraw object, skipping test.\n");
1234 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
1235 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1237 memset(&ddsd, 0, sizeof(ddsd));
1238 ddsd.dwSize = sizeof(ddsd);
1239 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
1240 ddsd.dwHeight = 128;
1242 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
1243 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &src, NULL);
1244 ok(SUCCEEDED(hr), "Failed to create source texture, hr %#x.\n", hr);
1245 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1246 hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &dst, NULL);
1247 ok(SUCCEEDED(hr), "Failed to create destination texture, hr %#x.\n", hr);
1249 hr = IDirectDrawSurface4_QueryInterface(src, &IID_IDirect3DTexture2, (void **)&src_tex);
1250 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get Direct3DTexture2 interface, hr %#x.\n", hr);
1253 /* 64 bit ddraw does not support d3d */
1254 skip("Could not get Direct3DTexture2 interface, skipping texture::Load color keying tests.\n");
1255 IDirectDrawSurface4_Release(dst);
1256 IDirectDrawSurface4_Release(src);
1257 IDirectDraw4_Release(ddraw);
1260 hr = IDirectDrawSurface4_QueryInterface(dst, &IID_IDirect3DTexture2, (void **)&dst_tex);
1261 ok(SUCCEEDED(hr), "Failed to get Direct3DTexture2 interface, hr %#x.\n", hr);
1263 /* No surface has a color key */
1264 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1265 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1266 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0xdeadbeef;
1267 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1268 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1269 ok(ckey.dwColorSpaceLowValue == 0xdeadbeef, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1270 ok(ckey.dwColorSpaceHighValue == 0xdeadbeef, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1272 /* Source surface has a color key */
1273 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
1274 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
1275 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1276 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1277 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1278 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1279 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1280 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1281 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1283 /* Both surfaces have a color key: Dest ckey is overwritten */
1284 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x000000ff;
1285 hr = IDirectDrawSurface4_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1286 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1287 hr = IDirect3DTexture2_Load(dst_tex, src_tex);
1288 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1289 hr = IDirectDrawSurface4_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1290 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1291 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1292 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1294 /* Only the destination has a color key: It is not deleted */
1295 hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, NULL);
1296 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1297 hr = IDirectDrawSurface4_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
1298 ok(hr == DDERR_NOCOLORKEY, "Got unexpected 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 IDirect3DTexture2_Release(dst_tex);
1307 IDirect3DTexture2_Release(src_tex);
1308 IDirectDrawSurface4_Release(dst);
1309 IDirectDrawSurface4_Release(src);
1310 IDirectDraw4_Release(ddraw);
1313 static LONG get_refcount(IUnknown *test_iface)
1315 IUnknown_AddRef(test_iface);
1316 return IUnknown_Release(test_iface);
1319 static void test_viewport_interfaces(void)
1321 IDirectDraw4 *ddraw;
1323 HRESULT hr, old_d3d_ref;
1325 IDirect3DViewport *viewport;
1326 IDirect3DViewport2 *viewport2;
1327 IDirect3DViewport3 *viewport3;
1328 IDirectDrawGammaControl *gamma;
1331 if (!(ddraw = create_ddraw()))
1333 skip("Failed to create ddraw object, skipping test.\n");
1336 hr = IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d);
1337 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get d3d interface, hr %#x.\n", hr);
1340 skip("Direct3D not available, skipping tests\n");
1341 IDirectDraw4_Release(ddraw);
1344 old_d3d_ref = get_refcount((IUnknown *)d3d);
1346 hr = IDirect3D3_CreateViewport(d3d, &viewport3, NULL);
1347 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1348 ref = get_refcount((IUnknown *)viewport3);
1349 ok(ref == 1, "Initial IDirect3DViewport3 refcount is %d\n", ref);
1350 ref = get_refcount((IUnknown *)d3d);
1351 ok(ref == old_d3d_ref, "IDirect3D3 refcount is %d\n", ref);
1353 gamma = (IDirectDrawGammaControl *)0xdeadbeef;
1354 hr = IDirect3DViewport2_QueryInterface(viewport3, &IID_IDirectDrawGammaControl, (void **)&gamma);
1355 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
1356 ok(gamma == NULL, "Interface not set to NULL by failed QI call: %p\n", gamma);
1357 if (SUCCEEDED(hr)) IDirectDrawGammaControl_Release(gamma);
1358 /* NULL iid: Segfaults */
1360 hr = IDirect3DViewport3_QueryInterface(viewport3, &IID_IDirect3DViewport, (void **)&viewport);
1361 ok(SUCCEEDED(hr), "Failed to QI IDirect3DViewport, hr %#x.\n", hr);
1364 ref = get_refcount((IUnknown *)viewport);
1365 ok(ref == 2, "IDirect3DViewport refcount is %d\n", ref);
1366 ref = get_refcount((IUnknown *)viewport3);
1367 ok(ref == 2, "IDirect3DViewport3 refcount is %d\n", ref);
1368 IDirect3DViewport_Release(viewport);
1372 hr = IDirect3DViewport3_QueryInterface(viewport3, &IID_IDirect3DViewport3, (void **)&viewport2);
1373 ok(SUCCEEDED(hr), "Failed to QI IDirect3DViewport3, hr %#x.\n", hr);
1376 ref = get_refcount((IUnknown *)viewport2);
1377 ok(ref == 2, "IDirect3DViewport2 refcount is %d\n", ref);
1378 ref = get_refcount((IUnknown *)viewport3);
1379 ok(ref == 2, "IDirect3DViewport3 refcount is %d\n", ref);
1380 IDirect3DViewport3_Release(viewport2);
1383 hr = IDirect3DViewport3_QueryInterface(viewport2, &IID_IUnknown, (void **)&unknown);
1384 ok(SUCCEEDED(hr), "Failed to QI IUnknown, hr %#x.\n", hr);
1387 ref = get_refcount((IUnknown *)viewport3);
1388 ok(ref == 2, "IDirect3DViewport3 refcount is %d\n", ref);
1389 ref = get_refcount(unknown);
1390 ok(ref == 2, "IUnknown refcount is %d\n", ref);
1391 IUnknown_Release(unknown);
1394 IDirect3DViewport3_Release(viewport3);
1395 IDirect3D3_Release(d3d);
1396 IDirectDraw4_Release(ddraw);
1401 test_process_vertices();
1402 test_coop_level_create_device_window();
1404 test_coop_level_d3d_state();
1405 test_surface_interface_mismatch();
1406 test_coop_level_threaded();
1408 test_texture_load_ckey();
1409 test_viewport_interfaces();