comctl32: Update thumb position on WM_MOUSEMOVE instead of deferring it.
[wine/multimedia.git] / dlls / ddraw / tests / ddraw2.c
blob69313646ed9726df9c31199976afdac86805e333
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 "d3d.h"
23 struct create_window_thread_param
25 HWND window;
26 HANDLE window_created;
27 HANDLE destroy_window;
28 HANDLE thread;
31 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
33 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
34 c1 >>= 8; c2 >>= 8;
35 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
36 c1 >>= 8; c2 >>= 8;
37 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
38 c1 >>= 8; c2 >>= 8;
39 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
40 return TRUE;
43 static DWORD WINAPI create_window_thread_proc(void *param)
45 struct create_window_thread_param *p = param;
46 DWORD res;
47 BOOL ret;
49 p->window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
50 0, 0, 640, 480, 0, 0, 0, 0);
51 ret = SetEvent(p->window_created);
52 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
54 for (;;)
56 MSG msg;
58 while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
59 DispatchMessage(&msg);
60 res = WaitForSingleObject(p->destroy_window, 100);
61 if (res == WAIT_OBJECT_0)
62 break;
63 if (res != WAIT_TIMEOUT)
65 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
66 break;
70 DestroyWindow(p->window);
72 return 0;
75 static void create_window_thread(struct create_window_thread_param *p)
77 DWORD res, tid;
79 p->window_created = CreateEvent(NULL, FALSE, FALSE, NULL);
80 ok(!!p->window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
81 p->destroy_window = CreateEvent(NULL, FALSE, FALSE, NULL);
82 ok(!!p->destroy_window, "CreateEvent failed, last error %#x.\n", GetLastError());
83 p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
84 ok(!!p->thread, "Failed to create thread, last error %#x.\n", GetLastError());
85 res = WaitForSingleObject(p->window_created, INFINITE);
86 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
89 static void destroy_window_thread(struct create_window_thread_param *p)
91 SetEvent(p->destroy_window);
92 WaitForSingleObject(p->thread, INFINITE);
93 CloseHandle(p->destroy_window);
94 CloseHandle(p->window_created);
95 CloseHandle(p->thread);
98 static IDirectDrawSurface *get_depth_stencil(IDirect3DDevice2 *device)
100 IDirectDrawSurface *rt, *ret;
101 DDSCAPS caps = {DDSCAPS_ZBUFFER};
102 HRESULT hr;
104 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
105 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
106 hr = IDirectDrawSurface_GetAttachedSurface(rt, &caps, &ret);
107 ok(SUCCEEDED(hr) || hr == DDERR_NOTFOUND, "Failed to get the z buffer, hr %#x.\n", hr);
108 IDirectDrawSurface_Release(rt);
109 return ret;
112 static D3DCOLOR get_surface_color(IDirectDrawSurface *surface, UINT x, UINT y)
114 RECT rect = {x, y, x + 1, y + 1};
115 DDSURFACEDESC surface_desc;
116 D3DCOLOR color;
117 HRESULT hr;
119 memset(&surface_desc, 0, sizeof(surface_desc));
120 surface_desc.dwSize = sizeof(surface_desc);
122 hr = IDirectDrawSurface_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
123 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
124 if (FAILED(hr))
125 return 0xdeadbeef;
127 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
129 hr = IDirectDrawSurface_Unlock(surface, NULL);
130 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
132 return color;
135 static HRESULT CALLBACK enum_z_fmt(GUID *guid, char *description, char *name,
136 D3DDEVICEDESC *hal_desc, D3DDEVICEDESC *hel_desc, void *ctx)
138 DWORD *z_depth = ctx;
140 if (!IsEqualGUID(&IID_IDirect3DHALDevice, guid))
141 return D3DENUMRET_OK;
143 if (hal_desc->dwDeviceZBufferBitDepth & DDBD_32)
144 *z_depth = 32;
145 else if (hal_desc->dwDeviceZBufferBitDepth & DDBD_24)
146 *z_depth = 24;
147 else if (hal_desc->dwDeviceZBufferBitDepth & DDBD_16)
148 *z_depth = 16;
150 return DDENUMRET_OK;
153 static IDirectDraw2 *create_ddraw(void)
155 IDirectDraw2 *ddraw2;
156 IDirectDraw *ddraw1;
157 HRESULT hr;
159 if (FAILED(DirectDrawCreate(NULL, &ddraw1, NULL)))
160 return NULL;
162 hr = IDirectDraw_QueryInterface(ddraw1, &IID_IDirectDraw2, (void **)&ddraw2);
163 IDirectDraw_Release(ddraw1);
164 if (FAILED(hr))
165 return NULL;
167 return ddraw2;
170 static IDirect3DDevice2 *create_device(IDirectDraw2 *ddraw, HWND window, DWORD coop_level)
172 IDirectDrawSurface *surface, *ds;
173 IDirect3DDevice2 *device = NULL;
174 DDSURFACEDESC surface_desc;
175 DWORD z_depth = 0;
176 IDirect3D2 *d3d;
177 HRESULT hr;
179 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, coop_level);
180 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
182 memset(&surface_desc, 0, sizeof(surface_desc));
183 surface_desc.dwSize = sizeof(surface_desc);
184 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
185 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
186 surface_desc.dwWidth = 640;
187 surface_desc.dwHeight = 480;
189 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
190 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
192 if (coop_level & DDSCL_NORMAL)
194 IDirectDrawClipper *clipper;
196 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
197 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
198 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
199 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
200 hr = IDirectDrawSurface_SetClipper(surface, clipper);
201 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\n", hr);
202 IDirectDrawClipper_Release(clipper);
205 hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d);
206 if (FAILED(hr))
208 IDirectDrawSurface_Release(surface);
209 return NULL;
212 hr = IDirect3D2_EnumDevices(d3d, enum_z_fmt, &z_depth);
213 ok(SUCCEEDED(hr), "Failed to enumerate z-formats, hr %#x.\n", hr);
214 if (FAILED(hr) || !z_depth)
216 IDirect3D2_Release(d3d);
217 IDirectDrawSurface_Release(surface);
218 return NULL;
221 memset(&surface_desc, 0, sizeof(surface_desc));
222 surface_desc.dwSize = sizeof(surface_desc);
223 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
224 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
225 U2(surface_desc).dwZBufferBitDepth = z_depth;
226 surface_desc.dwWidth = 640;
227 surface_desc.dwHeight = 480;
228 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &ds, NULL);
229 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
230 if (FAILED(hr))
232 IDirect3D2_Release(d3d);
233 IDirectDrawSurface_Release(surface);
234 return NULL;
237 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
238 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
239 IDirectDrawSurface_Release(ds);
240 if (FAILED(hr))
242 IDirect3D2_Release(d3d);
243 IDirectDrawSurface_Release(surface);
244 return NULL;
247 hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, surface, &device);
248 IDirect3D2_Release(d3d);
249 IDirectDrawSurface_Release(surface);
250 if (FAILED(hr))
251 return NULL;
253 return device;
256 static HRESULT CALLBACK restore_callback(IDirectDrawSurface *surface, DDSURFACEDESC *desc, void *context)
258 HRESULT hr = IDirectDrawSurface_Restore(surface);
259 ok(SUCCEEDED(hr), "Failed to restore surface, hr %#x.\n", hr);
260 IDirectDrawSurface_Release(surface);
262 return DDENUMRET_OK;
265 static HRESULT restore_surfaces(IDirectDraw2 *ddraw)
267 return IDirectDraw2_EnumSurfaces(ddraw, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST,
268 NULL, NULL, restore_callback);
271 static void test_coop_level_create_device_window(void)
273 HWND focus_window, device_window;
274 IDirectDraw2 *ddraw;
275 HRESULT hr;
277 focus_window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
278 0, 0, 640, 480, 0, 0, 0, 0);
279 if (!(ddraw = create_ddraw()))
281 skip("Failed to create a ddraw object, skipping test.\n");
282 DestroyWindow(focus_window);
283 return;
286 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
287 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
288 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
289 ok(!device_window, "Unexpected device window found.\n");
290 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
291 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
292 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
293 ok(!device_window, "Unexpected device window found.\n");
294 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
295 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
296 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
297 ok(!device_window, "Unexpected device window found.\n");
298 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
299 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
300 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
301 ok(!device_window, "Unexpected device window found.\n");
302 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
303 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
304 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
305 ok(!device_window, "Unexpected device window found.\n");
307 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
308 if (broken(hr == DDERR_INVALIDPARAMS))
310 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
311 IDirectDraw2_Release(ddraw);
312 DestroyWindow(focus_window);
313 return;
316 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
317 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
318 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
319 ok(!device_window, "Unexpected device window found.\n");
320 hr = IDirectDraw2_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
321 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
322 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
323 ok(!device_window, "Unexpected device window found.\n");
325 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
326 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
327 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
328 ok(!device_window, "Unexpected device window found.\n");
329 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
330 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
331 ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
332 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
333 ok(!!device_window, "Device window not found.\n");
335 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
336 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
337 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
338 ok(!device_window, "Unexpected device window found.\n");
339 hr = IDirectDraw2_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
340 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
341 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
342 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
343 ok(!!device_window, "Device window not found.\n");
345 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
346 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
347 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
348 ok(!device_window, "Unexpected device window found.\n");
349 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
350 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
351 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
352 ok(!device_window, "Unexpected device window found.\n");
353 hr = IDirectDraw2_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
354 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
355 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
356 ok(!device_window, "Unexpected device window found.\n");
357 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
358 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
359 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
360 ok(!!device_window, "Device window not found.\n");
362 IDirectDraw2_Release(ddraw);
363 DestroyWindow(focus_window);
366 static void test_clipper_blt(void)
368 IDirectDrawSurface *src_surface, *dst_surface;
369 RECT client_rect, src_rect, *rect;
370 IDirectDrawClipper *clipper;
371 DDSURFACEDESC surface_desc;
372 unsigned int i, j, x, y;
373 IDirectDraw2 *ddraw;
374 RGNDATA *rgn_data;
375 D3DCOLOR color;
376 HRGN r1, r2;
377 HWND window;
378 DDBLTFX fx;
379 HRESULT hr;
380 DWORD *ptr;
381 DWORD ret;
383 static const DWORD src_data[] =
385 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
386 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
387 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
389 static const D3DCOLOR expected1[] =
391 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
392 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
393 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
394 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
396 static const D3DCOLOR expected2[] =
398 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
399 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
400 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
401 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
404 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
405 10, 10, 640, 480, 0, 0, 0, 0);
406 ShowWindow(window, SW_SHOW);
407 if (!(ddraw = create_ddraw()))
409 skip("Failed to create a ddraw object, skipping test.\n");
410 DestroyWindow(window);
411 return;
414 ret = GetClientRect(window, &client_rect);
415 ok(ret, "Failed to get client rect.\n");
416 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
417 ok(ret, "Failed to map client rect.\n");
419 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
420 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
422 hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL);
423 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
424 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
425 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
426 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
427 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
428 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
429 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
430 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
431 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
432 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
433 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
434 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
435 ok(rgn_data->rdh.nCount == 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
436 ok(rgn_data->rdh.nRgnSize == 16 || broken(rgn_data->rdh.nRgnSize == 168 /* NT4 */),
437 "Got unexpected region size %u.\n", rgn_data->rdh.nRgnSize);
438 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
439 "Got unexpected bounding rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
440 rgn_data->rdh.rcBound.left, rgn_data->rdh.rcBound.top,
441 rgn_data->rdh.rcBound.right, rgn_data->rdh.rcBound.bottom,
442 client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
443 rect = (RECT *)&rgn_data->Buffer[0];
444 ok(EqualRect(rect, &client_rect),
445 "Got unexpected clip rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
446 rect->left, rect->top, rect->right, rect->bottom,
447 client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
448 HeapFree(GetProcessHeap(), 0, rgn_data);
450 r1 = CreateRectRgn(0, 0, 320, 240);
451 ok(!!r1, "Failed to create region.\n");
452 r2 = CreateRectRgn(320, 240, 640, 480);
453 ok(!!r2, "Failed to create region.\n");
454 CombineRgn(r1, r1, r2, RGN_OR);
455 ret = GetRegionData(r1, 0, NULL);
456 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
457 ret = GetRegionData(r1, ret, rgn_data);
458 ok(!!ret, "Failed to get region data.\n");
460 DeleteObject(r2);
461 DeleteObject(r1);
463 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
464 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
465 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
466 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
467 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
468 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
470 HeapFree(GetProcessHeap(), 0, rgn_data);
472 memset(&surface_desc, 0, sizeof(surface_desc));
473 surface_desc.dwSize = sizeof(surface_desc);
474 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
475 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
476 surface_desc.dwWidth = 640;
477 surface_desc.dwHeight = 480;
478 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
479 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
480 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
481 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
482 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
483 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
485 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
486 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
487 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
488 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
490 memset(&fx, 0, sizeof(fx));
491 fx.dwSize = sizeof(fx);
492 hr = IDirectDrawSurface_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
493 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
494 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
495 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
497 hr = IDirectDrawSurface_Lock(src_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
498 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
499 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
500 ptr = surface_desc.lpSurface;
501 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
502 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
503 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
504 hr = IDirectDrawSurface_Unlock(src_surface, NULL);
505 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
507 hr = IDirectDrawSurface_SetClipper(dst_surface, clipper);
508 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
510 SetRect(&src_rect, 1, 1, 5, 2);
511 hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
512 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
513 for (i = 0; i < 4; ++i)
515 for (j = 0; j < 4; ++j)
517 x = 80 * ((2 * j) + 1);
518 y = 60 * ((2 * i) + 1);
519 color = get_surface_color(dst_surface, x, y);
520 ok(compare_color(color, expected1[i * 4 + j], 1),
521 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
525 U5(fx).dwFillColor = 0xff0000ff;
526 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
527 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
528 for (i = 0; i < 4; ++i)
530 for (j = 0; j < 4; ++j)
532 x = 80 * ((2 * j) + 1);
533 y = 60 * ((2 * i) + 1);
534 color = get_surface_color(dst_surface, x, y);
535 ok(compare_color(color, expected2[i * 4 + j], 1),
536 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
540 hr = IDirectDrawSurface_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
541 ok(hr == DDERR_BLTFASTCANTCLIP || broken(hr == E_NOTIMPL /* NT4 */), "Got unexpected hr %#x.\n", hr);
543 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
544 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
545 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
546 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
547 DestroyWindow(window);
548 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
549 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
550 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
551 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
552 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
553 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
554 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
555 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
556 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
557 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
558 hr = IDirectDrawSurface_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
559 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
561 IDirectDrawSurface_Release(dst_surface);
562 IDirectDrawSurface_Release(src_surface);
563 IDirectDrawClipper_Release(clipper);
564 IDirectDraw2_Release(ddraw);
567 static void test_coop_level_d3d_state(void)
569 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
570 D3DMATERIALHANDLE background_handle;
571 IDirectDrawSurface *rt, *surface;
572 IDirect3DMaterial2 *background;
573 IDirect3DViewport2 *viewport;
574 IDirect3DDevice2 *device;
575 D3DMATERIAL material;
576 IDirectDraw2 *ddraw;
577 D3DVIEWPORT2 vp;
578 IDirect3D2 *d3d;
579 D3DCOLOR color;
580 DWORD value;
581 HWND window;
582 HRESULT hr;
584 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
585 0, 0, 640, 480, 0, 0, 0, 0);
586 if (!(ddraw = create_ddraw()))
588 skip("Failed to create ddraw object, skipping test.\n");
589 DestroyWindow(window);
590 return;
592 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
594 skip("Failed to create D3D device, skipping test.\n");
595 IDirectDraw2_Release(ddraw);
596 DestroyWindow(window);
597 return;
600 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
601 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
602 hr = IDirect3D2_CreateViewport(d3d, &viewport, NULL);
603 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
604 hr = IDirect3D2_CreateMaterial(d3d, &background, NULL);
605 ok(SUCCEEDED(hr), "Failed to create material, hr %#x.\n", hr);
606 IDirect3D2_Release(d3d);
608 hr = IDirect3DDevice2_AddViewport(device, viewport);
609 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
610 memset(&vp, 0, sizeof(vp));
611 vp.dwSize = sizeof(vp);
612 vp.dwX = 0;
613 vp.dwY = 0;
614 vp.dwWidth = 640;
615 vp.dwHeight = 480;
616 vp.dvClipX = -1.0f;
617 vp.dvClipY = 1.0f;
618 vp.dvClipWidth = 2.0f;
619 vp.dvClipHeight = 2.0f;
620 vp.dvMinZ = 0.0f;
621 vp.dvMaxZ = 1.0f;
622 hr = IDirect3DViewport2_SetViewport2(viewport, &vp);
623 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
625 memset(&material, 0, sizeof(material));
626 material.dwSize = sizeof(material);
627 U1(U(material).diffuse).r = 1.0f;
628 U2(U(material).diffuse).g = 0.0f;
629 U3(U(material).diffuse).b = 0.0f;
630 U4(U(material).diffuse).a = 1.0f;
631 hr = IDirect3DMaterial2_SetMaterial(background, &material);
632 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
633 hr = IDirect3DMaterial2_GetHandle(background, device, &background_handle);
634 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
635 hr = IDirect3DViewport2_SetBackground(viewport, background_handle);
636 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
638 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
639 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
640 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
641 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
642 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
643 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
644 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
645 ok(!value, "Got unexpected alpha blend enable state %#x.\n", value);
646 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
647 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
648 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
649 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
650 color = get_surface_color(rt, 320, 240);
651 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
653 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
654 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
655 hr = IDirectDrawSurface_IsLost(rt);
656 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
657 hr = restore_surfaces(ddraw);
658 ok(SUCCEEDED(hr), "Failed to restore surfaces, hr %#x.\n", hr);
660 memset(&material, 0, sizeof(material));
661 material.dwSize = sizeof(material);
662 U1(U(material).diffuse).r = 0.0f;
663 U2(U(material).diffuse).g = 1.0f;
664 U3(U(material).diffuse).b = 0.0f;
665 U4(U(material).diffuse).a = 1.0f;
666 hr = IDirect3DMaterial2_SetMaterial(background, &material);
667 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
669 hr = IDirect3DDevice2_GetRenderTarget(device, &surface);
670 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
671 ok(surface == rt, "Got unexpected surface %p.\n", surface);
672 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
673 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
674 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
675 hr = IDirect3DDevice2_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
676 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
677 ok(!!value, "Got unexpected alpha blend enable state %#x.\n", value);
678 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
679 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
680 color = get_surface_color(rt, 320, 240);
681 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
683 hr = IDirect3DDevice2_DeleteViewport(device, viewport);
684 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
685 IDirect3DMaterial2_Release(background);
686 IDirect3DViewport2_Release(viewport);
687 IDirectDrawSurface_Release(surface);
688 IDirectDrawSurface_Release(rt);
689 IDirect3DDevice2_Release(device);
690 IDirectDraw2_Release(ddraw);
691 DestroyWindow(window);
694 static void test_surface_interface_mismatch(void)
696 IDirectDraw2 *ddraw = NULL;
697 IDirect3D2 *d3d = NULL;
698 IDirectDrawSurface *surface = NULL, *ds;
699 IDirectDrawSurface3 *surface3 = NULL;
700 IDirect3DDevice2 *device = NULL;
701 IDirect3DViewport2 *viewport = NULL;
702 IDirect3DMaterial2 *background = NULL;
703 DDSURFACEDESC surface_desc;
704 DWORD z_depth = 0;
705 ULONG refcount;
706 HRESULT hr;
707 D3DCOLOR color;
708 HWND window;
709 D3DVIEWPORT2 vp;
710 D3DMATERIAL material;
711 D3DMATERIALHANDLE background_handle;
712 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
714 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
715 0, 0, 640, 480, 0, 0, 0, 0);
717 if (!(ddraw = create_ddraw()))
719 skip("Failed to create a ddraw object, skipping test.\n");
720 goto cleanup;
723 hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
724 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
726 memset(&surface_desc, 0, sizeof(surface_desc));
727 surface_desc.dwSize = sizeof(surface_desc);
728 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
729 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
730 surface_desc.dwWidth = 640;
731 surface_desc.dwHeight = 480;
733 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
734 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
736 hr = IDirectDrawSurface2_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
737 if (FAILED(hr))
739 skip("Failed to get the IDirectDrawSurface3 interface, skipping test.\n");
740 goto cleanup;
743 hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d);
744 if (FAILED(hr))
746 skip("Failed to get the IDirect3D2 interface, skipping test.\n");
747 goto cleanup;
750 hr = IDirect3D2_EnumDevices(d3d, enum_z_fmt, &z_depth);
751 if (FAILED(hr) || !z_depth)
753 skip("No depth buffer formats available, skipping test.\n");
754 goto cleanup;
757 memset(&surface_desc, 0, sizeof(surface_desc));
758 surface_desc.dwSize = sizeof(surface_desc);
759 surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
760 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
761 U2(surface_desc).dwZBufferBitDepth = z_depth;
762 surface_desc.dwWidth = 640;
763 surface_desc.dwHeight = 480;
764 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &ds, NULL);
765 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
766 if (FAILED(hr))
767 goto cleanup;
769 /* Using a different surface interface version still works */
770 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
771 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
772 refcount = IDirectDrawSurface_Release(ds);
773 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
774 if (FAILED(hr))
775 goto cleanup;
777 /* Here too */
778 hr = IDirect3D2_CreateDevice(d3d, &IID_IDirect3DHALDevice, (IDirectDrawSurface *)surface3, &device);
779 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
780 if (FAILED(hr))
781 goto cleanup;
783 hr = IDirect3D2_CreateViewport(d3d, &viewport, NULL);
784 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
785 hr = IDirect3D2_CreateMaterial(d3d, &background, NULL);
786 ok(SUCCEEDED(hr), "Failed to create material, hr %#x.\n", hr);
788 hr = IDirect3DDevice2_AddViewport(device, viewport);
789 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
790 memset(&vp, 0, sizeof(vp));
791 vp.dwSize = sizeof(vp);
792 vp.dwX = 0;
793 vp.dwY = 0;
794 vp.dwWidth = 640;
795 vp.dwHeight = 480;
796 vp.dvClipX = -1.0f;
797 vp.dvClipY = 1.0f;
798 vp.dvClipWidth = 2.0f;
799 vp.dvClipHeight = 2.0f;
800 vp.dvMinZ = 0.0f;
801 vp.dvMaxZ = 1.0f;
802 hr = IDirect3DViewport2_SetViewport2(viewport, &vp);
803 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
805 memset(&material, 0, sizeof(material));
806 material.dwSize = sizeof(material);
807 U1(U(material).diffuse).r = 1.0f;
808 U2(U(material).diffuse).g = 0.0f;
809 U3(U(material).diffuse).b = 0.0f;
810 U4(U(material).diffuse).a = 1.0f;
811 hr = IDirect3DMaterial2_SetMaterial(background, &material);
812 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
813 hr = IDirect3DMaterial2_GetHandle(background, device, &background_handle);
814 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
815 hr = IDirect3DViewport2_SetBackground(viewport, background_handle);
816 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
818 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
819 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
820 color = get_surface_color(surface, 320, 240);
821 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
823 cleanup:
824 if (viewport)
826 IDirect3DDevice2_DeleteViewport(device, viewport);
827 IDirect3DViewport2_Release(viewport);
829 if (background) IDirect3DMaterial2_Release(background);
830 if (surface3) IDirectDrawSurface3_Release(surface3);
831 if (surface) IDirectDrawSurface_Release(surface);
832 if (device) IDirect3DDevice2_Release(device);
833 if (d3d) IDirect3D2_Release(d3d);
834 if (ddraw) IDirectDraw2_Release(ddraw);
835 DestroyWindow(window);
838 static void test_coop_level_threaded(void)
840 struct create_window_thread_param p;
841 IDirectDraw2 *ddraw;
842 HRESULT hr;
844 if (!(ddraw = create_ddraw()))
846 skip("Failed to create a ddraw object, skipping test.\n");
847 return;
849 create_window_thread(&p);
851 hr = IDirectDraw2_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
852 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
854 IDirectDraw2_Release(ddraw);
855 destroy_window_thread(&p);
858 static void test_depth_blit(void)
860 static D3DLVERTEX quad1[] =
862 {{-1.0}, { 1.0}, {0.50f}, 0, {0xff00ff00}},
863 {{ 1.0}, { 1.0}, {0.50f}, 0, {0xff00ff00}},
864 {{-1.0}, {-1.0}, {0.50f}, 0, {0xff00ff00}},
865 {{ 1.0}, {-1.0}, {0.50f}, 0, {0xff00ff00}},
867 static const D3DCOLOR expected_colors[4][4] =
869 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
870 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
871 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
872 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
874 static const BOOL todo[4][4] =
876 {FALSE, FALSE, TRUE, TRUE},
877 {FALSE, FALSE, TRUE, TRUE},
878 {TRUE, TRUE, TRUE, TRUE},
879 {TRUE, TRUE, TRUE, TRUE},
881 DDSURFACEDESC ddsd_new, ddsd_existing;
883 IDirect3DDevice2 *device;
884 IDirectDrawSurface *ds1, *ds2, *ds3, *rt;
885 IDirect3DViewport2 *viewport;
886 D3DVIEWPORT2 vp_data;
887 RECT src_rect, dst_rect;
888 unsigned int i, j;
889 D3DCOLOR color;
890 HRESULT hr;
891 IDirect3D2 *d3d;
892 IDirectDraw2 *ddraw;
893 DDBLTFX fx;
894 HWND window;
895 D3DRECT d3drect;
896 IDirect3DMaterial2 *background;
897 D3DMATERIALHANDLE background_handle;
898 D3DMATERIAL material;
900 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
901 0, 0, 640, 480, 0, 0, 0, 0);
902 if (!(ddraw = create_ddraw()))
904 skip("Failed to create ddraw object, skipping test.\n");
905 DestroyWindow(window);
906 return;
908 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
910 skip("Failed to create D3D device, skipping test.\n");
911 IDirectDraw2_Release(ddraw);
912 DestroyWindow(window);
913 return;
916 hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d);
917 ok(SUCCEEDED(hr), "Failed to get Direct3D2 interface, hr %#x.\n", hr);
918 hr = IDirect3D2_CreateViewport(d3d, &viewport, NULL);
919 ok(SUCCEEDED(hr), "Failed to create a viewport, hr %#x.\n", hr);
920 hr = IDirect3D2_CreateMaterial(d3d, &background, NULL);
921 ok(SUCCEEDED(hr), "Failed to create a material, hr %#x.\n", hr);
923 ds1 = get_depth_stencil(device);
925 memset(&ddsd_new, 0, sizeof(ddsd_new));
926 ddsd_new.dwSize = sizeof(ddsd_new);
927 memset(&ddsd_existing, 0, sizeof(ddsd_existing));
928 ddsd_existing.dwSize = sizeof(ddsd_existing);
929 hr = IDirectDrawSurface_GetSurfaceDesc(ds1, &ddsd_existing);
930 ddsd_new.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
931 ddsd_new.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
932 ddsd_new.dwWidth = ddsd_existing.dwWidth;
933 ddsd_new.dwHeight = ddsd_existing.dwHeight;
934 ddsd_new.ddpfPixelFormat = ddsd_existing.ddpfPixelFormat;
935 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd_new, &ds2, NULL);
936 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
937 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd_new, &ds3, NULL);
938 ok(SUCCEEDED(hr), "Failed to create a surface, hr %#x.\n", hr);
940 hr = IDirect3DDevice2_AddViewport(device, viewport);
941 ok(SUCCEEDED(hr), "Failed to add viewport to device, hr %#x.\n", hr);
942 memset(&vp_data, 0, sizeof(vp_data));
943 vp_data.dwSize = sizeof(vp_data);
944 vp_data.dwWidth = ddsd_existing.dwWidth;
945 vp_data.dwHeight = ddsd_existing.dwHeight;
946 vp_data.dvMaxZ = 1.0;
947 vp_data.dvClipX = -1.0f;
948 vp_data.dvClipWidth = 2.0f;
949 vp_data.dvClipY = 1.0f;
950 vp_data.dvClipHeight = 2.0f;
951 hr = IDirect3DViewport2_SetViewport2(viewport, &vp_data);
952 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
953 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
954 ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
956 memset(&material, 0, sizeof(material));
957 material.dwSize = sizeof(material);
958 U1(U(material).diffuse).r = 1.0f;
959 U2(U(material).diffuse).g = 0.0f;
960 U3(U(material).diffuse).b = 0.0f;
961 U4(U(material).diffuse).a = 1.0f;
962 hr = IDirect3DMaterial2_SetMaterial(background, &material);
963 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
964 hr = IDirect3DMaterial2_GetHandle(background, device, &background_handle);
965 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
966 hr = IDirect3DViewport2_SetBackground(viewport, background_handle);
967 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
969 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
970 ok(SUCCEEDED(hr), "Failed to enable z testing, hr %#x.\n", hr);
971 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
972 ok(SUCCEEDED(hr), "Failed to set the z function, hr %#x.\n", hr);
974 U1(d3drect).x1 = U2(d3drect).y1 = 0;
975 U3(d3drect).x2 = vp_data.dwWidth; U4(d3drect).y2 = vp_data.dwHeight;
976 hr = IDirect3DViewport2_Clear(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER);
977 ok(SUCCEEDED(hr), "Failed to clear the z buffer, hr %#x.\n", hr);
979 /* Partial blit. */
980 SetRect(&src_rect, 0, 0, 320, 240);
981 SetRect(&dst_rect, 0, 0, 320, 240);
982 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
983 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
984 /* Different locations. */
985 SetRect(&src_rect, 0, 0, 320, 240);
986 SetRect(&dst_rect, 320, 240, 640, 480);
987 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
988 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
989 /* Streched. */
990 SetRect(&src_rect, 0, 0, 320, 240);
991 SetRect(&dst_rect, 0, 0, 640, 480);
992 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
993 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
994 /* Flipped. */
995 SetRect(&src_rect, 0, 480, 640, 0);
996 SetRect(&dst_rect, 0, 0, 640, 480);
997 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
998 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
999 SetRect(&src_rect, 0, 0, 640, 480);
1000 SetRect(&dst_rect, 0, 480, 640, 0);
1001 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1002 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1003 /* Full, explicit. */
1004 SetRect(&src_rect, 0, 0, 640, 480);
1005 SetRect(&dst_rect, 0, 0, 640, 480);
1006 hr = IDirectDrawSurface_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1007 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1008 /* Depth -> color blit: Succeeds on Win7 + Radeon HD 5700, fails on WinXP + Radeon X1600 */
1010 /* Depth blit inside a BeginScene / EndScene pair */
1011 hr = IDirect3DDevice2_BeginScene(device);
1012 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
1013 /* From the current depth stencil */
1014 hr = IDirectDrawSurface_Blt(ds2, NULL, ds1, NULL, DDBLT_WAIT, NULL);
1015 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1016 /* To the current depth stencil */
1017 hr = IDirectDrawSurface_Blt(ds1, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1018 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1019 /* Between unbound surfaces */
1020 hr = IDirectDrawSurface_Blt(ds3, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1021 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1022 hr = IDirect3DDevice2_EndScene(device);
1023 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1025 /* Avoid changing the depth stencil, it doesn't work properly on Windows.
1026 * Instead use DDBLT_DEPTHFILL to clear the depth stencil. Unfortunately
1027 * drivers disagree on the meaning of dwFillDepth. Only 0 seems to produce
1028 * a reliable result(z = 0.0) */
1029 memset(&fx, 0, sizeof(fx));
1030 fx.dwSize = sizeof(fx);
1031 U5(fx).dwFillDepth = 0;
1032 hr = IDirectDrawSurface_Blt(ds2, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
1033 ok(SUCCEEDED(hr), "Failed to clear the source z buffer, hr %#x.\n", hr);
1035 /* This clears the Z buffer with 1.0 */
1036 hr = IDirect3DViewport2_Clear(viewport, 1, &d3drect, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET);
1037 ok(SUCCEEDED(hr), "Failed to clear the color and z buffers, hr %#x.\n", hr);
1039 SetRect(&dst_rect, 0, 0, 320, 240);
1040 hr = IDirectDrawSurface_Blt(ds1, &dst_rect, ds2, NULL, DDBLT_WAIT, NULL);
1041 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1042 IDirectDrawSurface_Release(ds3);
1043 IDirectDrawSurface_Release(ds2);
1044 IDirectDrawSurface_Release(ds1);
1046 hr = IDirect3DDevice2_BeginScene(device);
1047 ok(SUCCEEDED(hr), "Failed to start a scene, hr %#x.\n", hr);
1048 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad1, 4, 0);
1049 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1050 hr = IDirect3DDevice2_EndScene(device);
1051 ok(SUCCEEDED(hr), "Failed to end a scene, hr %#x.\n", hr);
1053 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1054 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1055 for (i = 0; i < 4; ++i)
1057 for (j = 0; j < 4; ++j)
1059 unsigned int x = 80 * ((2 * j) + 1);
1060 unsigned int y = 60 * ((2 * i) + 1);
1061 color = get_surface_color(rt, x, y);
1062 if (todo[i][j])
1063 todo_wine ok(compare_color(color, expected_colors[i][j], 1),
1064 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
1065 else
1066 ok(compare_color(color, expected_colors[i][j], 1),
1067 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
1070 IDirectDrawSurface_Release(rt);
1072 hr = IDirect3DDevice2_DeleteViewport(device, viewport);
1073 ok(SUCCEEDED(hr), "Failed to delete viewport from device, hr %#x.\n", hr);
1074 IDirect3DMaterial2_Release(background);
1075 IDirect3DViewport2_Release(viewport);
1076 IDirect3D2_Release(d3d);
1077 IDirect3DDevice2_Release(device);
1078 IDirectDraw2_Release(ddraw);
1079 DestroyWindow(window);
1082 static void test_texture_load_ckey(void)
1084 IDirectDraw2 *ddraw = NULL;
1085 IDirectDrawSurface *src = NULL;
1086 IDirectDrawSurface *dst = NULL;
1087 IDirect3DTexture *src_tex = NULL;
1088 IDirect3DTexture *dst_tex = NULL;
1089 DDSURFACEDESC ddsd;
1090 HRESULT hr;
1091 DDCOLORKEY ckey;
1093 if (!(ddraw = create_ddraw()))
1095 skip("Failed to create ddraw object, skipping test.\n");
1096 return;
1098 hr = IDirectDraw2_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
1099 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1101 memset(&ddsd, 0, sizeof(ddsd));
1102 ddsd.dwSize = sizeof(ddsd);
1103 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
1104 ddsd.dwHeight = 128;
1105 ddsd.dwWidth = 128;
1106 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
1107 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &src, NULL);
1108 ok(SUCCEEDED(hr), "Failed to create source texture, hr %#x.\n", hr);
1109 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1110 hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &dst, NULL);
1111 ok(SUCCEEDED(hr), "Failed to create destination texture, hr %#x.\n", hr);
1113 hr = IDirectDrawSurface_QueryInterface(src, &IID_IDirect3DTexture, (void **)&src_tex);
1114 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get Direct3DTexture interface, hr %#x.\n", hr);
1115 if (FAILED(hr))
1117 /* 64 bit ddraw does not support d3d */
1118 skip("Could not get Direct3DTexture interface, skipping texture::Load color keying tests.\n");
1119 goto done;
1121 hr = IDirectDrawSurface_QueryInterface(dst, &IID_IDirect3DTexture, (void **)&dst_tex);
1122 ok(SUCCEEDED(hr), "Failed to get Direct3DTexture interface, hr %#x.\n", hr);
1124 /* No surface has a color key */
1125 hr = IDirect3DTexture_Load(dst_tex, src_tex);
1126 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDCAPS), "Got unexpected hr %#x.\n", hr);
1127 if (FAILED(hr))
1129 /* Testbot Windows NT VMs */
1130 skip("IDirect3DTexture::Load does not work, skipping color keying tests.\n");
1131 goto done;
1134 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0xdeadbeef;
1135 hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1136 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1137 ok(ckey.dwColorSpaceLowValue == 0xdeadbeef, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1138 ok(ckey.dwColorSpaceHighValue == 0xdeadbeef, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1140 /* Source surface has a color key */
1141 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
1142 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
1143 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1144 hr = IDirect3DTexture_Load(dst_tex, src_tex);
1145 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1146 hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1147 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1148 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1149 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1151 /* Both surfaces have a color key: Dest ckey is overwritten */
1152 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x000000ff;
1153 hr = IDirectDrawSurface_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1154 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1155 hr = IDirect3DTexture_Load(dst_tex, src_tex);
1156 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1157 hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1158 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1159 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1160 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1162 /* Only the destination has a color key: It is not deleted */
1163 hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, NULL);
1164 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1165 hr = IDirectDrawSurface_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
1166 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1167 hr = IDirect3DTexture_Load(dst_tex, src_tex);
1168 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1169 hr = IDirectDrawSurface_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1170 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1171 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1172 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1174 done:
1175 if (dst_tex) IDirect3DTexture_Release(dst_tex);
1176 if (src_tex) IDirect3DTexture_Release(src_tex);
1177 if (dst) IDirectDrawSurface_Release(dst);
1178 if (src) IDirectDrawSurface_Release(src);
1179 if (ddraw) IDirectDraw2_Release(ddraw);
1182 static ULONG get_refcount(IUnknown *test_iface)
1184 IUnknown_AddRef(test_iface);
1185 return IUnknown_Release(test_iface);
1188 static void test_viewport_interfaces(void)
1190 IDirectDraw2 *ddraw;
1191 IDirect3D2 *d3d;
1192 HRESULT hr;
1193 ULONG ref, old_d3d_ref;
1194 IDirect3DViewport *viewport;
1195 IDirect3DViewport2 *viewport2;
1196 IDirect3DViewport3 *viewport3;
1197 IDirectDrawGammaControl *gamma;
1198 IUnknown *unknown;
1200 if (!(ddraw = create_ddraw()))
1202 skip("Failed to create ddraw object, skipping test.\n");
1203 return;
1206 hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d);
1207 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to get d3d interface, hr %#x.\n", hr);
1208 if (FAILED(hr))
1210 skip("Direct3D not available, skipping tests\n");
1211 IDirectDraw2_Release(ddraw);
1212 return;
1214 old_d3d_ref = get_refcount((IUnknown *)d3d);
1216 hr = IDirect3D2_CreateViewport(d3d, &viewport2, NULL);
1217 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1218 ref = get_refcount((IUnknown *)viewport2);
1219 ok(ref == 1, "Initial IDirect3DViewport2 refcount is %u\n", ref);
1220 ref = get_refcount((IUnknown *)d3d);
1221 ok(ref == old_d3d_ref, "IDirect3D2 refcount is %u\n", ref);
1223 gamma = (IDirectDrawGammaControl *)0xdeadbeef;
1224 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IDirectDrawGammaControl, (void **)&gamma);
1225 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
1226 ok(gamma == NULL, "Interface not set to NULL by failed QI call: %p\n", gamma);
1227 if (SUCCEEDED(hr)) IDirectDrawGammaControl_Release(gamma);
1228 /* NULL iid: Segfaults */
1230 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IDirect3DViewport, (void **)&viewport);
1231 ok(SUCCEEDED(hr), "Failed to QI IDirect3DViewport, hr %#x.\n", hr);
1232 if (viewport)
1234 ref = get_refcount((IUnknown *)viewport);
1235 ok(ref == 2, "IDirect3DViewport refcount is %u\n", ref);
1236 ref = get_refcount((IUnknown *)viewport2);
1237 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
1238 IDirect3DViewport_Release(viewport);
1239 viewport = NULL;
1242 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IDirect3DViewport3, (void **)&viewport3);
1243 ok(SUCCEEDED(hr) || hr == E_NOINTERFACE, "Failed to QI IDirect3DViewport3, hr %#x.\n", hr);
1244 if (viewport3)
1246 ref = get_refcount((IUnknown *)viewport2);
1247 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
1248 ref = get_refcount((IUnknown *)viewport3);
1249 ok(ref == 2, "IDirect3DViewport3 refcount is %u\n", ref);
1250 IDirect3DViewport3_Release(viewport3);
1253 hr = IDirect3DViewport2_QueryInterface(viewport2, &IID_IUnknown, (void **)&unknown);
1254 ok(SUCCEEDED(hr), "Failed to QI IUnknown, hr %#x.\n", hr);
1255 if (unknown)
1257 ref = get_refcount((IUnknown *)viewport2);
1258 ok(ref == 2, "IDirect3DViewport2 refcount is %u\n", ref);
1259 ref = get_refcount(unknown);
1260 ok(ref == 2, "IUnknown refcount is %u\n", ref);
1261 IUnknown_Release(unknown);
1264 IDirect3DViewport2_Release(viewport2);
1265 IDirect3D2_Release(d3d);
1266 IDirectDraw2_Release(ddraw);
1269 static void test_zenable(void)
1271 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1272 static D3DTLVERTEX tquad[] =
1274 {{ 0.0f}, {480.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1275 {{ 0.0f}, { 0.0f}, {-0.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1276 {{640.0f}, {480.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1277 {{640.0f}, { 0.0f}, { 1.5f}, {1.0f}, {0xff00ff00}, {0x00000000}, {0.0f}, {0.0f}},
1279 D3DMATERIALHANDLE background_handle;
1280 IDirect3DMaterial2 *background;
1281 IDirect3DViewport2 *viewport;
1282 IDirect3DDevice2 *device;
1283 IDirectDrawSurface *rt;
1284 D3DMATERIAL material;
1285 IDirectDraw2 *ddraw;
1286 D3DVIEWPORT2 vp;
1287 IDirect3D2 *d3d;
1288 D3DCOLOR color;
1289 HWND window;
1290 HRESULT hr;
1291 UINT x, y;
1292 UINT i, j;
1294 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1295 0, 0, 640, 480, 0, 0, 0, 0);
1296 if (!(ddraw = create_ddraw()))
1298 skip("Failed to create ddraw object, skipping test.\n");
1299 DestroyWindow(window);
1300 return;
1302 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1304 skip("Failed to create D3D device, skipping test.\n");
1305 IDirectDraw2_Release(ddraw);
1306 DestroyWindow(window);
1307 return;
1310 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
1311 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1312 hr = IDirect3D2_CreateMaterial(d3d, &background, NULL);
1313 ok(SUCCEEDED(hr), "Failed to create material, hr %#x.\n", hr);
1314 hr = IDirect3D2_CreateViewport(d3d, &viewport, NULL);
1315 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1317 hr = IDirect3DDevice2_AddViewport(device, viewport);
1318 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
1319 memset(&vp, 0, sizeof(vp));
1320 vp.dwSize = sizeof(vp);
1321 vp.dwX = 0;
1322 vp.dwY = 0;
1323 vp.dwWidth = 640;
1324 vp.dwHeight = 480;
1325 vp.dvClipX = -1.0f;
1326 vp.dvClipY = 1.0f;
1327 vp.dvClipWidth = 2.0f;
1328 vp.dvClipHeight = 2.0f;
1329 vp.dvMinZ = 0.0f;
1330 vp.dvMaxZ = 1.0f;
1331 hr = IDirect3DViewport2_SetViewport2(viewport, &vp);
1332 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
1333 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1334 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1336 memset(&material, 0, sizeof(material));
1337 material.dwSize = sizeof(material);
1338 U1(U(material).diffuse).r = 1.0f;
1339 U2(U(material).diffuse).g = 0.0f;
1340 U3(U(material).diffuse).b = 0.0f;
1341 U4(U(material).diffuse).a = 1.0f;
1342 hr = IDirect3DMaterial2_SetMaterial(background, &material);
1343 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
1344 hr = IDirect3DMaterial2_GetHandle(background, device, &background_handle);
1345 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
1346 hr = IDirect3DViewport2_SetBackground(viewport, background_handle);
1347 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
1349 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1350 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
1352 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
1353 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1354 hr = IDirect3DDevice2_BeginScene(device);
1355 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1356 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, tquad, 4, 0);
1357 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1358 hr = IDirect3DDevice2_EndScene(device);
1359 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1361 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1362 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1363 for (i = 0; i < 4; ++i)
1365 for (j = 0; j < 4; ++j)
1367 x = 80 * ((2 * j) + 1);
1368 y = 60 * ((2 * i) + 1);
1369 color = get_surface_color(rt, x, y);
1370 ok(compare_color(color, 0x0000ff00, 1),
1371 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1374 IDirectDrawSurface_Release(rt);
1376 IDirect3DMaterial2_Release(background);
1377 hr = IDirect3DDevice2_DeleteViewport(device, viewport);
1378 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
1379 IDirect3DViewport2_Release(viewport);
1380 IDirect3D2_Release(d3d);
1381 IDirect3DDevice2_Release(device);
1382 IDirectDraw2_Release(ddraw);
1383 DestroyWindow(window);
1386 static void test_ck_rgba(void)
1388 static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
1389 static D3DTLVERTEX tquad[] =
1391 {{ 0.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1392 {{ 0.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1393 {{640.0f}, {480.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1394 {{640.0f}, { 0.0f}, {0.25f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1395 {{ 0.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {0.0f}},
1396 {{ 0.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {0.0f}, {1.0f}},
1397 {{640.0f}, {480.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {0.0f}},
1398 {{640.0f}, { 0.0f}, {0.75f}, {1.0f}, {0xffffffff}, {0x00000000}, {1.0f}, {1.0f}},
1400 static const struct
1402 D3DCOLOR fill_color;
1403 BOOL color_key;
1404 BOOL blend;
1405 D3DCOLOR result1;
1406 D3DCOLOR result2;
1408 tests[] =
1410 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x000000ff},
1411 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x000000ff},
1412 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00},
1413 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00},
1414 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00807f00},
1415 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x0000ff00},
1416 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00},
1417 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00},
1420 D3DMATERIALHANDLE background_handle;
1421 D3DTEXTUREHANDLE texture_handle;
1422 IDirect3DMaterial2 *background;
1423 IDirectDrawSurface *surface;
1424 IDirect3DViewport2 *viewport;
1425 IDirect3DTexture2 *texture;
1426 DDSURFACEDESC surface_desc;
1427 IDirect3DDevice2 *device;
1428 IDirectDrawSurface *rt;
1429 D3DMATERIAL material;
1430 IDirectDraw2 *ddraw;
1431 D3DVIEWPORT2 vp;
1432 IDirect3D2 *d3d;
1433 D3DCOLOR color;
1434 HWND window;
1435 DDBLTFX fx;
1436 HRESULT hr;
1437 UINT i;
1439 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1440 0, 0, 640, 480, 0, 0, 0, 0);
1441 if (!(ddraw = create_ddraw()))
1443 skip("Failed to create ddraw object, skipping test.\n");
1444 DestroyWindow(window);
1445 return;
1447 if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
1449 skip("Failed to create D3D device, skipping test.\n");
1450 DestroyWindow(window);
1451 return;
1454 hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
1455 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1457 hr = IDirect3D2_CreateViewport(d3d, &viewport, NULL);
1458 ok(SUCCEEDED(hr), "Failed to create viewport, hr %#x.\n", hr);
1459 hr = IDirect3DDevice2_AddViewport(device, viewport);
1460 ok(SUCCEEDED(hr), "Failed to add viewport, hr %#x.\n", hr);
1461 memset(&vp, 0, sizeof(vp));
1462 vp.dwSize = sizeof(vp);
1463 vp.dwX = 0;
1464 vp.dwY = 0;
1465 vp.dwWidth = 640;
1466 vp.dwHeight = 480;
1467 vp.dvClipX = -1.0f;
1468 vp.dvClipY = 1.0f;
1469 vp.dvClipWidth = 2.0f;
1470 vp.dvClipHeight = 2.0f;
1471 vp.dvMinZ = 0.0f;
1472 vp.dvMaxZ = 1.0f;
1473 hr = IDirect3DViewport2_SetViewport2(viewport, &vp);
1474 ok(SUCCEEDED(hr), "Failed to set viewport data, hr %#x.\n", hr);
1475 hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
1476 ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
1478 hr = IDirect3D2_CreateMaterial(d3d, &background, NULL);
1479 ok(SUCCEEDED(hr), "Failed to create material, hr %#x.\n", hr);
1480 memset(&material, 0, sizeof(material));
1481 material.dwSize = sizeof(material);
1482 U1(U(material).diffuse).r = 1.0f;
1483 U2(U(material).diffuse).g = 0.0f;
1484 U3(U(material).diffuse).b = 0.0f;
1485 U4(U(material).diffuse).a = 1.0f;
1486 hr = IDirect3DMaterial2_SetMaterial(background, &material);
1487 ok(SUCCEEDED(hr), "Failed to set material data, hr %#x.\n", hr);
1488 hr = IDirect3DMaterial2_GetHandle(background, device, &background_handle);
1489 ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
1490 hr = IDirect3DViewport2_SetBackground(viewport, background_handle);
1491 ok(SUCCEEDED(hr), "Failed to set viewport background, hr %#x.\n", hr);
1493 IDirect3D2_Release(d3d);
1495 memset(&surface_desc, 0, sizeof(surface_desc));
1496 surface_desc.dwSize = sizeof(surface_desc);
1497 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1498 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1499 surface_desc.dwWidth = 256;
1500 surface_desc.dwHeight = 256;
1501 surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1502 surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1503 U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1504 U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1505 U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1506 U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
1507 U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1508 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1509 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1510 hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1511 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1512 hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DTexture2, (void **)&texture);
1513 ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
1514 IDirect3DTexture2_GetHandle(texture, device, &texture_handle);
1515 ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
1516 IDirect3DTexture2_Release(texture);
1518 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, texture_handle);
1519 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1520 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1521 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1522 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1523 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1525 hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
1526 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1528 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
1530 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1531 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1532 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1533 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1535 memset(&fx, 0, sizeof(fx));
1536 fx.dwSize = sizeof(fx);
1537 U5(fx).dwFillColor = tests[i].fill_color;
1538 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1539 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1541 hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
1542 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
1543 hr = IDirect3DDevice2_BeginScene(device);
1544 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1545 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[0], 4, 0);
1546 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1547 hr = IDirect3DDevice2_EndScene(device);
1548 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1550 color = get_surface_color(rt, 320, 240);
1551 if (i == 2)
1552 todo_wine ok(compare_color(color, tests[i].result1, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1553 tests[i].result1, i, color);
1554 else
1555 ok(compare_color(color, tests[i].result1, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1556 tests[i].result1, i, color);
1558 U5(fx).dwFillColor = 0xff0000ff;
1559 hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1560 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1562 hr = IDirect3DDevice2_BeginScene(device);
1563 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1564 hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_TLVERTEX, &tquad[4], 4, 0);
1565 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1566 hr = IDirect3DDevice2_EndScene(device);
1567 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1569 /* This tests that fragments that are masked out by the color key are
1570 * discarded, instead of just fully transparent. */
1571 color = get_surface_color(rt, 320, 240);
1572 if (i == 2)
1573 todo_wine ok(compare_color(color, tests[i].result2, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1574 tests[i].result2, i, color);
1575 else
1576 ok(compare_color(color, tests[i].result2, 1), "Expected color 0x%08x for test %u, got 0x%08x.\n",
1577 tests[i].result2, i, color);
1580 IDirectDrawSurface_Release(rt);
1581 hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
1582 ok(SUCCEEDED(hr), "Failed to unset texture, hr %#x.\n", hr);
1583 IDirectDrawSurface_Release(surface);
1584 IDirect3DMaterial2_Release(background);
1585 hr = IDirect3DDevice2_DeleteViewport(device, viewport);
1586 ok(SUCCEEDED(hr), "Failed to delete viewport, hr %#x.\n", hr);
1587 IDirect3DViewport2_Release(viewport);
1588 IDirect3DDevice2_Release(device);
1589 IDirectDraw2_Release(ddraw);
1590 DestroyWindow(window);
1593 START_TEST(ddraw2)
1595 test_coop_level_create_device_window();
1596 test_clipper_blt();
1597 test_coop_level_d3d_state();
1598 test_surface_interface_mismatch();
1599 test_coop_level_threaded();
1600 test_depth_blit();
1601 test_texture_load_ckey();
1602 test_viewport_interfaces();
1603 test_zenable();
1604 test_ck_rgba();