ddraw/tests: Use correct COM macros in a couple of places.
[wine/multimedia.git] / dlls / ddraw / tests / ddraw4.c
blob07509b90f8ee88a3687c78008de096a74bed6e77
1 /*
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
18 #define COBJMACROS
20 #include "wine/test.h"
21 #include <limits.h>
22 #include "d3d.h"
24 struct vec3
26 float x, y, z;
29 struct vec4
31 float x, y, z, w;
34 struct create_window_thread_param
36 HWND window;
37 HANDLE window_created;
38 HANDLE destroy_window;
39 HANDLE thread;
42 static BOOL compare_float(float f, float g, unsigned int ulps)
44 int x = *(int *)&f;
45 int y = *(int *)&g;
47 if (x < 0)
48 x = INT_MIN - x;
49 if (y < 0)
50 y = INT_MIN - y;
52 if (abs(x - y) > ulps)
53 return FALSE;
55 return TRUE;
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;
69 c1 >>= 8; c2 >>= 8;
70 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
71 c1 >>= 8; c2 >>= 8;
72 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
73 c1 >>= 8; c2 >>= 8;
74 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
75 return TRUE;
78 static DWORD WINAPI create_window_thread_proc(void *param)
80 struct create_window_thread_param *p = param;
81 DWORD res;
82 BOOL ret;
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());
89 for (;;)
91 MSG msg;
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)
97 break;
98 if (res != WAIT_TIMEOUT)
100 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
101 break;
105 DestroyWindow(p->window);
107 return 0;
110 static void create_window_thread(struct create_window_thread_param *p)
112 DWORD res, tid;
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 D3DCOLOR get_surface_color(IDirectDrawSurface4 *surface, UINT x, UINT y)
135 RECT rect = {x, y, x + 1, y + 1};
136 DDSURFACEDESC2 surface_desc;
137 D3DCOLOR color;
138 HRESULT hr;
140 memset(&surface_desc, 0, sizeof(surface_desc));
141 surface_desc.dwSize = sizeof(surface_desc);
143 hr = IDirectDrawSurface4_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
144 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
145 if (FAILED(hr))
146 return 0xdeadbeef;
148 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
150 hr = IDirectDrawSurface4_Unlock(surface, &rect);
151 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
153 return color;
156 static HRESULT CALLBACK enum_z_fmt(DDPIXELFORMAT *format, void *ctx)
158 DDPIXELFORMAT *z_fmt = ctx;
160 if (U1(*format).dwZBufferBitDepth > U1(*z_fmt).dwZBufferBitDepth)
161 *z_fmt = *format;
163 return DDENUMRET_OK;
166 static IDirectDraw4 *create_ddraw(void)
168 IDirectDraw4 *ddraw4;
169 IDirectDraw *ddraw1;
170 HRESULT hr;
172 if (FAILED(DirectDrawCreate(NULL, &ddraw1, NULL)))
173 return NULL;
175 hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw4, (void **)&ddraw4);
176 IDirectDraw_Release(ddraw1);
177 if (FAILED(hr))
178 return NULL;
180 return ddraw4;
183 static IDirect3DDevice3 *create_device(HWND window, DWORD coop_level)
185 IDirectDrawSurface4 *surface, *ds;
186 IDirect3DDevice3 *device = NULL;
187 DDSURFACEDESC2 surface_desc;
188 IDirectDraw4 *ddraw4;
189 DDPIXELFORMAT z_fmt;
190 IDirect3D3 *d3d3;
191 HRESULT hr;
193 if (!(ddraw4 = create_ddraw()))
194 return NULL;
196 hr = IDirectDraw4_SetCooperativeLevel(ddraw4, window, coop_level);
197 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
199 memset(&surface_desc, 0, sizeof(surface_desc));
200 surface_desc.dwSize = sizeof(surface_desc);
201 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
202 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
203 surface_desc.dwWidth = 640;
204 surface_desc.dwHeight = 480;
206 hr = IDirectDraw4_CreateSurface(ddraw4, &surface_desc, &surface, NULL);
207 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
209 if (coop_level & DDSCL_NORMAL)
211 IDirectDrawClipper *clipper;
213 hr = IDirectDraw4_CreateClipper(ddraw4, 0, &clipper, NULL);
214 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
215 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
216 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
217 hr = IDirectDrawSurface4_SetClipper(surface, clipper);
218 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\n", hr);
219 IDirectDrawClipper_Release(clipper);
222 hr = IDirectDraw4_QueryInterface(ddraw4, &IID_IDirect3D3, (void **)&d3d3);
223 IDirectDraw4_Release(ddraw4);
224 if (FAILED(hr))
226 IDirectDrawSurface4_Release(surface);
227 return NULL;
230 memset(&z_fmt, 0, sizeof(z_fmt));
231 hr = IDirect3D3_EnumZBufferFormats(d3d3, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
232 if (FAILED(hr) || !z_fmt.dwSize)
234 IDirect3D3_Release(d3d3);
235 IDirectDrawSurface4_Release(surface);
236 return NULL;
239 memset(&surface_desc, 0, sizeof(surface_desc));
240 surface_desc.dwSize = sizeof(surface_desc);
241 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
242 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
243 U4(surface_desc).ddpfPixelFormat = z_fmt;
244 surface_desc.dwWidth = 640;
245 surface_desc.dwHeight = 480;
246 hr = IDirectDraw4_CreateSurface(ddraw4, &surface_desc, &ds, NULL);
247 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
248 if (FAILED(hr))
250 IDirect3D3_Release(d3d3);
251 IDirectDrawSurface4_Release(surface);
252 return NULL;
255 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
256 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
257 IDirectDrawSurface4_Release(ds);
258 if (FAILED(hr))
260 IDirect3D3_Release(d3d3);
261 IDirectDrawSurface4_Release(surface);
262 return NULL;
265 hr = IDirect3D3_CreateDevice(d3d3, &IID_IDirect3DHALDevice, surface, &device, NULL);
266 IDirect3D3_Release(d3d3);
267 IDirectDrawSurface4_Release(surface);
268 if (FAILED(hr))
269 return NULL;
271 return device;
274 static void test_process_vertices(void)
276 IDirect3DVertexBuffer *src_vb, *dst_vb;
277 IDirect3DViewport3 *viewport;
278 D3DVERTEXBUFFERDESC vb_desc;
279 IDirect3DDevice3 *device;
280 struct vec3 *src_data;
281 struct vec4 *dst_data;
282 IDirect3D3 *d3d3;
283 D3DVIEWPORT2 vp2;
284 D3DVIEWPORT vp1;
285 HWND window;
286 HRESULT hr;
288 static D3DMATRIX identity =
290 1.0f, 0.0f, 0.0f, 0.0f,
291 0.0f, 1.0f, 0.0f, 0.0f,
292 0.0f, 0.0f, 1.0f, 0.0f,
293 0.0f, 0.0f, 0.0f, 1.0f,
295 static D3DMATRIX projection =
297 1.0f, 0.0f, 0.0f, 0.0f,
298 0.0f, 1.0f, 0.0f, 0.0f,
299 0.0f, 0.0f, 1.0f, 0.0f,
300 6.0f, 7.0f, 8.0f, 1.0f,
303 window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
304 0, 0, 640, 480, 0, 0, 0, 0);
305 if (!(device = create_device(window, DDSCL_NORMAL)))
307 skip("Failed to create a 3D device, skipping test.\n");
308 DestroyWindow(window);
309 return;
312 hr = IDirect3DDevice3_GetDirect3D(device, &d3d3);
313 ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
315 memset(&vb_desc, 0, sizeof(vb_desc));
316 vb_desc.dwSize = sizeof(vb_desc);
317 vb_desc.dwFVF = D3DFVF_XYZ;
318 vb_desc.dwNumVertices = 3;
319 hr = IDirect3D3_CreateVertexBuffer(d3d3, &vb_desc, &src_vb, 0, NULL);
320 ok(SUCCEEDED(hr), "Failed to create source vertex buffer, hr %#x.\n", hr);
322 hr = IDirect3DVertexBuffer_Lock(src_vb, DDLOCK_WRITEONLY, (void **)&src_data, NULL);
323 ok(SUCCEEDED(hr), "Failed to lock source vertex buffer, hr %#x.\n", hr);
324 src_data[0].x = -1.0f;
325 src_data[0].y = -1.0f;
326 src_data[0].z = -1.0f;
327 src_data[1].x = 0.0f;
328 src_data[1].y = 0.0f;
329 src_data[1].z = 0.0f;
330 src_data[2].x = 1.0f;
331 src_data[2].y = 1.0f;
332 src_data[2].z = 1.0f;
333 hr = IDirect3DVertexBuffer_Unlock(src_vb);
334 ok(SUCCEEDED(hr), "Failed to unlock source vertex buffer, hr %#x.\n", hr);
336 memset(&vb_desc, 0, sizeof(vb_desc));
337 vb_desc.dwSize = sizeof(vb_desc);
338 vb_desc.dwFVF = D3DFVF_XYZRHW;
339 vb_desc.dwNumVertices = 3;
340 hr = IDirect3D3_CreateVertexBuffer(d3d3, &vb_desc, &dst_vb, 0, NULL);
341 ok(SUCCEEDED(hr), "Failed to create destination vertex buffer, hr %#x.\n", hr);
343 hr = IDirect3D3_CreateViewport(d3d3, &viewport, NULL);
344 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
345 hr = IDirect3DDevice3_AddViewport(device, viewport);
346 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
347 vp2.dwSize = sizeof(vp2);
348 vp2.dwX = 10;
349 vp2.dwY = 20;
350 vp2.dwWidth = 100;
351 vp2.dwHeight = 200;
352 vp2.dvClipX = 2.0f;
353 vp2.dvClipY = 3.0f;
354 vp2.dvClipWidth = 4.0f;
355 vp2.dvClipHeight = 5.0f;
356 vp2.dvMinZ = -2.0f;
357 vp2.dvMaxZ = 3.0f;
358 hr = IDirect3DViewport3_SetViewport2(viewport, &vp2);
359 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
360 hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
361 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
363 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &identity);
364 ok(SUCCEEDED(hr), "Failed to set world transformation, hr %#x.\n", hr);
365 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &identity);
366 ok(SUCCEEDED(hr), "Failed to set view transformation, hr %#x.\n", hr);
367 hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &identity);
368 ok(SUCCEEDED(hr), "Failed to set projection transformation, hr %#x.\n", hr);
370 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
371 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
373 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
374 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
375 ok(compare_vec4(&dst_data[0], -6.500e+1f, +1.800e+2f, +2.000e-1f, +1.000e+0f, 4096),
376 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
377 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
378 ok(compare_vec4(&dst_data[1], -4.000e+1f, +1.400e+2f, +4.000e-1f, +1.000e+0f, 4096),
379 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
380 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
381 ok(compare_vec4(&dst_data[2], -1.500e+1f, +1.000e+2f, +6.000e-1f, +1.000e+0f, 4096),
382 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
383 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
384 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
385 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
387 hr = IDirect3DDevice3_MultiplyTransform(device, D3DTRANSFORMSTATE_PROJECTION, &projection);
388 ok(SUCCEEDED(hr), "Failed to set projection transformation, hr %#x.\n", hr);
390 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
391 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
393 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
394 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
395 ok(compare_vec4(&dst_data[0], +8.500e+1f, -1.000e+2f, +1.800e+0f, +1.000e+0f, 4096),
396 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
397 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
398 ok(compare_vec4(&dst_data[1], +1.100e+2f, -1.400e+2f, +2.000e+0f, +1.000e+0f, 4096),
399 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
400 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
401 ok(compare_vec4(&dst_data[2], +1.350e+2f, -1.800e+2f, +2.200e+0f, +1.000e+0f, 4096),
402 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
403 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
404 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
405 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
407 vp2.dwSize = sizeof(vp2);
408 vp2.dwX = 30;
409 vp2.dwY = 40;
410 vp2.dwWidth = 90;
411 vp2.dwHeight = 80;
412 vp2.dvClipX = 4.0f;
413 vp2.dvClipY = 6.0f;
414 vp2.dvClipWidth = 2.0f;
415 vp2.dvClipHeight = 4.0f;
416 vp2.dvMinZ = 3.0f;
417 vp2.dvMaxZ = -2.0f;
418 hr = IDirect3DViewport3_SetViewport2(viewport, &vp2);
419 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
421 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
422 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
424 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
425 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
426 ok(compare_vec4(&dst_data[0], +7.500e+1f, +4.000e+1f, -8.000e-1f, +1.000e+0f, 4096),
427 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
428 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
429 ok(compare_vec4(&dst_data[1], +1.200e+2f, +2.000e+1f, -1.000e+0f, +1.000e+0f, 4096),
430 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
431 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
432 ok(compare_vec4(&dst_data[2], +1.650e+2f, +0.000e+0f, -1.200e+0f, +1.000e+0f, 4096),
433 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
434 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
435 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
436 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
438 vp1.dwSize = sizeof(vp1);
439 vp1.dwX = 30;
440 vp1.dwY = 40;
441 vp1.dwWidth = 90;
442 vp1.dwHeight = 80;
443 vp1.dvScaleX = 7.0f;
444 vp1.dvScaleY = 2.0f;
445 vp1.dvMaxX = 6.0f;
446 vp1.dvMaxY = 10.0f;
447 vp1.dvMinZ = -2.0f;
448 vp1.dvMaxZ = 3.0f;
449 hr = IDirect3DViewport3_SetViewport(viewport, &vp1);
450 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
452 hr = IDirect3DVertexBuffer_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0, 3, src_vb, 0, device, 0);
453 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
455 hr = IDirect3DVertexBuffer_Lock(dst_vb, DDLOCK_READONLY, (void **)&dst_data, NULL);
456 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
457 ok(compare_vec4(&dst_data[0], +1.100e+2f, +6.800e+1f, +7.000e+0f, +1.000e+0f, 4096),
458 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
459 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
460 ok(compare_vec4(&dst_data[1], +1.170e+2f, +6.600e+1f, +8.000e+0f, +1.000e+0f, 4096),
461 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
462 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
463 ok(compare_vec4(&dst_data[2], +1.240e+2f, +6.400e+1f, +9.000e+0f, +1.000e+0f, 4096),
464 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
465 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
466 hr = IDirect3DVertexBuffer_Unlock(dst_vb);
467 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
469 hr = IDirect3DDevice3_DeleteViewport(device, viewport);
470 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
472 IDirect3DVertexBuffer_Release(dst_vb);
473 IDirect3DVertexBuffer_Release(src_vb);
474 IDirect3DViewport3_Release(viewport);
475 IDirect3D3_Release(d3d3);
476 IDirect3DDevice3_Release(device);
477 DestroyWindow(window);
480 static void test_coop_level_create_device_window(void)
482 HWND focus_window, device_window;
483 IDirectDraw4 *ddraw;
484 HRESULT hr;
486 focus_window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
487 0, 0, 640, 480, 0, 0, 0, 0);
488 if (!(ddraw = create_ddraw()))
490 skip("Failed to create a ddraw object, skipping test.\n");
491 DestroyWindow(focus_window);
492 return;
495 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
496 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
497 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
498 ok(!device_window, "Unexpected device window found.\n");
499 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
500 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
501 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
502 ok(!device_window, "Unexpected device window found.\n");
503 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
504 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
505 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
506 ok(!device_window, "Unexpected device window found.\n");
507 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
508 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
509 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
510 ok(!device_window, "Unexpected device window found.\n");
511 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
512 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
513 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
514 ok(!device_window, "Unexpected device window found.\n");
516 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
517 if (broken(hr == DDERR_INVALIDPARAMS))
519 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
520 IDirectDraw4_Release(ddraw);
521 DestroyWindow(focus_window);
522 return;
525 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
526 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
527 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
528 ok(!device_window, "Unexpected device window found.\n");
529 hr = IDirectDraw4_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
530 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
531 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
532 ok(!device_window, "Unexpected device window found.\n");
534 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
535 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
536 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
537 ok(!device_window, "Unexpected device window found.\n");
538 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
539 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
540 ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
541 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
542 ok(!!device_window, "Device window not found.\n");
544 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
545 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
546 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
547 ok(!device_window, "Unexpected device window found.\n");
548 hr = IDirectDraw4_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
549 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
550 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
551 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
552 ok(!!device_window, "Device window not found.\n");
554 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
555 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
556 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
557 ok(!device_window, "Unexpected device window found.\n");
558 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
559 ok(hr == DDERR_NOFOCUSWINDOW, "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 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
564 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
565 ok(!device_window, "Unexpected device window found.\n");
566 hr = IDirectDraw4_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
567 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
568 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
569 ok(!!device_window, "Device window not found.\n");
571 IDirectDraw4_Release(ddraw);
572 DestroyWindow(focus_window);
575 static void test_clipper_blt(void)
577 IDirectDrawSurface4 *src_surface, *dst_surface;
578 RECT client_rect, src_rect, *rect;
579 IDirectDrawClipper *clipper;
580 DDSURFACEDESC2 surface_desc;
581 unsigned int i, j, x, y;
582 IDirectDraw4 *ddraw;
583 RGNDATA *rgn_data;
584 D3DCOLOR color;
585 HRGN r1, r2;
586 HWND window;
587 DDBLTFX fx;
588 HRESULT hr;
589 DWORD *ptr;
590 DWORD ret;
592 static const DWORD src_data[] =
594 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
595 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
596 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
598 static const D3DCOLOR expected1[] =
600 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
601 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
602 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
603 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
605 static const D3DCOLOR expected2[] =
607 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
608 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
609 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
610 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
613 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
614 10, 10, 640, 480, 0, 0, 0, 0);
615 ShowWindow(window, SW_SHOW);
616 if (!(ddraw = create_ddraw()))
618 skip("Failed to create a ddraw object, skipping test.\n");
619 DestroyWindow(window);
620 return;
623 ret = GetClientRect(window, &client_rect);
624 ok(ret, "Failed to get client rect.\n");
625 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
626 ok(ret, "Failed to map client rect.\n");
628 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
629 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
631 hr = IDirectDraw4_CreateClipper(ddraw, 0, &clipper, NULL);
632 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
633 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
634 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
635 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
636 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
637 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
638 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
639 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
640 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
641 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
642 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
643 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
644 ok(rgn_data->rdh.nCount == 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
645 ok(rgn_data->rdh.nRgnSize == 16, "Got unexpected region size %u.\n", rgn_data->rdh.nRgnSize);
646 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
647 "Got unexpected bounding rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
648 rgn_data->rdh.rcBound.left, rgn_data->rdh.rcBound.top,
649 rgn_data->rdh.rcBound.right, rgn_data->rdh.rcBound.bottom,
650 client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
651 rect = (RECT *)&rgn_data->Buffer[0];
652 ok(EqualRect(rect, &client_rect),
653 "Got unexpected clip rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
654 rect->left, rect->top, rect->right, rect->bottom,
655 client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
656 HeapFree(GetProcessHeap(), 0, rgn_data);
658 r1 = CreateRectRgn(0, 0, 320, 240);
659 ok(!!r1, "Failed to create region.\n");
660 r2 = CreateRectRgn(320, 240, 640, 480);
661 ok(!!r2, "Failed to create region.\n");
662 CombineRgn(r1, r1, r2, RGN_OR);
663 ret = GetRegionData(r1, 0, NULL);
664 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
665 ret = GetRegionData(r1, ret, rgn_data);
666 ok(!!ret, "Failed to get region data.\n");
668 DeleteObject(r2);
669 DeleteObject(r1);
671 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
672 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
673 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
674 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
675 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
676 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
678 HeapFree(GetProcessHeap(), 0, rgn_data);
680 memset(&surface_desc, 0, sizeof(surface_desc));
681 surface_desc.dwSize = sizeof(surface_desc);
682 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
683 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
684 surface_desc.dwWidth = 640;
685 surface_desc.dwHeight = 480;
686 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
687 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
688 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
689 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
690 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
691 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
693 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
694 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
695 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
696 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
698 memset(&fx, 0, sizeof(fx));
699 fx.dwSize = sizeof(fx);
700 hr = IDirectDrawSurface4_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
701 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
702 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
703 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
705 hr = IDirectDrawSurface4_Lock(src_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
706 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
707 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
708 ptr = surface_desc.lpSurface;
709 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
710 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
711 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
712 hr = IDirectDrawSurface4_Unlock(src_surface, NULL);
713 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
715 hr = IDirectDrawSurface4_SetClipper(dst_surface, clipper);
716 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
718 SetRect(&src_rect, 1, 1, 5, 2);
719 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
720 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
721 for (i = 0; i < 4; ++i)
723 for (j = 0; j < 4; ++j)
725 x = 80 * ((2 * j) + 1);
726 y = 60 * ((2 * i) + 1);
727 color = get_surface_color(dst_surface, x, y);
728 ok(compare_color(color, expected1[i * 4 + j], 1),
729 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
733 U5(fx).dwFillColor = 0xff0000ff;
734 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
735 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
736 for (i = 0; i < 4; ++i)
738 for (j = 0; j < 4; ++j)
740 x = 80 * ((2 * j) + 1);
741 y = 60 * ((2 * i) + 1);
742 color = get_surface_color(dst_surface, x, y);
743 ok(compare_color(color, expected2[i * 4 + j], 1),
744 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
748 hr = IDirectDrawSurface4_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
749 ok(hr == DDERR_BLTFASTCANTCLIP, "Got unexpected hr %#x.\n", hr);
751 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
752 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
753 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
754 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
755 DestroyWindow(window);
756 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
757 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
758 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
759 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
760 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
761 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
762 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
763 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
764 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
765 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
766 hr = IDirectDrawSurface4_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
767 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
769 IDirectDrawSurface4_Release(dst_surface);
770 IDirectDrawSurface4_Release(src_surface);
771 IDirectDrawClipper_Release(clipper);
772 IDirectDraw4_Release(ddraw);
775 static void test_coop_level_d3d_state(void)
777 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
778 IDirectDrawSurface4 *rt, *surface;
779 IDirect3DViewport3 *viewport;
780 IDirect3DDevice3 *device;
781 IDirectDraw4 *ddraw;
782 D3DVIEWPORT2 vp;
783 IDirect3D3 *d3d;
784 D3DCOLOR color;
785 DWORD value;
786 HWND window;
787 HRESULT hr;
789 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
790 0, 0, 640, 480, 0, 0, 0, 0);
791 if (!(device = create_device(window, DDSCL_NORMAL)))
793 skip("Failed to create D3D device, skipping test.\n");
794 DestroyWindow(window);
795 return;
798 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
799 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
801 hr = IDirect3D3_CreateViewport(d3d, &viewport, NULL);
802 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
803 hr = IDirect3DDevice3_AddViewport(device, viewport);
804 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
805 memset(&vp, 0, sizeof(vp));
806 vp.dwSize = sizeof(vp);
807 vp.dwX = 0;
808 vp.dwY = 0;
809 vp.dwWidth = 640;
810 vp.dwHeight = 480;
811 vp.dvClipX = -1.0f;
812 vp.dvClipY = 1.0f;
813 vp.dvClipWidth = 2.0f;
814 vp.dvClipHeight = 2.0f;
815 vp.dvMinZ = 0.0f;
816 vp.dvMaxZ = 1.0f;
817 hr = IDirect3DViewport3_SetViewport2(viewport, &vp);
818 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
820 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
821 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
822 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
823 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
824 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
825 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
826 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
827 ok(!value, "Got unexpected alpha blend enable state %#x.\n", value);
828 hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
829 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
830 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
831 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
832 color = get_surface_color(rt, 320, 240);
833 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
835 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
836 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
837 IDirect3D3_Release(d3d);
838 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
839 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
840 hr = IDirectDrawSurface4_IsLost(rt);
841 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
842 hr = IDirectDraw4_RestoreAllSurfaces(ddraw);
843 ok(SUCCEEDED(hr), "Failed to restore surfaces, hr %#x.\n", hr);
844 IDirectDraw4_Release(ddraw);
846 hr = IDirect3DDevice3_GetRenderTarget(device, &surface);
847 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
848 ok(surface == rt, "Got unexpected surface %p.\n", surface);
849 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
850 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
851 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
852 hr = IDirect3DDevice3_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
853 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
854 ok(!!value, "Got unexpected alpha blend enable state %#x.\n", value);
855 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
856 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
857 color = get_surface_color(rt, 320, 240);
858 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
860 hr = IDirect3DDevice3_DeleteViewport(device, viewport);
861 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
862 IDirect3DViewport3_Release(viewport);
863 IDirectDrawSurface4_Release(surface);
864 IDirectDrawSurface4_Release(rt);
865 IDirect3DDevice3_Release(device);
866 DestroyWindow(window);
869 static void test_surface_interface_mismatch(void)
871 IDirectDraw4 *ddraw = NULL;
872 IDirect3D3 *d3d = NULL;
873 IDirectDrawSurface4 *surface = NULL, *ds;
874 IDirectDrawSurface3 *surface3 = NULL;
875 IDirect3DDevice3 *device = NULL;
876 IDirect3DViewport3 *viewport = NULL;
877 DDSURFACEDESC2 surface_desc;
878 DDPIXELFORMAT z_fmt;
879 ULONG refcount;
880 HRESULT hr;
881 D3DCOLOR color;
882 HWND window;
883 D3DVIEWPORT2 vp;
884 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
886 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
887 0, 0, 640, 480, 0, 0, 0, 0);
889 if (!(ddraw = create_ddraw()))
891 skip("Failed to create a ddraw object, skipping test.\n");
892 goto cleanup;
895 hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
896 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
898 memset(&surface_desc, 0, sizeof(surface_desc));
899 surface_desc.dwSize = sizeof(surface_desc);
900 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
901 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
902 surface_desc.dwWidth = 640;
903 surface_desc.dwHeight = 480;
905 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
906 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
908 hr = IDirectDrawSurface4_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
909 ok(SUCCEEDED(hr), "Failed to QI IDirectDrawSurface3, hr %#x.\n", hr);
911 hr = IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d);
912 if (FAILED(hr))
914 skip("Failed to get the IDirect3D7 interface, skipping test.\n");
915 goto cleanup;
918 memset(&z_fmt, 0, sizeof(z_fmt));
919 hr = IDirect3D3_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
920 if (FAILED(hr) || !z_fmt.dwSize)
922 skip("No depth buffer formats available, skipping test.\n");
923 goto cleanup;
926 memset(&surface_desc, 0, sizeof(surface_desc));
927 surface_desc.dwSize = sizeof(surface_desc);
928 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
929 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
930 U4(surface_desc).ddpfPixelFormat = z_fmt;
931 surface_desc.dwWidth = 640;
932 surface_desc.dwHeight = 480;
933 hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &ds, NULL);
934 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
935 if (FAILED(hr))
936 goto cleanup;
938 /* Using a different surface interface version still works */
939 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
940 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
941 refcount = IDirectDrawSurface4_Release(ds);
942 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
943 if (FAILED(hr))
944 goto cleanup;
946 /* Here too */
947 hr = IDirect3D3_CreateDevice(d3d, &IID_IDirect3DHALDevice, (IDirectDrawSurface4 *)surface3, &device, NULL);
948 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
949 if (FAILED(hr))
950 goto cleanup;
952 hr = IDirect3D3_CreateViewport(d3d, &viewport, NULL);
953 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
954 hr = IDirect3DDevice3_AddViewport(device, viewport);
955 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
956 memset(&vp, 0, sizeof(vp));
957 vp.dwSize = sizeof(vp);
958 vp.dwX = 0;
959 vp.dwY = 0;
960 vp.dwWidth = 640;
961 vp.dwHeight = 480;
962 vp.dvClipX = -1.0f;
963 vp.dvClipY = 1.0f;
964 vp.dvClipWidth = 2.0f;
965 vp.dvClipHeight = 2.0f;
966 vp.dvMinZ = 0.0f;
967 vp.dvMaxZ = 1.0f;
968 hr = IDirect3DViewport3_SetViewport2(viewport, &vp);
969 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
971 hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
972 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
973 color = get_surface_color(surface, 320, 240);
974 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
976 cleanup:
977 if (viewport)
979 IDirect3DDevice3_DeleteViewport(device, viewport);
980 IDirect3DViewport3_Release(viewport);
982 if (surface3) IDirectDrawSurface3_Release(surface3);
983 if (surface) IDirectDrawSurface4_Release(surface);
984 if (device) IDirect3DDevice3_Release(device);
985 if (d3d) IDirect3D3_Release(d3d);
986 if (ddraw) IDirectDraw4_Release(ddraw);
987 DestroyWindow(window);
990 static void test_coop_level_threaded(void)
992 struct create_window_thread_param p;
993 IDirectDraw4 *ddraw;
994 HRESULT hr;
996 if (!(ddraw = create_ddraw()))
998 skip("Failed to create a ddraw object, skipping test.\n");
999 return;
1001 create_window_thread(&p);
1003 hr = IDirectDraw4_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1004 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1006 IDirectDraw4_Release(ddraw);
1007 destroy_window_thread(&p);
1010 static IDirectDrawSurface4 *get_depth_stencil(IDirect3DDevice3 *device)
1012 IDirectDrawSurface4 *rt, *ret;
1013 DDSCAPS2 caps = {DDSCAPS_ZBUFFER, 0, 0, 0};
1014 HRESULT hr;
1016 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
1017 ok(SUCCEEDED(hr), "Failed to get the render target, hr %#x.\n", hr);
1018 hr = IDirectDrawSurface4_GetAttachedSurface(rt, &caps, &ret);
1019 ok(SUCCEEDED(hr) || hr == DDERR_NOTFOUND, "Failed to get the z buffer, hr %#x.\n", hr);
1020 IDirectDrawSurface4_Release(rt);
1021 return ret;
1024 static void test_depth_blit(void)
1026 static struct
1028 float x, y, z;
1029 DWORD color;
1031 quad1[] =
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;
1052 unsigned int i, j;
1053 D3DCOLOR color;
1054 HRESULT hr;
1055 IDirect3D3 *d3d;
1056 IDirectDraw4 *ddraw;
1057 DDBLTFX fx;
1058 HWND window;
1059 D3DRECT d3drect;
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);
1067 return;
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);
1124 /* Partial blit. */
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);
1134 /* Streched. */
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);
1139 /* Flipped. */
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,
1191 quad1, 4, 0);
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;
1226 HRESULT hr;
1227 DDCOLORKEY ckey;
1229 if (!(ddraw = create_ddraw()))
1231 skip("Failed to create ddraw object, skipping test.\n");
1232 return;
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;
1241 ddsd.dwWidth = 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);
1251 if (FAILED(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);
1258 return;
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;
1322 IDirect3D3 *d3d;
1323 HRESULT hr, old_d3d_ref;
1324 LONG ref;
1325 IDirect3DViewport *viewport;
1326 IDirect3DViewport2 *viewport2;
1327 IDirect3DViewport3 *viewport3;
1328 IDirectDrawGammaControl *gamma;
1329 IUnknown *unknown;
1331 if (!(ddraw = create_ddraw()))
1333 skip("Failed to create ddraw object, skipping test.\n");
1334 return;
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);
1338 if (FAILED(hr))
1340 skip("Direct3D not available, skipping tests\n");
1341 IDirectDraw4_Release(ddraw);
1342 return;
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);
1362 if (viewport)
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);
1369 viewport = NULL;
1372 hr = IDirect3DViewport3_QueryInterface(viewport3, &IID_IDirect3DViewport3, (void **)&viewport2);
1373 ok(SUCCEEDED(hr), "Failed to QI IDirect3DViewport3, hr %#x.\n", hr);
1374 if (viewport2)
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);
1385 if (unknown)
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);
1399 START_TEST(ddraw4)
1401 test_process_vertices();
1402 test_coop_level_create_device_window();
1403 test_clipper_blt();
1404 test_coop_level_d3d_state();
1405 test_surface_interface_mismatch();
1406 test_coop_level_threaded();
1407 test_depth_blit();
1408 test_texture_load_ckey();
1409 test_viewport_interfaces();