ddraw: Return the right error if range color keys are used.
[wine.git] / dlls / ddraw / tests / ddraw7.c
blobfc119f65377ecd7d456e07897d1d76b9d644c512
1 /*
2 * Copyright 2006, 2012-2014 Stefan Dösinger for CodeWeavers
3 * Copyright 2011-2014 Henri Verbeet for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define COBJMACROS
21 #include "wine/test.h"
22 #include <limits.h>
23 #include <math.h>
24 #include "d3d.h"
26 static HRESULT (WINAPI *pDirectDrawCreateEx)(GUID *guid, void **ddraw, REFIID iid, IUnknown *outer_unknown);
27 static DEVMODEW registry_mode;
29 struct vec2
31 float x, y;
34 struct vec3
36 float x, y, z;
39 struct vec4
41 float x, y, z, w;
44 struct create_window_thread_param
46 HWND window;
47 HANDLE window_created;
48 HANDLE destroy_window;
49 HANDLE thread;
52 static BOOL compare_float(float f, float g, unsigned int ulps)
54 int x = *(int *)&f;
55 int y = *(int *)&g;
57 if (x < 0)
58 x = INT_MIN - x;
59 if (y < 0)
60 y = INT_MIN - y;
62 if (abs(x - y) > ulps)
63 return FALSE;
65 return TRUE;
68 static BOOL compare_vec3(struct vec3 *vec, float x, float y, float z, unsigned int ulps)
70 return compare_float(vec->x, x, ulps)
71 && compare_float(vec->y, y, ulps)
72 && compare_float(vec->z, z, ulps);
75 static BOOL compare_vec4(struct vec4 *vec, float x, float y, float z, float w, unsigned int ulps)
77 return compare_float(vec->x, x, ulps)
78 && compare_float(vec->y, y, ulps)
79 && compare_float(vec->z, z, ulps)
80 && compare_float(vec->w, w, ulps);
83 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
85 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
86 c1 >>= 8; c2 >>= 8;
87 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
88 c1 >>= 8; c2 >>= 8;
89 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
90 c1 >>= 8; c2 >>= 8;
91 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
92 return TRUE;
95 static ULONG get_refcount(IUnknown *iface)
97 IUnknown_AddRef(iface);
98 return IUnknown_Release(iface);
101 static DWORD WINAPI create_window_thread_proc(void *param)
103 struct create_window_thread_param *p = param;
104 DWORD res;
105 BOOL ret;
107 p->window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
108 0, 0, 640, 480, 0, 0, 0, 0);
109 ret = SetEvent(p->window_created);
110 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
112 for (;;)
114 MSG msg;
116 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
117 DispatchMessageA(&msg);
118 res = WaitForSingleObject(p->destroy_window, 100);
119 if (res == WAIT_OBJECT_0)
120 break;
121 if (res != WAIT_TIMEOUT)
123 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
124 break;
128 DestroyWindow(p->window);
130 return 0;
133 static void create_window_thread(struct create_window_thread_param *p)
135 DWORD res, tid;
137 p->window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
138 ok(!!p->window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
139 p->destroy_window = CreateEventA(NULL, FALSE, FALSE, NULL);
140 ok(!!p->destroy_window, "CreateEvent failed, last error %#x.\n", GetLastError());
141 p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
142 ok(!!p->thread, "Failed to create thread, last error %#x.\n", GetLastError());
143 res = WaitForSingleObject(p->window_created, INFINITE);
144 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
147 static void destroy_window_thread(struct create_window_thread_param *p)
149 SetEvent(p->destroy_window);
150 WaitForSingleObject(p->thread, INFINITE);
151 CloseHandle(p->destroy_window);
152 CloseHandle(p->window_created);
153 CloseHandle(p->thread);
156 static IDirectDrawSurface7 *get_depth_stencil(IDirect3DDevice7 *device)
158 IDirectDrawSurface7 *rt, *ret;
159 DDSCAPS2 caps = {DDSCAPS_ZBUFFER, 0, 0, {0}};
160 HRESULT hr;
162 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
163 ok(SUCCEEDED(hr), "Failed to get the render target, hr %#x.\n", hr);
164 hr = IDirectDrawSurface7_GetAttachedSurface(rt, &caps, &ret);
165 ok(SUCCEEDED(hr) || hr == DDERR_NOTFOUND, "Failed to get the z buffer, hr %#x.\n", hr);
166 IDirectDrawSurface7_Release(rt);
167 return ret;
170 static HRESULT set_display_mode(IDirectDraw7 *ddraw, DWORD width, DWORD height)
172 if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
173 return DD_OK;
174 return IDirectDraw7_SetDisplayMode(ddraw, width, height, 24, 0, 0);
177 static D3DCOLOR get_surface_color(IDirectDrawSurface7 *surface, UINT x, UINT y)
179 RECT rect = {x, y, x + 1, y + 1};
180 DDSURFACEDESC2 surface_desc;
181 D3DCOLOR color;
182 HRESULT hr;
184 memset(&surface_desc, 0, sizeof(surface_desc));
185 surface_desc.dwSize = sizeof(surface_desc);
187 hr = IDirectDrawSurface7_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY, NULL);
188 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
189 if (FAILED(hr))
190 return 0xdeadbeef;
192 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
194 hr = IDirectDrawSurface7_Unlock(surface, &rect);
195 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
197 return color;
200 static HRESULT CALLBACK enum_z_fmt(DDPIXELFORMAT *format, void *ctx)
202 DDPIXELFORMAT *z_fmt = ctx;
204 if (U1(*format).dwZBufferBitDepth > U1(*z_fmt).dwZBufferBitDepth)
205 *z_fmt = *format;
207 return DDENUMRET_OK;
210 static IDirectDraw7 *create_ddraw(void)
212 IDirectDraw7 *ddraw;
214 if (FAILED(pDirectDrawCreateEx(NULL, (void **)&ddraw, &IID_IDirectDraw7, NULL)))
215 return NULL;
217 return ddraw;
220 static HRESULT WINAPI enum_devtype_cb(char *desc_str, char *name, D3DDEVICEDESC7 *desc, void *ctx)
222 BOOL *hal_ok = ctx;
223 if (IsEqualGUID(&desc->deviceGUID, &IID_IDirect3DTnLHalDevice))
225 *hal_ok = TRUE;
226 return DDENUMRET_CANCEL;
228 return DDENUMRET_OK;
231 static IDirect3DDevice7 *create_device(HWND window, DWORD coop_level)
233 IDirectDrawSurface7 *surface, *ds;
234 IDirect3DDevice7 *device = NULL;
235 DDSURFACEDESC2 surface_desc;
236 DDPIXELFORMAT z_fmt;
237 IDirectDraw7 *ddraw;
238 IDirect3D7 *d3d7;
239 HRESULT hr;
240 BOOL hal_ok = FALSE;
241 const GUID *devtype = &IID_IDirect3DHALDevice;
243 if (!(ddraw = create_ddraw()))
244 return NULL;
246 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, coop_level);
247 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
249 memset(&surface_desc, 0, sizeof(surface_desc));
250 surface_desc.dwSize = sizeof(surface_desc);
251 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
252 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
253 surface_desc.dwWidth = 640;
254 surface_desc.dwHeight = 480;
256 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
257 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
259 if (coop_level & DDSCL_NORMAL)
261 IDirectDrawClipper *clipper;
263 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
264 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
265 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
266 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
267 hr = IDirectDrawSurface7_SetClipper(surface, clipper);
268 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\n", hr);
269 IDirectDrawClipper_Release(clipper);
272 hr = IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d7);
273 IDirectDraw7_Release(ddraw);
274 if (FAILED(hr))
276 IDirectDrawSurface7_Release(surface);
277 return NULL;
280 hr = IDirect3D7_EnumDevices(d3d7, enum_devtype_cb, &hal_ok);
281 ok(SUCCEEDED(hr), "Failed to enumerate devices, hr %#x.\n", hr);
282 if (hal_ok) devtype = &IID_IDirect3DTnLHalDevice;
284 memset(&z_fmt, 0, sizeof(z_fmt));
285 hr = IDirect3D7_EnumZBufferFormats(d3d7, devtype, enum_z_fmt, &z_fmt);
286 if (FAILED(hr) || !z_fmt.dwSize)
288 IDirect3D7_Release(d3d7);
289 IDirectDrawSurface7_Release(surface);
290 return NULL;
293 memset(&surface_desc, 0, sizeof(surface_desc));
294 surface_desc.dwSize = sizeof(surface_desc);
295 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
296 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
297 U4(surface_desc).ddpfPixelFormat = z_fmt;
298 surface_desc.dwWidth = 640;
299 surface_desc.dwHeight = 480;
300 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL);
301 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
302 if (FAILED(hr))
304 IDirect3D7_Release(d3d7);
305 IDirectDrawSurface7_Release(surface);
306 return NULL;
309 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
310 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
311 IDirectDrawSurface7_Release(ds);
312 if (FAILED(hr))
314 IDirect3D7_Release(d3d7);
315 IDirectDrawSurface7_Release(surface);
316 return NULL;
319 hr = IDirect3D7_CreateDevice(d3d7, devtype, surface, &device);
320 IDirect3D7_Release(d3d7);
321 IDirectDrawSurface7_Release(surface);
322 if (FAILED(hr))
323 return NULL;
325 return device;
328 struct message
330 UINT message;
331 BOOL check_wparam;
332 WPARAM expect_wparam;
335 static const struct message *expect_messages;
337 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
339 if (expect_messages && message == expect_messages->message)
341 if (expect_messages->check_wparam)
342 ok (wparam == expect_messages->expect_wparam,
343 "Got unexpected wparam %lx for message %x, expected %lx.\n",
344 wparam, message, expect_messages->expect_wparam);
346 ++expect_messages;
349 return DefWindowProcA(hwnd, message, wparam, lparam);
352 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
353 * interface. This prevents subsequent SetCooperativeLevel() calls on a
354 * different window from failing with DDERR_HWNDALREADYSET. */
355 static void fix_wndproc(HWND window, LONG_PTR proc)
357 IDirectDraw7 *ddraw;
358 HRESULT hr;
360 if (!(ddraw = create_ddraw()))
361 return;
363 SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
364 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
365 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
366 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
367 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
369 IDirectDraw7_Release(ddraw);
372 static void test_process_vertices(void)
374 IDirect3DVertexBuffer7 *src_vb, *dst_vb1, *dst_vb2;
375 D3DVERTEXBUFFERDESC vb_desc;
376 IDirect3DDevice7 *device;
377 struct vec4 *dst_data;
378 struct vec3 *dst_data2;
379 struct vec3 *src_data;
380 IDirect3D7 *d3d7;
381 D3DVIEWPORT7 vp;
382 HWND window;
383 HRESULT hr;
385 static D3DMATRIX world =
387 0.0f, 1.0f, 0.0f, 0.0f,
388 1.0f, 0.0f, 0.0f, 0.0f,
389 0.0f, 0.0f, 0.0f, 1.0f,
390 0.0f, 1.0f, 1.0f, 1.0f,
392 static D3DMATRIX view =
394 2.0f, 0.0f, 0.0f, 0.0f,
395 0.0f, -1.0f, 0.0f, 0.0f,
396 0.0f, 0.0f, 1.0f, 0.0f,
397 0.0f, 0.0f, 0.0f, 3.0f,
399 static D3DMATRIX proj =
401 1.0f, 0.0f, 0.0f, 1.0f,
402 0.0f, 1.0f, 1.0f, 0.0f,
403 0.0f, 1.0f, 1.0f, 0.0f,
404 1.0f, 0.0f, 0.0f, 1.0f,
407 window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
408 0, 0, 640, 480, 0, 0, 0, 0);
409 if (!(device = create_device(window, DDSCL_NORMAL)))
411 skip("Failed to create a 3D device, skipping test.\n");
412 DestroyWindow(window);
413 return;
416 hr = IDirect3DDevice7_GetDirect3D(device, &d3d7);
417 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
419 memset(&vb_desc, 0, sizeof(vb_desc));
420 vb_desc.dwSize = sizeof(vb_desc);
421 vb_desc.dwFVF = D3DFVF_XYZ;
422 vb_desc.dwNumVertices = 4;
423 hr = IDirect3D7_CreateVertexBuffer(d3d7, &vb_desc, &src_vb, 0);
424 ok(SUCCEEDED(hr), "Failed to create source vertex buffer, hr %#x.\n", hr);
426 hr = IDirect3DVertexBuffer7_Lock(src_vb, 0, (void **)&src_data, NULL);
427 ok(SUCCEEDED(hr), "Failed to lock source vertex buffer, hr %#x.\n", hr);
428 src_data[0].x = 0.0f;
429 src_data[0].y = 0.0f;
430 src_data[0].z = 0.0f;
431 src_data[1].x = 1.0f;
432 src_data[1].y = 1.0f;
433 src_data[1].z = 1.0f;
434 src_data[2].x = -1.0f;
435 src_data[2].y = -1.0f;
436 src_data[2].z = 0.5f;
437 src_data[3].x = 0.5f;
438 src_data[3].y = -0.5f;
439 src_data[3].z = 0.25f;
440 hr = IDirect3DVertexBuffer7_Unlock(src_vb);
441 ok(SUCCEEDED(hr), "Failed to unlock source vertex buffer, hr %#x.\n", hr);
443 memset(&vb_desc, 0, sizeof(vb_desc));
444 vb_desc.dwSize = sizeof(vb_desc);
445 vb_desc.dwFVF = D3DFVF_XYZRHW;
446 vb_desc.dwNumVertices = 4;
447 /* MSDN says that the last parameter must be 0 - check that. */
448 hr = IDirect3D7_CreateVertexBuffer(d3d7, &vb_desc, &dst_vb1, 4);
449 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
451 memset(&vb_desc, 0, sizeof(vb_desc));
452 vb_desc.dwSize = sizeof(vb_desc);
453 vb_desc.dwFVF = D3DFVF_XYZ;
454 vb_desc.dwNumVertices = 5;
455 /* MSDN says that the last parameter must be 0 - check that. */
456 hr = IDirect3D7_CreateVertexBuffer(d3d7, &vb_desc, &dst_vb2, 12345678);
457 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
459 memset(&vp, 0, sizeof(vp));
460 vp.dwX = 64;
461 vp.dwY = 64;
462 vp.dwWidth = 128;
463 vp.dwHeight = 128;
464 vp.dvMinZ = 0.0f;
465 vp.dvMaxZ = 1.0f;
466 hr = IDirect3DDevice7_SetViewport(device, &vp);
467 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
469 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
470 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
471 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb2, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
472 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
474 hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
475 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
476 ok(compare_vec4(&dst_data[0], +1.280e+2f, +1.280e+2f, +0.000e+0f, +1.000e+0f, 4096),
477 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
478 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
479 ok(compare_vec4(&dst_data[1], +1.920e+2f, +6.400e+1f, +1.000e+0f, +1.000e+0f, 4096),
480 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
481 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
482 ok(compare_vec4(&dst_data[2], +6.400e+1f, +1.920e+2f, +5.000e-1f, +1.000e+0f, 4096),
483 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
484 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
485 ok(compare_vec4(&dst_data[3], +1.600e+2f, +1.600e+2f, +2.500e-1f, +1.000e+0f, 4096),
486 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
487 dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
488 hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
489 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
491 hr = IDirect3DVertexBuffer7_Lock(dst_vb2, 0, (void **)&dst_data2, NULL);
492 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
493 /* Small thing without much practical meaning, but I stumbled upon it,
494 * so let's check for it: If the output vertex buffer has no RHW value,
495 * the RHW value of the last vertex is written into the next vertex. */
496 ok(compare_vec3(&dst_data2[4], +1.000e+0f, +0.000e+0f, +0.000e+0f, 4096),
497 "Got unexpected vertex 4 {%.8e, %.8e, %.8e}.\n",
498 dst_data2[4].x, dst_data2[4].y, dst_data2[4].z);
499 hr = IDirect3DVertexBuffer7_Unlock(dst_vb2);
500 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
502 /* Try a more complicated viewport, same vertices. */
503 memset(&vp, 0, sizeof(vp));
504 vp.dwX = 10;
505 vp.dwY = 5;
506 vp.dwWidth = 246;
507 vp.dwHeight = 130;
508 vp.dvMinZ = -2.0f;
509 vp.dvMaxZ = 4.0f;
510 hr = IDirect3DDevice7_SetViewport(device, &vp);
511 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
513 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
514 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
516 hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
517 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
518 ok(compare_vec4(&dst_data[0], +1.330e+2f, +7.000e+1f, -2.000e+0f, +1.000e+0f, 4096),
519 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
520 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
521 ok(compare_vec4(&dst_data[1], +2.560e+2f, +5.000e+0f, +4.000e+0f, +1.000e+0f, 4096),
522 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
523 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
524 ok(compare_vec4(&dst_data[2], +1.000e+1f, +1.350e+2f, +1.000e+0f, +1.000e+0f, 4096),
525 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
526 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
527 ok(compare_vec4(&dst_data[3], +1.945e+2f, +1.025e+2f, -5.000e-1f, +1.000e+0f, 4096),
528 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
529 dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
530 hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
531 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
533 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &world);
534 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
535 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &view);
536 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
537 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &proj);
538 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
540 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
541 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
543 hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
544 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
545 ok(compare_vec4(&dst_data[0], +2.560e+2f, +7.000e+1f, -2.000e+0f, +3.333e-1f, 4096),
546 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
547 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
548 ok(compare_vec4(&dst_data[1], +2.560e+2f, +7.813e+1f, -2.750e+0f, +1.250e-1f, 4096),
549 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
550 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
551 ok(compare_vec4(&dst_data[2], +2.560e+2f, +4.400e+1f, +4.000e-1f, +4.000e-1f, 4096),
552 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
553 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
554 ok(compare_vec4(&dst_data[3], +2.560e+2f, +8.182e+1f, -3.091e+0f, +3.636e-1f, 4096),
555 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
556 dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
557 hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
558 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
560 IDirect3DVertexBuffer7_Release(dst_vb2);
561 IDirect3DVertexBuffer7_Release(dst_vb1);
562 IDirect3DVertexBuffer7_Release(src_vb);
563 IDirect3D7_Release(d3d7);
564 IDirect3DDevice7_Release(device);
565 DestroyWindow(window);
568 static void test_coop_level_create_device_window(void)
570 HWND focus_window, device_window;
571 IDirectDraw7 *ddraw;
572 HRESULT hr;
574 focus_window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
575 0, 0, 640, 480, 0, 0, 0, 0);
576 ddraw = create_ddraw();
577 ok(!!ddraw, "Failed to create a ddraw object.\n");
579 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
580 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
581 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
582 ok(!device_window, "Unexpected device window found.\n");
583 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
584 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
585 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
586 ok(!device_window, "Unexpected device window found.\n");
587 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
588 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
589 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
590 ok(!device_window, "Unexpected device window found.\n");
591 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
592 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
593 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
594 ok(!device_window, "Unexpected device window found.\n");
595 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
596 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
597 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
598 ok(!device_window, "Unexpected device window found.\n");
600 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
601 if (broken(hr == DDERR_INVALIDPARAMS))
603 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
604 IDirectDraw7_Release(ddraw);
605 DestroyWindow(focus_window);
606 return;
609 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
610 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
611 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
612 ok(!device_window, "Unexpected device window found.\n");
613 hr = IDirectDraw7_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
614 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
615 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
616 ok(!device_window, "Unexpected device window found.\n");
618 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
619 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
620 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
621 ok(!device_window, "Unexpected device window found.\n");
622 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
623 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
624 ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
625 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
626 ok(!!device_window, "Device window not found.\n");
628 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
629 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
630 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
631 ok(!device_window, "Unexpected device window found.\n");
632 hr = IDirectDraw7_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
633 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
634 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
635 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
636 ok(!!device_window, "Device window not found.\n");
638 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
639 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
640 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
641 ok(!device_window, "Unexpected device window found.\n");
642 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
643 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
644 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
645 ok(!device_window, "Unexpected device window found.\n");
646 hr = IDirectDraw7_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
647 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
648 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
649 ok(!device_window, "Unexpected device window found.\n");
650 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
651 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
652 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
653 ok(!!device_window, "Device window not found.\n");
655 IDirectDraw7_Release(ddraw);
656 DestroyWindow(focus_window);
659 static void test_clipper_blt(void)
661 IDirectDrawSurface7 *src_surface, *dst_surface;
662 RECT client_rect, src_rect;
663 IDirectDrawClipper *clipper;
664 DDSURFACEDESC2 surface_desc;
665 unsigned int i, j, x, y;
666 IDirectDraw7 *ddraw;
667 RGNDATA *rgn_data;
668 D3DCOLOR color;
669 ULONG refcount;
670 HRGN r1, r2;
671 HWND window;
672 DDBLTFX fx;
673 HRESULT hr;
674 DWORD *ptr;
675 DWORD ret;
677 static const DWORD src_data[] =
679 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
680 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
681 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
683 static const D3DCOLOR expected1[] =
685 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
686 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
687 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
688 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
690 /* Nvidia on Windows seems to have an off-by-one error
691 * when processing source rectangles. Our left = 1 and
692 * right = 5 input reads from x = {1, 2, 3}. x = 4 is
693 * read as well, but only for the edge pixels on the
694 * output image. The bug happens on the y axis as well,
695 * but we only read one row there, and all source rows
696 * contain the same data. This bug is not dependent on
697 * the presence of a clipper. */
698 static const D3DCOLOR expected1_broken[] =
700 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
701 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
702 0x00000000, 0x00000000, 0x00ff0000, 0x00ff0000,
703 0x00000000, 0x00000000, 0x0000ff00, 0x00ff0000,
705 static const D3DCOLOR expected2[] =
707 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
708 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
709 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
710 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
713 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
714 10, 10, 640, 480, 0, 0, 0, 0);
715 ShowWindow(window, SW_SHOW);
716 ddraw = create_ddraw();
717 ok(!!ddraw, "Failed to create a ddraw object.\n");
719 ret = GetClientRect(window, &client_rect);
720 ok(ret, "Failed to get client rect.\n");
721 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
722 ok(ret, "Failed to map client rect.\n");
724 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
725 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
727 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
728 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
729 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
730 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
731 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
732 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
733 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
734 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
735 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
736 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
737 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
738 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
739 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
740 ok(rgn_data->rdh.nCount >= 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
741 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
742 "Got unexpected bounding rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
743 rgn_data->rdh.rcBound.left, rgn_data->rdh.rcBound.top,
744 rgn_data->rdh.rcBound.right, rgn_data->rdh.rcBound.bottom,
745 client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
746 HeapFree(GetProcessHeap(), 0, rgn_data);
748 r1 = CreateRectRgn(0, 0, 320, 240);
749 ok(!!r1, "Failed to create region.\n");
750 r2 = CreateRectRgn(320, 240, 640, 480);
751 ok(!!r2, "Failed to create region.\n");
752 CombineRgn(r1, r1, r2, RGN_OR);
753 ret = GetRegionData(r1, 0, NULL);
754 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
755 ret = GetRegionData(r1, ret, rgn_data);
756 ok(!!ret, "Failed to get region data.\n");
758 DeleteObject(r2);
759 DeleteObject(r1);
761 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
762 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
763 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
764 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
765 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
766 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
768 HeapFree(GetProcessHeap(), 0, rgn_data);
770 memset(&surface_desc, 0, sizeof(surface_desc));
771 surface_desc.dwSize = sizeof(surface_desc);
772 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
773 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
774 surface_desc.dwWidth = 640;
775 surface_desc.dwHeight = 480;
776 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
777 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
778 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
779 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
780 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
781 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
783 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
784 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
785 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
786 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
788 memset(&fx, 0, sizeof(fx));
789 fx.dwSize = sizeof(fx);
790 hr = IDirectDrawSurface7_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
791 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
792 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
793 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
795 hr = IDirectDrawSurface7_Lock(src_surface, NULL, &surface_desc, 0, NULL);
796 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
797 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
798 ptr = surface_desc.lpSurface;
799 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
800 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
801 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
802 hr = IDirectDrawSurface7_Unlock(src_surface, NULL);
803 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
805 hr = IDirectDrawSurface7_SetClipper(dst_surface, clipper);
806 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
808 SetRect(&src_rect, 1, 1, 5, 2);
809 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
810 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
811 for (i = 0; i < 4; ++i)
813 for (j = 0; j < 4; ++j)
815 x = 80 * ((2 * j) + 1);
816 y = 60 * ((2 * i) + 1);
817 color = get_surface_color(dst_surface, x, y);
818 ok(compare_color(color, expected1[i * 4 + j], 1)
819 || broken(compare_color(color, expected1_broken[i * 4 + j], 1)),
820 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
824 U5(fx).dwFillColor = 0xff0000ff;
825 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
826 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
827 for (i = 0; i < 4; ++i)
829 for (j = 0; j < 4; ++j)
831 x = 80 * ((2 * j) + 1);
832 y = 60 * ((2 * i) + 1);
833 color = get_surface_color(dst_surface, x, y);
834 ok(compare_color(color, expected2[i * 4 + j], 1),
835 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
839 hr = IDirectDrawSurface7_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
840 ok(hr == DDERR_BLTFASTCANTCLIP, "Got unexpected hr %#x.\n", hr);
842 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
843 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
844 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
845 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
846 DestroyWindow(window);
847 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
848 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
849 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
850 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
851 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
852 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
853 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
854 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
855 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
856 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
857 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
858 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
860 IDirectDrawSurface7_Release(dst_surface);
861 IDirectDrawSurface7_Release(src_surface);
862 refcount = IDirectDrawClipper_Release(clipper);
863 ok(!refcount, "Clipper has %u references left.\n", refcount);
864 IDirectDraw7_Release(ddraw);
867 static void test_coop_level_d3d_state(void)
869 IDirectDrawSurface7 *rt, *surface;
870 IDirect3DDevice7 *device;
871 IDirectDraw7 *ddraw;
872 IDirect3D7 *d3d;
873 D3DCOLOR color;
874 DWORD value;
875 HWND window;
876 HRESULT hr;
878 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
879 0, 0, 640, 480, 0, 0, 0, 0);
880 if (!(device = create_device(window, DDSCL_NORMAL)))
882 skip("Failed to create a 3D device, skipping test.\n");
883 DestroyWindow(window);
884 return;
887 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
888 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
889 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
890 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
891 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
892 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
893 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
894 ok(!value, "Got unexpected alpha blend enable state %#x.\n", value);
895 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
896 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
897 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
898 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
899 color = get_surface_color(rt, 320, 240);
900 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
902 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
903 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
904 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
905 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
906 IDirect3D7_Release(d3d);
907 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
908 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
909 hr = IDirectDrawSurface7_IsLost(rt);
910 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
911 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
912 ok(SUCCEEDED(hr), "Failed to restore surfaces, hr %#x.\n", hr);
913 IDirectDraw7_Release(ddraw);
915 hr = IDirect3DDevice7_GetRenderTarget(device, &surface);
916 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
917 ok(surface == rt, "Got unexpected surface %p.\n", surface);
918 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
919 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
920 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
921 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
922 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
923 ok(!!value, "Got unexpected alpha blend enable state %#x.\n", value);
924 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
925 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
926 color = get_surface_color(rt, 320, 240);
927 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
929 IDirectDrawSurface7_Release(surface);
930 IDirectDrawSurface7_Release(rt);
931 IDirect3DDevice7_Release(device);
932 DestroyWindow(window);
935 static void test_surface_interface_mismatch(void)
937 IDirectDraw7 *ddraw = NULL;
938 IDirect3D7 *d3d = NULL;
939 IDirectDrawSurface7 *surface = NULL, *ds;
940 IDirectDrawSurface3 *surface3 = NULL;
941 IDirect3DDevice7 *device = NULL;
942 DDSURFACEDESC2 surface_desc;
943 DDPIXELFORMAT z_fmt;
944 ULONG refcount;
945 HRESULT hr;
946 D3DCOLOR color;
947 HWND window;
949 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
950 0, 0, 640, 480, 0, 0, 0, 0);
951 ddraw = create_ddraw();
952 ok(!!ddraw, "Failed to create a ddraw object.\n");
953 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
954 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
956 memset(&surface_desc, 0, sizeof(surface_desc));
957 surface_desc.dwSize = sizeof(surface_desc);
958 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
959 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
960 surface_desc.dwWidth = 640;
961 surface_desc.dwHeight = 480;
963 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
964 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
966 hr = IDirectDrawSurface7_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
967 ok(SUCCEEDED(hr), "Failed to QI IDirectDrawSurface3, hr %#x.\n", hr);
969 if (FAILED(IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d)))
971 skip("D3D interface is not available, skipping test.\n");
972 goto cleanup;
975 memset(&z_fmt, 0, sizeof(z_fmt));
976 hr = IDirect3D7_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
977 if (FAILED(hr) || !z_fmt.dwSize)
979 skip("No depth buffer formats available, skipping test.\n");
980 goto cleanup;
983 memset(&surface_desc, 0, sizeof(surface_desc));
984 surface_desc.dwSize = sizeof(surface_desc);
985 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
986 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
987 U4(surface_desc).ddpfPixelFormat = z_fmt;
988 surface_desc.dwWidth = 640;
989 surface_desc.dwHeight = 480;
990 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL);
991 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
992 if (FAILED(hr))
993 goto cleanup;
995 /* Using a different surface interface version still works */
996 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
997 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
998 refcount = IDirectDrawSurface7_Release(ds);
999 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
1000 if (FAILED(hr))
1001 goto cleanup;
1003 /* Here too */
1004 hr = IDirect3D7_CreateDevice(d3d, &IID_IDirect3DHALDevice, (IDirectDrawSurface7 *)surface3, &device);
1005 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
1006 if (FAILED(hr))
1007 goto cleanup;
1009 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
1010 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1011 color = get_surface_color(surface, 320, 240);
1012 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1014 cleanup:
1015 if (surface3) IDirectDrawSurface3_Release(surface3);
1016 if (surface) IDirectDrawSurface7_Release(surface);
1017 if (device) IDirect3DDevice7_Release(device);
1018 if (d3d) IDirect3D7_Release(d3d);
1019 if (ddraw) IDirectDraw7_Release(ddraw);
1020 DestroyWindow(window);
1023 static void test_coop_level_threaded(void)
1025 struct create_window_thread_param p;
1026 IDirectDraw7 *ddraw;
1027 HRESULT hr;
1029 ddraw = create_ddraw();
1030 ok(!!ddraw, "Failed to create a ddraw object.\n");
1031 create_window_thread(&p);
1033 hr = IDirectDraw7_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1034 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1036 IDirectDraw7_Release(ddraw);
1037 destroy_window_thread(&p);
1040 static void test_depth_blit(void)
1042 IDirect3DDevice7 *device;
1043 static struct
1045 float x, y, z;
1046 DWORD color;
1048 quad1[] =
1050 { -1.0, 1.0, 0.50f, 0xff00ff00},
1051 { 1.0, 1.0, 0.50f, 0xff00ff00},
1052 { -1.0, -1.0, 0.50f, 0xff00ff00},
1053 { 1.0, -1.0, 0.50f, 0xff00ff00},
1055 static const D3DCOLOR expected_colors[4][4] =
1057 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1058 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1059 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1060 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1062 DDSURFACEDESC2 ddsd_new, ddsd_existing;
1064 IDirectDrawSurface7 *ds1, *ds2, *ds3, *rt;
1065 RECT src_rect, dst_rect;
1066 unsigned int i, j;
1067 D3DCOLOR color;
1068 HRESULT hr;
1069 IDirect3D7 *d3d;
1070 IDirectDraw7 *ddraw;
1071 DDBLTFX fx;
1072 HWND window;
1074 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1075 0, 0, 640, 480, 0, 0, 0, 0);
1076 if (!(device = create_device(window, DDSCL_NORMAL)))
1078 skip("Failed to create a 3D device, skipping test.\n");
1079 DestroyWindow(window);
1080 return;
1083 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1084 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
1085 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1086 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
1087 IDirect3D7_Release(d3d);
1089 ds1 = get_depth_stencil(device);
1091 memset(&ddsd_new, 0, sizeof(ddsd_new));
1092 ddsd_new.dwSize = sizeof(ddsd_new);
1093 memset(&ddsd_existing, 0, sizeof(ddsd_existing));
1094 ddsd_existing.dwSize = sizeof(ddsd_existing);
1095 hr = IDirectDrawSurface7_GetSurfaceDesc(ds1, &ddsd_existing);
1096 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
1097 ddsd_new.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1098 ddsd_new.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1099 ddsd_new.dwWidth = ddsd_existing.dwWidth;
1100 ddsd_new.dwHeight = ddsd_existing.dwHeight;
1101 U4(ddsd_new).ddpfPixelFormat = U4(ddsd_existing).ddpfPixelFormat;
1102 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd_new, &ds2, NULL);
1103 ok(SUCCEEDED(hr), "Failed to create a z buffer, hr %#x.\n", hr);
1104 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd_new, &ds3, NULL);
1105 ok(SUCCEEDED(hr), "Failed to create a z buffer, hr %#x.\n", hr);
1106 IDirectDraw7_Release(ddraw);
1108 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
1109 ok(SUCCEEDED(hr), "Failed to enable z testing, hr %#x.\n", hr);
1110 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
1111 ok(SUCCEEDED(hr), "Failed to set the z function, hr %#x.\n", hr);
1112 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
1113 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
1115 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
1116 ok(SUCCEEDED(hr), "Failed to clear the z buffer, hr %#x.\n", hr);
1118 /* Partial blit. */
1119 SetRect(&src_rect, 0, 0, 320, 240);
1120 SetRect(&dst_rect, 0, 0, 320, 240);
1121 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1122 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1123 /* Different locations. */
1124 SetRect(&src_rect, 0, 0, 320, 240);
1125 SetRect(&dst_rect, 320, 240, 640, 480);
1126 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1127 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1128 /* Streched. */
1129 SetRect(&src_rect, 0, 0, 320, 240);
1130 SetRect(&dst_rect, 0, 0, 640, 480);
1131 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1132 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1133 /* Flipped. */
1134 SetRect(&src_rect, 0, 480, 640, 0);
1135 SetRect(&dst_rect, 0, 0, 640, 480);
1136 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1137 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1138 SetRect(&src_rect, 0, 0, 640, 480);
1139 SetRect(&dst_rect, 0, 480, 640, 0);
1140 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1141 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1142 /* Full, explicit. */
1143 SetRect(&src_rect, 0, 0, 640, 480);
1144 SetRect(&dst_rect, 0, 0, 640, 480);
1145 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1146 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1147 /* Depth -> color blit: Succeeds on Win7 + Radeon HD 5700, fails on WinXP + Radeon X1600 */
1149 /* Depth blit inside a BeginScene / EndScene pair */
1150 hr = IDirect3DDevice7_BeginScene(device);
1151 ok(SUCCEEDED(hr), "Failed to start scene, hr %#x.\n", hr);
1152 /* From the current depth stencil */
1153 hr = IDirectDrawSurface7_Blt(ds2, NULL, ds1, NULL, DDBLT_WAIT, NULL);
1154 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1155 /* To the current depth stencil */
1156 hr = IDirectDrawSurface7_Blt(ds1, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1157 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1158 /* Between unbound surfaces */
1159 hr = IDirectDrawSurface7_Blt(ds3, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1160 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1161 hr = IDirect3DDevice7_EndScene(device);
1162 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1164 /* Avoid changing the depth stencil, it doesn't work properly on Windows.
1165 * Instead use DDBLT_DEPTHFILL to clear the depth stencil. Unfortunately
1166 * drivers disagree on the meaning of dwFillDepth. Only 0 seems to produce
1167 * a reliable result(z = 0.0) */
1168 memset(&fx, 0, sizeof(fx));
1169 fx.dwSize = sizeof(fx);
1170 hr = IDirectDrawSurface7_Blt(ds2, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
1171 ok(SUCCEEDED(hr), "Failed to clear the source z buffer, hr %#x.\n", hr);
1173 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET, 0xffff0000, 1.0f, 0);
1174 ok(SUCCEEDED(hr), "Failed to clear the color and z buffers, hr %#x.\n", hr);
1175 SetRect(&dst_rect, 0, 0, 320, 240);
1176 hr = IDirectDrawSurface7_Blt(ds1, &dst_rect, ds2, NULL, DDBLT_WAIT, NULL);
1177 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1178 IDirectDrawSurface7_Release(ds3);
1179 IDirectDrawSurface7_Release(ds2);
1180 IDirectDrawSurface7_Release(ds1);
1182 hr = IDirect3DDevice7_BeginScene(device);
1183 ok(SUCCEEDED(hr), "Failed to start scene, hr %#x.\n", hr);
1184 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
1185 quad1, 4, 0);
1186 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1187 hr = IDirect3DDevice7_EndScene(device);
1188 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1190 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1191 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1192 for (i = 0; i < 4; ++i)
1194 for (j = 0; j < 4; ++j)
1196 unsigned int x = 80 * ((2 * j) + 1);
1197 unsigned int y = 60 * ((2 * i) + 1);
1198 color = get_surface_color(rt, x, y);
1199 ok(compare_color(color, expected_colors[i][j], 1),
1200 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
1204 IDirectDrawSurface7_Release(rt);
1205 IDirect3DDevice7_Release(device);
1206 DestroyWindow(window);
1209 static void test_texture_load_ckey(void)
1211 HWND window;
1212 IDirect3DDevice7 *device;
1213 IDirectDraw7 *ddraw;
1214 IDirectDrawSurface7 *src;
1215 IDirectDrawSurface7 *dst;
1216 DDSURFACEDESC2 ddsd;
1217 HRESULT hr;
1218 DDCOLORKEY ckey;
1219 IDirect3D7 *d3d;
1221 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1222 0, 0, 640, 480, 0, 0, 0, 0);
1223 if (!(device = create_device(window, DDSCL_NORMAL)))
1225 skip("Failed to create a 3D device, skipping test.\n");
1226 DestroyWindow(window);
1227 return;
1230 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1231 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
1232 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1233 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
1234 IDirect3D7_Release(d3d);
1236 memset(&ddsd, 0, sizeof(ddsd));
1237 ddsd.dwSize = sizeof(ddsd);
1238 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
1239 ddsd.dwHeight = 128;
1240 ddsd.dwWidth = 128;
1241 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
1242 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &src, NULL);
1243 ok(SUCCEEDED(hr), "Failed to create source texture, hr %#x.\n", hr);
1244 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1245 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &dst, NULL);
1246 ok(SUCCEEDED(hr), "Failed to create destination texture, hr %#x.\n", hr);
1248 /* No surface has a color key */
1249 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1250 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1251 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0xdeadbeef;
1252 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1253 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1254 ok(ckey.dwColorSpaceLowValue == 0xdeadbeef, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1255 ok(ckey.dwColorSpaceHighValue == 0xdeadbeef, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1257 /* Source surface has a color key */
1258 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
1259 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
1260 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1261 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1262 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1263 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1264 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1265 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1266 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1268 /* Both surfaces have a color key: Dest ckey is overwritten */
1269 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x000000ff;
1270 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1271 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1272 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1273 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1274 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1275 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1276 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1277 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1279 /* Only the destination has a color key: It is deleted. This behavior differs from
1280 * IDirect3DTexture(2)::Load */
1281 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, NULL);
1282 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1283 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
1284 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1285 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1286 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1287 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1288 todo_wine ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1290 IDirectDrawSurface7_Release(dst);
1291 IDirectDrawSurface7_Release(src);
1292 IDirectDraw7_Release(ddraw);
1293 IDirect3DDevice7_Release(device);
1294 DestroyWindow(window);
1297 static void test_zenable(void)
1299 static struct
1301 struct vec4 position;
1302 D3DCOLOR diffuse;
1304 tquad[] =
1306 {{ 0.0f, 480.0f, -0.5f, 1.0f}, 0xff00ff00},
1307 {{ 0.0f, 0.0f, -0.5f, 1.0f}, 0xff00ff00},
1308 {{640.0f, 480.0f, 1.5f, 1.0f}, 0xff00ff00},
1309 {{640.0f, 0.0f, 1.5f, 1.0f}, 0xff00ff00},
1311 IDirect3DDevice7 *device;
1312 IDirectDrawSurface7 *rt;
1313 D3DCOLOR color;
1314 HWND window;
1315 HRESULT hr;
1316 UINT x, y;
1317 UINT i, j;
1319 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1320 0, 0, 640, 480, 0, 0, 0, 0);
1321 if (!(device = create_device(window, DDSCL_NORMAL)))
1323 skip("Failed to create a 3D device, skipping test.\n");
1324 DestroyWindow(window);
1325 return;
1328 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1329 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
1331 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 0.0f, 0);
1332 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1333 hr = IDirect3DDevice7_BeginScene(device);
1334 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1335 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_DIFFUSE, tquad, 4, 0);
1336 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1337 hr = IDirect3DDevice7_EndScene(device);
1338 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1340 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1341 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1342 for (i = 0; i < 4; ++i)
1344 for (j = 0; j < 4; ++j)
1346 x = 80 * ((2 * j) + 1);
1347 y = 60 * ((2 * i) + 1);
1348 color = get_surface_color(rt, x, y);
1349 ok(compare_color(color, 0x0000ff00, 1),
1350 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1353 IDirectDrawSurface7_Release(rt);
1355 IDirect3DDevice7_Release(device);
1356 DestroyWindow(window);
1359 static void test_ck_rgba(void)
1361 static struct
1363 struct vec4 position;
1364 struct vec2 texcoord;
1366 tquad[] =
1368 {{ 0.0f, 480.0f, 0.25f, 1.0f}, {0.0f, 0.0f}},
1369 {{ 0.0f, 0.0f, 0.25f, 1.0f}, {0.0f, 1.0f}},
1370 {{640.0f, 480.0f, 0.25f, 1.0f}, {1.0f, 0.0f}},
1371 {{640.0f, 0.0f, 0.25f, 1.0f}, {1.0f, 1.0f}},
1372 {{ 0.0f, 480.0f, 0.75f, 1.0f}, {0.0f, 0.0f}},
1373 {{ 0.0f, 0.0f, 0.75f, 1.0f}, {0.0f, 1.0f}},
1374 {{640.0f, 480.0f, 0.75f, 1.0f}, {1.0f, 0.0f}},
1375 {{640.0f, 0.0f, 0.75f, 1.0f}, {1.0f, 1.0f}},
1377 static const struct
1379 D3DCOLOR fill_color;
1380 BOOL color_key;
1381 BOOL blend;
1382 D3DCOLOR result1, result1_broken;
1383 D3DCOLOR result2, result2_broken;
1385 tests[] =
1387 /* r200 on Windows doesn't check the alpha component when applying the color
1388 * key, so the key matches on every texel. */
1389 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1390 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1391 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1392 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1393 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00ff0000, 0x00807f00, 0x000000ff},
1394 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x00ff0000, 0x0000ff00, 0x000000ff},
1395 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00, 0x00807f00, 0x00807f00},
1396 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1399 IDirectDrawSurface7 *texture;
1400 DDSURFACEDESC2 surface_desc;
1401 IDirect3DDevice7 *device;
1402 IDirectDrawSurface7 *rt;
1403 IDirectDraw7 *ddraw;
1404 IDirect3D7 *d3d;
1405 D3DCOLOR color;
1406 HWND window;
1407 DDBLTFX fx;
1408 HRESULT hr;
1409 UINT i;
1411 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1412 0, 0, 640, 480, 0, 0, 0, 0);
1413 if (!(device = create_device(window, DDSCL_NORMAL)))
1415 skip("Failed to create a 3D device, skipping test.\n");
1416 DestroyWindow(window);
1417 return;
1420 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1421 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1422 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1423 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1424 IDirect3D7_Release(d3d);
1426 memset(&surface_desc, 0, sizeof(surface_desc));
1427 surface_desc.dwSize = sizeof(surface_desc);
1428 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1429 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1430 surface_desc.dwWidth = 256;
1431 surface_desc.dwHeight = 256;
1432 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1433 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1434 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1435 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1436 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1437 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1438 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1439 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1440 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1441 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
1442 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1444 hr = IDirect3DDevice7_SetTexture(device, 0, texture);
1445 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1446 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1447 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1448 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1449 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1451 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1452 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1454 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
1456 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1457 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1458 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1459 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1461 memset(&fx, 0, sizeof(fx));
1462 fx.dwSize = sizeof(fx);
1463 U5(fx).dwFillColor = tests[i].fill_color;
1464 hr = IDirectDrawSurface7_Blt(texture, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1465 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1467 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 1.0f, 0);
1468 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1469 hr = IDirect3DDevice7_BeginScene(device);
1470 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1471 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1472 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1473 hr = IDirect3DDevice7_EndScene(device);
1474 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1476 color = get_surface_color(rt, 320, 240);
1477 ok(compare_color(color, tests[i].result1, 1) || compare_color(color, tests[i].result1_broken, 1),
1478 "Expected color 0x%08x for test %u, got 0x%08x.\n",
1479 tests[i].result1, i, color);
1481 U5(fx).dwFillColor = 0xff0000ff;
1482 hr = IDirectDrawSurface7_Blt(texture, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1483 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1485 hr = IDirect3DDevice7_BeginScene(device);
1486 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1487 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[4], 4, 0);
1488 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1489 hr = IDirect3DDevice7_EndScene(device);
1490 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1492 /* This tests that fragments that are masked out by the color key are
1493 * discarded, instead of just fully transparent. */
1494 color = get_surface_color(rt, 320, 240);
1495 ok(compare_color(color, tests[i].result2, 1) || compare_color(color, tests[i].result2_broken, 1),
1496 "Expected color 0x%08x for test %u, got 0x%08x.\n",
1497 tests[i].result2, i, color);
1500 IDirectDrawSurface7_Release(rt);
1501 IDirectDrawSurface7_Release(texture);
1502 IDirectDraw7_Release(ddraw);
1503 IDirect3DDevice7_Release(device);
1504 DestroyWindow(window);
1507 static void test_ck_default(void)
1509 static struct
1511 struct vec4 position;
1512 struct vec2 texcoord;
1514 tquad[] =
1516 {{ 0.0f, 480.0f, 0.0f, 1.0f}, {0.0f, 0.0f}},
1517 {{ 0.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 1.0f}},
1518 {{640.0f, 480.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
1519 {{640.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
1521 IDirectDrawSurface7 *surface, *rt;
1522 DDSURFACEDESC2 surface_desc;
1523 IDirect3DDevice7 *device;
1524 IDirectDraw7 *ddraw;
1525 IDirect3D7 *d3d;
1526 D3DCOLOR color;
1527 DWORD value;
1528 HWND window;
1529 DDBLTFX fx;
1530 HRESULT hr;
1532 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1533 0, 0, 640, 480, 0, 0, 0, 0);
1535 if (!(device = create_device(window, DDSCL_NORMAL)))
1537 skip("Failed to create a 3D device, skipping test.\n");
1538 DestroyWindow(window);
1539 return;
1542 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1543 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1544 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1545 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1546 IDirect3D7_Release(d3d);
1548 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1549 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1551 memset(&surface_desc, 0, sizeof(surface_desc));
1552 surface_desc.dwSize = sizeof(surface_desc);
1553 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1554 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1555 surface_desc.dwWidth = 256;
1556 surface_desc.dwHeight = 256;
1557 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1558 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
1559 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1560 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1561 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1562 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1563 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
1564 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
1565 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1566 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1567 hr = IDirect3DDevice7_SetTexture(device, 0, surface);
1568 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1570 memset(&fx, 0, sizeof(fx));
1571 fx.dwSize = sizeof(fx);
1572 U5(fx).dwFillColor = 0x000000ff;
1573 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1574 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
1576 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
1577 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1578 hr = IDirect3DDevice7_BeginScene(device);
1579 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1580 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1581 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1582 ok(!value, "Got unexpected color keying state %#x.\n", value);
1583 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1584 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1585 hr = IDirect3DDevice7_EndScene(device);
1586 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1587 color = get_surface_color(rt, 320, 240);
1588 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1590 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
1591 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1592 hr = IDirect3DDevice7_BeginScene(device);
1593 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1594 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
1595 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1596 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1597 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1598 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1599 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1600 ok(!!value, "Got unexpected color keying state %#x.\n", value);
1601 hr = IDirect3DDevice7_EndScene(device);
1602 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1603 color = get_surface_color(rt, 320, 240);
1604 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1606 IDirectDrawSurface7_Release(surface);
1607 IDirectDrawSurface7_Release(rt);
1608 IDirect3DDevice7_Release(device);
1609 IDirectDraw7_Release(ddraw);
1610 DestroyWindow(window);
1613 static void test_ck_complex(void)
1615 IDirectDrawSurface7 *surface, *mipmap, *tmp;
1616 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
1617 DDSURFACEDESC2 surface_desc;
1618 IDirect3DDevice7 *device;
1619 DDCOLORKEY color_key;
1620 IDirectDraw7 *ddraw;
1621 IDirect3D7 *d3d;
1622 unsigned int i;
1623 ULONG refcount;
1624 HWND window;
1625 HRESULT hr;
1627 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1628 0, 0, 640, 480, 0, 0, 0, 0);
1629 if (!(device = create_device(window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
1631 skip("Failed to create a 3D device, skipping test.\n");
1632 DestroyWindow(window);
1633 return;
1635 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1636 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1637 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1638 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1639 IDirect3D7_Release(d3d);
1641 memset(&surface_desc, 0, sizeof(surface_desc));
1642 surface_desc.dwSize = sizeof(surface_desc);
1643 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1644 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1645 surface_desc.dwWidth = 128;
1646 surface_desc.dwHeight = 128;
1647 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1648 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1650 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1651 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1652 color_key.dwColorSpaceLowValue = 0x0000ff00;
1653 color_key.dwColorSpaceHighValue = 0x0000ff00;
1654 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1655 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1656 memset(&color_key, 0, sizeof(color_key));
1657 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1658 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1659 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1660 color_key.dwColorSpaceLowValue);
1661 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1662 color_key.dwColorSpaceHighValue);
1664 mipmap = surface;
1665 IDirectDrawSurface_AddRef(mipmap);
1666 for (i = 0; i < 7; ++i)
1668 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
1669 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
1670 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1671 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1673 color_key.dwColorSpaceLowValue = 0x000000ff;
1674 color_key.dwColorSpaceHighValue = 0x000000ff;
1675 hr = IDirectDrawSurface7_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1676 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x, i %u.\n", hr, i);
1678 IDirectDrawSurface_Release(mipmap);
1679 mipmap = tmp;
1682 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
1683 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
1684 IDirectDrawSurface_Release(mipmap);
1685 refcount = IDirectDrawSurface7_Release(surface);
1686 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1688 memset(&surface_desc, 0, sizeof(surface_desc));
1689 surface_desc.dwSize = sizeof(surface_desc);
1690 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
1691 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
1692 U5(surface_desc).dwBackBufferCount = 1;
1693 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1694 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1696 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1697 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1698 color_key.dwColorSpaceLowValue = 0x0000ff00;
1699 color_key.dwColorSpaceHighValue = 0x0000ff00;
1700 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1701 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1702 memset(&color_key, 0, sizeof(color_key));
1703 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1704 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1705 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1706 color_key.dwColorSpaceLowValue);
1707 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1708 color_key.dwColorSpaceHighValue);
1710 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &tmp);
1711 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
1713 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1714 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1715 color_key.dwColorSpaceLowValue = 0x0000ff00;
1716 color_key.dwColorSpaceHighValue = 0x0000ff00;
1717 hr = IDirectDrawSurface7_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1718 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1719 memset(&color_key, 0, sizeof(color_key));
1720 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1721 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1722 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1723 color_key.dwColorSpaceLowValue);
1724 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1725 color_key.dwColorSpaceHighValue);
1727 IDirectDrawSurface_Release(tmp);
1729 refcount = IDirectDrawSurface7_Release(surface);
1730 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1731 IDirectDraw7_Release(ddraw);
1732 refcount = IDirect3DDevice7_Release(device);
1733 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1734 DestroyWindow(window);
1737 struct qi_test
1739 REFIID iid;
1740 REFIID refcount_iid;
1741 HRESULT hr;
1744 static void test_qi(const char *test_name, IUnknown *base_iface,
1745 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
1747 ULONG refcount, expected_refcount;
1748 IUnknown *iface1, *iface2;
1749 HRESULT hr;
1750 UINT i, j;
1752 for (i = 0; i < entry_count; ++i)
1754 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
1755 ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
1756 if (SUCCEEDED(hr))
1758 for (j = 0; j < entry_count; ++j)
1760 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
1761 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
1762 if (SUCCEEDED(hr))
1764 expected_refcount = 0;
1765 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
1766 ++expected_refcount;
1767 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
1768 ++expected_refcount;
1769 refcount = IUnknown_Release(iface2);
1770 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
1771 refcount, test_name, i, j, expected_refcount);
1775 expected_refcount = 0;
1776 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
1777 ++expected_refcount;
1778 refcount = IUnknown_Release(iface1);
1779 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
1780 refcount, test_name, i, expected_refcount);
1785 static void test_surface_qi(void)
1787 static const struct qi_test tests[] =
1789 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
1790 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
1791 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
1792 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1793 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
1794 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
1795 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
1796 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
1797 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
1798 {&IID_IDirect3DDevice7, NULL, E_NOINTERFACE},
1799 {&IID_IDirect3DDevice3, NULL, E_NOINTERFACE},
1800 {&IID_IDirect3DDevice2, NULL, E_NOINTERFACE},
1801 {&IID_IDirect3DDevice, NULL, E_NOINTERFACE},
1802 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
1803 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
1804 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
1805 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
1806 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
1807 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
1808 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
1809 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
1810 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
1811 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
1812 {&IID_IDirect3D, NULL, E_NOINTERFACE},
1813 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
1814 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
1815 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
1816 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
1817 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
1818 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
1819 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
1820 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
1821 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
1822 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
1823 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
1824 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
1825 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
1826 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
1827 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
1828 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
1829 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
1830 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
1833 IDirectDrawSurface7 *surface;
1834 DDSURFACEDESC2 surface_desc;
1835 IDirect3DDevice7 *device;
1836 IDirectDraw7 *ddraw;
1837 HWND window;
1838 HRESULT hr;
1840 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1841 0, 0, 640, 480, 0, 0, 0, 0);
1842 /* Try to create a D3D device to see if the ddraw implementation supports
1843 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
1844 * doesn't support e.g. the IDirect3DTexture interfaces. */
1845 if (!(device = create_device(window, DDSCL_NORMAL)))
1847 skip("Failed to create a 3D device, skipping test.\n");
1848 DestroyWindow(window);
1849 return;
1851 IDirect3DDevice_Release(device);
1852 ddraw = create_ddraw();
1853 ok(!!ddraw, "Failed to create a ddraw object.\n");
1854 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1855 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1857 memset(&surface_desc, 0, sizeof(surface_desc));
1858 surface_desc.dwSize = sizeof(surface_desc);
1859 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1860 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1861 surface_desc.dwWidth = 512;
1862 surface_desc.dwHeight = 512;
1863 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1864 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1866 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface7, tests, sizeof(tests) / sizeof(*tests));
1868 IDirectDrawSurface7_Release(surface);
1869 IDirectDraw7_Release(ddraw);
1870 DestroyWindow(window);
1873 static void test_device_qi(void)
1875 static const struct qi_test tests[] =
1877 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
1878 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
1879 {&IID_IDirectDrawGammaControl, NULL, E_NOINTERFACE},
1880 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1881 {&IID_IDirectDrawSurface7, NULL, E_NOINTERFACE},
1882 {&IID_IDirectDrawSurface4, NULL, E_NOINTERFACE},
1883 {&IID_IDirectDrawSurface3, NULL, E_NOINTERFACE},
1884 {&IID_IDirectDrawSurface2, NULL, E_NOINTERFACE},
1885 {&IID_IDirectDrawSurface, NULL, E_NOINTERFACE},
1886 {&IID_IDirect3DDevice7, &IID_IDirect3DDevice7, S_OK },
1887 {&IID_IDirect3DDevice3, NULL, E_NOINTERFACE},
1888 {&IID_IDirect3DDevice2, NULL, E_NOINTERFACE},
1889 {&IID_IDirect3DDevice, NULL, E_NOINTERFACE},
1890 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
1891 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
1892 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
1893 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
1894 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
1895 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
1896 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
1897 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
1898 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
1899 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
1900 {&IID_IDirect3D, NULL, E_NOINTERFACE},
1901 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
1902 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
1903 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
1904 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
1905 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
1906 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
1907 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
1908 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
1909 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
1910 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
1911 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
1912 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
1913 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
1914 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
1915 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
1916 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
1917 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
1918 {&IID_IUnknown, &IID_IDirect3DDevice7, S_OK },
1921 IDirect3DDevice7 *device;
1922 HWND window;
1924 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1925 0, 0, 640, 480, 0, 0, 0, 0);
1926 if (!(device = create_device(window, DDSCL_NORMAL)))
1928 skip("Failed to create a 3D device, skipping test.\n");
1929 DestroyWindow(window);
1930 return;
1933 test_qi("device_qi", (IUnknown *)device, &IID_IDirect3DDevice7, tests, sizeof(tests) / sizeof(*tests));
1935 IDirect3DDevice7_Release(device);
1936 DestroyWindow(window);
1939 static void test_wndproc(void)
1941 LONG_PTR proc, ddraw_proc;
1942 IDirectDraw7 *ddraw;
1943 WNDCLASSA wc = {0};
1944 HWND window;
1945 HRESULT hr;
1946 ULONG ref;
1948 static struct message messages[] =
1950 {WM_WINDOWPOSCHANGING, FALSE, 0},
1951 {WM_MOVE, FALSE, 0},
1952 {WM_SIZE, FALSE, 0},
1953 {WM_WINDOWPOSCHANGING, FALSE, 0},
1954 {WM_ACTIVATE, FALSE, 0},
1955 {WM_SETFOCUS, FALSE, 0},
1956 {0, FALSE, 0},
1959 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
1960 ddraw = create_ddraw();
1961 ok(!!ddraw, "Failed to create a ddraw object.\n");
1963 wc.lpfnWndProc = test_proc;
1964 wc.lpszClassName = "ddraw_test_wndproc_wc";
1965 ok(RegisterClassA(&wc), "Failed to register window class.\n");
1967 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
1968 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
1970 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1971 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1972 (LONG_PTR)test_proc, proc);
1973 expect_messages = messages;
1974 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1975 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1976 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
1977 expect_messages = NULL;
1978 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1979 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1980 (LONG_PTR)test_proc, proc);
1981 ref = IDirectDraw7_Release(ddraw);
1982 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1983 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1984 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1985 (LONG_PTR)test_proc, proc);
1987 /* DDSCL_NORMAL doesn't. */
1988 ddraw = create_ddraw();
1989 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1990 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1991 (LONG_PTR)test_proc, proc);
1992 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
1993 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
1994 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
1995 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1996 (LONG_PTR)test_proc, proc);
1997 ref = IDirectDraw7_Release(ddraw);
1998 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
1999 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2000 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2001 (LONG_PTR)test_proc, proc);
2003 /* The original window proc is only restored by ddraw if the current
2004 * window proc matches the one ddraw set. This also affects switching
2005 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
2006 ddraw = create_ddraw();
2007 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2008 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2009 (LONG_PTR)test_proc, proc);
2010 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2011 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2012 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2013 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2014 (LONG_PTR)test_proc, proc);
2015 ddraw_proc = proc;
2016 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2017 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2018 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2019 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2020 (LONG_PTR)test_proc, proc);
2021 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2022 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2023 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2024 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2025 (LONG_PTR)test_proc, proc);
2026 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2027 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2028 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2029 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2030 (LONG_PTR)DefWindowProcA, proc);
2031 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2032 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2033 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc);
2034 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2035 (LONG_PTR)DefWindowProcA, proc);
2036 ref = IDirectDraw7_Release(ddraw);
2037 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2038 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2039 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2040 (LONG_PTR)test_proc, proc);
2042 ddraw = create_ddraw();
2043 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2044 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2045 (LONG_PTR)test_proc, proc);
2046 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2047 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2048 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2049 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2050 (LONG_PTR)test_proc, proc);
2051 ref = IDirectDraw7_Release(ddraw);
2052 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2053 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2054 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2055 (LONG_PTR)DefWindowProcA, proc);
2057 fix_wndproc(window, (LONG_PTR)test_proc);
2058 expect_messages = NULL;
2059 DestroyWindow(window);
2060 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2063 static void test_window_style(void)
2065 LONG style, exstyle, tmp, expected_style;
2066 RECT fullscreen_rect, r;
2067 IDirectDraw7 *ddraw;
2068 HWND window;
2069 HRESULT hr;
2070 ULONG ref;
2071 BOOL ret;
2073 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2074 0, 0, 100, 100, 0, 0, 0, 0);
2075 ddraw = create_ddraw();
2076 ok(!!ddraw, "Failed to create a ddraw object.\n");
2078 style = GetWindowLongA(window, GWL_STYLE);
2079 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
2080 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2082 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2083 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2085 tmp = GetWindowLongA(window, GWL_STYLE);
2086 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2087 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2088 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2090 GetWindowRect(window, &r);
2091 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2092 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2093 r.left, r.top, r.right, r.bottom);
2094 GetClientRect(window, &r);
2095 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2097 ret = SetForegroundWindow(GetDesktopWindow());
2098 ok(ret, "Failed to set foreground window.\n");
2100 tmp = GetWindowLongA(window, GWL_STYLE);
2101 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2102 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2103 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2105 ret = SetForegroundWindow(window);
2106 ok(ret, "Failed to set foreground window.\n");
2107 /* Windows 7 (but not Vista and XP) shows the window when it receives focus. Hide it again,
2108 * the next tests expect this. */
2109 ShowWindow(window, SW_HIDE);
2111 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2112 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2114 tmp = GetWindowLongA(window, GWL_STYLE);
2115 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2116 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2117 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2119 ShowWindow(window, SW_SHOW);
2120 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2121 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2123 tmp = GetWindowLongA(window, GWL_STYLE);
2124 expected_style = style | WS_VISIBLE;
2125 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2126 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2127 expected_style = exstyle | WS_EX_TOPMOST;
2128 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2130 ret = SetForegroundWindow(GetDesktopWindow());
2131 ok(ret, "Failed to set foreground window.\n");
2132 tmp = GetWindowLongA(window, GWL_STYLE);
2133 expected_style = style | WS_VISIBLE | WS_MINIMIZE;
2134 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2135 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2136 expected_style = exstyle | WS_EX_TOPMOST;
2137 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2139 ref = IDirectDraw7_Release(ddraw);
2140 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2142 DestroyWindow(window);
2145 static void test_redundant_mode_set(void)
2147 DDSURFACEDESC2 surface_desc = {0};
2148 IDirectDraw7 *ddraw;
2149 HWND window;
2150 HRESULT hr;
2151 RECT r, s;
2152 ULONG ref;
2154 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2155 0, 0, 100, 100, 0, 0, 0, 0);
2156 ddraw = create_ddraw();
2157 ok(!!ddraw, "Failed to create a ddraw object.\n");
2158 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2159 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2161 surface_desc.dwSize = sizeof(surface_desc);
2162 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
2163 ok(SUCCEEDED(hr), "GetDipslayMode failed, hr %#x.\n", hr);
2165 hr = IDirectDraw7_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2166 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
2167 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2169 GetWindowRect(window, &r);
2170 r.right /= 2;
2171 r.bottom /= 2;
2172 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
2173 GetWindowRect(window, &s);
2174 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2175 r.left, r.top, r.right, r.bottom,
2176 s.left, s.top, s.right, s.bottom);
2178 hr = IDirectDraw7_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2179 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
2180 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2182 GetWindowRect(window, &s);
2183 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2184 r.left, r.top, r.right, r.bottom,
2185 s.left, s.top, s.right, s.bottom);
2187 ref = IDirectDraw7_Release(ddraw);
2188 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2190 DestroyWindow(window);
2193 static SIZE screen_size, screen_size2;
2195 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2197 if (message == WM_SIZE)
2199 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2200 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2203 return test_proc(hwnd, message, wparam, lparam);
2206 static LRESULT CALLBACK mode_set_proc2(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2208 if (message == WM_SIZE)
2210 screen_size2.cx = GetSystemMetrics(SM_CXSCREEN);
2211 screen_size2.cy = GetSystemMetrics(SM_CYSCREEN);
2214 return test_proc(hwnd, message, wparam, lparam);
2217 struct test_coop_level_mode_set_enum_param
2219 DWORD ddraw_width, ddraw_height, user32_width, user32_height;
2222 static HRESULT CALLBACK test_coop_level_mode_set_enum_cb(DDSURFACEDESC2 *surface_desc, void *context)
2224 struct test_coop_level_mode_set_enum_param *param = context;
2226 if (U1(U4(*surface_desc).ddpfPixelFormat).dwRGBBitCount != registry_mode.dmBitsPerPel)
2227 return DDENUMRET_OK;
2228 if (surface_desc->dwWidth == registry_mode.dmPelsWidth
2229 && surface_desc->dwHeight == registry_mode.dmPelsHeight)
2230 return DDENUMRET_OK;
2232 if (!param->ddraw_width)
2234 param->ddraw_width = surface_desc->dwWidth;
2235 param->ddraw_height = surface_desc->dwHeight;
2236 return DDENUMRET_OK;
2238 if (surface_desc->dwWidth == param->ddraw_width && surface_desc->dwHeight == param->ddraw_height)
2239 return DDENUMRET_OK;
2241 param->user32_width = surface_desc->dwWidth;
2242 param->user32_height = surface_desc->dwHeight;
2243 return DDENUMRET_CANCEL;
2246 static void test_coop_level_mode_set(void)
2248 IDirectDrawSurface7 *primary;
2249 RECT registry_rect, ddraw_rect, user32_rect, r;
2250 IDirectDraw7 *ddraw;
2251 DDSURFACEDESC2 ddsd;
2252 WNDCLASSA wc = {0};
2253 HWND window, window2;
2254 HRESULT hr;
2255 ULONG ref;
2256 MSG msg;
2257 struct test_coop_level_mode_set_enum_param param;
2258 DEVMODEW devmode;
2259 BOOL ret;
2260 LONG change_ret;
2262 static const struct message exclusive_messages[] =
2264 {WM_WINDOWPOSCHANGING, FALSE, 0},
2265 {WM_WINDOWPOSCHANGED, FALSE, 0},
2266 {WM_SIZE, FALSE, 0},
2267 {WM_DISPLAYCHANGE, FALSE, 0},
2268 {0, FALSE, 0},
2270 static const struct message exclusive_focus_loss_messages[] =
2272 {WM_ACTIVATE, TRUE, WA_INACTIVE},
2273 {WM_DISPLAYCHANGE, FALSE, 0},
2274 {WM_WINDOWPOSCHANGING, FALSE, 0},
2275 /* Like d3d8 and d3d9 ddraw seems to use SW_SHOWMINIMIZED instead of
2276 * SW_MINIMIZED, causing a recursive window activation that does not
2277 * produce the same result in Wine yet. Ignore the difference for now.
2278 * {WM_ACTIVATE, TRUE, 0x200000 | WA_ACTIVE}, */
2279 {WM_WINDOWPOSCHANGED, FALSE, 0},
2280 {WM_MOVE, FALSE, 0},
2281 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2282 {WM_ACTIVATEAPP, TRUE, FALSE},
2283 {0, FALSE, 0},
2285 static const struct message exclusive_focus_restore_messages[] =
2287 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* From the ShowWindow(SW_RESTORE). */
2288 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Generated by ddraw, matches d3d9 behavior. */
2289 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching previous message. */
2290 {WM_SIZE, FALSE, 0}, /* DefWindowProc. */
2291 {WM_DISPLAYCHANGE, FALSE, 0}, /* Ddraw restores mode. */
2292 /* Native redundantly sets the window size here. */
2293 {WM_ACTIVATEAPP, TRUE, TRUE}, /* End of ddraw's hooks. */
2294 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching the one from ShowWindow. */
2295 {WM_MOVE, FALSE, 0}, /* DefWindowProc. */
2296 {WM_SIZE, TRUE, SIZE_RESTORED}, /* DefWindowProc. */
2297 {0, FALSE, 0},
2299 static const struct message sc_restore_messages[] =
2301 {WM_SYSCOMMAND, TRUE, SC_RESTORE},
2302 {WM_WINDOWPOSCHANGING, FALSE, 0},
2303 {WM_WINDOWPOSCHANGED, FALSE, 0},
2304 {WM_SIZE, TRUE, SIZE_RESTORED},
2305 {0, FALSE, 0},
2307 static const struct message sc_minimize_messages[] =
2309 {WM_SYSCOMMAND, TRUE, SC_MINIMIZE},
2310 {WM_WINDOWPOSCHANGING, FALSE, 0},
2311 {WM_WINDOWPOSCHANGED, FALSE, 0},
2312 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2313 {0, FALSE, 0},
2315 static const struct message sc_maximize_messages[] =
2317 {WM_SYSCOMMAND, TRUE, SC_MAXIMIZE},
2318 {WM_WINDOWPOSCHANGING, FALSE, 0},
2319 {WM_WINDOWPOSCHANGED, FALSE, 0},
2320 {WM_SIZE, TRUE, SIZE_MAXIMIZED},
2321 {0, FALSE, 0},
2324 static const struct message normal_messages[] =
2326 {WM_DISPLAYCHANGE, FALSE, 0},
2327 {0, FALSE, 0},
2330 ddraw = create_ddraw();
2331 ok(!!ddraw, "Failed to create a ddraw object.\n");
2333 memset(&param, 0, sizeof(param));
2334 hr = IDirectDraw7_EnumDisplayModes(ddraw, 0, NULL, &param, test_coop_level_mode_set_enum_cb);
2335 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
2336 ref = IDirectDraw7_Release(ddraw);
2337 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2339 if (!param.user32_height)
2341 skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
2342 return;
2345 SetRect(&registry_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2346 SetRect(&ddraw_rect, 0, 0, param.ddraw_width, param.ddraw_height);
2347 SetRect(&user32_rect, 0, 0, param.user32_width, param.user32_height);
2349 memset(&devmode, 0, sizeof(devmode));
2350 devmode.dmSize = sizeof(devmode);
2351 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2352 devmode.dmPelsWidth = param.user32_width;
2353 devmode.dmPelsHeight = param.user32_height;
2354 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2355 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2357 ddraw = create_ddraw();
2358 ok(!!ddraw, "Failed to create a ddraw object.\n");
2360 wc.lpfnWndProc = mode_set_proc;
2361 wc.lpszClassName = "ddraw_test_wndproc_wc";
2362 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2363 wc.lpfnWndProc = mode_set_proc2;
2364 wc.lpszClassName = "ddraw_test_wndproc_wc2";
2365 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2367 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
2368 0, 0, 100, 100, 0, 0, 0, 0);
2369 window2 = CreateWindowA("ddraw_test_wndproc_wc2", "ddraw_test", WS_OVERLAPPEDWINDOW,
2370 0, 0, 100, 100, 0, 0, 0, 0);
2372 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2373 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2375 GetWindowRect(window, &r);
2376 ok(EqualRect(&r, &user32_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2377 user32_rect.left, user32_rect.top, user32_rect.right, user32_rect.bottom,
2378 r.left, r.top, r.right, r.bottom);
2380 memset(&ddsd, 0, sizeof(ddsd));
2381 ddsd.dwSize = sizeof(ddsd);
2382 ddsd.dwFlags = DDSD_CAPS;
2383 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2385 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2386 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2387 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2388 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2389 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2390 param.user32_width, ddsd.dwWidth);
2391 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2392 param.user32_height, ddsd.dwHeight);
2394 GetWindowRect(window, &r);
2395 ok(EqualRect(&r, &user32_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2396 user32_rect.left, user32_rect.top, user32_rect.right, user32_rect.bottom,
2397 r.left, r.top, r.right, r.bottom);
2399 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2400 expect_messages = exclusive_messages;
2401 screen_size.cx = 0;
2402 screen_size.cy = 0;
2404 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2405 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2407 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2408 expect_messages = NULL;
2409 ok(screen_size.cx == param.ddraw_width && screen_size.cy == param.ddraw_height,
2410 "Expected screen size %ux%u, got %ux%u.\n",
2411 param.ddraw_width, param.ddraw_height, screen_size.cx, screen_size.cy);
2413 GetWindowRect(window, &r);
2414 ok(EqualRect(&r, &ddraw_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2415 ddraw_rect.left, ddraw_rect.top, ddraw_rect.right, ddraw_rect.bottom,
2416 r.left, r.top, r.right, r.bottom);
2418 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2419 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2420 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2421 param.user32_width, ddsd.dwWidth);
2422 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2423 param.user32_height, ddsd.dwHeight);
2424 IDirectDrawSurface7_Release(primary);
2426 memset(&ddsd, 0, sizeof(ddsd));
2427 ddsd.dwSize = sizeof(ddsd);
2428 ddsd.dwFlags = DDSD_CAPS;
2429 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2431 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2432 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2433 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2434 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2435 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2436 param.ddraw_width, ddsd.dwWidth);
2437 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2438 param.ddraw_height, ddsd.dwHeight);
2440 GetWindowRect(window, &r);
2441 ok(EqualRect(&r, &ddraw_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2442 ddraw_rect.left, ddraw_rect.top, ddraw_rect.right, ddraw_rect.bottom,
2443 r.left, r.top, r.right, r.bottom);
2445 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2446 expect_messages = exclusive_messages;
2447 screen_size.cx = 0;
2448 screen_size.cy = 0;
2450 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2451 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2453 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2454 expect_messages = NULL;
2455 ok(screen_size.cx == param.user32_width && screen_size.cy == param.user32_height,
2456 "Expected screen size %ux%u, got %ux%u.\n",
2457 param.user32_width, param.user32_height, screen_size.cx, screen_size.cy);
2459 GetWindowRect(window, &r);
2460 ok(EqualRect(&r, &user32_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2461 user32_rect.left, user32_rect.top, user32_rect.right, user32_rect.bottom,
2462 r.left, r.top, r.right, r.bottom);
2464 expect_messages = exclusive_focus_loss_messages;
2465 ret = SetForegroundWindow(GetDesktopWindow());
2466 ok(ret, "Failed to set foreground window.\n");
2467 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2468 memset(&devmode, 0, sizeof(devmode));
2469 devmode.dmSize = sizeof(devmode);
2470 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2471 ok(ret, "Failed to get display mode.\n");
2472 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2473 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
2474 devmode.dmPelsWidth, devmode.dmPelsHeight);
2476 expect_messages = exclusive_focus_restore_messages;
2477 ShowWindow(window, SW_RESTORE);
2478 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2480 GetWindowRect(window, &r);
2481 ok(EqualRect(&r, &ddraw_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2482 ddraw_rect.left, ddraw_rect.top, ddraw_rect.right, ddraw_rect.bottom,
2483 r.left, r.top, r.right, r.bottom);
2484 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2485 ok(ret, "Failed to get display mode.\n");
2486 ok(devmode.dmPelsWidth == param.ddraw_width
2487 && devmode.dmPelsHeight == param.ddraw_height, "Got unexpect screen size %ux%u.\n",
2488 devmode.dmPelsWidth, devmode.dmPelsHeight);
2490 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2491 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2492 /* Normally the primary should be restored here. Unfortunately this causes the
2493 * GetSurfaceDesc call after the next display mode change to crash on the Windows 8
2494 * testbot. Another Restore call would presumably avoid the crash, but it also moots
2495 * the point of the GetSurfaceDesc call. */
2497 expect_messages = sc_minimize_messages;
2498 SendMessageA(window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
2499 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2500 expect_messages = NULL;
2502 expect_messages = sc_restore_messages;
2503 SendMessageA(window, WM_SYSCOMMAND, SC_RESTORE, 0);
2504 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2505 expect_messages = NULL;
2507 expect_messages = sc_maximize_messages;
2508 SendMessageA(window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
2509 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2510 expect_messages = NULL;
2512 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2513 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2515 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2516 expect_messages = exclusive_messages;
2517 screen_size.cx = 0;
2518 screen_size.cy = 0;
2520 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
2521 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2523 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2524 expect_messages = NULL;
2525 ok(screen_size.cx == registry_mode.dmPelsWidth
2526 && screen_size.cy == registry_mode.dmPelsHeight,
2527 "Expected screen size %ux%u, got %ux%u.\n",
2528 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size.cx, screen_size.cy);
2530 GetWindowRect(window, &r);
2531 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2532 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2533 r.left, r.top, r.right, r.bottom);
2535 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2536 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2537 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2538 param.ddraw_width, ddsd.dwWidth);
2539 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2540 param.ddraw_height, ddsd.dwHeight);
2541 IDirectDrawSurface7_Release(primary);
2543 /* For Wine. */
2544 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
2545 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2547 memset(&ddsd, 0, sizeof(ddsd));
2548 ddsd.dwSize = sizeof(ddsd);
2549 ddsd.dwFlags = DDSD_CAPS;
2550 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2552 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2553 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2554 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2555 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2556 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2557 registry_mode.dmPelsWidth, ddsd.dwWidth);
2558 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2559 registry_mode.dmPelsHeight, ddsd.dwHeight);
2561 GetWindowRect(window, &r);
2562 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2563 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2564 r.left, r.top, r.right, r.bottom);
2566 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2567 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2569 GetWindowRect(window, &r);
2570 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2571 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2572 r.left, r.top, r.right, r.bottom);
2574 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2575 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2576 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2577 registry_mode.dmPelsWidth, ddsd.dwWidth);
2578 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2579 registry_mode.dmPelsHeight, ddsd.dwHeight);
2580 IDirectDrawSurface7_Release(primary);
2582 memset(&ddsd, 0, sizeof(ddsd));
2583 ddsd.dwSize = sizeof(ddsd);
2584 ddsd.dwFlags = DDSD_CAPS;
2585 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2587 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2588 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2589 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2590 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2591 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2592 registry_mode.dmPelsWidth, ddsd.dwWidth);
2593 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2594 registry_mode.dmPelsHeight, ddsd.dwHeight);
2596 GetWindowRect(window, &r);
2597 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2598 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2599 r.left, r.top, r.right, r.bottom);
2601 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2602 expect_messages = normal_messages;
2603 screen_size.cx = 0;
2604 screen_size.cy = 0;
2606 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2607 devmode.dmPelsWidth = param.user32_width;
2608 devmode.dmPelsHeight = param.user32_height;
2609 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2610 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2612 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2613 expect_messages = NULL;
2614 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2616 GetWindowRect(window, &r);
2617 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2618 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2619 r.left, r.top, r.right, r.bottom);
2621 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2622 expect_messages = normal_messages;
2623 screen_size.cx = 0;
2624 screen_size.cy = 0;
2626 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2627 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2629 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2630 expect_messages = NULL;
2631 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2633 GetWindowRect(window, &r);
2634 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2635 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2636 r.left, r.top, r.right, r.bottom);
2638 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2639 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2640 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2641 registry_mode.dmPelsWidth, ddsd.dwWidth);
2642 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2643 registry_mode.dmPelsHeight, ddsd.dwHeight);
2644 IDirectDrawSurface7_Release(primary);
2646 memset(&ddsd, 0, sizeof(ddsd));
2647 ddsd.dwSize = sizeof(ddsd);
2648 ddsd.dwFlags = DDSD_CAPS;
2649 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2651 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2652 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2653 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2654 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2655 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2656 param.ddraw_width, ddsd.dwWidth);
2657 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2658 param.ddraw_height, ddsd.dwHeight);
2660 GetWindowRect(window, &r);
2661 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2662 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2663 r.left, r.top, r.right, r.bottom);
2665 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2666 expect_messages = normal_messages;
2667 screen_size.cx = 0;
2668 screen_size.cy = 0;
2670 hr = IDirectDraw_RestoreDisplayMode(ddraw);
2671 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2673 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2674 expect_messages = NULL;
2675 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2677 GetWindowRect(window, &r);
2678 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2679 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2680 r.left, r.top, r.right, r.bottom);
2682 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2683 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2684 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2685 param.ddraw_width, ddsd.dwWidth);
2686 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2687 param.ddraw_height, ddsd.dwHeight);
2688 IDirectDrawSurface7_Release(primary);
2690 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2691 ok(ret, "Failed to get display mode.\n");
2692 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2693 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
2694 "Expected resolution %ux%u, got %ux%u.\n",
2695 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
2696 devmode.dmPelsWidth, devmode.dmPelsHeight);
2697 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
2698 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2700 memset(&ddsd, 0, sizeof(ddsd));
2701 ddsd.dwSize = sizeof(ddsd);
2702 ddsd.dwFlags = DDSD_CAPS;
2703 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2705 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2706 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2707 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2708 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2709 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2710 registry_mode.dmPelsWidth, ddsd.dwWidth);
2711 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2712 registry_mode.dmPelsHeight, ddsd.dwHeight);
2714 GetWindowRect(window, &r);
2715 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2716 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2717 r.left, r.top, r.right, r.bottom);
2719 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
2720 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
2721 * not DDSCL_FULLSCREEN. */
2722 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2723 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2725 GetWindowRect(window, &r);
2726 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2727 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2728 r.left, r.top, r.right, r.bottom);
2730 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2731 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2732 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2733 registry_mode.dmPelsWidth, ddsd.dwWidth);
2734 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2735 registry_mode.dmPelsHeight, ddsd.dwHeight);
2736 IDirectDrawSurface7_Release(primary);
2738 memset(&ddsd, 0, sizeof(ddsd));
2739 ddsd.dwSize = sizeof(ddsd);
2740 ddsd.dwFlags = DDSD_CAPS;
2741 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2743 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2744 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2745 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2746 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2747 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2748 registry_mode.dmPelsWidth, ddsd.dwWidth);
2749 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2750 registry_mode.dmPelsHeight, ddsd.dwHeight);
2752 GetWindowRect(window, &r);
2753 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2754 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2755 r.left, r.top, r.right, r.bottom);
2757 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2758 expect_messages = normal_messages;
2759 screen_size.cx = 0;
2760 screen_size.cy = 0;
2762 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2763 devmode.dmPelsWidth = param.user32_width;
2764 devmode.dmPelsHeight = param.user32_height;
2765 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2766 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2768 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2769 expect_messages = NULL;
2770 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2772 GetWindowRect(window, &r);
2773 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2774 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2775 r.left, r.top, r.right, r.bottom);
2777 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2778 expect_messages = normal_messages;
2779 screen_size.cx = 0;
2780 screen_size.cy = 0;
2782 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2783 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2785 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2786 expect_messages = NULL;
2787 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2789 GetWindowRect(window, &r);
2790 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2791 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2792 r.left, r.top, r.right, r.bottom);
2794 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2795 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2796 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2797 registry_mode.dmPelsWidth, ddsd.dwWidth);
2798 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2799 registry_mode.dmPelsHeight, ddsd.dwHeight);
2800 IDirectDrawSurface7_Release(primary);
2802 memset(&ddsd, 0, sizeof(ddsd));
2803 ddsd.dwSize = sizeof(ddsd);
2804 ddsd.dwFlags = DDSD_CAPS;
2805 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2807 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2808 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2809 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2810 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2811 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2812 param.ddraw_width, ddsd.dwWidth);
2813 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2814 param.ddraw_height, ddsd.dwHeight);
2816 GetWindowRect(window, &r);
2817 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2818 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2819 r.left, r.top, r.right, r.bottom);
2821 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2822 expect_messages = normal_messages;
2823 screen_size.cx = 0;
2824 screen_size.cy = 0;
2826 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
2827 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2829 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2830 expect_messages = NULL;
2831 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2833 GetWindowRect(window, &r);
2834 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2835 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2836 r.left, r.top, r.right, r.bottom);
2838 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2839 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2840 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2841 param.ddraw_width, ddsd.dwWidth);
2842 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2843 param.ddraw_height, ddsd.dwHeight);
2844 IDirectDrawSurface7_Release(primary);
2846 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2847 ok(ret, "Failed to get display mode.\n");
2848 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2849 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
2850 "Expected resolution %ux%u, got %ux%u.\n",
2851 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
2852 devmode.dmPelsWidth, devmode.dmPelsHeight);
2853 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
2854 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2856 memset(&ddsd, 0, sizeof(ddsd));
2857 ddsd.dwSize = sizeof(ddsd);
2858 ddsd.dwFlags = DDSD_CAPS;
2859 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2861 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2862 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2863 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2864 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2865 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2866 registry_mode.dmPelsWidth, ddsd.dwWidth);
2867 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2868 registry_mode.dmPelsHeight, ddsd.dwHeight);
2869 IDirectDrawSurface7_Release(primary);
2871 GetWindowRect(window, &r);
2872 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2873 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2874 r.left, r.top, r.right, r.bottom);
2876 /* Changing the coop level from EXCLUSIVE to NORMAL restores the screen resolution */
2877 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2878 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2879 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2880 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2882 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2883 expect_messages = exclusive_messages;
2884 screen_size.cx = 0;
2885 screen_size.cy = 0;
2887 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2888 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2890 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2891 expect_messages = NULL;
2892 ok(screen_size.cx == registry_mode.dmPelsWidth
2893 && screen_size.cy == registry_mode.dmPelsHeight,
2894 "Expected screen size %ux%u, got %ux%u.\n",
2895 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
2896 screen_size.cx, screen_size.cy);
2898 GetWindowRect(window, &r);
2899 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2900 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2901 r.left, r.top, r.right, r.bottom);
2903 memset(&ddsd, 0, sizeof(ddsd));
2904 ddsd.dwSize = sizeof(ddsd);
2905 ddsd.dwFlags = DDSD_CAPS;
2906 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2908 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2909 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2910 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2911 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2912 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2913 registry_mode.dmPelsWidth, ddsd.dwWidth);
2914 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2915 registry_mode.dmPelsHeight, ddsd.dwHeight);
2916 IDirectDrawSurface7_Release(primary);
2918 /* The screen restore is a property of DDSCL_EXCLUSIVE */
2919 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2920 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2921 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2922 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2924 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2925 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2927 memset(&ddsd, 0, sizeof(ddsd));
2928 ddsd.dwSize = sizeof(ddsd);
2929 ddsd.dwFlags = DDSD_CAPS;
2930 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2932 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2933 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2934 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2935 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2936 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2937 param.ddraw_width, ddsd.dwWidth);
2938 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2939 param.ddraw_height, ddsd.dwHeight);
2940 IDirectDrawSurface7_Release(primary);
2942 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
2943 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2945 /* If the window is changed at the same time, messages are sent to the new window. */
2946 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2947 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2948 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2949 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2951 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2952 expect_messages = exclusive_messages;
2953 screen_size.cx = 0;
2954 screen_size.cy = 0;
2955 screen_size2.cx = 0;
2956 screen_size2.cy = 0;
2958 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
2959 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2961 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2962 expect_messages = NULL;
2963 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n",
2964 screen_size.cx, screen_size.cy);
2965 ok(screen_size2.cx == registry_mode.dmPelsWidth && screen_size2.cy == registry_mode.dmPelsHeight,
2966 "Expected screen size 2 %ux%u, got %ux%u.\n",
2967 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size2.cx, screen_size2.cy);
2969 GetWindowRect(window, &r);
2970 ok(EqualRect(&r, &ddraw_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2971 ddraw_rect.left, ddraw_rect.top, ddraw_rect.right, ddraw_rect.bottom,
2972 r.left, r.top, r.right, r.bottom);
2973 GetWindowRect(window2, &r);
2974 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2975 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2976 r.left, r.top, r.right, r.bottom);
2978 memset(&ddsd, 0, sizeof(ddsd));
2979 ddsd.dwSize = sizeof(ddsd);
2980 ddsd.dwFlags = DDSD_CAPS;
2981 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2983 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2984 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2985 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2986 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2987 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2988 registry_mode.dmPelsWidth, ddsd.dwWidth);
2989 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2990 registry_mode.dmPelsHeight, ddsd.dwHeight);
2991 IDirectDrawSurface7_Release(primary);
2993 ref = IDirectDraw7_Release(ddraw);
2994 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2996 GetWindowRect(window, &r);
2997 ok(EqualRect(&r, &ddraw_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2998 ddraw_rect.left, ddraw_rect.top, ddraw_rect.right, ddraw_rect.bottom,
2999 r.left, r.top, r.right, r.bottom);
3001 expect_messages = NULL;
3002 DestroyWindow(window);
3003 DestroyWindow(window2);
3004 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
3005 UnregisterClassA("ddraw_test_wndproc_wc2", GetModuleHandleA(NULL));
3008 static void test_coop_level_mode_set_multi(void)
3010 IDirectDraw7 *ddraw1, *ddraw2;
3011 UINT w, h;
3012 HWND window;
3013 HRESULT hr;
3014 ULONG ref;
3016 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3017 0, 0, 100, 100, 0, 0, 0, 0);
3018 ddraw1 = create_ddraw();
3019 ok(!!ddraw1, "Failed to create a ddraw object.\n");
3021 /* With just a single ddraw object, the display mode is restored on
3022 * release. */
3023 hr = set_display_mode(ddraw1, 800, 600);
3024 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3025 w = GetSystemMetrics(SM_CXSCREEN);
3026 ok(w == 800, "Got unexpected screen width %u.\n", w);
3027 h = GetSystemMetrics(SM_CYSCREEN);
3028 ok(h == 600, "Got unexpected screen height %u.\n", h);
3030 ref = IDirectDraw7_Release(ddraw1);
3031 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3032 w = GetSystemMetrics(SM_CXSCREEN);
3033 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3034 h = GetSystemMetrics(SM_CYSCREEN);
3035 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3037 /* When there are multiple ddraw objects, the display mode is restored to
3038 * the initial mode, before the first SetDisplayMode() call. */
3039 ddraw1 = create_ddraw();
3040 hr = set_display_mode(ddraw1, 800, 600);
3041 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3042 w = GetSystemMetrics(SM_CXSCREEN);
3043 ok(w == 800, "Got unexpected screen width %u.\n", w);
3044 h = GetSystemMetrics(SM_CYSCREEN);
3045 ok(h == 600, "Got unexpected screen height %u.\n", h);
3047 ddraw2 = create_ddraw();
3048 hr = set_display_mode(ddraw2, 640, 480);
3049 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3050 w = GetSystemMetrics(SM_CXSCREEN);
3051 ok(w == 640, "Got unexpected screen width %u.\n", w);
3052 h = GetSystemMetrics(SM_CYSCREEN);
3053 ok(h == 480, "Got unexpected screen height %u.\n", h);
3055 ref = IDirectDraw7_Release(ddraw2);
3056 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3057 w = GetSystemMetrics(SM_CXSCREEN);
3058 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3059 h = GetSystemMetrics(SM_CYSCREEN);
3060 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3062 ref = IDirectDraw7_Release(ddraw1);
3063 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3064 w = GetSystemMetrics(SM_CXSCREEN);
3065 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3066 h = GetSystemMetrics(SM_CYSCREEN);
3067 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3069 /* Regardless of release ordering. */
3070 ddraw1 = create_ddraw();
3071 hr = set_display_mode(ddraw1, 800, 600);
3072 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3073 w = GetSystemMetrics(SM_CXSCREEN);
3074 ok(w == 800, "Got unexpected screen width %u.\n", w);
3075 h = GetSystemMetrics(SM_CYSCREEN);
3076 ok(h == 600, "Got unexpected screen height %u.\n", h);
3078 ddraw2 = create_ddraw();
3079 hr = set_display_mode(ddraw2, 640, 480);
3080 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3081 w = GetSystemMetrics(SM_CXSCREEN);
3082 ok(w == 640, "Got unexpected screen width %u.\n", w);
3083 h = GetSystemMetrics(SM_CYSCREEN);
3084 ok(h == 480, "Got unexpected screen height %u.\n", h);
3086 ref = IDirectDraw7_Release(ddraw1);
3087 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3088 w = GetSystemMetrics(SM_CXSCREEN);
3089 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3090 h = GetSystemMetrics(SM_CYSCREEN);
3091 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3093 ref = IDirectDraw7_Release(ddraw2);
3094 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3095 w = GetSystemMetrics(SM_CXSCREEN);
3096 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3097 h = GetSystemMetrics(SM_CYSCREEN);
3098 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3100 /* But only for ddraw objects that called SetDisplayMode(). */
3101 ddraw1 = create_ddraw();
3102 ddraw2 = create_ddraw();
3103 hr = set_display_mode(ddraw2, 640, 480);
3104 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3105 w = GetSystemMetrics(SM_CXSCREEN);
3106 ok(w == 640, "Got unexpected screen width %u.\n", w);
3107 h = GetSystemMetrics(SM_CYSCREEN);
3108 ok(h == 480, "Got unexpected screen height %u.\n", h);
3110 ref = IDirectDraw7_Release(ddraw1);
3111 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3112 w = GetSystemMetrics(SM_CXSCREEN);
3113 ok(w == 640, "Got unexpected screen width %u.\n", w);
3114 h = GetSystemMetrics(SM_CYSCREEN);
3115 ok(h == 480, "Got unexpected screen height %u.\n", h);
3117 ref = IDirectDraw7_Release(ddraw2);
3118 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3119 w = GetSystemMetrics(SM_CXSCREEN);
3120 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3121 h = GetSystemMetrics(SM_CYSCREEN);
3122 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3124 /* If there's a ddraw object that's currently in exclusive mode, it blocks
3125 * restoring the display mode. */
3126 ddraw1 = create_ddraw();
3127 hr = set_display_mode(ddraw1, 800, 600);
3128 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3129 w = GetSystemMetrics(SM_CXSCREEN);
3130 ok(w == 800, "Got unexpected screen width %u.\n", w);
3131 h = GetSystemMetrics(SM_CYSCREEN);
3132 ok(h == 600, "Got unexpected screen height %u.\n", h);
3134 ddraw2 = create_ddraw();
3135 hr = set_display_mode(ddraw2, 640, 480);
3136 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3137 w = GetSystemMetrics(SM_CXSCREEN);
3138 ok(w == 640, "Got unexpected screen width %u.\n", w);
3139 h = GetSystemMetrics(SM_CYSCREEN);
3140 ok(h == 480, "Got unexpected screen height %u.\n", h);
3142 hr = IDirectDraw7_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3143 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3145 ref = IDirectDraw7_Release(ddraw1);
3146 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3147 w = GetSystemMetrics(SM_CXSCREEN);
3148 ok(w == 640, "Got unexpected screen width %u.\n", w);
3149 h = GetSystemMetrics(SM_CYSCREEN);
3150 ok(h == 480, "Got unexpected screen height %u.\n", h);
3152 ref = IDirectDraw7_Release(ddraw2);
3153 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3154 w = GetSystemMetrics(SM_CXSCREEN);
3155 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3156 h = GetSystemMetrics(SM_CYSCREEN);
3157 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3159 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
3160 ddraw1 = create_ddraw();
3161 hr = set_display_mode(ddraw1, 800, 600);
3162 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3163 w = GetSystemMetrics(SM_CXSCREEN);
3164 ok(w == 800, "Got unexpected screen width %u.\n", w);
3165 h = GetSystemMetrics(SM_CYSCREEN);
3166 ok(h == 600, "Got unexpected screen height %u.\n", h);
3168 hr = IDirectDraw7_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3169 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3171 ddraw2 = create_ddraw();
3172 hr = set_display_mode(ddraw2, 640, 480);
3173 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
3175 ref = IDirectDraw7_Release(ddraw1);
3176 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3177 w = GetSystemMetrics(SM_CXSCREEN);
3178 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3179 h = GetSystemMetrics(SM_CYSCREEN);
3180 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3182 ref = IDirectDraw7_Release(ddraw2);
3183 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3184 w = GetSystemMetrics(SM_CXSCREEN);
3185 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3186 h = GetSystemMetrics(SM_CYSCREEN);
3187 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3189 DestroyWindow(window);
3192 static void test_initialize(void)
3194 IDirectDraw7 *ddraw;
3195 HRESULT hr;
3197 ddraw = create_ddraw();
3198 ok(!!ddraw, "Failed to create a ddraw object.\n");
3200 hr = IDirectDraw7_Initialize(ddraw, NULL);
3201 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
3202 IDirectDraw7_Release(ddraw);
3204 CoInitialize(NULL);
3205 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw7, (void **)&ddraw);
3206 ok(SUCCEEDED(hr), "Failed to create IDirectDraw7 instance, hr %#x.\n", hr);
3207 hr = IDirectDraw7_Initialize(ddraw, NULL);
3208 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
3209 hr = IDirectDraw7_Initialize(ddraw, NULL);
3210 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
3211 IDirectDraw7_Release(ddraw);
3212 CoUninitialize();
3215 static void test_coop_level_surf_create(void)
3217 IDirectDrawSurface7 *surface;
3218 IDirectDraw7 *ddraw;
3219 DDSURFACEDESC2 ddsd;
3220 HRESULT hr;
3222 ddraw = create_ddraw();
3223 ok(!!ddraw, "Failed to create a ddraw object.\n");
3225 memset(&ddsd, 0, sizeof(ddsd));
3226 ddsd.dwSize = sizeof(ddsd);
3227 ddsd.dwFlags = DDSD_CAPS;
3228 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3229 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
3230 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
3232 IDirectDraw7_Release(ddraw);
3235 static void test_vb_discard(void)
3237 static const struct vec4 quad[] =
3239 { 0.0f, 480.0f, 0.0f, 1.0f},
3240 { 0.0f, 0.0f, 0.0f, 1.0f},
3241 {640.0f, 480.0f, 0.0f, 1.0f},
3242 {640.0f, 0.0f, 0.0f, 1.0f},
3245 IDirect3DDevice7 *device;
3246 IDirect3D7 *d3d;
3247 IDirect3DVertexBuffer7 *buffer;
3248 HWND window;
3249 HRESULT hr;
3250 D3DVERTEXBUFFERDESC desc;
3251 BYTE *data;
3252 static const unsigned int vbsize = 16;
3253 unsigned int i;
3255 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3256 0, 0, 640, 480, 0, 0, 0, 0);
3258 if (!(device = create_device(window, DDSCL_NORMAL)))
3260 skip("Failed to create a 3D device, skipping test.\n");
3261 DestroyWindow(window);
3262 return;
3265 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
3266 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
3268 memset(&desc, 0, sizeof(desc));
3269 desc.dwSize = sizeof(desc);
3270 desc.dwCaps = D3DVBCAPS_WRITEONLY;
3271 desc.dwFVF = D3DFVF_XYZRHW;
3272 desc.dwNumVertices = vbsize;
3273 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &buffer, 0);
3274 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
3276 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3277 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3278 memcpy(data, quad, sizeof(quad));
3279 hr = IDirect3DVertexBuffer7_Unlock(buffer);
3280 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3282 hr = IDirect3DDevice7_BeginScene(device);
3283 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3284 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
3285 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3286 hr = IDirect3DDevice7_EndScene(device);
3287 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3289 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3290 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3291 memset(data, 0xaa, sizeof(struct vec4) * vbsize);
3292 hr = IDirect3DVertexBuffer7_Unlock(buffer);
3293 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3295 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3296 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3297 for (i = 0; i < sizeof(struct vec4) * vbsize; i++)
3299 if (data[i] != 0xaa)
3301 ok(FALSE, "Vertex buffer data byte %u is 0x%02x, expected 0xaa\n", i, data[i]);
3302 break;
3305 hr = IDirect3DVertexBuffer7_Unlock(buffer);
3306 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3308 IDirect3DVertexBuffer7_Release(buffer);
3309 IDirect3D7_Release(d3d);
3310 IDirect3DDevice7_Release(device);
3311 DestroyWindow(window);
3314 static void test_coop_level_multi_window(void)
3316 HWND window1, window2;
3317 IDirectDraw7 *ddraw;
3318 HRESULT hr;
3320 window1 = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
3321 0, 0, 640, 480, 0, 0, 0, 0);
3322 window2 = CreateWindowA("static", "ddraw_test2", WS_OVERLAPPEDWINDOW,
3323 0, 0, 640, 480, 0, 0, 0, 0);
3324 ddraw = create_ddraw();
3325 ok(!!ddraw, "Failed to create a ddraw object.\n");
3327 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
3328 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3329 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3330 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3331 ok(IsWindow(window1), "Window 1 was destroyed.\n");
3332 ok(IsWindow(window2), "Window 2 was destroyed.\n");
3334 IDirectDraw7_Release(ddraw);
3335 DestroyWindow(window2);
3336 DestroyWindow(window1);
3339 static void test_draw_strided(void)
3341 static struct vec3 position[] =
3343 {-1.0, -1.0, 0.0},
3344 {-1.0, 1.0, 0.0},
3345 { 1.0, 1.0, 0.0},
3346 { 1.0, -1.0, 0.0},
3348 static DWORD diffuse[] =
3350 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
3352 static WORD indices[] =
3354 0, 1, 2, 2, 3, 0
3357 IDirectDrawSurface7 *rt;
3358 IDirect3DDevice7 *device;
3359 D3DCOLOR color;
3360 HWND window;
3361 HRESULT hr;
3362 D3DDRAWPRIMITIVESTRIDEDDATA strided;
3364 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3365 0, 0, 640, 480, 0, 0, 0, 0);
3367 if (!(device = create_device(window, DDSCL_NORMAL)))
3369 skip("Failed to create a 3D device, skipping test.\n");
3370 DestroyWindow(window);
3371 return;
3374 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
3375 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3377 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
3378 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
3379 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 1.0f, 0);
3380 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
3381 hr = IDirect3DDevice7_BeginScene(device);
3382 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3384 memset(&strided, 0x55, sizeof(strided));
3385 strided.position.lpvData = position;
3386 strided.position.dwStride = sizeof(*position);
3387 strided.diffuse.lpvData = diffuse;
3388 strided.diffuse.dwStride = sizeof(*diffuse);
3389 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device, D3DPT_TRIANGLELIST, D3DFVF_XYZ | D3DFVF_DIFFUSE,
3390 &strided, 4, indices, 6, 0);
3391 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3393 hr = IDirect3DDevice7_EndScene(device);
3394 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3396 color = get_surface_color(rt, 320, 240);
3397 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
3399 IDirectDrawSurface7_Release(rt);
3400 IDirect3DDevice7_Release(device);
3401 DestroyWindow(window);
3404 static void test_lighting(void)
3406 static D3DMATRIX mat =
3408 1.0f, 0.0f, 0.0f, 0.0f,
3409 0.0f, 1.0f, 0.0f, 0.0f,
3410 0.0f, 0.0f, 1.0f, 0.0f,
3411 0.0f, 0.0f, 0.0f, 1.0f,
3413 mat_singular =
3415 1.0f, 0.0f, 1.0f, 0.0f,
3416 0.0f, 1.0f, 0.0f, 0.0f,
3417 1.0f, 0.0f, 1.0f, 0.0f,
3418 0.0f, 0.0f, 0.5f, 1.0f,
3420 mat_transf =
3422 0.0f, 0.0f, 1.0f, 0.0f,
3423 0.0f, 1.0f, 0.0f, 0.0f,
3424 -1.0f, 0.0f, 0.0f, 0.0f,
3425 10.f, 10.0f, 10.0f, 1.0f,
3427 mat_nonaffine =
3429 1.0f, 0.0f, 0.0f, 0.0f,
3430 0.0f, 1.0f, 0.0f, 0.0f,
3431 0.0f, 0.0f, 1.0f, -1.0f,
3432 10.f, 10.0f, 10.0f, 0.0f,
3434 static struct
3436 struct vec3 position;
3437 DWORD diffuse;
3439 unlitquad[] =
3441 {{-1.0f, -1.0f, 0.1f}, 0xffff0000},
3442 {{-1.0f, 0.0f, 0.1f}, 0xffff0000},
3443 {{ 0.0f, 0.0f, 0.1f}, 0xffff0000},
3444 {{ 0.0f, -1.0f, 0.1f}, 0xffff0000},
3446 litquad[] =
3448 {{-1.0f, 0.0f, 0.1f}, 0xff00ff00},
3449 {{-1.0f, 1.0f, 0.1f}, 0xff00ff00},
3450 {{ 0.0f, 1.0f, 0.1f}, 0xff00ff00},
3451 {{ 0.0f, 0.0f, 0.1f}, 0xff00ff00},
3453 static struct
3455 struct vec3 position;
3456 struct vec3 normal;
3457 DWORD diffuse;
3459 unlitnquad[] =
3461 {{0.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3462 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3463 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3464 {{1.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3466 litnquad[] =
3468 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3469 {{0.0f, 1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3470 {{1.0f, 1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3471 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3473 nquad[] =
3475 {{-1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3476 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3477 {{ 1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3478 {{ 1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3480 rotatedquad[] =
3482 {{-10.0f, -11.0f, 11.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3483 {{-10.0f, -9.0f, 11.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3484 {{-10.0f, -9.0f, 9.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3485 {{-10.0f, -11.0f, 9.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3487 translatedquad[] =
3489 {{-11.0f, -11.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3490 {{-11.0f, -9.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3491 {{ -9.0f, -9.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3492 {{ -9.0f, -11.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3494 static WORD indices[] = {0, 1, 2, 2, 3, 0};
3495 static const struct
3497 D3DMATRIX *world_matrix;
3498 void *quad;
3499 DWORD expected;
3500 const char *message;
3502 tests[] =
3504 {&mat, nquad, 0x000000ff, "Lit quad with light"},
3505 {&mat_singular, nquad, 0x000000ff, "Lit quad with singular world matrix"},
3506 {&mat_transf, rotatedquad, 0x000000ff, "Lit quad with transformation matrix"},
3507 {&mat_nonaffine, translatedquad, 0x00000000, "Lit quad with non-affine matrix"},
3510 HWND window;
3511 IDirect3DDevice7 *device;
3512 IDirectDrawSurface7 *rt;
3513 HRESULT hr;
3514 DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
3515 DWORD nfvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL;
3516 D3DCOLOR color;
3517 ULONG refcount;
3518 unsigned int i;
3520 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3521 0, 0, 640, 480, 0, 0, 0, 0);
3522 if (!(device = create_device(window, DDSCL_NORMAL)))
3524 skip("Failed to create a 3D device, skipping test.\n");
3525 DestroyWindow(window);
3526 return;
3529 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
3530 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3532 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
3533 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
3535 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
3536 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
3537 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
3538 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
3539 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
3540 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
3541 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
3542 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
3543 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
3544 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
3545 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
3546 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
3547 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
3548 ok(SUCCEEDED(hr), "Failed to disable stencil buffering, hr %#x.\n", hr);
3549 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
3550 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
3552 hr = IDirect3DDevice7_BeginScene(device);
3553 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3555 /* No lights are defined... That means, lit vertices should be entirely black. */
3556 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
3557 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
3558 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, unlitquad, 4,
3559 indices, 6, 0);
3560 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3562 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
3563 ok(SUCCEEDED(hr), "Failed to enable lighting, hr %#x.\n", hr);
3564 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, litquad, 4,
3565 indices, 6, 0);
3566 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3568 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
3569 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
3570 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, unlitnquad, 4,
3571 indices, 6, 0);
3572 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3574 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
3575 ok(SUCCEEDED(hr), "Failed to enable lighting, hr %#x.\n", hr);
3576 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, litnquad, 4,
3577 indices, 6, 0);
3578 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3580 hr = IDirect3DDevice7_EndScene(device);
3581 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3583 color = get_surface_color(rt, 160, 360);
3584 ok(color == 0x00ff0000, "Unlit quad without normals has color 0x%08x, expected 0x00ff0000.\n", color);
3585 color = get_surface_color(rt, 160, 120);
3586 ok(color == 0x00000000, "Lit quad without normals has color 0x%08x, expected 0x00000000.\n", color);
3587 color = get_surface_color(rt, 480, 360);
3588 ok(color == 0x000000ff, "Unlit quad with normals has color 0x%08x, expected 0x000000ff.\n", color);
3589 color = get_surface_color(rt, 480, 120);
3590 ok(color == 0x00000000, "Lit quad with normals has color 0x%08x, expected 0x00000000.\n", color);
3592 hr = IDirect3DDevice7_LightEnable(device, 0, TRUE);
3593 ok(SUCCEEDED(hr), "Failed to enable light 0, hr %#x.\n", hr);
3595 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
3597 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, tests[i].world_matrix);
3598 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
3600 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
3601 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
3603 hr = IDirect3DDevice7_BeginScene(device);
3604 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3606 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, tests[i].quad,
3607 4, indices, 6, 0);
3608 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3610 hr = IDirect3DDevice7_EndScene(device);
3611 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3613 color = get_surface_color(rt, 320, 240);
3614 ok(color == tests[i].expected, "%s has color 0x%08x.\n", tests[i].message, color);
3617 IDirectDrawSurface7_Release(rt);
3619 refcount = IDirect3DDevice7_Release(device);
3620 ok(!refcount, "Device has %u references left.\n", refcount);
3621 DestroyWindow(window);
3624 static void test_specular_lighting(void)
3626 static const unsigned int vertices_side = 5;
3627 const unsigned int indices_count = (vertices_side - 1) * (vertices_side - 1) * 2 * 3;
3628 static const DWORD fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3629 static D3DMATRIX mat =
3631 1.0f, 0.0f, 0.0f, 0.0f,
3632 0.0f, 1.0f, 0.0f, 0.0f,
3633 0.0f, 0.0f, 1.0f, 0.0f,
3634 0.0f, 0.0f, 0.0f, 1.0f,
3636 static D3DLIGHT7 directional =
3638 D3DLIGHT_DIRECTIONAL,
3639 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3640 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
3641 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3642 {{0.0f}, {0.0f}, {0.0f}},
3643 {{0.0f}, {0.0f}, {1.0f}},
3645 point =
3647 D3DLIGHT_POINT,
3648 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3649 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
3650 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3651 {{0.0f}, {0.0f}, {0.0f}},
3652 {{0.0f}, {0.0f}, {0.0f}},
3653 100.0f,
3654 0.0f,
3655 0.0f, 0.0f, 1.0f,
3657 spot =
3659 D3DLIGHT_SPOT,
3660 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3661 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
3662 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3663 {{0.0f}, {0.0f}, {0.0f}},
3664 {{0.0f}, {0.0f}, {1.0f}},
3665 100.0f,
3666 1.0f,
3667 0.0f, 0.0f, 1.0f,
3668 M_PI / 12.0f, M_PI / 3.0f
3670 /* The chosen range value makes the test fail when using a manhattan
3671 * distance metric vs the correct euclidean distance. */
3672 point_range =
3674 D3DLIGHT_POINT,
3675 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3676 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
3677 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3678 {{0.0f}, {0.0f}, {0.0f}},
3679 {{0.0f}, {0.0f}, {0.0f}},
3680 1.2f,
3681 0.0f,
3682 0.0f, 0.0f, 1.0f,
3684 static const struct expected_color
3686 unsigned int x, y;
3687 D3DCOLOR color;
3689 expected_directional[] =
3691 {160, 120, 0x00ffffff},
3692 {320, 120, 0x00ffffff},
3693 {480, 120, 0x00ffffff},
3694 {160, 240, 0x00ffffff},
3695 {320, 240, 0x00ffffff},
3696 {480, 240, 0x00ffffff},
3697 {160, 360, 0x00ffffff},
3698 {320, 360, 0x00ffffff},
3699 {480, 360, 0x00ffffff},
3701 expected_directional_local[] =
3703 {160, 120, 0x003c3c3c},
3704 {320, 120, 0x00717171},
3705 {480, 120, 0x003c3c3c},
3706 {160, 240, 0x00717171},
3707 {320, 240, 0x00ffffff},
3708 {480, 240, 0x00717171},
3709 {160, 360, 0x003c3c3c},
3710 {320, 360, 0x00717171},
3711 {480, 360, 0x003c3c3c},
3713 expected_point[] =
3715 {160, 120, 0x00282828},
3716 {320, 120, 0x005a5a5a},
3717 {480, 120, 0x00282828},
3718 {160, 240, 0x005a5a5a},
3719 {320, 240, 0x00ffffff},
3720 {480, 240, 0x005a5a5a},
3721 {160, 360, 0x00282828},
3722 {320, 360, 0x005a5a5a},
3723 {480, 360, 0x00282828},
3725 expected_point_local[] =
3727 {160, 120, 0x00000000},
3728 {320, 120, 0x00070707},
3729 {480, 120, 0x00000000},
3730 {160, 240, 0x00070707},
3731 {320, 240, 0x00ffffff},
3732 {480, 240, 0x00070707},
3733 {160, 360, 0x00000000},
3734 {320, 360, 0x00070707},
3735 {480, 360, 0x00000000},
3737 expected_spot[] =
3739 {160, 120, 0x00000000},
3740 {320, 120, 0x00141414},
3741 {480, 120, 0x00000000},
3742 {160, 240, 0x00141414},
3743 {320, 240, 0x00ffffff},
3744 {480, 240, 0x00141414},
3745 {160, 360, 0x00000000},
3746 {320, 360, 0x00141414},
3747 {480, 360, 0x00000000},
3749 expected_spot_local[] =
3751 {160, 120, 0x00000000},
3752 {320, 120, 0x00020202},
3753 {480, 120, 0x00000000},
3754 {160, 240, 0x00020202},
3755 {320, 240, 0x00ffffff},
3756 {480, 240, 0x00020202},
3757 {160, 360, 0x00000000},
3758 {320, 360, 0x00020202},
3759 {480, 360, 0x00000000},
3761 expected_point_range[] =
3763 {160, 120, 0x00000000},
3764 {320, 120, 0x005a5a5a},
3765 {480, 120, 0x00000000},
3766 {160, 240, 0x005a5a5a},
3767 {320, 240, 0x00ffffff},
3768 {480, 240, 0x005a5a5a},
3769 {160, 360, 0x00000000},
3770 {320, 360, 0x005a5a5a},
3771 {480, 360, 0x00000000},
3773 static const struct
3775 D3DLIGHT7 *light;
3776 BOOL local_viewer;
3777 const struct expected_color *expected;
3778 unsigned int expected_count;
3780 tests[] =
3782 {&directional, FALSE, expected_directional,
3783 sizeof(expected_directional) / sizeof(expected_directional[0])},
3784 {&directional, TRUE, expected_directional_local,
3785 sizeof(expected_directional_local) / sizeof(expected_directional_local[0])},
3786 {&point, FALSE, expected_point,
3787 sizeof(expected_point) / sizeof(expected_point[0])},
3788 {&point, TRUE, expected_point_local,
3789 sizeof(expected_point_local) / sizeof(expected_point_local[0])},
3790 {&spot, FALSE, expected_spot,
3791 sizeof(expected_spot) / sizeof(expected_spot[0])},
3792 {&spot, TRUE, expected_spot_local,
3793 sizeof(expected_spot_local) / sizeof(expected_spot_local[0])},
3794 {&point_range, FALSE, expected_point_range,
3795 sizeof(expected_point_range) / sizeof(expected_point_range[0])},
3797 IDirect3DDevice7 *device;
3798 IDirectDrawSurface7 *rt;
3799 D3DMATERIAL7 material;
3800 D3DCOLOR color;
3801 ULONG refcount;
3802 HWND window;
3803 HRESULT hr;
3804 unsigned int i, j, x, y;
3805 struct
3807 struct vec3 position;
3808 struct vec3 normal;
3809 } *quad;
3810 WORD *indices;
3812 quad = HeapAlloc(GetProcessHeap(), 0, vertices_side * vertices_side * sizeof(*quad));
3813 indices = HeapAlloc(GetProcessHeap(), 0, indices_count * sizeof(*indices));
3814 for (i = 0, y = 0; y < vertices_side; ++y)
3816 for (x = 0; x < vertices_side; ++x)
3818 quad[i].position.x = x * 2.0f / (vertices_side - 1) - 1.0f;
3819 quad[i].position.y = y * 2.0f / (vertices_side - 1) - 1.0f;
3820 quad[i].position.z = 1.0f;
3821 quad[i].normal.x = 0.0f;
3822 quad[i].normal.y = 0.0f;
3823 quad[i++].normal.z = -1.0f;
3826 for (i = 0, y = 0; y < (vertices_side - 1); ++y)
3828 for (x = 0; x < (vertices_side - 1); ++x)
3830 indices[i++] = y * vertices_side + x + 1;
3831 indices[i++] = y * vertices_side + x;
3832 indices[i++] = (y + 1) * vertices_side + x;
3833 indices[i++] = y * vertices_side + x + 1;
3834 indices[i++] = (y + 1) * vertices_side + x;
3835 indices[i++] = (y + 1) * vertices_side + x + 1;
3839 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3840 0, 0, 640, 480, 0, 0, 0, 0);
3841 if (!(device = create_device(window, DDSCL_NORMAL)))
3843 skip("Failed to create a 3D device, skipping test.\n");
3844 DestroyWindow(window);
3845 return;
3848 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
3849 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3851 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
3852 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
3853 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
3854 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
3855 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
3856 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
3857 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
3858 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
3859 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
3860 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
3861 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
3862 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
3864 memset(&material, 0, sizeof(material));
3865 U1(U2(material).specular).r = 1.0f;
3866 U2(U2(material).specular).g = 1.0f;
3867 U3(U2(material).specular).b = 1.0f;
3868 U4(U2(material).specular).a = 1.0f;
3869 U4(material).power = 30.0f;
3870 hr = IDirect3DDevice7_SetMaterial(device, &material);
3871 ok(SUCCEEDED(hr), "Failed to set material, hr %#x.\n", hr);
3873 hr = IDirect3DDevice7_LightEnable(device, 0, TRUE);
3874 ok(SUCCEEDED(hr), "Failed to enable light 0, hr %#x.\n", hr);
3875 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, TRUE);
3876 ok(SUCCEEDED(hr), "Failed to enable specular lighting, hr %#x.\n", hr);
3878 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
3880 hr = IDirect3DDevice7_SetLight(device, 0, tests[i].light);
3881 ok(SUCCEEDED(hr), "Failed to set light parameters, hr %#x.\n", hr);
3883 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LOCALVIEWER, tests[i].local_viewer);
3884 ok(SUCCEEDED(hr), "Failed to set local viewer state, hr %#x.\n", hr);
3886 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
3887 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
3889 hr = IDirect3DDevice7_BeginScene(device);
3890 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3892 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, quad,
3893 vertices_side * vertices_side, indices, indices_count, 0);
3894 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3896 hr = IDirect3DDevice7_EndScene(device);
3897 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3899 for (j = 0; j < tests[i].expected_count; ++j)
3901 color = get_surface_color(rt, tests[i].expected[j].x, tests[i].expected[j].y);
3902 ok(compare_color(color, tests[i].expected[j].color, 1),
3903 "Expected color 0x%08x at location (%u, %u), got 0x%08x, case %u.\n",
3904 tests[i].expected[j].color, tests[i].expected[j].x,
3905 tests[i].expected[j].y, color, i);
3909 IDirectDrawSurface7_Release(rt);
3911 refcount = IDirect3DDevice7_Release(device);
3912 ok(!refcount, "Device has %u references left.\n", refcount);
3913 DestroyWindow(window);
3914 HeapFree(GetProcessHeap(), 0, indices);
3915 HeapFree(GetProcessHeap(), 0, quad);
3918 static void test_clear_rect_count(void)
3920 IDirectDrawSurface7 *rt;
3921 IDirect3DDevice7 *device;
3922 D3DCOLOR color;
3923 HWND window;
3924 HRESULT hr;
3925 D3DRECT rect = {{0}, {0}, {640}, {480}};
3927 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3928 0, 0, 640, 480, 0, 0, 0, 0);
3929 if (!(device = create_device(window, DDSCL_NORMAL)))
3931 skip("Failed to create a 3D device, skipping test.\n");
3932 DestroyWindow(window);
3933 return;
3936 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
3937 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3939 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ffffff, 1.0f, 0);
3940 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
3941 hr = IDirect3DDevice7_Clear(device, 0, &rect, D3DCLEAR_TARGET, 0x00ff0000, 1.0f, 0);
3942 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
3944 color = get_surface_color(rt, 320, 240);
3945 ok(compare_color(color, 0x00ffffff, 1) || broken(compare_color(color, 0x00ff0000, 1)),
3946 "Clear with count = 0, rect != NULL has color %#08x.\n", color);
3948 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ffffff, 1.0f, 0);
3949 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
3950 hr = IDirect3DDevice7_Clear(device, 1, NULL, D3DCLEAR_TARGET, 0x0000ff00, 1.0f, 0);
3951 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
3953 color = get_surface_color(rt, 320, 240);
3954 ok(compare_color(color, 0x0000ff00, 1),
3955 "Clear with count = 1, rect = NULL has color %#08x.\n", color);
3957 IDirectDrawSurface7_Release(rt);
3958 IDirect3DDevice7_Release(device);
3959 DestroyWindow(window);
3962 static BOOL test_mode_restored(IDirectDraw7 *ddraw, HWND window)
3964 DDSURFACEDESC2 ddsd1, ddsd2;
3965 HRESULT hr;
3967 memset(&ddsd1, 0, sizeof(ddsd1));
3968 ddsd1.dwSize = sizeof(ddsd1);
3969 hr = IDirectDraw7_GetDisplayMode(ddraw, &ddsd1);
3970 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
3972 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3973 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3974 hr = set_display_mode(ddraw, 640, 480);
3975 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3976 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3977 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3979 memset(&ddsd2, 0, sizeof(ddsd2));
3980 ddsd2.dwSize = sizeof(ddsd2);
3981 hr = IDirectDraw7_GetDisplayMode(ddraw, &ddsd2);
3982 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
3983 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
3984 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3986 return ddsd1.dwWidth == ddsd2.dwWidth && ddsd1.dwHeight == ddsd2.dwHeight;
3989 static void test_coop_level_versions(void)
3991 HWND window;
3992 IDirectDraw *ddraw;
3993 HRESULT hr;
3994 BOOL restored;
3995 IDirectDrawSurface *surface;
3996 IDirectDraw7 *ddraw7;
3997 DDSURFACEDESC ddsd;
3999 window = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
4000 0, 0, 640, 480, 0, 0, 0, 0);
4002 ddraw7 = create_ddraw();
4003 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4004 /* Newly created ddraw objects restore the mode on ddraw2+::SetCooperativeLevel(NORMAL) */
4005 restored = test_mode_restored(ddraw7, window);
4006 ok(restored, "Display mode not restored in new ddraw object\n");
4008 /* A failing ddraw1::SetCooperativeLevel call does not have an effect */
4009 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4010 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4012 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4013 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
4014 restored = test_mode_restored(ddraw7, window);
4015 ok(restored, "Display mode not restored after bad ddraw1::SetCooperativeLevel call\n");
4017 /* A successful one does */
4018 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4019 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4020 restored = test_mode_restored(ddraw7, window);
4021 ok(!restored, "Display mode restored after good ddraw1::SetCooperativeLevel call\n");
4023 IDirectDraw_Release(ddraw);
4024 IDirectDraw7_Release(ddraw7);
4026 ddraw7 = create_ddraw();
4027 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4028 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4029 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4031 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_SETFOCUSWINDOW);
4032 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4033 restored = test_mode_restored(ddraw7, window);
4034 ok(!restored, "Display mode restored after ddraw1::SetCooperativeLevel(SETFOCUSWINDOW) call\n");
4036 IDirectDraw_Release(ddraw);
4037 IDirectDraw7_Release(ddraw7);
4039 /* A failing call does not restore the ddraw2+ behavior */
4040 ddraw7 = create_ddraw();
4041 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4042 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4043 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4045 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4046 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4047 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4048 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
4049 restored = test_mode_restored(ddraw7, window);
4050 ok(!restored, "Display mode restored after good-bad ddraw1::SetCooperativeLevel() call sequence\n");
4052 IDirectDraw_Release(ddraw);
4053 IDirectDraw7_Release(ddraw7);
4055 /* Neither does a sequence of successful calls with the new interface */
4056 ddraw7 = create_ddraw();
4057 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4058 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4059 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4061 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4062 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4063 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4064 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4065 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
4066 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4068 restored = test_mode_restored(ddraw7, window);
4069 ok(!restored, "Display mode restored after ddraw1-ddraw7 SetCooperativeLevel() call sequence\n");
4070 IDirectDraw_Release(ddraw);
4071 IDirectDraw7_Release(ddraw7);
4073 /* ddraw1::CreateSurface does not triger the ddraw1 behavior */
4074 ddraw7 = create_ddraw();
4075 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4076 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4077 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4079 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
4080 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4082 memset(&ddsd, 0, sizeof(ddsd));
4083 ddsd.dwSize = sizeof(ddsd);
4084 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
4085 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4086 ddsd.dwWidth = ddsd.dwHeight = 8;
4087 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
4088 ok(SUCCEEDED(hr), "CreateSurface failed, hr %#x.\n", hr);
4089 IDirectDrawSurface_Release(surface);
4090 restored = test_mode_restored(ddraw7, window);
4091 ok(restored, "Display mode not restored after ddraw1::CreateSurface() call\n");
4093 IDirectDraw_Release(ddraw);
4094 IDirectDraw7_Release(ddraw7);
4095 DestroyWindow(window);
4098 static void test_fog_special(void)
4100 static struct
4102 struct vec3 position;
4103 D3DCOLOR diffuse;
4105 quad[] =
4107 {{ -1.0f, 1.0f, 0.0f}, 0xff00ff00},
4108 {{ 1.0f, 1.0f, 1.0f}, 0xff00ff00},
4109 {{ -1.0f, -1.0f, 0.0f}, 0xff00ff00},
4110 {{ 1.0f, -1.0f, 1.0f}, 0xff00ff00},
4112 static const struct
4114 DWORD vertexmode, tablemode;
4115 D3DCOLOR color_left, color_right;
4117 tests[] =
4119 {D3DFOG_LINEAR, D3DFOG_NONE, 0x00ff0000, 0x00ff0000},
4120 {D3DFOG_NONE, D3DFOG_LINEAR, 0x0000ff00, 0x00ff0000},
4122 union
4124 float f;
4125 DWORD d;
4126 } conv;
4127 D3DCOLOR color;
4128 HRESULT hr;
4129 unsigned int i;
4130 HWND window;
4131 IDirect3DDevice7 *device;
4132 IDirectDrawSurface7 *rt;
4134 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4135 0, 0, 640, 480, 0, 0, 0, 0);
4137 if (!(device = create_device(window, DDSCL_NORMAL)))
4139 skip("Failed to create a 3D device, skipping test.\n");
4140 DestroyWindow(window);
4141 return;
4144 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
4145 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4147 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
4148 ok(SUCCEEDED(hr), "Failed to enable fog, hr %#x.\n", hr);
4149 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0xffff0000);
4150 ok(SUCCEEDED(hr), "Failed to set fog color, hr %#x.\n", hr);
4151 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
4152 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
4153 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
4154 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
4156 conv.f = 0.5f;
4157 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGSTART, conv.d);
4158 ok(SUCCEEDED(hr), "Failed to set fog start, hr %#x.\n", hr);
4159 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGEND, conv.d);
4160 ok(SUCCEEDED(hr), "Failed to set fog end, hr %#x.\n", hr);
4162 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
4164 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x000000ff, 1.0f, 0);
4165 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4167 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, tests[i].vertexmode);
4168 ok(SUCCEEDED(hr), "Failed to set fogvertexmode, hr %#x.\n", hr);
4169 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, tests[i].tablemode);
4170 ok(SUCCEEDED(hr), "Failed to set fogtablemode, hr %#x.\n", hr);
4172 hr = IDirect3DDevice7_BeginScene(device);
4173 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4174 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, 4, 0);
4175 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4176 hr = IDirect3DDevice7_EndScene(device);
4177 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4179 color = get_surface_color(rt, 310, 240);
4180 ok(compare_color(color, tests[i].color_left, 1),
4181 "Expected left color 0x%08x, got 0x%08x, case %u.\n", tests[i].color_left, color, i);
4182 color = get_surface_color(rt, 330, 240);
4183 ok(compare_color(color, tests[i].color_right, 1),
4184 "Expected right color 0x%08x, got 0x%08x, case %u.\n", tests[i].color_right, color, i);
4187 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
4188 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
4190 IDirectDrawSurface7_Release(rt);
4191 IDirect3DDevice7_Release(device);
4192 DestroyWindow(window);
4195 static void test_lighting_interface_versions(void)
4197 IDirect3DDevice7 *device;
4198 IDirectDrawSurface7 *rt;
4199 D3DCOLOR color;
4200 HWND window;
4201 HRESULT hr;
4202 DWORD rs;
4203 unsigned int i;
4204 ULONG ref;
4205 D3DMATERIAL7 material;
4206 static D3DVERTEX quad[] =
4208 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4209 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4210 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4211 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4214 #define FVF_COLORVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_SPECULAR)
4215 static struct
4217 struct vec3 position;
4218 struct vec3 normal;
4219 DWORD diffuse, specular;
4221 quad2[] =
4223 {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4224 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4225 {{-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4226 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4229 static D3DLVERTEX lquad[] =
4231 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4232 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4233 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4234 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4237 #define FVF_LVERTEX2 (D3DFVF_LVERTEX & ~D3DFVF_RESERVED1)
4238 static struct
4240 struct vec3 position;
4241 DWORD diffuse, specular;
4242 struct vec2 texcoord;
4244 lquad2[] =
4246 {{-1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
4247 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
4248 {{-1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
4249 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
4252 static D3DTLVERTEX tlquad[] =
4254 {{ 0.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4255 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4256 {{ 640.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4257 {{ 640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4260 static const struct
4262 DWORD vertextype;
4263 void *data;
4264 DWORD d3drs_lighting, d3drs_specular;
4265 DWORD draw_flags;
4266 D3DCOLOR color;
4268 tests[] =
4270 /* Lighting is enabled when D3DFVF_XYZ is used and D3DRENDERSTATE_LIGHTING is
4271 * enabled. D3DDP_DONOTLIGHT is ignored. Lighting is also enabled when normals
4272 * are not available
4274 * Note that the specular result is 0x00000000 when lighting is on even if the
4275 * input vertex has specular color because D3DRENDERSTATE_COLORVERTEX is not
4276 * enabled */
4278 /* 0 */
4279 { D3DFVF_VERTEX, quad, FALSE, FALSE, 0, 0x00ffffff},
4280 { D3DFVF_VERTEX, quad, TRUE, FALSE, 0, 0x0000ff00},
4281 { D3DFVF_VERTEX, quad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
4282 { D3DFVF_VERTEX, quad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
4283 { D3DFVF_VERTEX, quad, FALSE, TRUE, 0, 0x00ffffff},
4284 { D3DFVF_VERTEX, quad, TRUE, TRUE, 0, 0x0000ff00},
4285 { D3DFVF_VERTEX, quad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
4286 { D3DFVF_VERTEX, quad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
4288 /* 8 */
4289 { FVF_COLORVERTEX, quad2, FALSE, FALSE, 0, 0x00ff0000},
4290 { FVF_COLORVERTEX, quad2, TRUE, FALSE, 0, 0x0000ff00},
4291 { FVF_COLORVERTEX, quad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4292 { FVF_COLORVERTEX, quad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
4293 { FVF_COLORVERTEX, quad2, FALSE, TRUE, 0, 0x00ff8080},
4294 { FVF_COLORVERTEX, quad2, TRUE, TRUE, 0, 0x0000ff00},
4295 { FVF_COLORVERTEX, quad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4296 { FVF_COLORVERTEX, quad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
4298 /* 16 */
4299 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, 0, 0x00ff0000},
4300 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, 0, 0x0000ff00},
4301 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4302 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
4303 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, 0, 0x00ff8080},
4304 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, 0, 0x0000ff00},
4305 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4306 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
4308 /* 24 */
4309 { FVF_LVERTEX2, lquad2, FALSE, FALSE, 0, 0x00ff0000},
4310 { FVF_LVERTEX2, lquad2, TRUE, FALSE, 0, 0x0000ff00},
4311 { FVF_LVERTEX2, lquad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4312 { FVF_LVERTEX2, lquad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
4313 { FVF_LVERTEX2, lquad2, FALSE, TRUE, 0, 0x00ff8080},
4314 { FVF_LVERTEX2, lquad2, TRUE, TRUE, 0, 0x0000ff00},
4315 { FVF_LVERTEX2, lquad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4316 { FVF_LVERTEX2, lquad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
4318 /* 32 */
4319 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, 0, 0x000000ff},
4320 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, 0, 0x000000ff},
4321 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
4322 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
4323 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, 0, 0x008080ff},
4324 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, 0, 0x008080ff},
4325 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
4326 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
4329 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4330 0, 0, 640, 480, 0, 0, 0, 0);
4332 if (!(device = create_device(window, DDSCL_NORMAL)))
4334 skip("Failed to create a 3D device, skipping test.\n");
4335 DestroyWindow(window);
4336 return;
4339 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
4340 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4342 memset(&material, 0, sizeof(material));
4343 U2(U3(material).emissive).g = 1.0f;
4344 hr = IDirect3DDevice7_SetMaterial(device, &material);
4345 ok(SUCCEEDED(hr), "Failed set material, hr %#x.\n", hr);
4346 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
4347 ok(SUCCEEDED(hr), "Failed to disable z test, hr %#x.\n", hr);
4349 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &rs);
4350 ok(SUCCEEDED(hr), "Failed to get lighting render state, hr %#x.\n", hr);
4351 ok(rs == TRUE, "Initial D3DRENDERSTATE_LIGHTING is %#x, expected TRUE.\n", rs);
4352 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, &rs);
4353 ok(SUCCEEDED(hr), "Failed to get specularenable render state, hr %#x.\n", hr);
4354 ok(rs == FALSE, "Initial D3DRENDERSTATE_SPECULARENABLE is %#x, expected FALSE.\n", rs);
4356 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
4358 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff202020, 0.0f, 0);
4359 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
4361 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, tests[i].d3drs_lighting);
4362 ok(SUCCEEDED(hr), "Failed to set lighting render state, hr %#x.\n", hr);
4363 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE,
4364 tests[i].d3drs_specular);
4365 ok(SUCCEEDED(hr), "Failed to set specularenable render state, hr %#x.\n", hr);
4367 hr = IDirect3DDevice7_BeginScene(device);
4368 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4369 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
4370 tests[i].vertextype, tests[i].data, 4, tests[i].draw_flags | D3DDP_WAIT);
4371 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4372 hr = IDirect3DDevice7_EndScene(device);
4373 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4375 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &rs);
4376 ok(SUCCEEDED(hr), "Failed to get lighting render state, hr %#x.\n", hr);
4377 ok(rs == tests[i].d3drs_lighting, "D3DRENDERSTATE_LIGHTING is %#x, expected %#x.\n",
4378 rs, tests[i].d3drs_lighting);
4380 color = get_surface_color(rt, 320, 240);
4381 ok(compare_color(color, tests[i].color, 1),
4382 "Got unexpected color 0x%08x, expected 0x%08x, test %u.\n",
4383 color, tests[i].color, i);
4386 IDirectDrawSurface7_Release(rt);
4387 ref = IDirect3DDevice7_Release(device);
4388 ok(ref == 0, "Device not properly released, refcount %u.\n", ref);
4389 DestroyWindow(window);
4392 static struct
4394 BOOL received;
4395 IDirectDraw7 *ddraw;
4396 HWND window;
4397 DWORD coop_level;
4398 } activateapp_testdata;
4400 static LRESULT CALLBACK activateapp_test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
4402 if (message == WM_ACTIVATEAPP)
4404 if (activateapp_testdata.ddraw)
4406 HRESULT hr;
4407 activateapp_testdata.received = FALSE;
4408 hr = IDirectDraw7_SetCooperativeLevel(activateapp_testdata.ddraw,
4409 activateapp_testdata.window, activateapp_testdata.coop_level);
4410 ok(SUCCEEDED(hr), "Recursive SetCooperativeLevel call failed, hr %#x.\n", hr);
4411 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP during recursive SetCooperativeLevel call.\n");
4413 activateapp_testdata.received = TRUE;
4416 return DefWindowProcA(hwnd, message, wparam, lparam);
4419 static void test_coop_level_activateapp(void)
4421 IDirectDraw7 *ddraw;
4422 HRESULT hr;
4423 HWND window;
4424 WNDCLASSA wc = {0};
4425 DDSURFACEDESC2 ddsd;
4426 IDirectDrawSurface7 *surface;
4428 ddraw = create_ddraw();
4429 ok(!!ddraw, "Failed to create a ddraw object.\n");
4431 wc.lpfnWndProc = activateapp_test_proc;
4432 wc.lpszClassName = "ddraw_test_wndproc_wc";
4433 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4435 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
4436 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
4438 /* Exclusive with window already active. */
4439 SetForegroundWindow(window);
4440 activateapp_testdata.received = FALSE;
4441 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4442 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4443 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP although window was already active.\n");
4444 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4445 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4447 /* Exclusive with window not active. */
4448 SetForegroundWindow(GetDesktopWindow());
4449 activateapp_testdata.received = FALSE;
4450 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4451 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4452 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4453 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4454 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4456 /* Normal with window not active, then exclusive with the same window. */
4457 SetForegroundWindow(GetDesktopWindow());
4458 activateapp_testdata.received = FALSE;
4459 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4460 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4461 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP when setting DDSCL_NORMAL.\n");
4462 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4463 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4464 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4465 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4466 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4468 /* Recursive set of DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. */
4469 SetForegroundWindow(GetDesktopWindow());
4470 activateapp_testdata.received = FALSE;
4471 activateapp_testdata.ddraw = ddraw;
4472 activateapp_testdata.window = window;
4473 activateapp_testdata.coop_level = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
4474 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4475 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4476 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4477 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4478 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4480 /* The recursive call seems to have some bad effect on native ddraw, despite (apparently)
4481 * succeeding. Another switch to exclusive and back to normal is needed to release the
4482 * window properly. Without doing this, SetCooperativeLevel(EXCLUSIVE) will not send
4483 * WM_ACTIVATEAPP messages. */
4484 activateapp_testdata.ddraw = NULL;
4485 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4486 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4487 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4488 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4490 /* Setting DDSCL_NORMAL with recursive invocation. */
4491 SetForegroundWindow(GetDesktopWindow());
4492 activateapp_testdata.received = FALSE;
4493 activateapp_testdata.ddraw = ddraw;
4494 activateapp_testdata.window = window;
4495 activateapp_testdata.coop_level = DDSCL_NORMAL;
4496 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4497 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4498 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4500 /* DDraw is in exlusive mode now. */
4501 memset(&ddsd, 0, sizeof(ddsd));
4502 ddsd.dwSize = sizeof(ddsd);
4503 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
4504 U5(ddsd).dwBackBufferCount = 1;
4505 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
4506 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
4507 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4508 IDirectDrawSurface7_Release(surface);
4510 /* Recover again, just to be sure. */
4511 activateapp_testdata.ddraw = NULL;
4512 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4513 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4514 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4515 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4517 DestroyWindow(window);
4518 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
4519 IDirectDraw7_Release(ddraw);
4522 static void test_texturemanage(void)
4524 IDirectDraw7 *ddraw;
4525 HRESULT hr;
4526 DDSURFACEDESC2 ddsd;
4527 IDirectDrawSurface7 *surface;
4528 unsigned int i;
4529 DDCAPS hal_caps, hel_caps;
4530 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
4531 static const struct
4533 DWORD caps_in, caps2_in;
4534 HRESULT hr;
4535 DWORD caps_out, caps2_out;
4537 tests[] =
4539 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4540 ~0U, ~0U},
4541 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4542 ~0U, ~0U},
4543 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4544 ~0U, ~0U},
4545 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4546 ~0U, ~0U},
4547 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DD_OK,
4548 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE},
4549 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DD_OK,
4550 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE},
4551 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
4552 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_LOCALVIDMEM, 0},
4553 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
4554 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0},
4556 {0, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4557 ~0U, ~0U},
4558 {0, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4559 ~0U, ~0U},
4560 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4561 ~0U, ~0U},
4562 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4563 ~0U, ~0U},
4564 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4565 ~0U, ~0U},
4566 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4567 ~0U, ~0U},
4568 {DDSCAPS_VIDEOMEMORY, 0, DD_OK,
4569 DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY, 0},
4570 {DDSCAPS_SYSTEMMEMORY, 0, DD_OK,
4571 DDSCAPS_SYSTEMMEMORY, 0},
4574 ddraw = create_ddraw();
4575 ok(!!ddraw, "Failed to create a ddraw object.\n");
4576 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4577 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4579 memset(&hal_caps, 0, sizeof(hal_caps));
4580 hal_caps.dwSize = sizeof(hal_caps);
4581 memset(&hel_caps, 0, sizeof(hel_caps));
4582 hel_caps.dwSize = sizeof(hel_caps);
4583 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, &hel_caps);
4584 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
4585 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps)
4587 skip("Managed textures not supported, skipping managed texture test.\n");
4588 IDirectDraw7_Release(ddraw);
4589 return;
4592 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
4594 memset(&ddsd, 0, sizeof(ddsd));
4595 ddsd.dwSize = sizeof(ddsd);
4596 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
4597 ddsd.ddsCaps.dwCaps = tests[i].caps_in;
4598 ddsd.ddsCaps.dwCaps2 = tests[i].caps2_in;
4599 ddsd.dwWidth = 4;
4600 ddsd.dwHeight = 4;
4602 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
4603 ok(hr == tests[i].hr, "Got unexpected, hr %#x, case %u.\n", hr, i);
4604 if (FAILED(hr))
4605 continue;
4607 memset(&ddsd, 0, sizeof(ddsd));
4608 ddsd.dwSize = sizeof(ddsd);
4609 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
4610 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4612 ok(ddsd.ddsCaps.dwCaps == tests[i].caps_out,
4613 "Input caps %#x, %#x, expected output caps %#x, got %#x, case %u.\n",
4614 tests[i].caps_in, tests[i].caps2_in, tests[i].caps_out, ddsd.ddsCaps.dwCaps, i);
4615 ok(ddsd.ddsCaps.dwCaps2 == tests[i].caps2_out,
4616 "Input caps %#x, %#x, expected output caps %#x, got %#x, case %u.\n",
4617 tests[i].caps_in, tests[i].caps2_in, tests[i].caps2_out, ddsd.ddsCaps.dwCaps2, i);
4619 IDirectDrawSurface7_Release(surface);
4622 IDirectDraw7_Release(ddraw);
4625 #define SUPPORT_DXT1 0x01
4626 #define SUPPORT_DXT2 0x02
4627 #define SUPPORT_DXT3 0x04
4628 #define SUPPORT_DXT4 0x08
4629 #define SUPPORT_DXT5 0x10
4630 #define SUPPORT_YUY2 0x20
4631 #define SUPPORT_UYVY 0x40
4633 static HRESULT WINAPI test_block_formats_creation_cb(DDPIXELFORMAT *fmt, void *ctx)
4635 DWORD *supported_fmts = ctx;
4637 if (!(fmt->dwFlags & DDPF_FOURCC))
4638 return DDENUMRET_OK;
4640 switch (fmt->dwFourCC)
4642 case MAKEFOURCC('D','X','T','1'):
4643 *supported_fmts |= SUPPORT_DXT1;
4644 break;
4645 case MAKEFOURCC('D','X','T','2'):
4646 *supported_fmts |= SUPPORT_DXT2;
4647 break;
4648 case MAKEFOURCC('D','X','T','3'):
4649 *supported_fmts |= SUPPORT_DXT3;
4650 break;
4651 case MAKEFOURCC('D','X','T','4'):
4652 *supported_fmts |= SUPPORT_DXT4;
4653 break;
4654 case MAKEFOURCC('D','X','T','5'):
4655 *supported_fmts |= SUPPORT_DXT5;
4656 break;
4657 case MAKEFOURCC('Y','U','Y','2'):
4658 *supported_fmts |= SUPPORT_YUY2;
4659 break;
4660 case MAKEFOURCC('U','Y','V','Y'):
4661 *supported_fmts |= SUPPORT_UYVY;
4662 break;
4663 default:
4664 break;
4667 return DDENUMRET_OK;
4670 static void test_block_formats_creation(void)
4672 HRESULT hr, expect_hr;
4673 unsigned int i, j, w, h;
4674 HWND window;
4675 IDirectDraw7 *ddraw;
4676 IDirect3D7 *d3d;
4677 IDirect3DDevice7 *device;
4678 IDirectDrawSurface7 *surface;
4679 DWORD supported_fmts = 0, supported_overlay_fmts = 0;
4680 DWORD num_fourcc_codes = 0, *fourcc_codes;
4681 DDSURFACEDESC2 ddsd;
4682 DDCAPS hal_caps;
4683 void *mem;
4685 static const struct
4687 DWORD fourcc;
4688 const char *name;
4689 DWORD support_flag;
4690 unsigned int block_width;
4691 unsigned int block_height;
4692 unsigned int block_size;
4693 BOOL create_size_checked, overlay;
4695 formats[] =
4697 {MAKEFOURCC('D','X','T','1'), "D3DFMT_DXT1", SUPPORT_DXT1, 4, 4, 8, TRUE, FALSE},
4698 {MAKEFOURCC('D','X','T','2'), "D3DFMT_DXT2", SUPPORT_DXT2, 4, 4, 16, TRUE, FALSE},
4699 {MAKEFOURCC('D','X','T','3'), "D3DFMT_DXT3", SUPPORT_DXT3, 4, 4, 16, TRUE, FALSE},
4700 {MAKEFOURCC('D','X','T','4'), "D3DFMT_DXT4", SUPPORT_DXT4, 4, 4, 16, TRUE, FALSE},
4701 {MAKEFOURCC('D','X','T','5'), "D3DFMT_DXT5", SUPPORT_DXT5, 4, 4, 16, TRUE, FALSE},
4702 {MAKEFOURCC('Y','U','Y','2'), "D3DFMT_YUY2", SUPPORT_YUY2, 2, 1, 4, FALSE, TRUE },
4703 {MAKEFOURCC('U','Y','V','Y'), "D3DFMT_UYVY", SUPPORT_UYVY, 2, 1, 4, FALSE, TRUE },
4705 static const struct
4707 DWORD caps, caps2;
4708 const char *name;
4709 BOOL overlay;
4711 types[] =
4713 /* DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY fails to create any fourcc
4714 * surface with DDERR_INVALIDPIXELFORMAT. Don't care about it for now.
4716 * Nvidia returns E_FAIL on DXTN DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY.
4717 * Other hw / drivers successfully create those surfaces. Ignore them, this
4718 * suggests that no game uses this, otherwise Nvidia would support it. */
4720 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0,
4721 "videomemory texture", FALSE
4724 DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY, 0,
4725 "videomemory overlay", TRUE
4728 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0,
4729 "systemmemory texture", FALSE
4732 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
4733 "managed texture", FALSE
4736 enum size_type
4738 SIZE_TYPE_ZERO,
4739 SIZE_TYPE_PITCH,
4740 SIZE_TYPE_SIZE,
4742 static const struct
4744 DWORD flags;
4745 enum size_type size_type;
4746 int rel_size;
4747 HRESULT hr;
4749 user_mem_tests[] =
4751 {DDSD_LINEARSIZE, SIZE_TYPE_ZERO, 0, DD_OK},
4752 {DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
4753 {DDSD_PITCH, SIZE_TYPE_ZERO, 0, DD_OK},
4754 {DDSD_PITCH, SIZE_TYPE_PITCH, 0, DD_OK},
4755 {DDSD_LPSURFACE, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
4756 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
4757 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_PITCH, 0, DDERR_INVALIDPARAMS},
4758 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
4759 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 1, DD_OK},
4760 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, -1, DDERR_INVALIDPARAMS},
4761 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
4762 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_PITCH, 0, DDERR_INVALIDPARAMS},
4763 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_SIZE, 0, DDERR_INVALIDPARAMS},
4764 {DDSD_LPSURFACE | DDSD_PITCH | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DDERR_INVALIDPARAMS},
4767 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4768 0, 0, 640, 480, 0, 0, 0, 0);
4770 if (!(device = create_device(window, DDSCL_NORMAL)))
4772 skip("Failed to create a 3D device, skipping test.\n");
4773 DestroyWindow(window);
4774 return;
4777 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
4778 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
4779 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **) &ddraw);
4780 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
4781 IDirect3D7_Release(d3d);
4783 hr = IDirect3DDevice7_EnumTextureFormats(device, test_block_formats_creation_cb,
4784 &supported_fmts);
4785 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
4787 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
4788 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
4789 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
4790 num_fourcc_codes * sizeof(*fourcc_codes));
4791 if (!fourcc_codes)
4792 goto cleanup;
4793 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
4794 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
4795 for (i = 0; i < num_fourcc_codes; i++)
4797 for (j = 0; j < sizeof(formats) / sizeof(*formats); j++)
4799 if (fourcc_codes[i] == formats[j].fourcc)
4800 supported_overlay_fmts |= formats[j].support_flag;
4803 HeapFree(GetProcessHeap(), 0, fourcc_codes);
4805 memset(&hal_caps, 0, sizeof(hal_caps));
4806 hal_caps.dwSize = sizeof(hal_caps);
4807 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
4808 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
4810 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 2 * 2 * 16 + 1);
4812 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
4814 for (j = 0; j < sizeof(types) / sizeof(*types); j++)
4816 BOOL support;
4818 if (formats[i].overlay != types[j].overlay
4819 || (types[j].overlay && !(hal_caps.dwCaps & DDCAPS_OVERLAY)))
4820 continue;
4822 if (formats[i].overlay)
4823 support = supported_overlay_fmts & formats[i].support_flag;
4824 else
4825 support = supported_fmts & formats[i].support_flag;
4827 for (w = 1; w <= 8; w++)
4829 for (h = 1; h <= 8; h++)
4831 BOOL block_aligned = TRUE;
4832 BOOL todo = FALSE;
4834 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
4835 block_aligned = FALSE;
4837 memset(&ddsd, 0, sizeof(ddsd));
4838 ddsd.dwSize = sizeof(ddsd);
4839 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
4840 ddsd.ddsCaps.dwCaps = types[j].caps;
4841 ddsd.ddsCaps.dwCaps2 = types[j].caps2;
4842 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
4843 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
4844 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
4845 ddsd.dwWidth = w;
4846 ddsd.dwHeight = h;
4848 /* TODO: Handle power of two limitations. I cannot test the pow2
4849 * behavior on windows because I have no hardware that doesn't at
4850 * least support np2_conditional. There's probably no HW that
4851 * supports DXTN textures but no conditional np2 textures. */
4852 if (!support && !(types[j].caps & DDSCAPS_SYSTEMMEMORY))
4853 expect_hr = DDERR_INVALIDPARAMS;
4854 else if (formats[i].create_size_checked && !block_aligned)
4856 expect_hr = DDERR_INVALIDPARAMS;
4857 if (!(types[j].caps & DDSCAPS_TEXTURE))
4858 todo = TRUE;
4860 else
4861 expect_hr = D3D_OK;
4863 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
4864 if (todo)
4865 todo_wine ok(hr == expect_hr,
4866 "Got unexpected hr %#x for format %s, resource type %s, size %ux%u, expected %#x.\n",
4867 hr, formats[i].name, types[j].name, w, h, expect_hr);
4868 else
4869 ok(hr == expect_hr,
4870 "Got unexpected hr %#x for format %s, resource type %s, size %ux%u, expected %#x.\n",
4871 hr, formats[i].name, types[j].name, w, h, expect_hr);
4873 if (SUCCEEDED(hr))
4874 IDirectDrawSurface7_Release(surface);
4879 if (formats[i].overlay)
4880 continue;
4882 for (j = 0; j < sizeof(user_mem_tests) / sizeof(*user_mem_tests); ++j)
4884 memset(&ddsd, 0, sizeof(ddsd));
4885 ddsd.dwSize = sizeof(ddsd);
4886 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | user_mem_tests[j].flags;
4887 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE;
4889 switch (user_mem_tests[j].size_type)
4891 case SIZE_TYPE_ZERO:
4892 U1(ddsd).dwLinearSize = 0;
4893 break;
4895 case SIZE_TYPE_PITCH:
4896 U1(ddsd).dwLinearSize = 2 * formats[i].block_size;
4897 break;
4899 case SIZE_TYPE_SIZE:
4900 U1(ddsd).dwLinearSize = 2 * 2 * formats[i].block_size;
4901 break;
4903 U1(ddsd).dwLinearSize += user_mem_tests[j].rel_size;
4905 ddsd.lpSurface = mem;
4906 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
4907 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
4908 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
4909 ddsd.dwWidth = 8;
4910 ddsd.dwHeight = 8;
4912 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
4913 ok(hr == user_mem_tests[j].hr, "Test %u: Got unexpected hr %#x, format %s.\n", j, hr, formats[i].name);
4915 if (FAILED(hr))
4916 continue;
4918 memset(&ddsd, 0, sizeof(ddsd));
4919 ddsd.dwSize = sizeof(ddsd);
4920 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
4921 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", j, hr);
4922 ok(ddsd.dwFlags == (DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_LINEARSIZE),
4923 "Test %u: Got unexpected flags %#x.\n", j, ddsd.dwFlags);
4924 if (user_mem_tests[j].flags & DDSD_LPSURFACE)
4925 ok(U1(ddsd).dwLinearSize == ~0u, "Test %u: Got unexpected linear size %#x.\n",
4926 j, U1(ddsd).dwLinearSize);
4927 else
4928 ok(U1(ddsd).dwLinearSize == 2 * 2 * formats[i].block_size,
4929 "Test %u: Got unexpected linear size %#x, expected %#x.\n",
4930 j, U1(ddsd).dwLinearSize, 2 * 2 * formats[i].block_size);
4931 IDirectDrawSurface7_Release(surface);
4935 HeapFree(GetProcessHeap(), 0, mem);
4936 cleanup:
4937 IDirectDraw7_Release(ddraw);
4938 IDirect3DDevice7_Release(device);
4939 DestroyWindow(window);
4942 struct format_support_check
4944 const DDPIXELFORMAT *format;
4945 BOOL supported;
4948 static HRESULT WINAPI test_unsupported_formats_cb(DDPIXELFORMAT *fmt, void *ctx)
4950 struct format_support_check *format = ctx;
4952 if (!memcmp(format->format, fmt, sizeof(*fmt)))
4954 format->supported = TRUE;
4955 return DDENUMRET_CANCEL;
4958 return DDENUMRET_OK;
4961 static void test_unsupported_formats(void)
4963 HRESULT hr;
4964 BOOL expect_success;
4965 HWND window;
4966 IDirectDraw7 *ddraw;
4967 IDirect3D7 *d3d;
4968 IDirect3DDevice7 *device;
4969 IDirectDrawSurface7 *surface;
4970 DDSURFACEDESC2 ddsd;
4971 unsigned int i, j;
4972 DWORD expected_caps;
4973 static const struct
4975 const char *name;
4976 DDPIXELFORMAT fmt;
4978 formats[] =
4981 "D3DFMT_A8R8G8B8",
4983 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
4984 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
4988 "D3DFMT_P8",
4990 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
4991 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
4995 static const DWORD caps[] = {0, DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY};
4997 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4998 0, 0, 640, 480, 0, 0, 0, 0);
5000 if (!(device = create_device(window, DDSCL_NORMAL)))
5002 skip("Failed to create a 3D device, skipping test.\n");
5003 DestroyWindow(window);
5004 return;
5007 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
5008 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
5009 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **) &ddraw);
5010 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
5011 IDirect3D7_Release(d3d);
5013 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
5015 struct format_support_check check = {&formats[i].fmt, FALSE};
5016 hr = IDirect3DDevice7_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
5017 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
5019 for (j = 0; j < sizeof(caps) / sizeof(*caps); j++)
5021 memset(&ddsd, 0, sizeof(ddsd));
5022 ddsd.dwSize = sizeof(ddsd);
5023 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
5024 U4(ddsd).ddpfPixelFormat = formats[i].fmt;
5025 ddsd.dwWidth = 4;
5026 ddsd.dwHeight = 4;
5027 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | caps[j];
5029 if (caps[j] & DDSCAPS_VIDEOMEMORY && !check.supported)
5030 expect_success = FALSE;
5031 else
5032 expect_success = TRUE;
5034 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5035 ok(SUCCEEDED(hr) == expect_success,
5036 "Got unexpected hr %#x for format %s, caps %#x, expected %s.\n",
5037 hr, formats[i].name, caps[j], expect_success ? "success" : "failure");
5038 if (FAILED(hr))
5039 continue;
5041 memset(&ddsd, 0, sizeof(ddsd));
5042 ddsd.dwSize = sizeof(ddsd);
5043 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
5044 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5046 if (caps[j] & DDSCAPS_VIDEOMEMORY)
5047 expected_caps = DDSCAPS_VIDEOMEMORY;
5048 else if (caps[j] & DDSCAPS_SYSTEMMEMORY)
5049 expected_caps = DDSCAPS_SYSTEMMEMORY;
5050 else if (check.supported)
5051 expected_caps = DDSCAPS_VIDEOMEMORY;
5052 else
5053 expected_caps = DDSCAPS_SYSTEMMEMORY;
5055 ok(ddsd.ddsCaps.dwCaps & expected_caps,
5056 "Expected capability %#x, format %s, input cap %#x.\n",
5057 expected_caps, formats[i].name, caps[j]);
5059 IDirectDrawSurface7_Release(surface);
5063 IDirectDraw7_Release(ddraw);
5064 IDirect3DDevice7_Release(device);
5065 DestroyWindow(window);
5068 static void test_rt_caps(void)
5070 const GUID *devtype = &IID_IDirect3DHALDevice;
5071 PALETTEENTRY palette_entries[256];
5072 IDirectDrawPalette *palette;
5073 IDirectDraw7 *ddraw;
5074 BOOL hal_ok = FALSE;
5075 DDPIXELFORMAT z_fmt;
5076 IDirect3D7 *d3d;
5077 unsigned int i;
5078 ULONG refcount;
5079 HWND window;
5080 HRESULT hr;
5082 static const DDPIXELFORMAT p8_fmt =
5084 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
5085 {8}, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000},
5088 const struct
5090 const DDPIXELFORMAT *pf;
5091 DWORD caps_in;
5092 DWORD caps_out;
5093 HRESULT create_device_hr;
5094 HRESULT set_rt_hr, alternative_set_rt_hr;
5096 test_data[] =
5099 NULL,
5100 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
5101 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5102 D3D_OK,
5103 D3D_OK,
5104 D3D_OK,
5107 NULL,
5108 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5109 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5110 D3D_OK,
5111 D3D_OK,
5112 D3D_OK,
5115 NULL,
5116 DDSCAPS_OFFSCREENPLAIN,
5117 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5118 DDERR_INVALIDCAPS,
5119 DDERR_INVALIDCAPS,
5120 DDERR_INVALIDCAPS,
5123 NULL,
5124 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5125 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5126 D3DERR_SURFACENOTINVIDMEM,
5127 DDERR_INVALIDPARAMS,
5128 D3D_OK,
5131 NULL,
5132 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5133 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5134 DDERR_INVALIDCAPS,
5135 DDERR_INVALIDCAPS,
5136 DDERR_INVALIDCAPS,
5139 NULL,
5140 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
5141 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5142 D3D_OK,
5143 D3D_OK,
5144 D3D_OK,
5147 NULL,
5148 DDSCAPS_3DDEVICE,
5149 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5150 D3D_OK,
5151 D3D_OK,
5152 D3D_OK,
5155 NULL,
5157 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5158 DDERR_INVALIDCAPS,
5159 DDERR_INVALIDCAPS,
5160 DDERR_INVALIDCAPS,
5163 NULL,
5164 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5165 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5166 D3DERR_SURFACENOTINVIDMEM,
5167 DDERR_INVALIDPARAMS,
5168 D3D_OK,
5171 NULL,
5172 DDSCAPS_SYSTEMMEMORY,
5173 DDSCAPS_SYSTEMMEMORY,
5174 DDERR_INVALIDCAPS,
5175 DDERR_INVALIDCAPS,
5176 DDERR_INVALIDCAPS,
5179 &p8_fmt,
5181 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5182 DDERR_INVALIDCAPS,
5183 DDERR_INVALIDCAPS,
5184 DDERR_INVALIDCAPS,
5187 &p8_fmt,
5188 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5189 ~0U /* AMD r200 */,
5190 DDERR_NOPALETTEATTACHED,
5191 DDERR_INVALIDCAPS,
5192 DDERR_INVALIDCAPS,
5195 &p8_fmt,
5196 DDSCAPS_OFFSCREENPLAIN,
5197 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5198 DDERR_INVALIDCAPS,
5199 DDERR_INVALIDCAPS,
5200 DDERR_INVALIDCAPS,
5203 &p8_fmt,
5204 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5205 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5206 DDERR_NOPALETTEATTACHED,
5207 DDERR_INVALIDCAPS,
5208 DDERR_INVALIDCAPS,
5211 &p8_fmt,
5212 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5213 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5214 DDERR_INVALIDCAPS,
5215 DDERR_INVALIDCAPS,
5216 DDERR_INVALIDCAPS,
5219 &z_fmt,
5220 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
5221 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5222 DDERR_INVALIDCAPS,
5223 DDERR_INVALIDPIXELFORMAT,
5224 DDERR_INVALIDPIXELFORMAT,
5227 &z_fmt,
5228 DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5229 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5230 DDERR_INVALIDCAPS,
5231 DDERR_INVALIDPIXELFORMAT,
5232 DDERR_INVALIDPIXELFORMAT,
5235 &z_fmt,
5236 DDSCAPS_ZBUFFER,
5237 DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5238 DDERR_INVALIDCAPS,
5239 DDERR_INVALIDCAPS,
5240 DDERR_INVALIDCAPS,
5243 &z_fmt,
5244 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5245 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5246 DDERR_INVALIDCAPS,
5247 DDERR_INVALIDPARAMS,
5248 DDERR_INVALIDPIXELFORMAT,
5251 &z_fmt,
5252 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
5253 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
5254 DDERR_INVALIDCAPS,
5255 DDERR_INVALIDCAPS,
5256 DDERR_INVALIDCAPS,
5260 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5261 0, 0, 640, 480, 0, 0, 0, 0);
5262 ddraw = create_ddraw();
5263 ok(!!ddraw, "Failed to create a ddraw object.\n");
5264 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5265 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5267 if (FAILED(IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d)))
5269 skip("D3D interface is not available, skipping test.\n");
5270 goto done;
5273 hr = IDirect3D7_EnumDevices(d3d, enum_devtype_cb, &hal_ok);
5274 ok(SUCCEEDED(hr), "Failed to enumerate devices, hr %#x.\n", hr);
5275 if (hal_ok)
5276 devtype = &IID_IDirect3DTnLHalDevice;
5278 memset(&z_fmt, 0, sizeof(z_fmt));
5279 hr = IDirect3D7_EnumZBufferFormats(d3d, devtype, enum_z_fmt, &z_fmt);
5280 if (FAILED(hr) || !z_fmt.dwSize)
5282 skip("No depth buffer formats available, skipping test.\n");
5283 IDirect3D7_Release(d3d);
5284 goto done;
5287 memset(palette_entries, 0, sizeof(palette_entries));
5288 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
5289 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
5291 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
5293 IDirectDrawSurface7 *surface, *rt, *expected_rt, *tmp;
5294 DDSURFACEDESC2 surface_desc;
5295 IDirect3DDevice7 *device;
5297 memset(&surface_desc, 0, sizeof(surface_desc));
5298 surface_desc.dwSize = sizeof(surface_desc);
5299 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5300 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5301 if (test_data[i].pf)
5303 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
5304 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
5306 surface_desc.dwWidth = 640;
5307 surface_desc.dwHeight = 480;
5308 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5309 ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
5310 i, test_data[i].caps_in, hr);
5312 memset(&surface_desc, 0, sizeof(surface_desc));
5313 surface_desc.dwSize = sizeof(surface_desc);
5314 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
5315 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
5316 ok(test_data[i].caps_out == ~0U || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out,
5317 "Test %u: Got unexpected caps %#x, expected %#x.\n",
5318 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
5320 hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
5321 ok(hr == test_data[i].create_device_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n",
5322 i, hr, test_data[i].create_device_hr);
5323 if (FAILED(hr))
5325 if (hr == DDERR_NOPALETTEATTACHED)
5327 hr = IDirectDrawSurface7_SetPalette(surface, palette);
5328 ok(SUCCEEDED(hr), "Test %u: Failed to set palette, hr %#x.\n", i, hr);
5329 hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
5330 if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
5331 ok(hr == DDERR_INVALIDPIXELFORMAT, "Test %u: Got unexpected hr %#x.\n", i, hr);
5332 else
5333 ok(hr == D3DERR_SURFACENOTINVIDMEM, "Test %u: Got unexpected hr %#x.\n", i, hr);
5335 IDirectDrawSurface7_Release(surface);
5337 memset(&surface_desc, 0, sizeof(surface_desc));
5338 surface_desc.dwSize = sizeof(surface_desc);
5339 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5340 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
5341 surface_desc.dwWidth = 640;
5342 surface_desc.dwHeight = 480;
5343 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5344 ok(SUCCEEDED(hr), "Test %u: Failed to create surface, hr %#x.\n", i, hr);
5346 hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
5347 ok(SUCCEEDED(hr), "Test %u: Failed to create device, hr %#x.\n", i, hr);
5350 memset(&surface_desc, 0, sizeof(surface_desc));
5351 surface_desc.dwSize = sizeof(surface_desc);
5352 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5353 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5354 if (test_data[i].pf)
5356 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
5357 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
5359 surface_desc.dwWidth = 640;
5360 surface_desc.dwHeight = 480;
5361 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &rt, NULL);
5362 ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
5363 i, test_data[i].caps_in, hr);
5365 hr = IDirect3DDevice7_SetRenderTarget(device, rt, 0);
5366 ok(hr == test_data[i].set_rt_hr || broken(hr == test_data[i].alternative_set_rt_hr),
5367 "Test %u: Got unexpected hr %#x, expected %#x.\n",
5368 i, hr, test_data[i].set_rt_hr);
5369 if (SUCCEEDED(hr) || hr == DDERR_INVALIDPIXELFORMAT)
5370 expected_rt = rt;
5371 else
5372 expected_rt = surface;
5374 hr = IDirect3DDevice7_GetRenderTarget(device, &tmp);
5375 ok(SUCCEEDED(hr), "Test %u: Failed to get render target, hr %#x.\n", i, hr);
5376 ok(tmp == expected_rt, "Test %u: Got unexpected rt %p.\n", i, tmp);
5378 IDirectDrawSurface7_Release(tmp);
5379 IDirectDrawSurface7_Release(rt);
5380 refcount = IDirect3DDevice7_Release(device);
5381 ok(refcount == 0, "Test %u: The device was not properly freed, refcount %u.\n", i, refcount);
5382 refcount = IDirectDrawSurface7_Release(surface);
5383 ok(refcount == 0, "Test %u: The surface was not properly freed, refcount %u.\n", i, refcount);
5386 IDirectDrawPalette_Release(palette);
5387 IDirect3D7_Release(d3d);
5389 done:
5390 refcount = IDirectDraw7_Release(ddraw);
5391 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5392 DestroyWindow(window);
5395 static void test_primary_caps(void)
5397 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
5398 IDirectDrawSurface7 *surface;
5399 DDSURFACEDESC2 surface_desc;
5400 IDirectDraw7 *ddraw;
5401 unsigned int i;
5402 ULONG refcount;
5403 HWND window;
5404 HRESULT hr;
5406 static const struct
5408 DWORD coop_level;
5409 DWORD caps_in;
5410 DWORD back_buffer_count;
5411 HRESULT hr;
5412 DWORD caps_out;
5414 test_data[] =
5417 DDSCL_NORMAL,
5418 DDSCAPS_PRIMARYSURFACE,
5419 ~0u,
5420 DD_OK,
5421 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE,
5424 DDSCL_NORMAL,
5425 DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE,
5426 ~0u,
5427 DDERR_INVALIDCAPS,
5428 ~0u,
5431 DDSCL_NORMAL,
5432 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
5433 ~0u,
5434 DDERR_INVALIDCAPS,
5435 ~0u,
5438 DDSCL_NORMAL,
5439 DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER,
5440 ~0u,
5441 DDERR_INVALIDCAPS,
5442 ~0u,
5445 DDSCL_NORMAL,
5446 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP,
5447 ~0u,
5448 DDERR_INVALIDCAPS,
5449 ~0u,
5452 DDSCL_NORMAL,
5453 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX,
5454 ~0u,
5455 DDERR_INVALIDCAPS,
5456 ~0u,
5459 DDSCL_NORMAL,
5460 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5461 ~0u,
5462 DDERR_INVALIDCAPS,
5463 ~0u,
5466 DDSCL_NORMAL,
5467 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5469 DDERR_INVALIDCAPS,
5470 ~0u,
5473 DDSCL_NORMAL,
5474 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5476 DDERR_NOEXCLUSIVEMODE,
5477 ~0u,
5480 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5481 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5483 DDERR_INVALIDCAPS,
5484 ~0u,
5487 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5488 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5490 DD_OK,
5491 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX,
5494 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5495 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER,
5497 DDERR_INVALIDCAPS,
5498 ~0u,
5501 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5502 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_BACKBUFFER,
5504 DDERR_INVALIDCAPS,
5505 ~0u,
5509 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5510 0, 0, 640, 480, 0, 0, 0, 0);
5511 ddraw = create_ddraw();
5512 ok(!!ddraw, "Failed to create a ddraw object.\n");
5514 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
5516 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, test_data[i].coop_level);
5517 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5519 memset(&surface_desc, 0, sizeof(surface_desc));
5520 surface_desc.dwSize = sizeof(surface_desc);
5521 surface_desc.dwFlags = DDSD_CAPS;
5522 if (test_data[i].back_buffer_count != ~0u)
5523 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
5524 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5525 U5(surface_desc).dwBackBufferCount = test_data[i].back_buffer_count;
5526 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5527 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
5528 if (FAILED(hr))
5529 continue;
5531 memset(&surface_desc, 0, sizeof(surface_desc));
5532 surface_desc.dwSize = sizeof(surface_desc);
5533 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
5534 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
5535 ok((surface_desc.ddsCaps.dwCaps & ~placement) == test_data[i].caps_out,
5536 "Test %u: Got unexpected caps %#x, expected %#x.\n",
5537 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
5539 IDirectDrawSurface7_Release(surface);
5542 refcount = IDirectDraw7_Release(ddraw);
5543 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5544 DestroyWindow(window);
5547 static void test_surface_lock(void)
5549 IDirectDraw7 *ddraw;
5550 IDirect3D7 *d3d = NULL;
5551 IDirectDrawSurface7 *surface;
5552 IDirect3DDevice7 *device;
5553 HRESULT hr;
5554 HWND window;
5555 unsigned int i;
5556 DDSURFACEDESC2 ddsd;
5557 ULONG refcount;
5558 DDPIXELFORMAT z_fmt;
5559 BOOL hal_ok = FALSE;
5560 const GUID *devtype = &IID_IDirect3DHALDevice;
5561 D3DDEVICEDESC7 device_desc;
5562 BOOL cubemap_supported;
5563 static const struct
5565 DWORD caps;
5566 DWORD caps2;
5567 const char *name;
5569 tests[] =
5572 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
5574 "videomemory offscreenplain"
5577 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5579 "systemmemory offscreenplain"
5582 DDSCAPS_PRIMARYSURFACE,
5584 "primary"
5587 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
5589 "videomemory texture"
5592 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
5593 DDSCAPS2_OPAQUE,
5594 "opaque videomemory texture"
5597 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
5599 "systemmemory texture"
5602 DDSCAPS_TEXTURE,
5603 DDSCAPS2_TEXTUREMANAGE,
5604 "managed texture"
5607 DDSCAPS_TEXTURE,
5608 DDSCAPS2_D3DTEXTUREMANAGE,
5609 "managed texture"
5612 DDSCAPS_TEXTURE,
5613 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_OPAQUE,
5614 "opaque managed texture"
5617 DDSCAPS_TEXTURE,
5618 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_OPAQUE,
5619 "opaque managed texture"
5622 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5624 "render target"
5627 DDSCAPS_ZBUFFER,
5629 "Z buffer"
5632 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY,
5633 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
5634 "videomemory cube"
5637 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY,
5638 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_OPAQUE,
5639 "opaque videomemory cube"
5642 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_SYSTEMMEMORY,
5643 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
5644 "systemmemory cube"
5647 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
5648 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
5649 "managed cube"
5652 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
5653 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
5654 "managed cube"
5657 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
5658 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_OPAQUE,
5659 "opaque managed cube"
5662 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
5663 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_OPAQUE,
5664 "opaque managed cube"
5668 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5669 0, 0, 640, 480, 0, 0, 0, 0);
5670 ddraw = create_ddraw();
5671 ok(!!ddraw, "Failed to create a ddraw object.\n");
5672 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5673 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5675 if (FAILED(IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d)))
5677 skip("D3D interface is not available, skipping test.\n");
5678 goto done;
5681 hr = IDirect3D7_EnumDevices(d3d, enum_devtype_cb, &hal_ok);
5682 ok(SUCCEEDED(hr), "Failed to enumerate devices, hr %#x.\n", hr);
5683 if (hal_ok)
5684 devtype = &IID_IDirect3DTnLHalDevice;
5686 memset(&z_fmt, 0, sizeof(z_fmt));
5687 hr = IDirect3D7_EnumZBufferFormats(d3d, devtype, enum_z_fmt, &z_fmt);
5688 if (FAILED(hr) || !z_fmt.dwSize)
5690 skip("No depth buffer formats available, skipping test.\n");
5691 goto done;
5694 memset(&ddsd, 0, sizeof(ddsd));
5695 ddsd.dwSize = sizeof(ddsd);
5696 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5697 ddsd.dwWidth = 64;
5698 ddsd.dwHeight = 64;
5699 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
5700 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5701 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5703 hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
5704 ok(SUCCEEDED(hr), "Failed to create device, hr %#x.\n", hr);
5705 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
5706 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5707 cubemap_supported = !!(device_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP);
5708 IDirect3DDevice7_Release(device);
5710 IDirectDrawSurface7_Release(surface);
5712 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
5714 if (!cubemap_supported && tests[i].caps2 & DDSCAPS2_CUBEMAP)
5715 continue;
5717 memset(&ddsd, 0, sizeof(ddsd));
5718 ddsd.dwSize = sizeof(ddsd);
5719 ddsd.dwFlags = DDSD_CAPS;
5720 if (!(tests[i].caps & DDSCAPS_PRIMARYSURFACE))
5722 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
5723 ddsd.dwWidth = 64;
5724 ddsd.dwHeight = 64;
5726 if (tests[i].caps & DDSCAPS_ZBUFFER)
5728 ddsd.dwFlags |= DDSD_PIXELFORMAT;
5729 U4(ddsd).ddpfPixelFormat = z_fmt;
5731 ddsd.ddsCaps.dwCaps = tests[i].caps;
5732 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
5734 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5735 ok(SUCCEEDED(hr), "Failed to create surface, type %s, hr %#x.\n", tests[i].name, hr);
5737 memset(&ddsd, 0, sizeof(ddsd));
5738 ddsd.dwSize = sizeof(ddsd);
5739 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
5740 ok(SUCCEEDED(hr), "Failed to lock surface, type %s, hr %#x.\n", tests[i].name, hr);
5741 if (SUCCEEDED(hr))
5743 hr = IDirectDrawSurface7_Unlock(surface, NULL);
5744 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
5747 IDirectDrawSurface7_Release(surface);
5750 done:
5751 if (d3d)
5752 IDirect3D7_Release(d3d);
5753 refcount = IDirectDraw7_Release(ddraw);
5754 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5755 DestroyWindow(window);
5758 static void test_surface_discard(void)
5760 IDirect3DDevice7 *device;
5761 IDirect3D7 *d3d;
5762 IDirectDraw7 *ddraw;
5763 HRESULT hr;
5764 HWND window;
5765 DDSURFACEDESC2 ddsd;
5766 IDirectDrawSurface7 *surface, *target;
5767 void *addr;
5768 static const struct
5770 DWORD caps, caps2;
5771 BOOL discard;
5773 tests[] =
5775 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, TRUE},
5776 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
5777 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, TRUE},
5778 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
5779 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE},
5780 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
5781 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE},
5782 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
5784 unsigned int i;
5786 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5787 0, 0, 640, 480, 0, 0, 0, 0);
5789 if (!(device = create_device(window, DDSCL_NORMAL)))
5791 skip("Failed to create a 3D device, skipping test.\n");
5792 DestroyWindow(window);
5793 return;
5795 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
5796 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
5797 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
5798 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
5799 hr = IDirect3DDevice7_GetRenderTarget(device, &target);
5800 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
5802 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
5804 BOOL discarded;
5806 memset(&ddsd, 0, sizeof(ddsd));
5807 ddsd.dwSize = sizeof(ddsd);
5808 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5809 ddsd.ddsCaps.dwCaps = tests[i].caps;
5810 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
5811 ddsd.dwWidth = 64;
5812 ddsd.dwHeight = 64;
5813 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5814 ok(SUCCEEDED(hr), "Failed to create offscreen surface, hr %#x, case %u.\n", hr, i);
5816 memset(&ddsd, 0, sizeof(ddsd));
5817 ddsd.dwSize = sizeof(ddsd);
5818 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, 0, NULL);
5819 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5820 addr = ddsd.lpSurface;
5821 hr = IDirectDrawSurface7_Unlock(surface, NULL);
5822 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5824 memset(&ddsd, 0, sizeof(ddsd));
5825 ddsd.dwSize = sizeof(ddsd);
5826 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
5827 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5828 discarded = ddsd.lpSurface != addr;
5829 hr = IDirectDrawSurface7_Unlock(surface, NULL);
5830 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5832 hr = IDirectDrawSurface7_Blt(target, NULL, surface, NULL, DDBLT_WAIT, NULL);
5833 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
5835 memset(&ddsd, 0, sizeof(ddsd));
5836 ddsd.dwSize = sizeof(ddsd);
5837 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
5838 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5839 discarded |= ddsd.lpSurface != addr;
5840 hr = IDirectDrawSurface7_Unlock(surface, NULL);
5841 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5843 IDirectDrawSurface7_Release(surface);
5845 /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler,
5846 * AMD r500, evergreen). Windows XP, at least on AMD r200, does not. */
5847 ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i);
5850 IDirectDrawSurface7_Release(target);
5851 IDirectDraw7_Release(ddraw);
5852 IDirect3D7_Release(d3d);
5853 IDirect3DDevice7_Release(device);
5854 DestroyWindow(window);
5857 static void test_flip(void)
5859 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
5860 IDirectDrawSurface7 *primary, *backbuffer1, *backbuffer2, *backbuffer3, *surface;
5861 DDSCAPS2 caps = {DDSCAPS_FLIP, 0, 0, {0}};
5862 DDSURFACEDESC2 surface_desc;
5863 BOOL sysmem_primary;
5864 IDirectDraw7 *ddraw;
5865 D3DCOLOR color;
5866 ULONG refcount;
5867 HWND window;
5868 DDBLTFX fx;
5869 HRESULT hr;
5871 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5872 0, 0, 640, 480, 0, 0, 0, 0);
5873 ddraw = create_ddraw();
5874 ok(!!ddraw, "Failed to create a ddraw object.\n");
5876 hr = set_display_mode(ddraw, 640, 480);
5877 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
5878 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5879 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5881 memset(&surface_desc, 0, sizeof(surface_desc));
5882 surface_desc.dwSize = sizeof(surface_desc);
5883 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
5884 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
5885 U5(surface_desc).dwBackBufferCount = 3;
5886 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
5887 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5889 memset(&surface_desc, 0, sizeof(surface_desc));
5890 surface_desc.dwSize = sizeof(surface_desc);
5891 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &surface_desc);
5892 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5893 ok((surface_desc.ddsCaps.dwCaps & ~placement)
5894 == (DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX),
5895 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
5896 sysmem_primary = surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
5898 hr = IDirectDrawSurface7_GetAttachedSurface(primary, &caps, &backbuffer1);
5899 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
5900 memset(&surface_desc, 0, sizeof(surface_desc));
5901 surface_desc.dwSize = sizeof(surface_desc);
5902 hr = IDirectDrawSurface7_GetSurfaceDesc(backbuffer1, &surface_desc);
5903 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5904 ok(!U5(surface_desc).dwBackBufferCount, "Got unexpected back buffer count %u.\n", U5(surface_desc).dwBackBufferCount);
5905 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_BACKBUFFER),
5906 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
5908 hr = IDirectDrawSurface7_GetAttachedSurface(backbuffer1, &caps, &backbuffer2);
5909 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
5910 memset(&surface_desc, 0, sizeof(surface_desc));
5911 surface_desc.dwSize = sizeof(surface_desc);
5912 hr = IDirectDrawSurface7_GetSurfaceDesc(backbuffer2, &surface_desc);
5913 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5914 ok(!U5(surface_desc).dwBackBufferCount, "Got unexpected back buffer count %u.\n", U5(surface_desc).dwBackBufferCount);
5915 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX),
5916 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
5918 hr = IDirectDrawSurface7_GetAttachedSurface(backbuffer2, &caps, &backbuffer3);
5919 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
5920 memset(&surface_desc, 0, sizeof(surface_desc));
5921 surface_desc.dwSize = sizeof(surface_desc);
5922 hr = IDirectDrawSurface7_GetSurfaceDesc(backbuffer3, &surface_desc);
5923 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5924 ok(!U5(surface_desc).dwBackBufferCount, "Got unexpected back buffer count %u.\n", U5(surface_desc).dwBackBufferCount);
5925 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX),
5926 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
5928 hr = IDirectDrawSurface7_GetAttachedSurface(backbuffer3, &caps, &surface);
5929 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
5930 ok(surface == primary, "Got unexpected surface %p, expected %p.\n", surface, primary);
5931 IDirectDrawSurface7_Release(surface);
5933 memset(&surface_desc, 0, sizeof(surface_desc));
5934 surface_desc.dwSize = sizeof(surface_desc);
5935 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5936 surface_desc.ddsCaps.dwCaps = 0;
5937 surface_desc.dwWidth = 640;
5938 surface_desc.dwHeight = 480;
5939 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5940 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5941 hr = IDirectDrawSurface7_Flip(primary, surface, DDFLIP_WAIT);
5942 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
5943 IDirectDrawSurface7_Release(surface);
5945 hr = IDirectDrawSurface7_Flip(primary, primary, DDFLIP_WAIT);
5946 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
5947 hr = IDirectDrawSurface7_Flip(backbuffer1, NULL, DDFLIP_WAIT);
5948 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
5949 hr = IDirectDrawSurface7_Flip(backbuffer2, NULL, DDFLIP_WAIT);
5950 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
5951 hr = IDirectDrawSurface7_Flip(backbuffer3, NULL, DDFLIP_WAIT);
5952 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
5954 memset(&fx, 0, sizeof(fx));
5955 fx.dwSize = sizeof(fx);
5956 U5(fx).dwFillColor = 0xffff0000;
5957 hr = IDirectDrawSurface7_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
5958 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
5959 U5(fx).dwFillColor = 0xff00ff00;
5960 hr = IDirectDrawSurface7_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
5961 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
5962 U5(fx).dwFillColor = 0xff0000ff;
5963 hr = IDirectDrawSurface7_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
5964 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
5966 hr = IDirectDrawSurface7_Flip(primary, NULL, DDFLIP_WAIT);
5967 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
5968 color = get_surface_color(backbuffer1, 320, 240);
5969 /* The testbot seems to just copy the contents of one surface to all the
5970 * others, instead of properly flipping. */
5971 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
5972 "Got unexpected color 0x%08x.\n", color);
5973 color = get_surface_color(backbuffer2, 320, 240);
5974 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
5975 U5(fx).dwFillColor = 0xffff0000;
5976 hr = IDirectDrawSurface7_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
5977 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
5979 hr = IDirectDrawSurface7_Flip(primary, NULL, DDFLIP_WAIT);
5980 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
5981 color = get_surface_color(backbuffer1, 320, 240);
5982 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
5983 "Got unexpected color 0x%08x.\n", color);
5984 color = get_surface_color(backbuffer2, 320, 240);
5985 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
5986 U5(fx).dwFillColor = 0xff00ff00;
5987 hr = IDirectDrawSurface7_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
5988 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
5990 hr = IDirectDrawSurface7_Flip(primary, NULL, DDFLIP_WAIT);
5991 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
5992 color = get_surface_color(backbuffer1, 320, 240);
5993 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
5994 "Got unexpected color 0x%08x.\n", color);
5995 color = get_surface_color(backbuffer2, 320, 240);
5996 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
5997 U5(fx).dwFillColor = 0xff0000ff;
5998 hr = IDirectDrawSurface7_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
5999 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
6001 hr = IDirectDrawSurface7_Flip(primary, backbuffer1, DDFLIP_WAIT);
6002 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
6003 color = get_surface_color(backbuffer2, 320, 240);
6004 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
6005 "Got unexpected color 0x%08x.\n", color);
6006 color = get_surface_color(backbuffer3, 320, 240);
6007 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
6008 U5(fx).dwFillColor = 0xffff0000;
6009 hr = IDirectDrawSurface7_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6010 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
6012 hr = IDirectDrawSurface7_Flip(primary, backbuffer2, DDFLIP_WAIT);
6013 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
6014 color = get_surface_color(backbuffer1, 320, 240);
6015 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
6016 color = get_surface_color(backbuffer3, 320, 240);
6017 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
6018 "Got unexpected color 0x%08x.\n", color);
6019 U5(fx).dwFillColor = 0xff00ff00;
6020 hr = IDirectDrawSurface7_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6021 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
6023 hr = IDirectDrawSurface7_Flip(primary, backbuffer3, DDFLIP_WAIT);
6024 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
6025 color = get_surface_color(backbuffer1, 320, 240);
6026 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
6027 "Got unexpected color 0x%08x.\n", color);
6028 color = get_surface_color(backbuffer2, 320, 240);
6029 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
6031 IDirectDrawSurface7_Release(backbuffer3);
6032 IDirectDrawSurface7_Release(backbuffer2);
6033 IDirectDrawSurface7_Release(backbuffer1);
6034 IDirectDrawSurface7_Release(primary);
6035 refcount = IDirectDraw7_Release(ddraw);
6036 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
6037 DestroyWindow(window);
6040 static void reset_ddsd(DDSURFACEDESC2 *ddsd)
6042 memset(ddsd, 0, sizeof(*ddsd));
6043 ddsd->dwSize = sizeof(*ddsd);
6046 static void test_set_surface_desc(void)
6048 IDirectDraw7 *ddraw;
6049 HWND window;
6050 HRESULT hr;
6051 DDSURFACEDESC2 ddsd;
6052 IDirectDrawSurface7 *surface;
6053 BYTE data[16*16*4];
6054 ULONG ref;
6055 unsigned int i;
6056 static const struct
6058 DWORD caps, caps2;
6059 BOOL supported;
6060 const char *name;
6062 invalid_caps_tests[] =
6064 {DDSCAPS_VIDEOMEMORY, 0, FALSE, "videomemory plain"},
6065 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, TRUE, "systemmemory texture"},
6066 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE, "managed texture"},
6067 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE, "managed texture"},
6068 {DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY, 0, FALSE, "systemmemory primary"},
6071 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6072 0, 0, 640, 480, 0, 0, 0, 0);
6073 ddraw = create_ddraw();
6074 ok(!!ddraw, "Failed to create a ddraw object.\n");
6075 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6076 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6078 reset_ddsd(&ddsd);
6079 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
6080 ddsd.dwWidth = 8;
6081 ddsd.dwHeight = 8;
6082 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6083 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6084 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6085 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6086 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6087 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6088 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6090 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6091 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6093 reset_ddsd(&ddsd);
6094 ddsd.dwFlags = DDSD_LPSURFACE;
6095 ddsd.lpSurface = data;
6096 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6097 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6099 /* Redundantly setting the same lpSurface is not an error. */
6100 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6101 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6103 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6104 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6105 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
6106 ok(ddsd.lpSurface == NULL, "lpSurface is %p, expected NULL.\n", ddsd.lpSurface);
6108 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, 0, NULL);
6109 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6110 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
6111 ok(ddsd.lpSurface == data, "lpSurface is %p, expected %p.\n", data, data);
6112 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6113 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6115 reset_ddsd(&ddsd);
6116 ddsd.dwFlags = DDSD_LPSURFACE;
6117 ddsd.lpSurface = data;
6118 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 1);
6119 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with flags=1 returned %#x.\n", hr);
6121 ddsd.lpSurface = NULL;
6122 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6123 ok(hr == DDERR_INVALIDPARAMS, "Setting lpSurface=NULL returned %#x.\n", hr);
6125 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, NULL, 0);
6126 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with NULL desc returned %#x.\n", hr);
6128 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6129 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6130 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
6131 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
6132 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#x.\n", 0);
6134 /* Setting the caps is an error. This also means the original description cannot be reapplied. */
6135 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6136 ok(hr == DDERR_INVALIDPARAMS, "Setting the original desc returned %#x.\n", hr);
6138 ddsd.dwFlags = DDSD_CAPS;
6139 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6140 ok(hr == DDERR_INVALIDPARAMS, "Setting DDSD_CAPS returned %#x.\n", hr);
6142 /* dwCaps = 0 is allowed, but ignored. Caps2 can be anything and is ignored too. */
6143 ddsd.dwFlags = DDSD_CAPS | DDSD_LPSURFACE;
6144 ddsd.lpSurface = data;
6145 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6146 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
6147 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6148 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6149 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
6150 ddsd.ddsCaps.dwCaps = 0;
6151 ddsd.ddsCaps.dwCaps2 = 0xdeadbeef;
6152 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6153 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6155 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6156 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6157 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
6158 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
6159 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#x.\n", 0);
6161 /* Setting the height is allowed, but it cannot be set to 0, and only if LPSURFACE is set too. */
6162 reset_ddsd(&ddsd);
6163 ddsd.dwFlags = DDSD_HEIGHT;
6164 ddsd.dwHeight = 16;
6165 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6166 ok(hr == DDERR_INVALIDPARAMS, "Setting height without lpSurface returned %#x.\n", hr);
6168 ddsd.lpSurface = data;
6169 ddsd.dwFlags = DDSD_HEIGHT | DDSD_LPSURFACE;
6170 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6171 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6173 ddsd.dwHeight = 0;
6174 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6175 ok(hr == DDERR_INVALIDPARAMS, "Setting height=0 returned %#x.\n", hr);
6177 reset_ddsd(&ddsd);
6178 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6179 ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr);
6180 ok(ddsd.dwWidth == 8, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
6181 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
6183 /* Pitch and width can be set, but only together, and only with LPSURFACE. They must not be 0. */
6184 reset_ddsd(&ddsd);
6185 ddsd.dwFlags = DDSD_PITCH;
6186 U1(ddsd).lPitch = 8 * 4;
6187 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6188 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch without lpSurface or width returned %#x.\n", hr);
6190 ddsd.dwFlags = DDSD_WIDTH;
6191 ddsd.dwWidth = 16;
6192 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6193 ok(hr == DDERR_INVALIDPARAMS, "Setting width without lpSurface or pitch returned %#x.\n", hr);
6195 ddsd.dwFlags = DDSD_PITCH | DDSD_LPSURFACE;
6196 ddsd.lpSurface = data;
6197 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6198 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch and lpSurface without width returned %#x.\n", hr);
6200 ddsd.dwFlags = DDSD_WIDTH | DDSD_LPSURFACE;
6201 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6202 ok(hr == DDERR_INVALIDPARAMS, "Setting width and lpSurface without pitch returned %#x.\n", hr);
6204 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6205 U1(ddsd).lPitch = 16 * 4;
6206 ddsd.dwWidth = 16;
6207 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6208 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6210 reset_ddsd(&ddsd);
6211 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6212 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6213 ok(ddsd.dwWidth == 16, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
6214 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
6215 ok(U1(ddsd).lPitch == 16 * 4, "SetSurfaceDesc: Expected pitch 64, got %u.\n", U1(ddsd).lPitch);
6217 /* The pitch must be 32 bit aligned and > 0, but is not verified for sanity otherwise.
6219 * VMware rejects those calls, but all real drivers accept it. Mark the VMware behavior broken. */
6220 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6221 U1(ddsd).lPitch = 4 * 4;
6222 ddsd.lpSurface = data;
6223 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6224 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
6226 U1(ddsd).lPitch = 4;
6227 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6228 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
6230 U1(ddsd).lPitch = 16 * 4 + 1;
6231 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6232 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
6234 U1(ddsd).lPitch = 16 * 4 + 3;
6235 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6236 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
6238 U1(ddsd).lPitch = -4;
6239 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6240 ok(hr == DDERR_INVALIDPARAMS, "Setting negative pitch returned %#x.\n", hr);
6242 U1(ddsd).lPitch = 16 * 4;
6243 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6244 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6246 reset_ddsd(&ddsd);
6247 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6248 U1(ddsd).lPitch = 0;
6249 ddsd.dwWidth = 16;
6250 ddsd.lpSurface = data;
6251 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6252 ok(hr == DDERR_INVALIDPARAMS, "Setting zero pitch returned %#x.\n", hr);
6254 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6255 U1(ddsd).lPitch = 16 * 4;
6256 ddsd.dwWidth = 0;
6257 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6258 ok(hr == DDERR_INVALIDPARAMS, "Setting zero width returned %#x.\n", hr);
6260 /* Setting the pixelformat without LPSURFACE is an error, but with LPSURFACE it works. */
6261 ddsd.dwFlags = DDSD_PIXELFORMAT;
6262 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6263 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6264 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6265 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6266 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6267 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6268 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6269 ok(hr == DDERR_INVALIDPARAMS, "Setting the pixel format returned %#x.\n", hr);
6271 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_LPSURFACE;
6272 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6273 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6275 /* Can't set color keys. */
6276 reset_ddsd(&ddsd);
6277 ddsd.dwFlags = DDSD_CKSRCBLT;
6278 ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff0000;
6279 ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff0000;
6280 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6281 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
6283 ddsd.dwFlags = DDSD_CKSRCBLT | DDSD_LPSURFACE;
6284 ddsd.lpSurface = data;
6285 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6286 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
6288 IDirectDrawSurface7_Release(surface);
6290 /* SetSurfaceDesc needs systemmemory surfaces.
6292 * As a sidenote, fourcc surfaces aren't allowed in sysmem, thus testing DDSD_LINEARSIZE is moot. */
6293 for (i = 0; i < sizeof(invalid_caps_tests) / sizeof(*invalid_caps_tests); i++)
6295 reset_ddsd(&ddsd);
6296 ddsd.dwFlags = DDSD_CAPS;
6297 ddsd.ddsCaps.dwCaps = invalid_caps_tests[i].caps;
6298 ddsd.ddsCaps.dwCaps2 = invalid_caps_tests[i].caps2;
6299 if (!(invalid_caps_tests[i].caps & DDSCAPS_PRIMARYSURFACE))
6301 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6302 ddsd.dwWidth = 8;
6303 ddsd.dwHeight = 8;
6304 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6305 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6306 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6307 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6308 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6309 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6312 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6313 ok(SUCCEEDED(hr) || hr == DDERR_NODIRECTDRAWHW, "Failed to create surface, hr %#x.\n", hr);
6314 if (FAILED(hr))
6316 skip("Cannot create a %s surface, skipping vidmem SetSurfaceDesc test.\n",
6317 invalid_caps_tests[i].name);
6318 goto done;
6321 reset_ddsd(&ddsd);
6322 ddsd.dwFlags = DDSD_LPSURFACE;
6323 ddsd.lpSurface = data;
6324 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6325 if (invalid_caps_tests[i].supported)
6327 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6329 else
6331 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
6332 invalid_caps_tests[i].name, hr);
6334 /* Check priority of error conditions. */
6335 ddsd.dwFlags = DDSD_WIDTH;
6336 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6337 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
6338 invalid_caps_tests[i].name, hr);
6341 IDirectDrawSurface7_Release(surface);
6344 done:
6345 ref = IDirectDraw7_Release(ddraw);
6346 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
6347 DestroyWindow(window);
6350 static void test_user_memory_getdc(void)
6352 IDirectDraw7 *ddraw;
6353 HWND window;
6354 HRESULT hr;
6355 DDSURFACEDESC2 ddsd;
6356 IDirectDrawSurface7 *surface;
6357 DWORD data[16][16];
6358 ULONG ref;
6359 HDC dc;
6360 unsigned int x, y;
6362 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6363 0, 0, 640, 480, 0, 0, 0, 0);
6364 ddraw = create_ddraw();
6365 ok(!!ddraw, "Failed to create a ddraw object.\n");
6366 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6367 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6369 reset_ddsd(&ddsd);
6370 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
6371 ddsd.dwWidth = 16;
6372 ddsd.dwHeight = 16;
6373 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6374 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6375 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6376 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6377 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6378 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6379 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6380 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6381 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6383 memset(data, 0xaa, sizeof(data));
6384 reset_ddsd(&ddsd);
6385 ddsd.dwFlags = DDSD_LPSURFACE;
6386 ddsd.lpSurface = data;
6387 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6388 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6390 hr = IDirectDrawSurface7_GetDC(surface, &dc);
6391 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
6392 BitBlt(dc, 0, 0, 16, 8, NULL, 0, 0, WHITENESS);
6393 BitBlt(dc, 0, 8, 16, 8, NULL, 0, 0, BLACKNESS);
6394 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
6395 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
6397 ok(data[0][0] == 0xffffffff, "Expected color 0xffffffff, got %#x.\n", data[0][0]);
6398 ok(data[15][15] == 0x00000000, "Expected color 0x00000000, got %#x.\n", data[15][15]);
6400 ddsd.dwFlags = DDSD_LPSURFACE | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH;
6401 ddsd.lpSurface = data;
6402 ddsd.dwWidth = 4;
6403 ddsd.dwHeight = 8;
6404 U1(ddsd).lPitch = sizeof(*data);
6405 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6406 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6408 memset(data, 0xaa, sizeof(data));
6409 hr = IDirectDrawSurface7_GetDC(surface, &dc);
6410 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
6411 BitBlt(dc, 0, 0, 4, 8, NULL, 0, 0, BLACKNESS);
6412 BitBlt(dc, 1, 1, 2, 2, NULL, 0, 0, WHITENESS);
6413 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
6414 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
6416 for (y = 0; y < 4; y++)
6418 for (x = 0; x < 4; x++)
6420 if ((x == 1 || x == 2) && (y == 1 || y == 2))
6421 ok(data[y][x] == 0xffffffff, "Expected color 0xffffffff on position %ux%u, got %#x.\n",
6422 x, y, data[y][x]);
6423 else
6424 ok(data[y][x] == 0x00000000, "Expected color 0x00000000 on position %ux%u, got %#x.\n",
6425 x, y, data[y][x]);
6428 ok(data[0][5] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 5x0, got %#x.\n",
6429 data[0][5]);
6430 ok(data[7][3] == 0x00000000, "Expected color 0x00000000 on position 3x7, got %#x.\n",
6431 data[7][3]);
6432 ok(data[7][4] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 4x7, got %#x.\n",
6433 data[7][4]);
6434 ok(data[8][0] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 0x8, got %#x.\n",
6435 data[8][0]);
6437 IDirectDrawSurface7_Release(surface);
6438 ref = IDirectDraw7_Release(ddraw);
6439 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
6440 DestroyWindow(window);
6443 static void test_sysmem_overlay(void)
6445 IDirectDraw7 *ddraw;
6446 HWND window;
6447 HRESULT hr;
6448 DDSURFACEDESC2 ddsd;
6449 IDirectDrawSurface7 *surface;
6450 ULONG ref;
6452 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6453 0, 0, 640, 480, 0, 0, 0, 0);
6454 ddraw = create_ddraw();
6455 ok(!!ddraw, "Failed to create a ddraw object.\n");
6456 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6457 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6459 reset_ddsd(&ddsd);
6460 ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
6461 ddsd.dwWidth = 16;
6462 ddsd.dwHeight = 16;
6463 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OVERLAY;
6464 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6465 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6466 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6467 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6468 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6469 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6470 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6471 ok(hr == DDERR_NOOVERLAYHW, "Got unexpected hr %#x.\n", hr);
6473 ref = IDirectDraw7_Release(ddraw);
6474 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
6475 DestroyWindow(window);
6478 static void test_primary_palette(void)
6480 DDSCAPS2 surface_caps = {DDSCAPS_FLIP, 0, 0, {0}};
6481 IDirectDrawSurface7 *primary, *backbuffer;
6482 PALETTEENTRY palette_entries[256];
6483 IDirectDrawPalette *palette, *tmp;
6484 DDSURFACEDESC2 surface_desc;
6485 IDirectDraw7 *ddraw;
6486 DWORD palette_caps;
6487 ULONG refcount;
6488 HWND window;
6489 HRESULT hr;
6491 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6492 0, 0, 640, 480, 0, 0, 0, 0);
6493 ddraw = create_ddraw();
6494 ok(!!ddraw, "Failed to create a ddraw object.\n");
6495 if (FAILED(IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
6497 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
6498 IDirectDraw7_Release(ddraw);
6499 DestroyWindow(window);
6500 return;
6502 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6503 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6505 memset(&surface_desc, 0, sizeof(surface_desc));
6506 surface_desc.dwSize = sizeof(surface_desc);
6507 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
6508 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
6509 U5(surface_desc).dwBackBufferCount = 1;
6510 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
6511 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6512 hr = IDirectDrawSurface7_GetAttachedSurface(primary, &surface_caps, &backbuffer);
6513 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
6515 memset(palette_entries, 0, sizeof(palette_entries));
6516 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_entries, &palette, NULL);
6517 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
6518 refcount = get_refcount((IUnknown *)palette);
6519 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6521 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
6522 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
6523 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
6525 hr = IDirectDrawSurface7_SetPalette(primary, palette);
6526 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6528 /* The Windows 8 testbot attaches the palette to the backbuffer as well,
6529 * and is generally somewhat broken with respect to 8 bpp / palette
6530 * handling. */
6531 if (SUCCEEDED(IDirectDrawSurface7_GetPalette(backbuffer, &tmp)))
6533 win_skip("Broken palette handling detected, skipping tests.\n");
6534 IDirectDrawPalette_Release(tmp);
6535 IDirectDrawPalette_Release(palette);
6536 /* The Windows 8 testbot keeps extra references to the primary and
6537 * backbuffer while in 8 bpp mode. */
6538 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
6539 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
6540 goto done;
6543 refcount = get_refcount((IUnknown *)palette);
6544 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
6546 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
6547 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
6548 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE | DDPCAPS_ALLOW256),
6549 "Got unexpected palette caps %#x.\n", palette_caps);
6551 hr = IDirectDrawSurface7_SetPalette(primary, NULL);
6552 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6553 refcount = get_refcount((IUnknown *)palette);
6554 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6556 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
6557 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
6558 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
6560 hr = IDirectDrawSurface7_SetPalette(primary, palette);
6561 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6562 refcount = get_refcount((IUnknown *)palette);
6563 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
6565 hr = IDirectDrawSurface7_GetPalette(primary, &tmp);
6566 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
6567 ok(tmp == palette, "Got unexpected palette %p, expected %p.\n", tmp, palette);
6568 IDirectDrawPalette_Release(tmp);
6569 hr = IDirectDrawSurface7_GetPalette(backbuffer, &tmp);
6570 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
6572 refcount = IDirectDrawPalette_Release(palette);
6573 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6574 refcount = IDirectDrawPalette_Release(palette);
6575 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6577 /* Note that this only seems to work when the palette is attached to the
6578 * primary surface. When attached to a regular surface, attempting to get
6579 * the palette here will cause an access violation. */
6580 hr = IDirectDrawSurface7_GetPalette(primary, &tmp);
6581 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
6583 done:
6584 refcount = IDirectDrawSurface7_Release(backbuffer);
6585 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6586 refcount = IDirectDrawSurface7_Release(primary);
6587 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6588 refcount = IDirectDraw7_Release(ddraw);
6589 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6590 DestroyWindow(window);
6593 static HRESULT WINAPI surface_counter(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
6595 UINT *surface_count = context;
6597 ++(*surface_count);
6598 IDirectDrawSurface_Release(surface);
6600 return DDENUMRET_OK;
6603 static void test_surface_attachment(void)
6605 IDirectDrawSurface7 *surface1, *surface2, *surface3, *surface4;
6606 IDirectDrawSurface *surface1v1, *surface2v1;
6607 DDSCAPS2 caps = {DDSCAPS_TEXTURE, 0, 0, {0}};
6608 DDSURFACEDESC2 surface_desc;
6609 IDirectDraw7 *ddraw;
6610 UINT surface_count;
6611 ULONG refcount;
6612 HWND window;
6613 HRESULT hr;
6615 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6616 0, 0, 640, 480, 0, 0, 0, 0);
6617 ddraw = create_ddraw();
6618 ok(!!ddraw, "Failed to create a ddraw object.\n");
6619 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6620 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6622 memset(&surface_desc, 0, sizeof(surface_desc));
6623 surface_desc.dwSize = sizeof(surface_desc);
6624 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
6625 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
6626 U2(surface_desc).dwMipMapCount = 3;
6627 surface_desc.dwWidth = 128;
6628 surface_desc.dwHeight = 128;
6629 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL)))
6631 skip("Failed to create a texture, skipping tests.\n");
6632 IDirectDraw7_Release(ddraw);
6633 DestroyWindow(window);
6634 return;
6637 hr = IDirectDrawSurface7_GetAttachedSurface(surface1, &caps, &surface2);
6638 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
6639 hr = IDirectDrawSurface7_GetAttachedSurface(surface2, &caps, &surface3);
6640 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
6641 hr = IDirectDrawSurface7_GetAttachedSurface(surface3, &caps, &surface4);
6642 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
6644 surface_count = 0;
6645 IDirectDrawSurface7_EnumAttachedSurfaces(surface1, &surface_count, surface_counter);
6646 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
6647 surface_count = 0;
6648 IDirectDrawSurface7_EnumAttachedSurfaces(surface2, &surface_count, surface_counter);
6649 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
6650 surface_count = 0;
6651 IDirectDrawSurface7_EnumAttachedSurfaces(surface3, &surface_count, surface_counter);
6652 ok(!surface_count, "Got unexpected surface_count %u.\n", surface_count);
6654 memset(&surface_desc, 0, sizeof(surface_desc));
6655 surface_desc.dwSize = sizeof(surface_desc);
6656 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6657 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6658 surface_desc.dwWidth = 16;
6659 surface_desc.dwHeight = 16;
6660 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
6661 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6663 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
6664 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6665 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
6666 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6667 hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface4);
6668 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6669 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface3);
6670 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6671 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface4);
6672 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6673 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface2);
6674 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6676 IDirectDrawSurface7_Release(surface4);
6678 memset(&surface_desc, 0, sizeof(surface_desc));
6679 surface_desc.dwSize = sizeof(surface_desc);
6680 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6681 surface_desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6682 surface_desc.dwWidth = 16;
6683 surface_desc.dwHeight = 16;
6684 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
6685 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6687 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
6688 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6689 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
6690 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6691 hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface4);
6692 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6693 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface3);
6694 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6695 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface4);
6696 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6697 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface2);
6698 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6700 IDirectDrawSurface7_Release(surface4);
6701 IDirectDrawSurface7_Release(surface3);
6702 IDirectDrawSurface7_Release(surface2);
6703 IDirectDrawSurface7_Release(surface1);
6705 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6706 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6708 /* Try a single primary and two offscreen plain surfaces. */
6709 memset(&surface_desc, 0, sizeof(surface_desc));
6710 surface_desc.dwSize = sizeof(surface_desc);
6711 surface_desc.dwFlags = DDSD_CAPS;
6712 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
6713 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
6714 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6716 memset(&surface_desc, 0, sizeof(surface_desc));
6717 surface_desc.dwSize = sizeof(surface_desc);
6718 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6719 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6720 surface_desc.dwWidth = registry_mode.dmPelsWidth;
6721 surface_desc.dwHeight = registry_mode.dmPelsHeight;
6722 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
6723 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6725 memset(&surface_desc, 0, sizeof(surface_desc));
6726 surface_desc.dwSize = sizeof(surface_desc);
6727 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6728 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6729 surface_desc.dwWidth = registry_mode.dmPelsWidth;
6730 surface_desc.dwHeight = registry_mode.dmPelsHeight;
6731 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
6732 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6734 /* This one has a different size. */
6735 memset(&surface_desc, 0, sizeof(surface_desc));
6736 surface_desc.dwSize = sizeof(surface_desc);
6737 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6738 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6739 surface_desc.dwWidth = 128;
6740 surface_desc.dwHeight = 128;
6741 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
6742 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6744 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
6745 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6746 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface1);
6747 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6748 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface3);
6749 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6750 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
6751 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6752 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
6753 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6755 IDirectDrawSurface7_Release(surface4);
6756 IDirectDrawSurface7_Release(surface3);
6757 IDirectDrawSurface7_Release(surface2);
6758 IDirectDrawSurface7_Release(surface1);
6760 /* Test DeleteAttachedSurface() and automatic detachment of attached surfaces on release. */
6761 memset(&surface_desc, 0, sizeof(surface_desc));
6762 surface_desc.dwSize = sizeof(surface_desc);
6763 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6764 surface_desc.dwWidth = 64;
6765 surface_desc.dwHeight = 64;
6766 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
6767 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
6768 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
6769 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
6770 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
6771 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
6772 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
6773 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
6774 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6775 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
6776 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6778 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
6779 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
6780 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = 16;
6781 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = 0x0000ffff;
6782 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
6783 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6785 hr = IDirectDrawSurface7_QueryInterface(surface1, &IID_IDirectDrawSurface, (void **)&surface1v1);
6786 ok(SUCCEEDED(hr), "Failed to get interface, hr %#x.\n", hr);
6787 hr = IDirectDrawSurface7_QueryInterface(surface2, &IID_IDirectDrawSurface, (void **)&surface2v1);
6788 ok(SUCCEEDED(hr), "Failed to get interface, hr %#x.\n", hr);
6790 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
6791 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
6792 refcount = get_refcount((IUnknown *)surface2);
6793 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
6794 refcount = get_refcount((IUnknown *)surface2v1);
6795 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6796 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
6797 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
6798 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
6799 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6800 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
6801 ok(hr == DDERR_SURFACENOTATTACHED, "Got unexpected hr %#x.\n", hr);
6803 /* Attaching while already attached to other surface. */
6804 hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface2);
6805 todo_wine ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
6806 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface3, 0, surface2);
6807 todo_wine ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
6808 IDirectDrawSurface7_Release(surface3);
6810 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface2);
6811 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
6812 refcount = get_refcount((IUnknown *)surface2);
6813 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6814 refcount = get_refcount((IUnknown *)surface2v1);
6815 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6817 /* DeleteAttachedSurface() when attaching via IDirectDrawSurface. */
6818 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
6819 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
6820 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface2);
6821 ok(hr == DDERR_SURFACENOTATTACHED, "Got unexpected hr %#x.\n", hr);
6822 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
6823 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
6824 refcount = IDirectDrawSurface7_Release(surface2);
6825 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6826 refcount = IDirectDrawSurface7_Release(surface1);
6827 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6829 /* Automatic detachment on release. */
6830 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
6831 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
6832 refcount = get_refcount((IUnknown *)surface2v1);
6833 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
6834 refcount = IDirectDrawSurface_Release(surface1v1);
6835 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6836 refcount = IDirectDrawSurface_Release(surface2v1);
6837 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6838 refcount = IDirectDraw7_Release(ddraw);
6839 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6840 DestroyWindow(window);
6843 static void test_private_data(void)
6845 IDirectDraw7 *ddraw;
6846 IDirectDrawSurface7 *surface, *surface2;
6847 DDSURFACEDESC2 surface_desc;
6848 ULONG refcount, refcount2, refcount3;
6849 IUnknown *ptr;
6850 DWORD size = sizeof(ptr);
6851 HRESULT hr;
6852 HWND window;
6853 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
6854 DWORD data[] = {1, 2, 3, 4};
6855 DDCAPS hal_caps;
6856 static const GUID ddraw_private_data_test_guid =
6858 0xfdb37466,
6859 0x428f,
6860 0x4edf,
6861 {0xa3,0x7f,0x9b,0x1d,0xf4,0x88,0xc5,0xfc}
6863 static const GUID ddraw_private_data_test_guid2 =
6865 0x2e5afac2,
6866 0x87b5,
6867 0x4c10,
6868 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
6871 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6872 0, 0, 640, 480, 0, 0, 0, 0);
6873 ddraw = create_ddraw();
6874 ok(!!ddraw, "Failed to create a ddraw object.\n");
6875 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6876 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6878 reset_ddsd(&surface_desc);
6879 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
6880 surface_desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
6881 surface_desc.dwHeight = 4;
6882 surface_desc.dwWidth = 4;
6883 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6884 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6886 /* NULL pointers are not valid, but don't cause a crash. */
6887 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL,
6888 sizeof(IUnknown *), DDSPD_IUNKNOWNPOINTER);
6889 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6890 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL, 0, 0);
6891 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6892 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL, 1, 0);
6893 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6895 /* DDSPD_IUNKNOWNPOINTER needs sizeof(IUnknown *) bytes of data. */
6896 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
6897 0, DDSPD_IUNKNOWNPOINTER);
6898 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6899 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
6900 5, DDSPD_IUNKNOWNPOINTER);
6901 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6902 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
6903 sizeof(ddraw) * 2, DDSPD_IUNKNOWNPOINTER);
6904 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6906 /* Note that with a size != 0 and size != sizeof(IUnknown *) and
6907 * DDSPD_IUNKNOWNPOINTER set SetPrivateData in ddraw4 and ddraw7
6908 * erases the old content and returns an error. This behavior has
6909 * been fixed in d3d8 and d3d9. Unless an application is found
6910 * that depends on this we don't care about this behavior. */
6911 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
6912 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
6913 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
6914 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
6915 0, DDSPD_IUNKNOWNPOINTER);
6916 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6917 size = sizeof(ptr);
6918 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
6919 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
6920 hr = IDirectDrawSurface7_FreePrivateData(surface, &ddraw_private_data_test_guid);
6921 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
6923 refcount = get_refcount((IUnknown *)ddraw);
6924 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
6925 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
6926 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
6927 refcount2 = get_refcount((IUnknown *)ddraw);
6928 ok(refcount2 == refcount + 1, "Got unexpected refcount %u.\n", refcount2);
6930 hr = IDirectDrawSurface7_FreePrivateData(surface, &ddraw_private_data_test_guid);
6931 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
6932 refcount2 = get_refcount((IUnknown *)ddraw);
6933 ok(refcount2 == refcount, "Got unexpected refcount %u.\n", refcount2);
6935 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
6936 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
6937 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
6938 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, surface,
6939 sizeof(surface), DDSPD_IUNKNOWNPOINTER);
6940 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
6941 refcount2 = get_refcount((IUnknown *)ddraw);
6942 ok(refcount2 == refcount, "Got unexpected refcount %u.\n", refcount2);
6944 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
6945 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
6946 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
6947 size = 2 * sizeof(ptr);
6948 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
6949 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
6950 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
6951 refcount2 = get_refcount(ptr);
6952 /* Object is NOT addref'ed by the getter. */
6953 ok(ptr == (IUnknown *)ddraw, "Returned interface pointer is %p, expected %p.\n", ptr, ddraw);
6954 ok(refcount2 == refcount + 1, "Got unexpected refcount %u.\n", refcount2);
6956 ptr = (IUnknown *)0xdeadbeef;
6957 size = 1;
6958 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, &size);
6959 ok(hr == DDERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
6960 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
6961 size = 2 * sizeof(ptr);
6962 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, &size);
6963 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6964 ok(size == 2 * sizeof(ptr), "Got unexpected size %u.\n", size);
6965 size = 1;
6966 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
6967 ok(hr == DDERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
6968 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
6969 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
6970 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid2, NULL, NULL);
6971 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
6972 size = 0xdeadbabe;
6973 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid2, &ptr, &size);
6974 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
6975 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
6976 ok(size == 0xdeadbabe, "Got unexpected size %u.\n", size);
6977 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, NULL);
6978 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6980 refcount3 = IDirectDrawSurface7_Release(surface);
6981 ok(!refcount3, "Got unexpected refcount %u.\n", refcount3);
6983 /* Destroying the surface frees the reference held on the private data. It also frees
6984 * the reference the surface is holding on its creating object. */
6985 refcount2 = get_refcount((IUnknown *)ddraw);
6986 ok(refcount2 == refcount - 1, "Got unexpected refcount %u.\n", refcount2);
6988 memset(&hal_caps, 0, sizeof(hal_caps));
6989 hal_caps.dwSize = sizeof(hal_caps);
6990 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
6991 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6992 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) == (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
6994 reset_ddsd(&surface_desc);
6995 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_MIPMAPCOUNT;
6996 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
6997 surface_desc.dwHeight = 4;
6998 surface_desc.dwWidth = 4;
6999 U2(surface_desc).dwMipMapCount = 2;
7000 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7001 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7002 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &surface2);
7003 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
7005 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, data, sizeof(data), 0);
7006 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7007 hr = IDirectDrawSurface7_GetPrivateData(surface2, &ddraw_private_data_test_guid, NULL, NULL);
7008 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7010 IDirectDrawSurface7_Release(surface2);
7011 IDirectDrawSurface7_Release(surface);
7013 else
7014 skip("Mipmapped textures not supported, skipping mipmap private data test.\n");
7016 refcount = IDirectDraw7_Release(ddraw);
7017 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7018 DestroyWindow(window);
7021 static void test_pixel_format(void)
7023 HWND window, window2 = NULL;
7024 HDC hdc, hdc2 = NULL;
7025 HMODULE gl = NULL;
7026 int format, test_format;
7027 PIXELFORMATDESCRIPTOR pfd;
7028 IDirectDraw7 *ddraw = NULL;
7029 IDirectDrawClipper *clipper = NULL;
7030 DDSURFACEDESC2 ddsd;
7031 IDirectDrawSurface7 *primary = NULL;
7032 DDBLTFX fx;
7033 HRESULT hr;
7035 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
7036 100, 100, 160, 160, NULL, NULL, NULL, NULL);
7037 if (!window)
7039 skip("Failed to create window\n");
7040 return;
7043 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
7044 100, 100, 160, 160, NULL, NULL, NULL, NULL);
7046 hdc = GetDC(window);
7047 if (!hdc)
7049 skip("Failed to get DC\n");
7050 goto cleanup;
7053 if (window2)
7054 hdc2 = GetDC(window2);
7056 gl = LoadLibraryA("opengl32.dll");
7057 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
7059 format = GetPixelFormat(hdc);
7060 ok(format == 0, "new window has pixel format %d\n", format);
7062 ZeroMemory(&pfd, sizeof(pfd));
7063 pfd.nSize = sizeof(pfd);
7064 pfd.nVersion = 1;
7065 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
7066 pfd.iPixelType = PFD_TYPE_RGBA;
7067 pfd.iLayerType = PFD_MAIN_PLANE;
7068 format = ChoosePixelFormat(hdc, &pfd);
7069 if (format <= 0)
7071 skip("no pixel format available\n");
7072 goto cleanup;
7075 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
7077 skip("failed to set pixel format\n");
7078 goto cleanup;
7081 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
7083 skip("failed to set pixel format on second window\n");
7084 if (hdc2)
7086 ReleaseDC(window2, hdc2);
7087 hdc2 = NULL;
7091 ddraw = create_ddraw();
7092 ok(!!ddraw, "Failed to create a ddraw object.\n");
7094 test_format = GetPixelFormat(hdc);
7095 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7097 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7098 if (FAILED(hr))
7100 skip("Failed to set cooperative level, hr %#x.\n", hr);
7101 goto cleanup;
7104 test_format = GetPixelFormat(hdc);
7105 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7107 if (hdc2)
7109 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
7110 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
7111 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window2);
7112 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
7114 test_format = GetPixelFormat(hdc);
7115 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7117 test_format = GetPixelFormat(hdc2);
7118 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7121 memset(&ddsd, 0, sizeof(ddsd));
7122 ddsd.dwSize = sizeof(ddsd);
7123 ddsd.dwFlags = DDSD_CAPS;
7124 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7126 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
7127 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
7129 test_format = GetPixelFormat(hdc);
7130 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7132 if (hdc2)
7134 test_format = GetPixelFormat(hdc2);
7135 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7138 if (clipper)
7140 hr = IDirectDrawSurface7_SetClipper(primary, clipper);
7141 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
7143 test_format = GetPixelFormat(hdc);
7144 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7146 test_format = GetPixelFormat(hdc2);
7147 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7150 memset(&fx, 0, sizeof(fx));
7151 fx.dwSize = sizeof(fx);
7152 hr = IDirectDrawSurface7_Blt(primary, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7153 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
7155 test_format = GetPixelFormat(hdc);
7156 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7158 if (hdc2)
7160 test_format = GetPixelFormat(hdc2);
7161 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7164 cleanup:
7165 if (primary) IDirectDrawSurface7_Release(primary);
7166 if (clipper) IDirectDrawClipper_Release(clipper);
7167 if (ddraw) IDirectDraw7_Release(ddraw);
7168 if (gl) FreeLibrary(gl);
7169 if (hdc) ReleaseDC(window, hdc);
7170 if (hdc2) ReleaseDC(window2, hdc2);
7171 if (window) DestroyWindow(window);
7172 if (window2) DestroyWindow(window2);
7175 static void test_create_surface_pitch(void)
7177 IDirectDrawSurface7 *surface;
7178 DDSURFACEDESC2 surface_desc;
7179 IDirectDraw7 *ddraw;
7180 unsigned int i;
7181 ULONG refcount;
7182 HWND window;
7183 HRESULT hr;
7184 void *mem;
7186 static const struct
7188 DWORD placement;
7189 DWORD flags_in;
7190 DWORD pitch_in;
7191 HRESULT hr;
7192 DWORD flags_out;
7193 DWORD pitch_out32;
7194 DWORD pitch_out64;
7196 test_data[] =
7198 {DDSCAPS_VIDEOMEMORY, 0, 0, DD_OK,
7199 DDSD_PITCH, 0x100, 0x100},
7200 {DDSCAPS_VIDEOMEMORY, DDSD_PITCH, 0x104, DD_OK,
7201 DDSD_PITCH, 0x100, 0x100},
7202 {DDSCAPS_VIDEOMEMORY, DDSD_PITCH, 0x0f8, DD_OK,
7203 DDSD_PITCH, 0x100, 0x100},
7204 {DDSCAPS_VIDEOMEMORY, DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
7205 0, 0, 0 },
7206 {DDSCAPS_SYSTEMMEMORY, 0, 0, DD_OK,
7207 DDSD_PITCH, 0x100, 0x0fc},
7208 {DDSCAPS_SYSTEMMEMORY, DDSD_PITCH, 0x104, DD_OK,
7209 DDSD_PITCH, 0x100, 0x0fc},
7210 {DDSCAPS_SYSTEMMEMORY, DDSD_PITCH, 0x0f8, DD_OK,
7211 DDSD_PITCH, 0x100, 0x0fc},
7212 {DDSCAPS_SYSTEMMEMORY, DDSD_PITCH | DDSD_LINEARSIZE, 0, DD_OK,
7213 DDSD_PITCH, 0x100, 0x0fc},
7214 {DDSCAPS_SYSTEMMEMORY, DDSD_LPSURFACE, 0, DDERR_INVALIDPARAMS,
7215 0, 0, 0 },
7216 {DDSCAPS_SYSTEMMEMORY, DDSD_LPSURFACE | DDSD_PITCH, 0x100, DD_OK,
7217 DDSD_PITCH, 0x100, 0x100},
7218 {DDSCAPS_SYSTEMMEMORY, DDSD_LPSURFACE | DDSD_PITCH, 0x0fe, DDERR_INVALIDPARAMS,
7219 0, 0, 0 },
7220 {DDSCAPS_SYSTEMMEMORY, DDSD_LPSURFACE | DDSD_PITCH, 0x0fc, DD_OK,
7221 DDSD_PITCH, 0x0fc, 0x0fc},
7222 {DDSCAPS_SYSTEMMEMORY, DDSD_LPSURFACE | DDSD_PITCH, 0x0f8, DDERR_INVALIDPARAMS,
7223 0, 0, 0 },
7224 {DDSCAPS_SYSTEMMEMORY, DDSD_LPSURFACE | DDSD_LINEARSIZE, 0x100, DDERR_INVALIDPARAMS,
7225 0, 0, 0 },
7226 {DDSCAPS_SYSTEMMEMORY, DDSD_LPSURFACE | DDSD_LINEARSIZE, 0x3f00, DDERR_INVALIDPARAMS,
7227 0, 0, 0 },
7228 {DDSCAPS_SYSTEMMEMORY, DDSD_LPSURFACE | DDSD_PITCH | DDSD_LINEARSIZE, 0x100, DD_OK,
7229 DDSD_PITCH, 0x100, 0x100},
7231 DWORD flags_mask = DDSD_PITCH | DDSD_LPSURFACE | DDSD_LINEARSIZE;
7233 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7234 0, 0, 640, 480, 0, 0, 0, 0);
7235 ddraw = create_ddraw();
7236 ok(!!ddraw, "Failed to create a ddraw object.\n");
7237 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7238 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7240 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((63 * 4) + 8) * 63);
7242 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
7244 memset(&surface_desc, 0, sizeof(surface_desc));
7245 surface_desc.dwSize = sizeof(surface_desc);
7246 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | test_data[i].flags_in;
7247 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | test_data[i].placement;
7248 surface_desc.dwWidth = 63;
7249 surface_desc.dwHeight = 63;
7250 U1(surface_desc).lPitch = test_data[i].pitch_in;
7251 surface_desc.lpSurface = mem;
7252 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7253 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
7254 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
7255 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7256 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7257 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7258 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7259 ok(hr == test_data[i].hr || (test_data[i].placement == DDSCAPS_VIDEOMEMORY && hr == DDERR_NODIRECTDRAWHW),
7260 "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
7261 if (FAILED(hr))
7262 continue;
7264 memset(&surface_desc, 0, sizeof(surface_desc));
7265 surface_desc.dwSize = sizeof(surface_desc);
7266 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
7267 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
7268 ok((surface_desc.dwFlags & flags_mask) == test_data[i].flags_out,
7269 "Test %u: Got unexpected flags %#x, expected %#x.\n",
7270 i, surface_desc.dwFlags & flags_mask, test_data[i].flags_out);
7271 if (sizeof(void *) != sizeof(DWORD) && test_data[i].pitch_out32 != test_data[i].pitch_out64)
7272 todo_wine ok(U1(surface_desc).lPitch == test_data[i].pitch_out64,
7273 "Test %u: Got unexpected pitch %u, expected %u.\n",
7274 i, U1(surface_desc).lPitch, test_data[i].pitch_out64);
7275 else
7276 ok(U1(surface_desc).lPitch == test_data[i].pitch_out32,
7277 "Test %u: Got unexpected pitch %u, expected %u.\n",
7278 i, U1(surface_desc).lPitch, test_data[i].pitch_out32);
7279 ok(!surface_desc.lpSurface, "Test %u: Got unexpected lpSurface %p.\n", i, surface_desc.lpSurface);
7281 IDirectDrawSurface7_Release(surface);
7284 HeapFree(GetProcessHeap(), 0, mem);
7285 refcount = IDirectDraw7_Release(ddraw);
7286 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7287 DestroyWindow(window);
7290 static void test_mipmap_lock(void)
7292 IDirectDrawSurface7 *surface, *surface2;
7293 DDSURFACEDESC2 surface_desc;
7294 IDirectDraw7 *ddraw;
7295 ULONG refcount;
7296 HWND window;
7297 HRESULT hr;
7298 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
7299 DDCAPS hal_caps;
7301 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7302 0, 0, 640, 480, 0, 0, 0, 0);
7303 ddraw = create_ddraw();
7304 ok(!!ddraw, "Failed to create a ddraw object.\n");
7305 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7306 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7308 memset(&hal_caps, 0, sizeof(hal_caps));
7309 hal_caps.dwSize = sizeof(hal_caps);
7310 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
7311 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7312 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
7314 skip("Mipmapped textures not supported, skipping mipmap lock test.\n");
7315 IDirectDraw7_Release(ddraw);
7316 DestroyWindow(window);
7317 return;
7320 memset(&surface_desc, 0, sizeof(surface_desc));
7321 surface_desc.dwSize = sizeof(surface_desc);
7322 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
7323 surface_desc.dwWidth = 4;
7324 surface_desc.dwHeight = 4;
7325 U2(surface_desc).dwMipMapCount = 2;
7326 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP
7327 | DDSCAPS_SYSTEMMEMORY;
7328 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7329 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7330 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &surface2);
7331 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
7333 memset(&surface_desc, 0, sizeof(surface_desc));
7334 surface_desc.dwSize = sizeof(surface_desc);
7335 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, 0, NULL);
7336 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7337 memset(&surface_desc, 0, sizeof(surface_desc));
7338 surface_desc.dwSize = sizeof(surface_desc);
7339 hr = IDirectDrawSurface7_Lock(surface2, NULL, &surface_desc, 0, NULL);
7340 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7341 IDirectDrawSurface7_Unlock(surface2, NULL);
7342 IDirectDrawSurface7_Unlock(surface, NULL);
7344 IDirectDrawSurface7_Release(surface2);
7345 IDirectDrawSurface7_Release(surface);
7346 refcount = IDirectDraw7_Release(ddraw);
7347 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7348 DestroyWindow(window);
7351 static void test_palette_complex(void)
7353 IDirectDrawSurface7 *surface, *mipmap, *tmp;
7354 DDSURFACEDESC2 surface_desc;
7355 IDirectDraw7 *ddraw;
7356 IDirectDrawPalette *palette, *palette2;
7357 ULONG refcount;
7358 HWND window;
7359 HRESULT hr;
7360 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
7361 DDCAPS hal_caps;
7362 PALETTEENTRY palette_entries[256];
7363 unsigned int i;
7365 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7366 0, 0, 640, 480, 0, 0, 0, 0);
7367 ddraw = create_ddraw();
7368 ok(!!ddraw, "Failed to create a ddraw object.\n");
7369 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7370 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7372 memset(&hal_caps, 0, sizeof(hal_caps));
7373 hal_caps.dwSize = sizeof(hal_caps);
7374 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
7375 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7376 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP))
7378 skip("Mipmapped textures not supported, skipping mipmap palette test.\n");
7379 IDirectDraw7_Release(ddraw);
7380 DestroyWindow(window);
7381 return;
7384 memset(&surface_desc, 0, sizeof(surface_desc));
7385 surface_desc.dwSize = sizeof(surface_desc);
7386 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7387 surface_desc.dwWidth = 128;
7388 surface_desc.dwHeight = 128;
7389 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7390 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7391 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
7392 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
7393 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7394 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7396 memset(palette_entries, 0, sizeof(palette_entries));
7397 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7398 palette_entries, &palette, NULL);
7399 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7401 palette2 = (void *)0xdeadbeef;
7402 hr = IDirectDrawSurface7_GetPalette(surface, &palette2);
7403 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
7404 ok(!palette2, "Got unexpected palette %p.\n", palette2);
7405 hr = IDirectDrawSurface7_SetPalette(surface, palette);
7406 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7407 hr = IDirectDrawSurface7_GetPalette(surface, &palette2);
7408 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
7409 ok(palette == palette2, "Got unexpected palette %p.\n", palette2);
7410 IDirectDrawPalette_Release(palette2);
7412 mipmap = surface;
7413 IDirectDrawSurface7_AddRef(mipmap);
7414 for (i = 0; i < 7; ++i)
7416 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
7417 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
7418 palette2 = (void *)0xdeadbeef;
7419 hr = IDirectDrawSurface7_GetPalette(tmp, &palette2);
7420 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x, i %u.\n", hr, i);
7421 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
7423 hr = IDirectDrawSurface7_SetPalette(tmp, palette);
7424 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x, i %u.\n", hr, i);
7426 hr = IDirectDrawSurface7_GetPalette(tmp, &palette2);
7427 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x, i %u.\n", hr, i);
7428 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
7430 /* Ddraw7 uses the palette of the mipmap for GetDC, just like previous
7431 * ddraw versions. Combined with the test results above this means no
7432 * palette is available. So depending on the driver either GetDC fails
7433 * or the DIB color table contains random data. */
7435 IDirectDrawSurface7_Release(mipmap);
7436 mipmap = tmp;
7439 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
7440 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7441 IDirectDrawSurface7_Release(mipmap);
7442 refcount = IDirectDrawSurface7_Release(surface);
7443 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7445 /* Test DDERR_INVALIDPIXELFORMAT vs DDERR_NOTONMIPMAPSUBLEVEL. */
7446 memset(&surface_desc, 0, sizeof(surface_desc));
7447 surface_desc.dwSize = sizeof(surface_desc);
7448 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7449 surface_desc.dwWidth = 128;
7450 surface_desc.dwHeight = 128;
7451 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7452 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7453 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
7454 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
7455 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7456 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7457 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7458 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7459 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7461 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
7462 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
7463 hr = IDirectDrawSurface7_SetPalette(mipmap, palette);
7464 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x.\n", hr);
7466 IDirectDrawSurface7_Release(mipmap);
7467 refcount = IDirectDrawSurface7_Release(surface);
7468 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7469 refcount = IDirectDrawPalette_Release(palette);
7470 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7472 refcount = IDirectDraw7_Release(ddraw);
7473 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7474 DestroyWindow(window);
7477 static void test_p8_rgb_blit(void)
7479 IDirectDrawSurface7 *src, *dst;
7480 DDSURFACEDESC2 surface_desc;
7481 IDirectDraw7 *ddraw;
7482 IDirectDrawPalette *palette;
7483 ULONG refcount;
7484 HWND window;
7485 HRESULT hr;
7486 PALETTEENTRY palette_entries[256];
7487 unsigned int x;
7488 static const BYTE src_data[] = {0x10, 0x1, 0x2, 0x3, 0x4, 0x5, 0xff, 0x80};
7489 static const D3DCOLOR expected[] =
7491 0x00101010, 0x00010101, 0x00020202, 0x00030303,
7492 0x00040404, 0x00050505, 0x00ffffff, 0x00808080,
7494 D3DCOLOR color;
7496 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7497 0, 0, 640, 480, 0, 0, 0, 0);
7498 ddraw = create_ddraw();
7499 ok(!!ddraw, "Failed to create a ddraw object.\n");
7500 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7501 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7503 memset(palette_entries, 0, sizeof(palette_entries));
7504 palette_entries[1].peGreen = 0xff;
7505 palette_entries[2].peBlue = 0xff;
7506 palette_entries[3].peFlags = 0xff;
7507 palette_entries[4].peRed = 0xff;
7508 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7509 palette_entries, &palette, NULL);
7510 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7512 memset(&surface_desc, 0, sizeof(surface_desc));
7513 surface_desc.dwSize = sizeof(surface_desc);
7514 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7515 surface_desc.dwWidth = 8;
7516 surface_desc.dwHeight = 1;
7517 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7518 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7519 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
7520 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
7521 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
7522 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7524 memset(&surface_desc, 0, sizeof(surface_desc));
7525 surface_desc.dwSize = sizeof(surface_desc);
7526 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7527 surface_desc.dwWidth = 8;
7528 surface_desc.dwHeight = 1;
7529 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7530 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7531 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
7532 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
7533 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7534 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7535 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7536 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
7537 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
7538 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7540 memset(&surface_desc, 0, sizeof(surface_desc));
7541 surface_desc.dwSize = sizeof(surface_desc);
7542 hr = IDirectDrawSurface7_Lock(src, NULL, &surface_desc, 0, NULL);
7543 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
7544 memcpy(surface_desc.lpSurface, src_data, sizeof(src_data));
7545 hr = IDirectDrawSurface7_Unlock(src, NULL);
7546 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
7548 hr = IDirectDrawSurface7_SetPalette(src, palette);
7549 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7550 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_WAIT, NULL);
7551 /* The r500 Windows 7 driver returns E_NOTIMPL. r200 on Windows XP works.
7552 * The Geforce 7 driver on Windows Vista returns E_FAIL. Newer Nvidia GPUs work. */
7553 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL) || broken(hr == E_FAIL),
7554 "Failed to blit, hr %#x.\n", hr);
7556 if (SUCCEEDED(hr))
7558 for (x = 0; x < sizeof(expected) / sizeof(*expected); x++)
7560 color = get_surface_color(dst, x, 0);
7561 todo_wine ok(compare_color(color, expected[x], 0),
7562 "Pixel %u: Got color %#x, expected %#x.\n",
7563 x, color, expected[x]);
7567 IDirectDrawSurface7_Release(src);
7568 IDirectDrawSurface7_Release(dst);
7569 IDirectDrawPalette_Release(palette);
7571 refcount = IDirectDraw7_Release(ddraw);
7572 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7573 DestroyWindow(window);
7576 static void test_material(void)
7578 static const D3DCOLORVALUE null_color;
7579 IDirect3DDevice7 *device;
7580 D3DMATERIAL7 material;
7581 ULONG refcount;
7582 HWND window;
7583 HRESULT hr;
7585 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7586 0, 0, 640, 480, 0, 0, 0, 0);
7587 if (!(device = create_device(window, DDSCL_NORMAL)))
7589 skip("Failed to create a 3D device, skipping test.\n");
7590 DestroyWindow(window);
7591 return;
7594 hr = IDirect3DDevice7_GetMaterial(device, &material);
7595 ok(SUCCEEDED(hr), "Failed to get material, hr %#x.\n", hr);
7596 ok(!memcmp(&U(material).diffuse, &null_color, sizeof(null_color)),
7597 "Got unexpected diffuse color {%.8e, %.8e, %.8e, %.8e}.\n",
7598 U1(U(material).diffuse).r, U2(U(material).diffuse).g,
7599 U3(U(material).diffuse).b, U4(U(material).diffuse).a);
7600 ok(!memcmp(&U1(material).ambient, &null_color, sizeof(null_color)),
7601 "Got unexpected ambient color {%.8e, %.8e, %.8e, %.8e}.\n",
7602 U1(U1(material).ambient).r, U2(U1(material).ambient).g,
7603 U3(U1(material).ambient).b, U4(U1(material).ambient).a);
7604 ok(!memcmp(&U2(material).specular, &null_color, sizeof(null_color)),
7605 "Got unexpected specular color {%.8e, %.8e, %.8e, %.8e}.\n",
7606 U1(U2(material).specular).r, U2(U2(material).specular).g,
7607 U3(U2(material).specular).b, U4(U2(material).specular).a);
7608 ok(!memcmp(&U3(material).emissive, &null_color, sizeof(null_color)),
7609 "Got unexpected emissive color {%.8e, %.8e, %.8e, %.8e}.\n",
7610 U1(U3(material).emissive).r, U2(U3(material).emissive).g,
7611 U3(U3(material).emissive).b, U4(U3(material).emissive).a);
7612 ok(U4(material).power == 0.0f, "Got unexpected power %.8e.\n", U4(material).power);
7614 refcount = IDirect3DDevice7_Release(device);
7615 ok(!refcount, "Device has %u references left.\n", refcount);
7616 DestroyWindow(window);
7619 static void test_palette_gdi(void)
7621 IDirectDrawSurface7 *surface, *primary;
7622 DDSURFACEDESC2 surface_desc;
7623 IDirectDraw7 *ddraw;
7624 IDirectDrawPalette *palette, *palette2;
7625 ULONG refcount;
7626 HWND window;
7627 HRESULT hr;
7628 PALETTEENTRY palette_entries[256];
7629 UINT i;
7630 HDC dc;
7631 /* On the Windows 8 testbot palette index 0 of the onscreen palette is forced to
7632 * r = 0, g = 0, b = 0. Do not attempt to set it to something else as this is
7633 * not the point of this test. */
7634 static const RGBQUAD expected1[] =
7636 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
7637 {0x03, 0x00, 0x00, 0x00}, {0x15, 0x14, 0x13, 0x00},
7639 static const RGBQUAD expected2[] =
7641 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
7642 {0x03, 0x00, 0x00, 0x00}, {0x25, 0x24, 0x23, 0x00},
7644 static const RGBQUAD expected3[] =
7646 {0x00, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x40, 0x00},
7647 {0x00, 0x40, 0x00, 0x00}, {0x56, 0x34, 0x12, 0x00},
7649 HPALETTE ddraw_palette_handle;
7650 /* Similar to index 0, index 255 is r = 0xff, g = 0xff, b = 0xff on the Win8 VMs. */
7651 RGBQUAD rgbquad[255];
7652 static const RGBQUAD rgb_zero = {0, 0, 0, 0};
7654 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7655 0, 0, 640, 480, 0, 0, 0, 0);
7656 ddraw = create_ddraw();
7657 ok(!!ddraw, "Failed to create a ddraw object.\n");
7658 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7659 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7661 memset(&surface_desc, 0, sizeof(surface_desc));
7662 surface_desc.dwSize = sizeof(surface_desc);
7663 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7664 surface_desc.dwWidth = 16;
7665 surface_desc.dwHeight = 16;
7666 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7667 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7668 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
7669 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
7670 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7671 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7673 /* Avoid colors from the Windows default palette. */
7674 memset(palette_entries, 0, sizeof(palette_entries));
7675 palette_entries[1].peRed = 0x01;
7676 palette_entries[2].peGreen = 0x02;
7677 palette_entries[3].peBlue = 0x03;
7678 palette_entries[4].peRed = 0x13;
7679 palette_entries[4].peGreen = 0x14;
7680 palette_entries[4].peBlue = 0x15;
7681 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7682 palette_entries, &palette, NULL);
7683 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7685 /* If there is no palette assigned and the display mode is not 8 bpp, some
7686 * drivers refuse to create a DC while others allow it. If a DC is created,
7687 * the DIB color table is uninitialized and contains random colors. No error
7688 * is generated when trying to read pixels and random garbage is returned.
7690 * The most likely explanation is that if the driver creates a DC, it (or
7691 * the higher-level runtime) uses GetSystemPaletteEntries to find the
7692 * palette, but GetSystemPaletteEntries fails when bpp > 8 and the palette
7693 * contains uninitialized garbage. See comments below for the P8 case. */
7695 hr = IDirectDrawSurface7_SetPalette(surface, palette);
7696 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7697 hr = IDirectDrawSurface7_GetDC(surface, &dc);
7698 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7699 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
7700 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
7701 "Got unexpected palette %p, expected %p.\n",
7702 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
7704 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
7705 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
7706 for (i = 0; i < sizeof(expected1) / sizeof(*expected1); i++)
7708 ok(!memcmp(&rgbquad[i], &expected1[i], sizeof(rgbquad[i])),
7709 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7710 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7711 expected1[i].rgbRed, expected1[i].rgbGreen, expected1[i].rgbBlue);
7713 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
7715 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7716 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7717 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7720 /* Update the palette while the DC is in use. This does not modify the DC. */
7721 palette_entries[4].peRed = 0x23;
7722 palette_entries[4].peGreen = 0x24;
7723 palette_entries[4].peBlue = 0x25;
7724 hr = IDirectDrawPalette_SetEntries(palette, 0, 4, 1, &palette_entries[4]);
7725 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
7727 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
7728 ok(i == 1, "Expected count 1, got %u.\n", i);
7729 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
7730 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7731 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
7732 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
7734 /* Neither does re-setting the palette. */
7735 hr = IDirectDrawSurface7_SetPalette(surface, NULL);
7736 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7737 hr = IDirectDrawSurface7_SetPalette(surface, palette);
7738 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7740 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
7741 ok(i == 1, "Expected count 1, got %u.\n", i);
7742 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
7743 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7744 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
7745 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
7747 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
7748 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7750 /* Refresh the DC. This updates the palette. */
7751 hr = IDirectDrawSurface7_GetDC(surface, &dc);
7752 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7753 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
7754 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
7755 for (i = 0; i < sizeof(expected2) / sizeof(*expected2); i++)
7757 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
7758 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7759 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7760 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
7762 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
7764 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7765 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7766 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7768 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
7769 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7771 refcount = IDirectDrawSurface7_Release(surface);
7772 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7774 if (FAILED(IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
7776 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
7777 IDirectDrawPalette_Release(palette);
7778 IDirectDraw7_Release(ddraw);
7779 DestroyWindow(window);
7780 return;
7782 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
7783 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
7784 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7786 memset(&surface_desc, 0, sizeof(surface_desc));
7787 surface_desc.dwSize = sizeof(surface_desc);
7788 surface_desc.dwFlags = DDSD_CAPS;
7789 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7790 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
7791 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7793 hr = IDirectDrawSurface7_SetPalette(primary, palette);
7794 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7795 hr = IDirectDrawSurface7_GetDC(primary, &dc);
7796 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7797 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
7798 /* Windows 2000 on the testbot assigns a different palette to the primary. Refrast? */
7799 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE) || broken(TRUE),
7800 "Got unexpected palette %p, expected %p.\n",
7801 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
7802 SelectPalette(dc, ddraw_palette_handle, FALSE);
7804 /* The primary uses the system palette. In exclusive mode, the system palette matches
7805 * the ddraw palette attached to the primary, so the result is what you would expect
7806 * from a regular surface. Tests for the interaction between the ddraw palette and
7807 * the system palette are not included pending an application that depends on this.
7808 * The relation between those causes problems on Windows Vista and newer for games
7809 * like Age of Empires or StarcCaft. Don't emulate it without a real need. */
7810 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
7811 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
7812 for (i = 0; i < sizeof(expected2) / sizeof(*expected2); i++)
7814 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
7815 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7816 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7817 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
7819 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
7821 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7822 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7823 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7825 hr = IDirectDrawSurface7_ReleaseDC(primary, dc);
7826 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7828 memset(&surface_desc, 0, sizeof(surface_desc));
7829 surface_desc.dwSize = sizeof(surface_desc);
7830 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7831 surface_desc.dwWidth = 16;
7832 surface_desc.dwHeight = 16;
7833 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7834 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7835 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7837 /* Here the offscreen surface appears to use the primary's palette,
7838 * but in all likelihood it is actually the system palette. */
7839 hr = IDirectDrawSurface7_GetDC(surface, &dc);
7840 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7841 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
7842 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
7843 for (i = 0; i < sizeof(expected2) / sizeof(*expected2); i++)
7845 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
7846 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7847 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7848 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
7850 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
7852 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7853 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7854 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7856 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
7857 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7859 /* On real hardware a change to the primary surface's palette applies immediately,
7860 * even on device contexts from offscreen surfaces that do not have their own
7861 * palette. On the testbot VMs this is not the case. Don't test this until we
7862 * know of an application that depends on this. */
7864 memset(palette_entries, 0, sizeof(palette_entries));
7865 palette_entries[1].peBlue = 0x40;
7866 palette_entries[2].peRed = 0x40;
7867 palette_entries[3].peGreen = 0x40;
7868 palette_entries[4].peRed = 0x12;
7869 palette_entries[4].peGreen = 0x34;
7870 palette_entries[4].peBlue = 0x56;
7871 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7872 palette_entries, &palette2, NULL);
7873 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7874 hr = IDirectDrawSurface7_SetPalette(surface, palette2);
7875 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7877 /* A palette assigned to the offscreen surface overrides the primary / system
7878 * palette. */
7879 hr = IDirectDrawSurface7_GetDC(surface, &dc);
7880 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7881 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
7882 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
7883 for (i = 0; i < sizeof(expected3) / sizeof(*expected3); i++)
7885 ok(!memcmp(&rgbquad[i], &expected3[i], sizeof(rgbquad[i])),
7886 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7887 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7888 expected3[i].rgbRed, expected3[i].rgbGreen, expected3[i].rgbBlue);
7890 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
7892 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7893 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7894 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7896 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
7897 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7899 refcount = IDirectDrawSurface7_Release(surface);
7900 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7902 /* The Windows 8 testbot keeps extra references to the primary and
7903 * backbuffer while in 8 bpp mode. */
7904 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
7905 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
7907 refcount = IDirectDrawSurface7_Release(primary);
7908 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7909 refcount = IDirectDrawPalette_Release(palette2);
7910 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7911 refcount = IDirectDrawPalette_Release(palette);
7912 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7913 refcount = IDirectDraw7_Release(ddraw);
7914 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7915 DestroyWindow(window);
7918 static void test_palette_alpha(void)
7920 IDirectDrawSurface7 *surface;
7921 DDSURFACEDESC2 surface_desc;
7922 IDirectDraw7 *ddraw;
7923 IDirectDrawPalette *palette;
7924 ULONG refcount;
7925 HWND window;
7926 HRESULT hr;
7927 PALETTEENTRY palette_entries[256];
7928 unsigned int i;
7929 static const struct
7931 DWORD caps, flags;
7932 BOOL attach_allowed;
7933 const char *name;
7935 test_data[] =
7937 {DDSCAPS_OFFSCREENPLAIN, DDSD_WIDTH | DDSD_HEIGHT, FALSE, "offscreenplain"},
7938 {DDSCAPS_TEXTURE, DDSD_WIDTH | DDSD_HEIGHT, TRUE, "texture"},
7939 {DDSCAPS_PRIMARYSURFACE, 0, FALSE, "primary"}
7942 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7943 0, 0, 640, 480, 0, 0, 0, 0);
7944 ddraw = create_ddraw();
7945 ok(!!ddraw, "Failed to create a ddraw object.\n");
7946 if (FAILED(IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
7948 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
7949 IDirectDraw7_Release(ddraw);
7950 DestroyWindow(window);
7951 return;
7953 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7954 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7956 memset(palette_entries, 0, sizeof(palette_entries));
7957 palette_entries[1].peFlags = 0x42;
7958 palette_entries[2].peFlags = 0xff;
7959 palette_entries[3].peFlags = 0x80;
7960 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
7961 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7963 memset(palette_entries, 0x66, sizeof(palette_entries));
7964 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
7965 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
7966 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
7967 palette_entries[0].peFlags);
7968 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
7969 palette_entries[1].peFlags);
7970 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
7971 palette_entries[2].peFlags);
7972 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
7973 palette_entries[3].peFlags);
7975 IDirectDrawPalette_Release(palette);
7977 memset(palette_entries, 0, sizeof(palette_entries));
7978 palette_entries[1].peFlags = 0x42;
7979 palette_entries[1].peRed = 0xff;
7980 palette_entries[2].peFlags = 0xff;
7981 palette_entries[3].peFlags = 0x80;
7982 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT | DDPCAPS_ALPHA,
7983 palette_entries, &palette, NULL);
7984 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7986 memset(palette_entries, 0x66, sizeof(palette_entries));
7987 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
7988 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
7989 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
7990 palette_entries[0].peFlags);
7991 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
7992 palette_entries[1].peFlags);
7993 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
7994 palette_entries[2].peFlags);
7995 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
7996 palette_entries[3].peFlags);
7998 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); i++)
8000 memset(&surface_desc, 0, sizeof(surface_desc));
8001 surface_desc.dwSize = sizeof(surface_desc);
8002 surface_desc.dwFlags = DDSD_CAPS | test_data[i].flags;
8003 surface_desc.dwWidth = 128;
8004 surface_desc.dwHeight = 128;
8005 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
8006 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8007 ok(SUCCEEDED(hr), "Failed to create %s surface, hr %#x.\n", test_data[i].name, hr);
8009 hr = IDirectDrawSurface7_SetPalette(surface, palette);
8010 if (test_data[i].attach_allowed)
8011 ok(SUCCEEDED(hr), "Failed to attach palette to %s surface, hr %#x.\n", test_data[i].name, hr);
8012 else
8013 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x, %s surface.\n", hr, test_data[i].name);
8015 if (SUCCEEDED(hr))
8017 HDC dc;
8018 RGBQUAD rgbquad;
8019 UINT retval;
8021 hr = IDirectDrawSurface7_GetDC(surface, &dc);
8022 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x, %s surface.\n", hr, test_data[i].name);
8023 retval = GetDIBColorTable(dc, 1, 1, &rgbquad);
8024 ok(retval == 1, "GetDIBColorTable returned unexpected result %u.\n", retval);
8025 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x, %s surface.\n",
8026 rgbquad.rgbRed, test_data[i].name);
8027 ok(rgbquad.rgbGreen == 0, "Expected rgbGreen = 0, got %#x, %s surface.\n",
8028 rgbquad.rgbGreen, test_data[i].name);
8029 ok(rgbquad.rgbBlue == 0, "Expected rgbBlue = 0, got %#x, %s surface.\n",
8030 rgbquad.rgbBlue, test_data[i].name);
8031 todo_wine ok(rgbquad.rgbReserved == 0, "Expected rgbReserved = 0, got %u, %s surface.\n",
8032 rgbquad.rgbReserved, test_data[i].name);
8033 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
8034 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8036 IDirectDrawSurface7_Release(surface);
8039 /* Test INVALIDSURFACETYPE vs INVALIDPIXELFORMAT. */
8040 memset(&surface_desc, 0, sizeof(surface_desc));
8041 surface_desc.dwSize = sizeof(surface_desc);
8042 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8043 surface_desc.dwWidth = 128;
8044 surface_desc.dwHeight = 128;
8045 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8046 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8047 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
8048 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
8049 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8050 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8051 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
8052 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8053 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8054 hr = IDirectDrawSurface7_SetPalette(surface, palette);
8055 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x.\n", hr);
8056 IDirectDrawSurface7_Release(surface);
8058 /* The Windows 8 testbot keeps extra references to the primary
8059 * while in 8 bpp mode. */
8060 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
8061 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
8063 refcount = IDirectDrawPalette_Release(palette);
8064 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8065 refcount = IDirectDraw7_Release(ddraw);
8066 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8067 DestroyWindow(window);
8070 static void test_vb_writeonly(void)
8072 IDirect3DDevice7 *device;
8073 IDirect3D7 *d3d;
8074 IDirect3DVertexBuffer7 *buffer;
8075 HWND window;
8076 HRESULT hr;
8077 D3DVERTEXBUFFERDESC desc;
8078 void *ptr;
8079 static const struct vec4 quad[] =
8081 { 0.0f, 480.0f, 0.0f, 1.0f},
8082 { 0.0f, 0.0f, 0.0f, 1.0f},
8083 {640.0f, 480.0f, 0.0f, 1.0f},
8084 {640.0f, 0.0f, 0.0f, 1.0f},
8087 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8088 0, 0, 640, 480, 0, 0, 0, 0);
8090 if (!(device = create_device(window, DDSCL_NORMAL)))
8092 skip("Failed to create a 3D device, skipping test.\n");
8093 DestroyWindow(window);
8094 return;
8097 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
8098 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
8100 memset(&desc, 0, sizeof(desc));
8101 desc.dwSize = sizeof(desc);
8102 desc.dwCaps = D3DVBCAPS_WRITEONLY;
8103 desc.dwFVF = D3DFVF_XYZRHW;
8104 desc.dwNumVertices = sizeof(quad) / sizeof(*quad);
8105 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &buffer, 0);
8106 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
8108 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, &ptr, NULL);
8109 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
8110 memcpy(ptr, quad, sizeof(quad));
8111 hr = IDirect3DVertexBuffer7_Unlock(buffer);
8112 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
8114 hr = IDirect3DDevice7_BeginScene(device);
8115 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8116 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
8117 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8118 hr = IDirect3DDevice7_EndScene(device);
8119 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8121 hr = IDirect3DVertexBuffer7_Lock(buffer, 0, &ptr, NULL);
8122 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
8123 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
8124 hr = IDirect3DVertexBuffer7_Unlock(buffer);
8125 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
8127 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_READONLY, &ptr, NULL);
8128 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
8129 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
8130 hr = IDirect3DVertexBuffer7_Unlock(buffer);
8131 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
8133 IDirect3DVertexBuffer7_Release(buffer);
8134 IDirect3D7_Release(d3d);
8135 IDirect3DDevice7_Release(device);
8136 DestroyWindow(window);
8139 static void test_lost_device(void)
8141 IDirectDrawSurface7 *surface;
8142 DDSURFACEDESC2 surface_desc;
8143 IDirectDraw7 *ddraw;
8144 ULONG refcount;
8145 HWND window;
8146 HRESULT hr;
8147 BOOL ret;
8149 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8150 0, 0, 640, 480, 0, 0, 0, 0);
8151 ddraw = create_ddraw();
8152 ok(!!ddraw, "Failed to create a ddraw object.\n");
8153 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8154 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8156 memset(&surface_desc, 0, sizeof(surface_desc));
8157 surface_desc.dwSize = sizeof(surface_desc);
8158 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
8159 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
8160 U5(surface_desc).dwBackBufferCount = 1;
8161 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8162 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8164 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8165 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8166 hr = IDirectDrawSurface7_IsLost(surface);
8167 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8168 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8169 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8171 ret = SetForegroundWindow(GetDesktopWindow());
8172 ok(ret, "Failed to set foreground window.\n");
8173 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8174 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8175 hr = IDirectDrawSurface7_IsLost(surface);
8176 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8177 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8178 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8180 ret = SetForegroundWindow(window);
8181 ok(ret, "Failed to set foreground window.\n");
8182 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8183 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8184 hr = IDirectDrawSurface7_IsLost(surface);
8185 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8186 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8187 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8189 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
8190 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8191 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8192 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8193 hr = IDirectDrawSurface7_IsLost(surface);
8194 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8195 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8196 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8198 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8199 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8200 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8201 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8202 hr = IDirectDrawSurface7_IsLost(surface);
8203 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8204 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8205 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8207 /* Trying to restore the primary will crash, probably because flippable
8208 * surfaces can't exist in DDSCL_NORMAL. */
8209 IDirectDrawSurface7_Release(surface);
8210 memset(&surface_desc, 0, sizeof(surface_desc));
8211 surface_desc.dwSize = sizeof(surface_desc);
8212 surface_desc.dwFlags = DDSD_CAPS;
8213 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8214 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8215 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8217 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8218 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8219 hr = IDirectDrawSurface7_IsLost(surface);
8220 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8222 ret = SetForegroundWindow(GetDesktopWindow());
8223 ok(ret, "Failed to set foreground window.\n");
8224 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8225 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8226 hr = IDirectDrawSurface7_IsLost(surface);
8227 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8229 ret = SetForegroundWindow(window);
8230 ok(ret, "Failed to set foreground window.\n");
8231 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8232 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8233 hr = IDirectDrawSurface7_IsLost(surface);
8234 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8236 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8237 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8238 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8239 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8240 hr = IDirectDrawSurface7_IsLost(surface);
8241 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8243 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
8244 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8245 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8246 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8247 hr = IDirectDrawSurface7_IsLost(surface);
8248 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8250 IDirectDrawSurface7_Release(surface);
8251 refcount = IDirectDraw7_Release(ddraw);
8252 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8253 DestroyWindow(window);
8256 static void test_resource_priority(void)
8258 IDirectDrawSurface7 *surface, *mipmap;
8259 DDSURFACEDESC2 surface_desc;
8260 IDirectDraw7 *ddraw;
8261 ULONG refcount;
8262 HWND window;
8263 HRESULT hr;
8264 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
8265 DDCAPS hal_caps;
8266 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_MIPMAP;
8267 unsigned int i;
8268 DWORD priority;
8269 static const struct
8271 DWORD caps, caps2;
8272 const char *name;
8273 HRESULT hr;
8274 /* SetPriority on offscreenplain surfaces crashes on AMD GPUs on Win7. */
8275 BOOL crash;
8277 test_data[] =
8279 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, "vidmem texture", DDERR_INVALIDPARAMS, FALSE},
8280 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, "sysmem texture", DDERR_INVALIDPARAMS, FALSE},
8281 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, "managed texture", DD_OK, FALSE},
8282 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, "managed texture", DD_OK, FALSE},
8283 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, "vidmem offscreenplain", DDERR_INVALIDOBJECT, TRUE},
8284 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, "sysmem offscreenplain", DDERR_INVALIDOBJECT, TRUE},
8287 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8288 0, 0, 640, 480, 0, 0, 0, 0);
8289 ddraw = create_ddraw();
8290 ok(!!ddraw, "Failed to create a ddraw object.\n");
8291 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8292 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8294 memset(&hal_caps, 0, sizeof(hal_caps));
8295 hal_caps.dwSize = sizeof(hal_caps);
8296 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
8297 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8298 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps
8299 || !(hal_caps.ddsCaps.dwCaps & DDSCAPS2_TEXTUREMANAGE))
8301 skip("Required surface types not supported, skipping test.\n");
8302 goto done;
8305 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); i++)
8307 memset(&surface_desc, 0, sizeof(surface_desc));
8308 surface_desc.dwSize = sizeof(surface_desc);
8309 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
8310 surface_desc.dwWidth = 32;
8311 surface_desc.dwHeight = 32;
8312 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
8313 surface_desc.ddsCaps.dwCaps2 = test_data[i].caps2;
8314 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8315 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n", hr, test_data[i].name);
8317 /* Priority == NULL segfaults. */
8318 priority = 0xdeadbeef;
8319 hr = IDirectDrawSurface7_GetPriority(surface, &priority);
8320 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
8321 if (SUCCEEDED(test_data[i].hr))
8322 ok(priority == 0, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
8323 else
8324 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
8326 if (!test_data[i].crash)
8328 hr = IDirectDrawSurface7_SetPriority(surface, 1);
8329 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
8330 hr = IDirectDrawSurface7_GetPriority(surface, &priority);
8331 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
8332 if (SUCCEEDED(test_data[i].hr))
8334 ok(priority == 1, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
8335 hr = IDirectDrawSurface7_SetPriority(surface, 2);
8336 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
8338 else
8339 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
8342 IDirectDrawSurface7_Release(surface);
8345 memset(&surface_desc, 0, sizeof(surface_desc));
8346 surface_desc.dwSize = sizeof(surface_desc);
8347 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_MIPMAPCOUNT;
8348 surface_desc.dwWidth = 32;
8349 surface_desc.dwHeight = 32;
8350 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
8351 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
8352 U2(surface_desc).dwMipMapCount = 2;
8353 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8354 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8355 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
8356 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
8358 priority = 0xdeadbeef;
8359 hr = IDirectDrawSurface7_GetPriority(mipmap, &priority);
8360 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type managed mipmap.\n", hr);
8361 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type managed mipmap.\n", priority);
8362 /* SetPriority on the mipmap surface crashes. */
8363 hr = IDirectDrawSurface7_GetPriority(surface, &priority);
8364 ok(SUCCEEDED(hr), "Failed to get priority, hr %#x.\n", hr);
8365 ok(priority == 0, "Got unexpected priority %u, type managed mipmap.\n", priority);
8367 IDirectDrawSurface7_Release(mipmap);
8368 refcount = IDirectDrawSurface7_Release(surface);
8369 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8371 done:
8372 refcount = IDirectDraw7_Release(ddraw);
8373 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8374 DestroyWindow(window);
8377 static void test_surface_desc_lock(void)
8379 IDirectDrawSurface7 *surface;
8380 DDSURFACEDESC2 surface_desc;
8381 IDirectDraw7 *ddraw;
8382 ULONG refcount;
8383 HWND window;
8384 HRESULT hr;
8386 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8387 0, 0, 640, 480, 0, 0, 0, 0);
8388 ddraw = create_ddraw();
8389 ok(!!ddraw, "Failed to create a ddraw object.\n");
8390 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8391 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8393 memset(&surface_desc, 0, sizeof(surface_desc));
8394 surface_desc.dwSize = sizeof(surface_desc);
8395 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8396 surface_desc.dwWidth = 16;
8397 surface_desc.dwHeight = 16;
8398 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8399 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8400 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8402 memset(&surface_desc, 0xaa, sizeof(surface_desc));
8403 surface_desc.dwSize = sizeof(surface_desc);
8404 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
8405 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8406 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
8408 memset(&surface_desc, 0xaa, sizeof(surface_desc));
8409 surface_desc.dwSize = sizeof(surface_desc);
8410 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, 0, NULL);
8411 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
8412 ok(surface_desc.lpSurface != NULL, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
8413 memset(&surface_desc, 0xaa, sizeof(surface_desc));
8414 surface_desc.dwSize = sizeof(surface_desc);
8415 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
8416 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8417 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
8418 hr = IDirectDrawSurface7_Unlock(surface, NULL);
8419 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8421 memset(&surface_desc, 0xaa, sizeof(surface_desc));
8422 surface_desc.dwSize = sizeof(surface_desc);
8423 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
8424 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8425 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
8427 IDirectDrawSurface7_Release(surface);
8428 refcount = IDirectDraw7_Release(ddraw);
8429 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8430 DestroyWindow(window);
8433 static void test_fog_interpolation(void)
8435 HRESULT hr;
8436 IDirect3DDevice7 *device;
8437 IDirectDrawSurface7 *rt;
8438 ULONG refcount;
8439 HWND window;
8440 D3DCOLOR color;
8441 static struct
8443 struct vec3 position;
8444 D3DCOLOR diffuse;
8445 D3DCOLOR specular;
8447 quad[] =
8449 {{-1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff000000},
8450 {{-1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff000000},
8451 {{ 1.0f, -1.0f, 1.0f}, 0xffff0000, 0x00000000},
8452 {{ 1.0f, 1.0f, 1.0f}, 0xffff0000, 0x00000000},
8454 union
8456 DWORD d;
8457 float f;
8458 } conv;
8459 unsigned int i;
8460 static const struct
8462 D3DFOGMODE vfog, tfog;
8463 D3DSHADEMODE shade;
8464 D3DCOLOR middle_color;
8465 BOOL todo;
8467 tests[] =
8469 {D3DFOG_NONE, D3DFOG_NONE, D3DSHADE_FLAT, 0x00007f80, FALSE},
8470 {D3DFOG_NONE, D3DFOG_NONE, D3DSHADE_GOURAUD, 0x00007f80, FALSE},
8471 {D3DFOG_EXP, D3DFOG_NONE, D3DSHADE_FLAT, 0x00007f80, TRUE},
8472 {D3DFOG_EXP, D3DFOG_NONE, D3DSHADE_GOURAUD, 0x00007f80, TRUE},
8473 {D3DFOG_NONE, D3DFOG_EXP, D3DSHADE_FLAT, 0x0000ea15, FALSE},
8474 {D3DFOG_NONE, D3DFOG_EXP, D3DSHADE_GOURAUD, 0x0000ea15, FALSE},
8475 {D3DFOG_EXP, D3DFOG_EXP, D3DSHADE_FLAT, 0x0000ea15, FALSE},
8476 {D3DFOG_EXP, D3DFOG_EXP, D3DSHADE_GOURAUD, 0x0000ea15, FALSE},
8478 D3DDEVICEDESC7 caps;
8480 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8481 0, 0, 640, 480, 0, 0, 0, 0);
8483 if (!(device = create_device(window, DDSCL_NORMAL)))
8485 skip("Failed to create a 3D device, skipping test.\n");
8486 DestroyWindow(window);
8487 return;
8490 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
8491 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8492 hr = IDirect3DDevice7_GetCaps(device, &caps);
8493 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
8494 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE))
8495 skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping some fog tests\n");
8497 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
8498 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8499 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
8500 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8501 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
8502 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8503 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x0000ff00);
8504 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8505 conv.f = 5.0;
8506 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGDENSITY, conv.d);
8507 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8509 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
8510 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
8511 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
8512 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
8513 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x000000ff);
8514 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8516 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
8518 if(!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE) && tests[i].tfog)
8519 continue;
8521 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00808080, 0.0f, 0);
8522 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
8524 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SHADEMODE, tests[i].shade);
8525 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8526 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, tests[i].vfog);
8527 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8528 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, tests[i].tfog);
8529 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8530 hr = IDirect3DDevice7_BeginScene(device);
8531 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8532 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
8533 D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR, quad, 4, 0);
8534 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8535 hr = IDirect3DDevice7_EndScene(device);
8536 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8538 color = get_surface_color(rt, 0, 240);
8539 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x, case %u.\n", color, i);
8540 color = get_surface_color(rt, 320, 240);
8541 if (tests[i].todo)
8542 todo_wine ok(compare_color(color, tests[i].middle_color, 2),
8543 "Got unexpected color 0x%08x, case %u.\n", color, i);
8544 else
8545 ok(compare_color(color, tests[i].middle_color, 2),
8546 "Got unexpected color 0x%08x, case %u.\n", color, i);
8547 color = get_surface_color(rt, 639, 240);
8548 ok(compare_color(color, 0x0000fd02, 2), "Got unexpected color 0x%08x, case %u.\n", color, i);
8551 IDirectDrawSurface7_Release(rt);
8552 refcount = IDirect3DDevice7_Release(device);
8553 ok(!refcount, "Device has %u references left.\n", refcount);
8554 DestroyWindow(window);
8557 static void test_negative_fixedfunction_fog(void)
8559 HRESULT hr;
8560 IDirect3DDevice7 *device;
8561 IDirectDrawSurface7 *rt;
8562 ULONG refcount;
8563 HWND window;
8564 D3DCOLOR color;
8565 static struct
8567 struct vec3 position;
8568 D3DCOLOR diffuse;
8570 quad[] =
8572 {{-1.0f, -1.0f, -0.5f}, 0xffff0000},
8573 {{-1.0f, 1.0f, -0.5f}, 0xffff0000},
8574 {{ 1.0f, -1.0f, -0.5f}, 0xffff0000},
8575 {{ 1.0f, 1.0f, -0.5f}, 0xffff0000},
8577 static struct
8579 struct vec4 position;
8580 D3DCOLOR diffuse;
8582 tquad[] =
8584 {{ 0.0f, 0.0f, -0.5f, 1.0f}, 0xffff0000},
8585 {{640.0f, 0.0f, -0.5f, 1.0f}, 0xffff0000},
8586 {{ 0.0f, 480.0f, -0.5f, 1.0f}, 0xffff0000},
8587 {{640.0f, 480.0f, -0.5f, 1.0f}, 0xffff0000},
8589 unsigned int i;
8590 static D3DMATRIX zero =
8592 1.0f, 0.0f, 0.0f, 0.0f,
8593 0.0f, 1.0f, 0.0f, 0.0f,
8594 0.0f, 0.0f, 0.0f, 0.0f,
8595 0.0f, 0.0f, 0.0f, 1.0f
8597 static D3DMATRIX identity =
8599 1.0f, 0.0f, 0.0f, 0.0f,
8600 0.0f, 1.0f, 0.0f, 0.0f,
8601 0.0f, 0.0f, 1.0f, 0.0f,
8602 0.0f, 0.0f, 0.0f, 1.0f
8604 static const struct
8606 DWORD pos_type;
8607 void *quad;
8608 D3DMATRIX *matrix;
8609 union
8611 float f;
8612 DWORD d;
8613 } start, end;
8614 D3DFOGMODE vfog, tfog;
8615 DWORD color, color_broken, color_broken2;
8617 tests[] =
8619 /* Run the XYZRHW tests first. Depth clamping is broken after RHW draws on the testbot.
8621 * Geforce8+ GPUs on Windows abs() table fog, everything else does not. */
8622 {D3DFVF_XYZRHW, tquad, &identity, { 0.0f}, {1.0f}, D3DFOG_NONE, D3DFOG_LINEAR,
8623 0x00ff0000, 0x00808000, 0x00808000},
8624 /* r200 GPUs and presumably all d3d8 and older HW clamp the fog
8625 * parameters to 0.0 and 1.0 in the table fog case. */
8626 {D3DFVF_XYZRHW, tquad, &identity, {-1.0f}, {0.0f}, D3DFOG_NONE, D3DFOG_LINEAR,
8627 0x00808000, 0x00ff0000, 0x0000ff00},
8628 /* test_fog_interpolation shows that vertex fog evaluates the fog
8629 * equation in the vertex pipeline. Start = -1.0 && end = 0.0 shows
8630 * that the abs happens before the fog equation is evaluated.
8632 * Vertex fog abs() behavior is the same on all GPUs. */
8633 {D3DFVF_XYZ, quad, &zero, { 0.0f}, {1.0f}, D3DFOG_LINEAR, D3DFOG_NONE,
8634 0x00808000, 0x00808000, 0x00808000},
8635 {D3DFVF_XYZ, quad, &zero, {-1.0f}, {0.0f}, D3DFOG_LINEAR, D3DFOG_NONE,
8636 0x0000ff00, 0x0000ff00, 0x0000ff00},
8637 {D3DFVF_XYZ, quad, &zero, { 0.0f}, {1.0f}, D3DFOG_EXP, D3DFOG_NONE,
8638 0x009b6400, 0x009b6400, 0x009b6400},
8640 D3DDEVICEDESC7 caps;
8642 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8643 0, 0, 640, 480, 0, 0, 0, 0);
8645 if (!(device = create_device(window, DDSCL_NORMAL)))
8647 skip("Failed to create a 3D device, skipping test.\n");
8648 DestroyWindow(window);
8649 return;
8652 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
8653 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8654 hr = IDirect3DDevice7_GetCaps(device, &caps);
8655 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
8656 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE))
8657 skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping some fog tests.\n");
8659 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
8660 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8661 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
8662 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8663 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
8664 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8665 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x0000ff00);
8666 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8667 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
8668 ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
8670 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
8672 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE) && tests[i].tfog)
8673 continue;
8675 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0);
8676 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
8678 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, tests[i].matrix);
8679 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
8680 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGSTART, tests[i].start.d);
8681 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8682 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGEND, tests[i].end.d);
8683 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8684 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, tests[i].vfog);
8685 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8686 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, tests[i].tfog);
8687 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8689 hr = IDirect3DDevice7_BeginScene(device);
8690 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8691 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
8692 tests[i].pos_type | D3DFVF_DIFFUSE, tests[i].quad, 4, 0);
8693 hr = IDirect3DDevice7_EndScene(device);
8694 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8696 color = get_surface_color(rt, 0, 240);
8697 ok(compare_color(color, tests[i].color, 2) || broken(compare_color(color, tests[i].color_broken, 2))
8698 || broken(compare_color(color, tests[i].color_broken2, 2)),
8699 "Got unexpected color 0x%08x, case %u.\n", color, i);
8702 IDirectDrawSurface7_Release(rt);
8703 refcount = IDirect3DDevice7_Release(device);
8704 ok(!refcount, "Device has %u references left.\n", refcount);
8705 DestroyWindow(window);
8708 static void test_table_fog_zw(void)
8710 HRESULT hr;
8711 IDirect3DDevice7 *device;
8712 IDirectDrawSurface7 *rt;
8713 ULONG refcount;
8714 HWND window;
8715 D3DCOLOR color;
8716 static struct
8718 struct vec4 position;
8719 D3DCOLOR diffuse;
8721 quad[] =
8723 {{ 0.0f, 0.0f, 0.0f, 0.0f}, 0xffff0000},
8724 {{640.0f, 0.0f, 0.0f, 0.0f}, 0xffff0000},
8725 {{ 0.0f, 480.0f, 0.0f, 0.0f}, 0xffff0000},
8726 {{640.0f, 480.0f, 0.0f, 0.0f}, 0xffff0000},
8728 static D3DMATRIX identity =
8730 1.0f, 0.0f, 0.0f, 0.0f,
8731 0.0f, 1.0f, 0.0f, 0.0f,
8732 0.0f, 0.0f, 1.0f, 0.0f,
8733 0.0f, 0.0f, 0.0f, 1.0f
8735 D3DDEVICEDESC7 caps;
8736 static const struct
8738 float z, w;
8739 D3DZBUFFERTYPE z_test;
8740 D3DCOLOR color;
8742 tests[] =
8744 {0.7f, 0.0f, D3DZB_TRUE, 0x004cb200},
8745 {0.7f, 0.0f, D3DZB_FALSE, 0x004cb200},
8746 {0.7f, 0.3f, D3DZB_TRUE, 0x004cb200},
8747 {0.7f, 0.3f, D3DZB_FALSE, 0x004cb200},
8748 {0.7f, 3.0f, D3DZB_TRUE, 0x004cb200},
8749 {0.7f, 3.0f, D3DZB_FALSE, 0x004cb200},
8750 {0.3f, 0.0f, D3DZB_TRUE, 0x00b24c00},
8751 {0.3f, 0.0f, D3DZB_FALSE, 0x00b24c00},
8753 unsigned int i;
8755 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8756 0, 0, 640, 480, 0, 0, 0, 0);
8758 if (!(device = create_device(window, DDSCL_NORMAL)))
8760 skip("Failed to create a 3D device, skipping test.\n");
8761 DestroyWindow(window);
8762 return;
8765 hr = IDirect3DDevice7_GetCaps(device, &caps);
8766 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
8767 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE))
8769 skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping POSITIONT table fog test.\n");
8770 goto done;
8772 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
8773 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8775 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
8776 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8777 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
8778 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8779 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x0000ff00);
8780 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8781 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
8782 ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
8783 /* Work around an AMD Windows driver bug. Needs a proj matrix applied redundantly. */
8784 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &identity);
8785 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
8786 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_LINEAR);
8787 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8789 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
8791 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x000000ff, 1.0f, 0);
8792 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
8794 quad[0].position.z = tests[i].z;
8795 quad[1].position.z = tests[i].z;
8796 quad[2].position.z = tests[i].z;
8797 quad[3].position.z = tests[i].z;
8798 quad[0].position.w = tests[i].w;
8799 quad[1].position.w = tests[i].w;
8800 quad[2].position.w = tests[i].w;
8801 quad[3].position.w = tests[i].w;
8802 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, tests[i].z_test);
8803 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8805 hr = IDirect3DDevice7_BeginScene(device);
8806 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8807 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
8808 D3DFVF_XYZRHW | D3DFVF_DIFFUSE, quad, 4, 0);
8809 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8810 hr = IDirect3DDevice7_EndScene(device);
8811 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8813 color = get_surface_color(rt, 0, 240);
8814 ok(compare_color(color, tests[i].color, 2),
8815 "Got unexpected color 0x%08x, expected 0x%8x, case %u.\n", color, tests[i].color, i);
8818 IDirectDrawSurface7_Release(rt);
8819 done:
8820 refcount = IDirect3DDevice7_Release(device);
8821 ok(!refcount, "Device has %u references left.\n", refcount);
8822 DestroyWindow(window);
8825 static void test_signed_formats(void)
8827 HRESULT hr;
8828 IDirect3DDevice7 *device;
8829 IDirect3D7 *d3d;
8830 IDirectDraw7 *ddraw;
8831 IDirectDrawSurface7 *surface, *rt;
8832 DDSURFACEDESC2 surface_desc;
8833 ULONG refcount;
8834 HWND window;
8835 D3DCOLOR color, expected_color;
8836 static struct
8838 struct vec3 position;
8839 struct vec2 texcoord;
8841 quad[] =
8843 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
8844 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
8845 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
8846 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
8848 /* See test_signed_formats() in dlls/d3d9/tests/visual.c for an explanation
8849 * of these values. */
8850 static const USHORT content_v8u8[4][4] =
8852 {0x0000, 0x7f7f, 0x8880, 0x0000},
8853 {0x0080, 0x8000, 0x7f00, 0x007f},
8854 {0x193b, 0xe8c8, 0x0808, 0xf8f8},
8855 {0x4444, 0xc0c0, 0xa066, 0x22e0},
8857 static const DWORD content_x8l8v8u8[4][4] =
8859 {0x00000000, 0x00ff7f7f, 0x00008880, 0x00ff0000},
8860 {0x00000080, 0x00008000, 0x00007f00, 0x0000007f},
8861 {0x0041193b, 0x0051e8c8, 0x00040808, 0x00fff8f8},
8862 {0x00824444, 0x0000c0c0, 0x00c2a066, 0x009222e0},
8864 static const USHORT content_l6v5u5[4][4] =
8866 {0x0000, 0xfdef, 0x0230, 0xfc00},
8867 {0x0010, 0x0200, 0x01e0, 0x000f},
8868 {0x4067, 0x53b9, 0x0421, 0xffff},
8869 {0x8108, 0x0318, 0xc28c, 0x909c},
8871 static const struct
8873 const char *name;
8874 const void *content;
8875 SIZE_T pixel_size;
8876 BOOL blue;
8877 unsigned int slop, slop_broken;
8878 DDPIXELFORMAT format;
8880 formats[] =
8883 "D3DFMT_V8U8", content_v8u8, sizeof(WORD), FALSE, 1, 0,
8885 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV, 0,
8886 {16}, {0x000000ff}, {0x0000ff00}, {0x00000000}, {0x00000000}
8890 "D3DFMT_X8L8V8U8", content_x8l8v8u8, sizeof(DWORD), TRUE, 1, 0,
8892 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE, 0,
8893 {32}, {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}
8897 "D3DFMT_L6V5U5", content_l6v5u5, sizeof(WORD), TRUE, 4, 7,
8899 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE, 0,
8900 {16}, {0x0000001f}, {0x000003e0}, {0x0000fc00}, {0x00000000}
8904 /* No V16U16 or Q8W8V8U8 support in ddraw. */
8906 static const D3DCOLOR expected_colors[4][4] =
8908 {0x00808080, 0x00fefeff, 0x00010780, 0x008080ff},
8909 {0x00018080, 0x00800180, 0x0080fe80, 0x00fe8080},
8910 {0x00ba98a0, 0x004767a8, 0x00888881, 0x007878ff},
8911 {0x00c3c3c0, 0x003f3f80, 0x00e51fe1, 0x005fa2c8},
8913 unsigned int i, width, x, y;
8914 D3DDEVICEDESC7 device_desc;
8916 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8917 0, 0, 640, 480, 0, 0, 0, 0);
8919 if (!(device = create_device(window, DDSCL_NORMAL)))
8921 skip("Failed to create a 3D device, skipping test.\n");
8922 DestroyWindow(window);
8923 return;
8926 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
8927 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
8928 if (!(device_desc.dwTextureOpCaps & D3DTEXOPCAPS_BLENDFACTORALPHA))
8930 skip("D3DTOP_BLENDFACTORALPHA not supported, skipping bumpmap format tests.\n");
8931 goto done;
8934 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
8935 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
8936 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
8937 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
8938 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
8939 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8941 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
8942 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8944 /* dst = tex * 0.5 + 1.0 * (1.0 - 0.5) = tex * 0.5 + 0.5 */
8945 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x80ffffff);
8946 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8947 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_BLENDFACTORALPHA);
8948 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
8949 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
8950 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
8951 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
8952 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
8954 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
8956 for (width = 1; width < 5; width += 3)
8958 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
8959 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
8961 memset(&surface_desc, 0, sizeof(surface_desc));
8962 surface_desc.dwSize = sizeof(surface_desc);
8963 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
8964 surface_desc.dwWidth = width;
8965 surface_desc.dwHeight = 4;
8966 U4(surface_desc).ddpfPixelFormat = formats[i].format;
8967 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
8968 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8969 if (FAILED(hr))
8971 skip("%s textures not supported, skipping.\n", formats[i].name);
8972 continue;
8974 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, format %s.\n", hr, formats[i].name);
8975 hr = IDirect3DDevice7_SetTexture(device, 0, surface);
8976 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x, format %s.\n", hr, formats[i].name);
8978 memset(&surface_desc, 0, sizeof(surface_desc));
8979 surface_desc.dwSize = sizeof(surface_desc);
8980 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, 0, NULL);
8981 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, format %s.\n", hr, formats[i].name);
8982 for (y = 0; y < 4; y++)
8984 memcpy((char *)surface_desc.lpSurface + y * U1(surface_desc).lPitch,
8985 (char *)formats[i].content + y * 4 * formats[i].pixel_size,
8986 width * formats[i].pixel_size);
8988 hr = IDirectDrawSurface7_Unlock(surface, NULL);
8989 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, format %s.\n", hr, formats[i].name);
8991 hr = IDirect3DDevice7_BeginScene(device);
8992 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8993 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
8994 D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
8995 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8996 hr = IDirect3DDevice7_EndScene(device);
8997 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8999 for (y = 0; y < 4; y++)
9001 for (x = 0; x < width; x++)
9003 expected_color = expected_colors[y][x];
9004 if (!formats[i].blue)
9005 expected_color |= 0x000000ff;
9007 color = get_surface_color(rt, 80 + 160 * x, 60 + 120 * y);
9008 ok(compare_color(color, expected_color, formats[i].slop)
9009 || broken(compare_color(color, expected_color, formats[i].slop_broken)),
9010 "Expected color 0x%08x, got 0x%08x, format %s, location %ux%u.\n",
9011 expected_color, color, formats[i].name, x, y);
9015 IDirectDrawSurface7_Release(surface);
9020 IDirectDrawSurface7_Release(rt);
9021 IDirectDraw7_Release(ddraw);
9022 IDirect3D7_Release(d3d);
9024 done:
9025 refcount = IDirect3DDevice7_Release(device);
9026 ok(!refcount, "Device has %u references left.\n", refcount);
9027 DestroyWindow(window);
9030 static void test_color_fill(void)
9032 HRESULT hr;
9033 IDirect3DDevice7 *device;
9034 IDirect3D7 *d3d;
9035 IDirectDraw7 *ddraw;
9036 IDirectDrawSurface7 *surface, *surface2;
9037 DDSURFACEDESC2 surface_desc;
9038 DDPIXELFORMAT z_fmt;
9039 ULONG refcount;
9040 HWND window;
9041 unsigned int i;
9042 DDBLTFX fx;
9043 RECT rect = {5, 5, 7, 7};
9044 DWORD *color;
9045 DWORD supported_fmts = 0, num_fourcc_codes, *fourcc_codes;
9046 DDCAPS hal_caps;
9047 static const struct
9049 DWORD caps, caps2;
9050 HRESULT colorfill_hr, depthfill_hr;
9051 BOOL rop_success;
9052 const char *name;
9053 DWORD result;
9054 BOOL check_result;
9055 DDPIXELFORMAT format;
9057 tests[] =
9060 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
9061 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain RGB", 0xdeadbeef, TRUE,
9063 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9064 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9068 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0,
9069 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain RGB", 0xdeadbeef, TRUE,
9071 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9072 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9076 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0,
9077 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem texture RGB", 0xdeadbeef, TRUE,
9079 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9080 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9084 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0,
9085 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem texture RGB", 0xdeadbeef, TRUE,
9087 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9088 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9092 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
9093 DD_OK, DDERR_INVALIDPARAMS, TRUE, "managed texture RGB", 0xdeadbeef, TRUE,
9095 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9096 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9100 DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY, 0,
9101 DDERR_INVALIDPARAMS, DD_OK, TRUE, "vidmem zbuffer", 0, FALSE,
9102 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
9105 DDSCAPS_ZBUFFER | DDSCAPS_SYSTEMMEMORY, 0,
9106 DDERR_INVALIDPARAMS, DD_OK, TRUE, "sysmem zbuffer", 0, FALSE,
9107 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
9110 /* Colorfill on YUV surfaces always returns DD_OK, but the content is
9111 * different afterwards. DX9+ GPUs set one of the two luminance values
9112 * in each block, but AMD and Nvidia GPUs disagree on which luminance
9113 * value they set. r200 (dx8) just sets the entire block to the clear
9114 * value. */
9115 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
9116 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain YUY2", 0, FALSE,
9118 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
9119 {0}, {0}, {0}, {0}, {0}
9123 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
9124 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain UYVY", 0, FALSE,
9126 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
9127 {0}, {0}, {0}, {0}, {0}
9131 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY, 0,
9132 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay YUY2", 0, FALSE,
9134 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
9135 {0}, {0}, {0}, {0}, {0}
9139 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY, 0,
9140 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay UYVY", 0, FALSE,
9142 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
9143 {0}, {0}, {0}, {0}, {0}
9147 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0,
9148 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "vidmem texture DXT1", 0, FALSE,
9150 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
9151 {0}, {0}, {0}, {0}, {0}
9155 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0,
9156 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "sysmem texture DXT1", 0, FALSE,
9158 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
9159 {0}, {0}, {0}, {0}, {0}
9163 /* The testbot fills this with 0x00 instead of the blue channel. The sysmem
9164 * surface works, presumably because it is handled by the runtime instead of
9165 * the driver. */
9166 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
9167 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain P8", 0xefefefef, FALSE,
9169 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
9170 {8}, {0}, {0}, {0}, {0}
9174 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0,
9175 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain P8", 0xefefefef, TRUE,
9177 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
9178 {8}, {0}, {0}, {0}, {0}
9182 static const struct
9184 DWORD rop;
9185 const char *name;
9186 HRESULT hr;
9188 rops[] =
9190 {SRCCOPY, "SRCCOPY", DD_OK},
9191 {SRCPAINT, "SRCPAINT", DDERR_NORASTEROPHW},
9192 {SRCAND, "SRCAND", DDERR_NORASTEROPHW},
9193 {SRCINVERT, "SRCINVERT", DDERR_NORASTEROPHW},
9194 {SRCERASE, "SRCERASE", DDERR_NORASTEROPHW},
9195 {NOTSRCCOPY, "NOTSRCCOPY", DDERR_NORASTEROPHW},
9196 {NOTSRCERASE, "NOTSRCERASE", DDERR_NORASTEROPHW},
9197 {MERGECOPY, "MERGECOPY", DDERR_NORASTEROPHW},
9198 {MERGEPAINT, "MERGEPAINT", DDERR_NORASTEROPHW},
9199 {PATCOPY, "PATCOPY", DDERR_NORASTEROPHW},
9200 {PATPAINT, "PATPAINT", DDERR_NORASTEROPHW},
9201 {PATINVERT, "PATINVERT", DDERR_NORASTEROPHW},
9202 {DSTINVERT, "DSTINVERT", DDERR_NORASTEROPHW},
9203 {BLACKNESS, "BLACKNESS", DD_OK},
9204 {WHITENESS, "WHITENESS", DD_OK},
9205 {0xaa0029, "0xaa0029", DDERR_NORASTEROPHW} /* noop */
9208 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9209 0, 0, 640, 480, 0, 0, 0, 0);
9211 if (!(device = create_device(window, DDSCL_NORMAL)))
9213 skip("Failed to create a 3D device, skipping test.\n");
9214 DestroyWindow(window);
9215 return;
9218 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
9219 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
9220 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
9221 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
9223 memset(&z_fmt, 0, sizeof(z_fmt));
9224 IDirect3D7_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
9225 if (!z_fmt.dwSize)
9226 skip("No Z buffer formats supported, skipping Z buffer colorfill test.\n");
9228 IDirect3DDevice7_EnumTextureFormats(device, test_block_formats_creation_cb, &supported_fmts);
9229 if (!(supported_fmts & SUPPORT_DXT1))
9230 skip("DXT1 textures not supported, skipping DXT1 colorfill test.\n");
9232 IDirect3D7_Release(d3d);
9234 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
9235 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
9236 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
9237 num_fourcc_codes * sizeof(*fourcc_codes));
9238 if (!fourcc_codes)
9239 goto done;
9240 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
9241 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
9242 for (i = 0; i < num_fourcc_codes; i++)
9244 if (fourcc_codes[i] == MAKEFOURCC('Y', 'U', 'Y', '2'))
9245 supported_fmts |= SUPPORT_YUY2;
9246 else if (fourcc_codes[i] == MAKEFOURCC('U', 'Y', 'V', 'Y'))
9247 supported_fmts |= SUPPORT_UYVY;
9249 HeapFree(GetProcessHeap(), 0, fourcc_codes);
9251 memset(&hal_caps, 0, sizeof(hal_caps));
9252 hal_caps.dwSize = sizeof(hal_caps);
9253 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
9254 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9256 if (!(supported_fmts & (SUPPORT_YUY2 | SUPPORT_UYVY)) || !(hal_caps.dwCaps & DDCAPS_OVERLAY))
9257 skip("Overlays or some YUV formats not supported, skipping YUV colorfill tests.\n");
9259 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
9261 /* Some Windows drivers modify dwFillColor when it is used on P8 or FourCC formats. */
9262 memset(&fx, 0, sizeof(fx));
9263 fx.dwSize = sizeof(fx);
9264 U5(fx).dwFillColor = 0xdeadbeef;
9266 memset(&surface_desc, 0, sizeof(surface_desc));
9267 surface_desc.dwSize = sizeof(surface_desc);
9268 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9269 surface_desc.dwWidth = 64;
9270 surface_desc.dwHeight = 64;
9271 U4(surface_desc).ddpfPixelFormat = tests[i].format;
9272 surface_desc.ddsCaps.dwCaps = tests[i].caps;
9273 surface_desc.ddsCaps.dwCaps2 = tests[i].caps2;
9275 if (tests[i].format.dwFourCC == MAKEFOURCC('D','X','T','1') && !(supported_fmts & SUPPORT_DXT1))
9276 continue;
9277 if (tests[i].format.dwFourCC == MAKEFOURCC('Y','U','Y','2') && !(supported_fmts & SUPPORT_YUY2))
9278 continue;
9279 if (tests[i].format.dwFourCC == MAKEFOURCC('U','Y','V','Y') && !(supported_fmts & SUPPORT_UYVY))
9280 continue;
9281 if (tests[i].caps & DDSCAPS_OVERLAY && !(hal_caps.dwCaps & DDCAPS_OVERLAY))
9282 continue;
9284 if (tests[i].caps & DDSCAPS_ZBUFFER)
9286 if (!z_fmt.dwSize)
9287 continue;
9289 U4(surface_desc).ddpfPixelFormat = z_fmt;
9292 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9293 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, surface %s.\n", hr, tests[i].name);
9295 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9296 if (tests[i].format.dwFourCC)
9297 todo_wine ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9298 hr, tests[i].colorfill_hr, tests[i].name);
9299 else
9300 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9301 hr, tests[i].colorfill_hr, tests[i].name);
9303 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9304 if (tests[i].format.dwFourCC)
9305 todo_wine ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9306 hr, tests[i].colorfill_hr, tests[i].name);
9307 else
9308 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9309 hr, tests[i].colorfill_hr, tests[i].name);
9311 if (SUCCEEDED(hr) && tests[i].check_result)
9313 memset(&surface_desc, 0, sizeof(surface_desc));
9314 surface_desc.dwSize = sizeof(surface_desc);
9315 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9316 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9317 color = surface_desc.lpSurface;
9318 ok(*color == tests[i].result, "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
9319 *color, tests[i].result, tests[i].name);
9320 hr = IDirectDrawSurface7_Unlock(surface, NULL);
9321 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9324 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9325 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9326 hr, tests[i].depthfill_hr, tests[i].name);
9327 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9328 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9329 hr, tests[i].depthfill_hr, tests[i].name);
9331 U5(fx).dwFillColor = 0xdeadbeef;
9332 fx.dwROP = BLACKNESS;
9333 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
9334 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
9335 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
9336 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
9337 U5(fx).dwFillColor, tests[i].name);
9339 if (SUCCEEDED(hr) && tests[i].check_result)
9341 memset(&surface_desc, 0, sizeof(surface_desc));
9342 surface_desc.dwSize = sizeof(surface_desc);
9343 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9344 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9345 color = surface_desc.lpSurface;
9346 ok(*color == 0, "Got clear result 0x%08x, expected 0x00000000, surface %s.\n",
9347 *color, tests[i].name);
9348 hr = IDirectDrawSurface7_Unlock(surface, NULL);
9349 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9352 fx.dwROP = WHITENESS;
9353 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
9354 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
9355 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
9356 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
9357 U5(fx).dwFillColor, tests[i].name);
9359 if (SUCCEEDED(hr) && tests[i].check_result)
9361 memset(&surface_desc, 0, sizeof(surface_desc));
9362 surface_desc.dwSize = sizeof(surface_desc);
9363 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9364 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9365 color = surface_desc.lpSurface;
9366 /* WHITENESS sets the alpha channel to 0x00. Ignore this for now. */
9367 ok((*color & 0x00ffffff) == 0x00ffffff, "Got clear result 0x%08x, expected 0xffffffff, surface %s.\n",
9368 *color, tests[i].name);
9369 hr = IDirectDrawSurface7_Unlock(surface, NULL);
9370 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9373 IDirectDrawSurface7_Release(surface);
9376 memset(&fx, 0, sizeof(fx));
9377 fx.dwSize = sizeof(fx);
9378 U5(fx).dwFillColor = 0xdeadbeef;
9379 fx.dwROP = WHITENESS;
9381 memset(&surface_desc, 0, sizeof(surface_desc));
9382 surface_desc.dwSize = sizeof(surface_desc);
9383 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9384 surface_desc.dwWidth = 64;
9385 surface_desc.dwHeight = 64;
9386 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9387 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
9388 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
9389 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9390 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9391 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
9392 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
9393 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9394 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9395 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
9396 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9398 /* No DDBLTFX. */
9399 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, NULL);
9400 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9401 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, NULL);
9402 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9404 /* Unused source rectangle. */
9405 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9406 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9407 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
9408 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9410 /* Unused source surface. */
9411 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9412 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9413 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
9414 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9415 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9416 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9417 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
9418 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9420 /* Inverted destination or source rectangle. */
9421 SetRect(&rect, 5, 7, 7, 5);
9422 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9423 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9424 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9425 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9426 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9427 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9428 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9429 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9430 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
9431 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9433 /* Negative rectangle. */
9434 SetRect(&rect, -1, -1, 5, 5);
9435 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9436 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9437 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9438 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9439 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9440 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9441 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9442 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9443 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
9444 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9446 /* Out of bounds rectangle. */
9447 SetRect(&rect, 0, 0, 65, 65);
9448 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9449 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9450 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
9451 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9453 /* Combine multiple flags. */
9454 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9455 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9456 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
9457 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9458 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
9459 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9461 for (i = 0; i < sizeof(rops) / sizeof(*rops); i++)
9463 fx.dwROP = rops[i].rop;
9464 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
9465 ok(hr == rops[i].hr, "Got unexpected hr %#x for rop %s.\n", hr, rops[i].name);
9468 IDirectDrawSurface7_Release(surface2);
9469 IDirectDrawSurface7_Release(surface);
9471 if (!z_fmt.dwSize)
9472 goto done;
9474 memset(&surface_desc, 0, sizeof(surface_desc));
9475 surface_desc.dwSize = sizeof(surface_desc);
9476 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9477 surface_desc.dwWidth = 64;
9478 surface_desc.dwHeight = 64;
9479 U4(surface_desc).ddpfPixelFormat = z_fmt;
9480 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
9481 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9482 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9483 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
9484 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9486 /* No DDBLTFX. */
9487 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, NULL);
9488 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9490 /* Unused source rectangle. */
9491 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9492 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9494 /* Unused source surface. */
9495 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9496 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9497 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9498 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9500 /* Inverted destination or source rectangle. */
9501 SetRect(&rect, 5, 7, 7, 5);
9502 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9503 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9504 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9505 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9506 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9507 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9508 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9509 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9511 /* Negative rectangle. */
9512 SetRect(&rect, -1, -1, 5, 5);
9513 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9514 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9515 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9516 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9517 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9518 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9519 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9520 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9522 /* Out of bounds rectangle. */
9523 SetRect(&rect, 0, 0, 65, 65);
9524 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9525 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9527 /* Combine multiple flags. */
9528 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9529 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9531 IDirectDrawSurface7_Release(surface2);
9532 IDirectDrawSurface7_Release(surface);
9534 done:
9535 IDirectDraw7_Release(ddraw);
9536 refcount = IDirect3DDevice7_Release(device);
9537 ok(!refcount, "Device has %u references left.\n", refcount);
9538 DestroyWindow(window);
9541 static void test_texcoordindex(void)
9543 static D3DMATRIX mat =
9545 1.0f, 0.0f, 0.0f, 0.0f,
9546 0.0f, 0.0f, 0.0f, 0.0f,
9547 0.0f, 0.0f, 0.0f, 0.0f,
9548 0.0f, 0.0f, 0.0f, 0.0f,
9550 static struct
9552 struct vec3 pos;
9553 struct vec2 texcoord1;
9554 struct vec2 texcoord2;
9555 struct vec2 texcoord3;
9557 quad[] =
9559 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f}},
9560 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 0.0f}},
9561 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}},
9562 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}},
9564 static const DWORD fvf = D3DFVF_XYZ | D3DFVF_TEX3;
9565 IDirect3DDevice7 *device;
9566 IDirect3D7 *d3d;
9567 IDirectDraw7 *ddraw;
9568 IDirectDrawSurface7 *rt;
9569 HWND window;
9570 HRESULT hr;
9571 IDirectDrawSurface7 *texture1, *texture2;
9572 DDSURFACEDESC2 surface_desc;
9573 ULONG refcount;
9574 D3DCOLOR color;
9575 DWORD *ptr;
9577 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9578 0, 0, 640, 480, 0, 0, 0, 0);
9579 if (!(device = create_device(window, DDSCL_NORMAL)))
9581 skip("Failed to create a 3D device, skipping test.\n");
9582 DestroyWindow(window);
9583 return;
9586 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
9587 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
9588 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
9589 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
9590 IDirect3D7_Release(d3d);
9592 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
9593 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9595 memset(&surface_desc, 0, sizeof(surface_desc));
9596 surface_desc.dwSize = sizeof(surface_desc);
9597 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9598 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
9599 surface_desc.dwWidth = 2;
9600 surface_desc.dwHeight = 2;
9601 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9602 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
9603 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
9604 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9605 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9606 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
9607 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
9608 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture1, NULL);
9609 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9610 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture2, NULL);
9611 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9613 memset(&surface_desc, 0, sizeof(surface_desc));
9614 surface_desc.dwSize = sizeof(surface_desc);
9615 hr = IDirectDrawSurface7_Lock(texture1, 0, &surface_desc, 0, NULL);
9616 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
9617 ptr = surface_desc.lpSurface;
9618 ptr[0] = 0xff000000;
9619 ptr[1] = 0xff00ff00;
9620 ptr += surface_desc.lPitch / sizeof(*ptr);
9621 ptr[0] = 0xff0000ff;
9622 ptr[1] = 0xff00ffff;
9623 hr = IDirectDrawSurface7_Unlock(texture1, NULL);
9624 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9626 memset(&surface_desc, 0, sizeof(surface_desc));
9627 surface_desc.dwSize = sizeof(surface_desc);
9628 hr = IDirectDrawSurface7_Lock(texture2, 0, &surface_desc, 0, NULL);
9629 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
9630 ptr = surface_desc.lpSurface;
9631 ptr[0] = 0xff000000;
9632 ptr[1] = 0xff0000ff;
9633 ptr += surface_desc.lPitch / sizeof(*ptr);
9634 ptr[0] = 0xffff0000;
9635 ptr[1] = 0xffff00ff;
9636 hr = IDirectDrawSurface7_Unlock(texture2, 0);
9637 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9639 hr = IDirect3DDevice7_SetTexture(device, 0, texture1);
9640 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
9641 hr = IDirect3DDevice7_SetTexture(device, 1, texture2);
9642 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
9643 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
9644 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
9645 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
9646 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
9647 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
9648 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
9649 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_ADD);
9650 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
9651 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
9652 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
9653 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
9654 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
9655 hr = IDirect3DDevice7_SetTextureStageState(device, 2, D3DTSS_COLOROP, D3DTOP_DISABLE);
9656 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
9658 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_TEXCOORDINDEX, 1);
9659 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
9660 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXCOORDINDEX, 0);
9661 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
9663 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
9664 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
9666 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
9667 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
9669 hr = IDirect3DDevice7_BeginScene(device);
9670 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9671 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
9672 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9673 hr = IDirect3DDevice7_EndScene(device);
9674 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9676 color = get_surface_color(rt, 160, 120);
9677 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9678 color = get_surface_color(rt, 480, 120);
9679 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
9680 color = get_surface_color(rt, 160, 360);
9681 ok(compare_color(color, 0x00ff0000, 2), "Got unexpected color 0x%08x.\n", color);
9682 color = get_surface_color(rt, 480, 360);
9683 ok(compare_color(color, 0x00ffffff, 2), "Got unexpected color 0x%08x.\n", color);
9685 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
9686 ok(SUCCEEDED(hr), "Failed to set texture transform flags, hr %#x.\n", hr);
9687 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_TEXTURE1, &mat);
9688 ok(SUCCEEDED(hr), "Failed to set transformation matrix, hr %#x.\n", hr);
9690 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
9691 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
9693 hr = IDirect3DDevice7_BeginScene(device);
9694 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9695 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
9696 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9697 hr = IDirect3DDevice7_EndScene(device);
9698 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9700 color = get_surface_color(rt, 160, 120);
9701 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9702 color = get_surface_color(rt, 480, 120);
9703 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
9704 color = get_surface_color(rt, 160, 360);
9705 ok(compare_color(color, 0x00000000, 2), "Got unexpected color 0x%08x.\n", color);
9706 color = get_surface_color(rt, 480, 360);
9707 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
9709 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
9710 ok(SUCCEEDED(hr), "Failed to set texture transform flags, hr %#x.\n", hr);
9711 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXCOORDINDEX, 2);
9712 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
9714 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
9715 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
9717 hr = IDirect3DDevice7_BeginScene(device);
9718 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9719 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
9720 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9721 hr = IDirect3DDevice7_EndScene(device);
9722 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9724 color = get_surface_color(rt, 160, 120);
9725 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
9726 color = get_surface_color(rt, 480, 120);
9727 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
9728 color = get_surface_color(rt, 160, 360);
9729 ok(compare_color(color, 0x00ff00ff, 2), "Got unexpected color 0x%08x.\n", color);
9730 color = get_surface_color(rt, 480, 360);
9731 ok(compare_color(color, 0x00ffff00, 2), "Got unexpected color 0x%08x.\n", color);
9733 IDirectDrawSurface7_Release(texture1);
9734 IDirectDrawSurface7_Release(texture2);
9736 IDirectDrawSurface7_Release(rt);
9737 IDirectDraw_Release(ddraw);
9738 refcount = IDirect3DDevice7_Release(device);
9739 ok(!refcount, "Device has %u references left.\n", refcount);
9740 DestroyWindow(window);
9743 static void test_colorkey_precision(void)
9745 static struct
9747 struct vec3 pos;
9748 struct vec2 texcoord;
9750 quad[] =
9752 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
9753 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
9754 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
9755 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
9757 IDirect3DDevice7 *device;
9758 IDirect3D7 *d3d;
9759 IDirectDraw7 *ddraw;
9760 IDirectDrawSurface7 *rt;
9761 HWND window;
9762 HRESULT hr;
9763 IDirectDrawSurface7 *src, *dst, *texture;
9764 DDSURFACEDESC2 surface_desc, lock_desc;
9765 ULONG refcount;
9766 D3DCOLOR color;
9767 unsigned int t, c;
9768 DDCOLORKEY ckey;
9769 DDBLTFX fx;
9770 DWORD data[4] = {0}, color_mask;
9771 D3DDEVICEDESC7 device_desc;
9772 BOOL warp;
9773 static const struct
9775 unsigned int max, shift, bpp, clear;
9776 const char *name;
9777 DDPIXELFORMAT fmt;
9779 tests[] =
9782 255, 0, 4, 0x00345678, "D3DFMT_X8R8G8B8",
9784 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
9785 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
9790 63, 5, 2, 0x5678, "D3DFMT_R5G6B5, G channel",
9792 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
9793 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
9798 31, 0, 2, 0x5678, "D3DFMT_R5G6B5, B channel",
9800 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
9801 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
9806 15, 0, 2, 0x0678, "D3DFMT_A4R4G4B4",
9808 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9809 {16}, {0x0f00}, {0x00f0}, {0x000f}, {0xf000}
9815 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9816 0, 0, 640, 480, 0, 0, 0, 0);
9817 if (!(device = create_device(window, DDSCL_NORMAL)))
9819 skip("Failed to create a 3D device, skipping test.\n");
9820 DestroyWindow(window);
9821 return;
9824 /* The Windows 8 WARP driver has plenty of false negatives in X8R8G8B8
9825 * (color key doesn't match although the values are equal), and a false
9826 * positive when the color key is 0 and the texture contains the value 1.
9827 * I don't want to mark this broken unconditionally since this would
9828 * essentially disable the test on Windows. Try to detect WARP (and I
9829 * guess mismatch other SW renderers) by its ability to texture from
9830 * system memory. Also on random occasions 254 == 255 and 255 != 255.*/
9831 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
9832 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
9833 warp = !!(device_desc.dwDevCaps & D3DDEVCAPS_TEXTURESYSTEMMEMORY);
9835 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
9836 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
9837 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
9838 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
9839 IDirect3D7_Release(d3d);
9840 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
9841 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9843 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
9844 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
9845 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
9846 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
9847 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
9848 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
9849 /* Multiply the texture read result with 0, that way the result color if the key doesn't
9850 * match is constant. In theory color keying works without reading the texture result
9851 * (meaning we could just op=arg1, arg1=tfactor), but the Geforce7 Windows driver begs
9852 * to differ. */
9853 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
9854 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
9855 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
9856 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
9857 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
9858 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
9859 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x00000000);
9860 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9862 memset(&fx, 0, sizeof(fx));
9863 fx.dwSize = sizeof(fx);
9864 memset(&lock_desc, 0, sizeof(lock_desc));
9865 lock_desc.dwSize = sizeof(lock_desc);
9867 for (t = 0; t < sizeof(tests) / sizeof(*tests); ++t)
9869 memset(&surface_desc, 0, sizeof(surface_desc));
9870 surface_desc.dwSize = sizeof(surface_desc);
9871 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9872 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9873 surface_desc.dwWidth = 4;
9874 surface_desc.dwHeight = 1;
9875 U4(surface_desc).ddpfPixelFormat = tests[t].fmt;
9876 /* Windows XP (at least with the r200 driver, other drivers untested) produces
9877 * garbage when doing color keyed texture->texture blits. */
9878 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
9879 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9880 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
9881 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9883 fx.dwFillColor = tests[t].clear;
9884 /* On the w8 testbot (WARP driver) the blit result has different values in the
9885 * X channel. */
9886 color_mask = U2(tests[t].fmt).dwRBitMask
9887 | U3(tests[t].fmt).dwGBitMask
9888 | U4(tests[t].fmt).dwBBitMask;
9890 for (c = 0; c <= tests[t].max; ++c)
9892 /* The idiotic Nvidia Windows driver can't change the color key on a d3d
9893 * texture after it has been set once... */
9894 surface_desc.dwFlags |= DDSD_CKSRCBLT;
9895 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
9896 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = c << tests[t].shift;
9897 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = c << tests[t].shift;
9898 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
9899 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9900 hr = IDirect3DDevice7_SetTexture(device, 0, texture);
9901 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
9903 hr = IDirectDrawSurface7_Blt(dst, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9904 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
9906 hr = IDirectDrawSurface7_Lock(src, NULL, &lock_desc, DDLOCK_WAIT, NULL);
9907 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
9908 switch (tests[t].bpp)
9910 case 4:
9911 ((DWORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
9912 ((DWORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
9913 ((DWORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
9914 ((DWORD *)lock_desc.lpSurface)[3] = 0xffffffff;
9915 break;
9917 case 2:
9918 ((WORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
9919 ((WORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
9920 ((WORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
9921 ((WORD *)lock_desc.lpSurface)[3] = 0xffff;
9922 break;
9924 hr = IDirectDrawSurface7_Unlock(src, 0);
9925 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9926 hr = IDirectDrawSurface7_Blt(texture, NULL, src, NULL, DDBLT_WAIT, NULL);
9927 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
9929 ckey.dwColorSpaceLowValue = c << tests[t].shift;
9930 ckey.dwColorSpaceHighValue = c << tests[t].shift;
9931 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
9932 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
9934 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_WAIT, NULL);
9935 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
9937 /* Don't make this read only, it somehow breaks the detection of the Nvidia bug below. */
9938 hr = IDirectDrawSurface7_Lock(dst, NULL, &lock_desc, DDLOCK_WAIT, NULL);
9939 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
9940 switch (tests[t].bpp)
9942 case 4:
9943 data[0] = ((DWORD *)lock_desc.lpSurface)[0] & color_mask;
9944 data[1] = ((DWORD *)lock_desc.lpSurface)[1] & color_mask;
9945 data[2] = ((DWORD *)lock_desc.lpSurface)[2] & color_mask;
9946 data[3] = ((DWORD *)lock_desc.lpSurface)[3] & color_mask;
9947 break;
9949 case 2:
9950 data[0] = ((WORD *)lock_desc.lpSurface)[0] & color_mask;
9951 data[1] = ((WORD *)lock_desc.lpSurface)[1] & color_mask;
9952 data[2] = ((WORD *)lock_desc.lpSurface)[2] & color_mask;
9953 data[3] = ((WORD *)lock_desc.lpSurface)[3] & color_mask;
9954 break;
9956 hr = IDirectDrawSurface7_Unlock(dst, 0);
9957 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9959 if (!c)
9961 ok(data[0] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
9962 tests[t].clear, data[0], tests[t].name, c);
9964 if (data[3] == tests[t].clear)
9966 /* My Geforce GTX 460 on Windows 7 misbehaves when A4R4G4B4 is blitted with color
9967 * keying: The blit takes ~0.5 seconds, and subsequent color keying draws are broken,
9968 * even when a different surface is used. The blit itself doesn't draw anything,
9969 * so we can detect the bug by looking at the otherwise unused 4th texel. It should
9970 * never be masked out by the key.
9972 * Also appears to affect the testbot in some way with R5G6B5. Color keying is
9973 * terrible on WARP. */
9974 skip("Nvidia A4R4G4B4 color keying blit bug detected, skipping.\n");
9975 IDirectDrawSurface7_Release(texture);
9976 IDirectDrawSurface7_Release(src);
9977 IDirectDrawSurface7_Release(dst);
9978 goto done;
9981 else
9982 ok(data[0] == (c - 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
9983 (c - 1) << tests[t].shift, data[0], tests[t].name, c);
9985 ok(data[1] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
9986 tests[t].clear, data[1], tests[t].name, c);
9988 if (c == tests[t].max)
9989 ok(data[2] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
9990 tests[t].clear, data[2], tests[t].name, c);
9991 else
9992 ok(data[2] == (c + 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
9993 (c + 1) << tests[t].shift, data[2], tests[t].name, c);
9995 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x0000ff00, 1.0f, 0);
9996 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
9998 hr = IDirect3DDevice7_BeginScene(device);
9999 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10000 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
10001 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10002 hr = IDirect3DDevice7_EndScene(device);
10003 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10005 color = get_surface_color(rt, 80, 240);
10006 if (!c)
10007 ok(compare_color(color, 0x0000ff00, 1) || broken(warp && compare_color(color, 0x00000000, 1)),
10008 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10009 color, tests[t].name, c);
10010 else
10011 ok(compare_color(color, 0x00000000, 1) || broken(warp && compare_color(color, 0x0000ff00, 1)),
10012 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10013 color, tests[t].name, c);
10015 color = get_surface_color(rt, 240, 240);
10016 ok(compare_color(color, 0x0000ff00, 1) || broken(warp && compare_color(color, 0x00000000, 1)),
10017 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10018 color, tests[t].name, c);
10020 color = get_surface_color(rt, 400, 240);
10021 if (c == tests[t].max)
10022 ok(compare_color(color, 0x0000ff00, 1) || broken(warp && compare_color(color, 0x00000000, 1)),
10023 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10024 color, tests[t].name, c);
10025 else
10026 ok(compare_color(color, 0x00000000, 1) || broken(warp && compare_color(color, 0x0000ff00, 1)),
10027 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10028 color, tests[t].name, c);
10030 IDirectDrawSurface7_Release(texture);
10032 IDirectDrawSurface7_Release(src);
10033 IDirectDrawSurface7_Release(dst);
10035 done:
10037 IDirectDrawSurface7_Release(rt);
10038 IDirectDraw7_Release(ddraw);
10039 refcount = IDirect3DDevice7_Release(device);
10040 ok(!refcount, "Device has %u references left.\n", refcount);
10041 DestroyWindow(window);
10044 static void test_range_colorkey(void)
10046 IDirectDraw7 *ddraw;
10047 HWND window;
10048 HRESULT hr;
10049 IDirectDrawSurface7 *surface;
10050 DDSURFACEDESC2 surface_desc;
10051 ULONG refcount;
10052 DDCOLORKEY ckey;
10054 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
10055 0, 0, 640, 480, 0, 0, 0, 0);
10056 ddraw = create_ddraw();
10057 ok(!!ddraw, "Failed to create a ddraw object.\n");
10058 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10059 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
10061 memset(&surface_desc, 0, sizeof(surface_desc));
10062 surface_desc.dwSize = sizeof(surface_desc);
10063 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
10064 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
10065 surface_desc.dwWidth = 1;
10066 surface_desc.dwHeight = 1;
10067 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
10068 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
10069 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
10070 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
10071 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
10072 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0x00000000;
10074 /* Creating a surface with a range color key fails with DDERR_NOCOLORKEY. */
10075 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
10076 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
10077 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10078 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10080 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
10081 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
10082 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10083 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10085 /* Same for DDSCAPS_OFFSCREENPLAIN. */
10086 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10087 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
10088 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
10089 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10090 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10092 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
10093 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
10094 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10095 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10097 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
10098 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
10099 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10100 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10102 /* Setting a range color key without DDCKEY_COLORSPACE collapses the key. */
10103 ckey.dwColorSpaceLowValue = 0x00000000;
10104 ckey.dwColorSpaceHighValue = 0x00000001;
10105 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10106 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10108 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10109 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
10110 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
10111 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
10113 ckey.dwColorSpaceLowValue = 0x00000001;
10114 ckey.dwColorSpaceHighValue = 0x00000000;
10115 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10116 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10118 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10119 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
10120 ok(ckey.dwColorSpaceLowValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
10121 ok(ckey.dwColorSpaceHighValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
10123 /* DDCKEY_COLORSPACE is ignored if the key is a single value. */
10124 ckey.dwColorSpaceLowValue = 0x00000000;
10125 ckey.dwColorSpaceHighValue = 0x00000000;
10126 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10127 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10129 /* Using it with a range key results in DDERR_NOCOLORKEYHW. */
10130 ckey.dwColorSpaceLowValue = 0x00000001;
10131 ckey.dwColorSpaceHighValue = 0x00000000;
10132 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10133 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10134 ckey.dwColorSpaceLowValue = 0x00000000;
10135 ckey.dwColorSpaceHighValue = 0x00000001;
10136 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10137 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10138 /* Range destination keys don't work either. */
10139 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_DESTBLT | DDCKEY_COLORSPACE, &ckey);
10140 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10142 /* Just to show it's not because of A, R, and G having equal values. */
10143 ckey.dwColorSpaceLowValue = 0x00000000;
10144 ckey.dwColorSpaceHighValue = 0x01010101;
10145 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10146 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10148 /* None of these operations modified the key. */
10149 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10150 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
10151 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
10152 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
10154 IDirectDrawSurface7_Release(surface),
10155 refcount = IDirectDraw7_Release(ddraw);
10156 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
10157 DestroyWindow(window);
10160 START_TEST(ddraw7)
10162 HMODULE module = GetModuleHandleA("ddraw.dll");
10163 IDirectDraw7 *ddraw;
10164 DEVMODEW current_mode;
10166 if (!(pDirectDrawCreateEx = (void *)GetProcAddress(module, "DirectDrawCreateEx")))
10168 win_skip("DirectDrawCreateEx not available, skipping tests.\n");
10169 return;
10172 if (!(ddraw = create_ddraw()))
10174 skip("Failed to create a ddraw object, skipping tests.\n");
10175 return;
10177 IDirectDraw7_Release(ddraw);
10179 memset(&current_mode, 0, sizeof(current_mode));
10180 current_mode.dmSize = sizeof(current_mode);
10181 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
10182 registry_mode.dmSize = sizeof(registry_mode);
10183 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
10184 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
10185 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
10187 skip("Current mode does not match registry mode, skipping test.\n");
10188 return;
10191 test_process_vertices();
10192 test_coop_level_create_device_window();
10193 test_clipper_blt();
10194 test_coop_level_d3d_state();
10195 test_surface_interface_mismatch();
10196 test_coop_level_threaded();
10197 test_depth_blit();
10198 test_texture_load_ckey();
10199 test_zenable();
10200 test_ck_rgba();
10201 test_ck_default();
10202 test_ck_complex();
10203 test_surface_qi();
10204 test_device_qi();
10205 test_wndproc();
10206 test_window_style();
10207 test_redundant_mode_set();
10208 test_coop_level_mode_set();
10209 test_coop_level_mode_set_multi();
10210 test_initialize();
10211 test_coop_level_surf_create();
10212 test_vb_discard();
10213 test_coop_level_multi_window();
10214 test_draw_strided();
10215 test_lighting();
10216 test_specular_lighting();
10217 test_clear_rect_count();
10218 test_coop_level_versions();
10219 test_fog_special();
10220 test_lighting_interface_versions();
10221 test_coop_level_activateapp();
10222 test_texturemanage();
10223 test_block_formats_creation();
10224 test_unsupported_formats();
10225 test_rt_caps();
10226 test_primary_caps();
10227 test_surface_lock();
10228 test_surface_discard();
10229 test_flip();
10230 test_set_surface_desc();
10231 test_user_memory_getdc();
10232 test_sysmem_overlay();
10233 test_primary_palette();
10234 test_surface_attachment();
10235 test_private_data();
10236 test_pixel_format();
10237 test_create_surface_pitch();
10238 test_mipmap_lock();
10239 test_palette_complex();
10240 test_p8_rgb_blit();
10241 test_material();
10242 test_palette_gdi();
10243 test_palette_alpha();
10244 test_vb_writeonly();
10245 test_lost_device();
10246 test_resource_priority();
10247 test_surface_desc_lock();
10248 test_fog_interpolation();
10249 test_negative_fixedfunction_fog();
10250 test_table_fog_zw();
10251 test_signed_formats();
10252 test_color_fill();
10253 test_texcoordindex();
10254 test_colorkey_precision();
10255 test_range_colorkey();