ddraw/tests: Rewrite yv12_test().
[wine.git] / dlls / ddraw / tests / ddraw7.c
blob9b5c698d42c54e76109ddf2dcd29695ffcdc0376
1 /*
2 * Copyright 2005 Antoine Chavasse (a.chavasse@gmail.com)
3 * Copyright 2006, 2008, 2011, 2012-2014 Stefan Dösinger for CodeWeavers
4 * Copyright 2011-2014 Henri Verbeet for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #define COBJMACROS
22 #include "wine/test.h"
23 #include <limits.h>
24 #include <math.h>
25 #include "d3d.h"
27 static HRESULT (WINAPI *pDirectDrawCreateEx)(GUID *guid, void **ddraw, REFIID iid, IUnknown *outer_unknown);
28 static BOOL is_ddraw64 = sizeof(DWORD) != sizeof(DWORD *);
29 static DEVMODEW registry_mode;
31 struct vec2
33 float x, y;
36 struct vec3
38 float x, y, z;
41 struct vec4
43 float x, y, z, w;
46 struct create_window_thread_param
48 HWND window;
49 HANDLE window_created;
50 HANDLE destroy_window;
51 HANDLE thread;
54 static BOOL compare_float(float f, float g, unsigned int ulps)
56 int x = *(int *)&f;
57 int y = *(int *)&g;
59 if (x < 0)
60 x = INT_MIN - x;
61 if (y < 0)
62 y = INT_MIN - y;
64 if (abs(x - y) > ulps)
65 return FALSE;
67 return TRUE;
70 static BOOL compare_vec3(struct vec3 *vec, float x, float y, float z, unsigned int ulps)
72 return compare_float(vec->x, x, ulps)
73 && compare_float(vec->y, y, ulps)
74 && compare_float(vec->z, z, ulps);
77 static BOOL compare_vec4(struct vec4 *vec, float x, float y, float z, float w, unsigned int ulps)
79 return compare_float(vec->x, x, ulps)
80 && compare_float(vec->y, y, ulps)
81 && compare_float(vec->z, z, ulps)
82 && compare_float(vec->w, w, ulps);
85 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
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 c1 >>= 8; c2 >>= 8;
93 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
94 return TRUE;
97 static ULONG get_refcount(IUnknown *iface)
99 IUnknown_AddRef(iface);
100 return IUnknown_Release(iface);
103 static IDirectDrawSurface7 *create_overlay(IDirectDraw7 *ddraw,
104 unsigned int width, unsigned int height, DWORD format)
106 IDirectDrawSurface7 *surface;
107 DDSURFACEDESC2 desc;
109 memset(&desc, 0, sizeof(desc));
110 desc.dwSize = sizeof(desc);
111 desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
112 desc.dwWidth = width;
113 desc.dwHeight = height;
114 desc.ddsCaps.dwCaps = DDSCAPS_OVERLAY;
115 U4(desc).ddpfPixelFormat.dwSize = sizeof(U4(desc).ddpfPixelFormat);
116 U4(desc).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
117 U4(desc).ddpfPixelFormat.dwFourCC = format;
119 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &desc, &surface, NULL)))
120 return NULL;
121 return surface;
124 static DWORD WINAPI create_window_thread_proc(void *param)
126 struct create_window_thread_param *p = param;
127 DWORD res;
128 BOOL ret;
130 p->window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
131 0, 0, 640, 480, 0, 0, 0, 0);
132 ret = SetEvent(p->window_created);
133 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
135 for (;;)
137 MSG msg;
139 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
140 DispatchMessageA(&msg);
141 res = WaitForSingleObject(p->destroy_window, 100);
142 if (res == WAIT_OBJECT_0)
143 break;
144 if (res != WAIT_TIMEOUT)
146 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
147 break;
151 DestroyWindow(p->window);
153 return 0;
156 static void create_window_thread(struct create_window_thread_param *p)
158 DWORD res, tid;
160 p->window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
161 ok(!!p->window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
162 p->destroy_window = CreateEventA(NULL, FALSE, FALSE, NULL);
163 ok(!!p->destroy_window, "CreateEvent failed, last error %#x.\n", GetLastError());
164 p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
165 ok(!!p->thread, "Failed to create thread, last error %#x.\n", GetLastError());
166 res = WaitForSingleObject(p->window_created, INFINITE);
167 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
170 static void destroy_window_thread(struct create_window_thread_param *p)
172 SetEvent(p->destroy_window);
173 WaitForSingleObject(p->thread, INFINITE);
174 CloseHandle(p->destroy_window);
175 CloseHandle(p->window_created);
176 CloseHandle(p->thread);
179 static IDirectDrawSurface7 *get_depth_stencil(IDirect3DDevice7 *device)
181 IDirectDrawSurface7 *rt, *ret;
182 DDSCAPS2 caps = {DDSCAPS_ZBUFFER, 0, 0, {0}};
183 HRESULT hr;
185 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
186 ok(SUCCEEDED(hr), "Failed to get the render target, hr %#x.\n", hr);
187 hr = IDirectDrawSurface7_GetAttachedSurface(rt, &caps, &ret);
188 ok(SUCCEEDED(hr) || hr == DDERR_NOTFOUND, "Failed to get the z buffer, hr %#x.\n", hr);
189 IDirectDrawSurface7_Release(rt);
190 return ret;
193 static HRESULT set_display_mode(IDirectDraw7 *ddraw, DWORD width, DWORD height)
195 if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
196 return DD_OK;
197 return IDirectDraw7_SetDisplayMode(ddraw, width, height, 24, 0, 0);
200 static D3DCOLOR get_surface_color(IDirectDrawSurface7 *surface, UINT x, UINT y)
202 RECT rect = {x, y, x + 1, y + 1};
203 DDSURFACEDESC2 surface_desc;
204 D3DCOLOR color;
205 HRESULT hr;
207 memset(&surface_desc, 0, sizeof(surface_desc));
208 surface_desc.dwSize = sizeof(surface_desc);
210 hr = IDirectDrawSurface7_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY, NULL);
211 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
212 if (FAILED(hr))
213 return 0xdeadbeef;
215 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
217 hr = IDirectDrawSurface7_Unlock(surface, &rect);
218 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
220 return color;
223 static HRESULT CALLBACK enum_z_fmt(DDPIXELFORMAT *format, void *ctx)
225 DDPIXELFORMAT *z_fmt = ctx;
227 if (U1(*format).dwZBufferBitDepth > U1(*z_fmt).dwZBufferBitDepth)
228 *z_fmt = *format;
230 return DDENUMRET_OK;
233 static IDirectDraw7 *create_ddraw(void)
235 IDirectDraw7 *ddraw;
237 if (FAILED(pDirectDrawCreateEx(NULL, (void **)&ddraw, &IID_IDirectDraw7, NULL)))
238 return NULL;
240 return ddraw;
243 static HRESULT WINAPI enum_devtype_cb(char *desc_str, char *name, D3DDEVICEDESC7 *desc, void *ctx)
245 BOOL *hal_ok = ctx;
246 if (IsEqualGUID(&desc->deviceGUID, &IID_IDirect3DTnLHalDevice))
248 *hal_ok = TRUE;
249 return DDENUMRET_CANCEL;
251 return DDENUMRET_OK;
254 static IDirect3DDevice7 *create_device(HWND window, DWORD coop_level)
256 IDirectDrawSurface7 *surface, *ds;
257 IDirect3DDevice7 *device = NULL;
258 DDSURFACEDESC2 surface_desc;
259 DDPIXELFORMAT z_fmt;
260 IDirectDraw7 *ddraw;
261 IDirect3D7 *d3d7;
262 HRESULT hr;
263 BOOL hal_ok = FALSE;
264 const GUID *devtype = &IID_IDirect3DHALDevice;
266 if (!(ddraw = create_ddraw()))
267 return NULL;
269 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, coop_level);
270 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
272 memset(&surface_desc, 0, sizeof(surface_desc));
273 surface_desc.dwSize = sizeof(surface_desc);
274 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
275 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
276 surface_desc.dwWidth = 640;
277 surface_desc.dwHeight = 480;
279 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
280 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
282 if (coop_level & DDSCL_NORMAL)
284 IDirectDrawClipper *clipper;
286 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
287 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
288 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
289 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
290 hr = IDirectDrawSurface7_SetClipper(surface, clipper);
291 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\n", hr);
292 IDirectDrawClipper_Release(clipper);
295 hr = IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d7);
296 IDirectDraw7_Release(ddraw);
297 if (FAILED(hr))
299 IDirectDrawSurface7_Release(surface);
300 return NULL;
303 hr = IDirect3D7_EnumDevices(d3d7, enum_devtype_cb, &hal_ok);
304 ok(SUCCEEDED(hr), "Failed to enumerate devices, hr %#x.\n", hr);
305 if (hal_ok) devtype = &IID_IDirect3DTnLHalDevice;
307 memset(&z_fmt, 0, sizeof(z_fmt));
308 hr = IDirect3D7_EnumZBufferFormats(d3d7, devtype, enum_z_fmt, &z_fmt);
309 if (FAILED(hr) || !z_fmt.dwSize)
311 IDirect3D7_Release(d3d7);
312 IDirectDrawSurface7_Release(surface);
313 return NULL;
316 memset(&surface_desc, 0, sizeof(surface_desc));
317 surface_desc.dwSize = sizeof(surface_desc);
318 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
319 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
320 U4(surface_desc).ddpfPixelFormat = z_fmt;
321 surface_desc.dwWidth = 640;
322 surface_desc.dwHeight = 480;
323 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL);
324 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
325 if (FAILED(hr))
327 IDirect3D7_Release(d3d7);
328 IDirectDrawSurface7_Release(surface);
329 return NULL;
332 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
333 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
334 IDirectDrawSurface7_Release(ds);
335 if (FAILED(hr))
337 IDirect3D7_Release(d3d7);
338 IDirectDrawSurface7_Release(surface);
339 return NULL;
342 hr = IDirect3D7_CreateDevice(d3d7, devtype, surface, &device);
343 IDirect3D7_Release(d3d7);
344 IDirectDrawSurface7_Release(surface);
345 if (FAILED(hr))
346 return NULL;
348 return device;
351 struct message
353 UINT message;
354 BOOL check_wparam;
355 WPARAM expect_wparam;
358 static const struct message *expect_messages;
360 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
362 if (expect_messages && message == expect_messages->message)
364 if (expect_messages->check_wparam)
365 ok (wparam == expect_messages->expect_wparam,
366 "Got unexpected wparam %lx for message %x, expected %lx.\n",
367 wparam, message, expect_messages->expect_wparam);
369 ++expect_messages;
372 return DefWindowProcA(hwnd, message, wparam, lparam);
375 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
376 * interface. This prevents subsequent SetCooperativeLevel() calls on a
377 * different window from failing with DDERR_HWNDALREADYSET. */
378 static void fix_wndproc(HWND window, LONG_PTR proc)
380 IDirectDraw7 *ddraw;
381 HRESULT hr;
383 if (!(ddraw = create_ddraw()))
384 return;
386 SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
387 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
388 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
389 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
390 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
392 IDirectDraw7_Release(ddraw);
395 static void test_process_vertices(void)
397 IDirect3DVertexBuffer7 *src_vb, *dst_vb1, *dst_vb2;
398 D3DVERTEXBUFFERDESC vb_desc;
399 IDirect3DDevice7 *device;
400 struct vec4 *dst_data;
401 struct vec3 *dst_data2;
402 struct vec3 *src_data;
403 IDirect3D7 *d3d7;
404 D3DVIEWPORT7 vp;
405 HWND window;
406 HRESULT hr;
408 static D3DMATRIX world =
410 0.0f, 1.0f, 0.0f, 0.0f,
411 1.0f, 0.0f, 0.0f, 0.0f,
412 0.0f, 0.0f, 0.0f, 1.0f,
413 0.0f, 1.0f, 1.0f, 1.0f,
415 static D3DMATRIX view =
417 2.0f, 0.0f, 0.0f, 0.0f,
418 0.0f, -1.0f, 0.0f, 0.0f,
419 0.0f, 0.0f, 1.0f, 0.0f,
420 0.0f, 0.0f, 0.0f, 3.0f,
422 static D3DMATRIX proj =
424 1.0f, 0.0f, 0.0f, 1.0f,
425 0.0f, 1.0f, 1.0f, 0.0f,
426 0.0f, 1.0f, 1.0f, 0.0f,
427 1.0f, 0.0f, 0.0f, 1.0f,
430 window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
431 0, 0, 640, 480, 0, 0, 0, 0);
432 if (!(device = create_device(window, DDSCL_NORMAL)))
434 skip("Failed to create a 3D device, skipping test.\n");
435 DestroyWindow(window);
436 return;
439 hr = IDirect3DDevice7_GetDirect3D(device, &d3d7);
440 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
442 memset(&vb_desc, 0, sizeof(vb_desc));
443 vb_desc.dwSize = sizeof(vb_desc);
444 vb_desc.dwFVF = D3DFVF_XYZ;
445 vb_desc.dwNumVertices = 4;
446 hr = IDirect3D7_CreateVertexBuffer(d3d7, &vb_desc, &src_vb, 0);
447 ok(SUCCEEDED(hr), "Failed to create source vertex buffer, hr %#x.\n", hr);
449 hr = IDirect3DVertexBuffer7_Lock(src_vb, 0, (void **)&src_data, NULL);
450 ok(SUCCEEDED(hr), "Failed to lock source vertex buffer, hr %#x.\n", hr);
451 src_data[0].x = 0.0f;
452 src_data[0].y = 0.0f;
453 src_data[0].z = 0.0f;
454 src_data[1].x = 1.0f;
455 src_data[1].y = 1.0f;
456 src_data[1].z = 1.0f;
457 src_data[2].x = -1.0f;
458 src_data[2].y = -1.0f;
459 src_data[2].z = 0.5f;
460 src_data[3].x = 0.5f;
461 src_data[3].y = -0.5f;
462 src_data[3].z = 0.25f;
463 hr = IDirect3DVertexBuffer7_Unlock(src_vb);
464 ok(SUCCEEDED(hr), "Failed to unlock source vertex buffer, hr %#x.\n", hr);
466 memset(&vb_desc, 0, sizeof(vb_desc));
467 vb_desc.dwSize = sizeof(vb_desc);
468 vb_desc.dwFVF = D3DFVF_XYZRHW;
469 vb_desc.dwNumVertices = 4;
470 /* MSDN says that the last parameter must be 0 - check that. */
471 hr = IDirect3D7_CreateVertexBuffer(d3d7, &vb_desc, &dst_vb1, 4);
472 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
474 memset(&vb_desc, 0, sizeof(vb_desc));
475 vb_desc.dwSize = sizeof(vb_desc);
476 vb_desc.dwFVF = D3DFVF_XYZ;
477 vb_desc.dwNumVertices = 5;
478 /* MSDN says that the last parameter must be 0 - check that. */
479 hr = IDirect3D7_CreateVertexBuffer(d3d7, &vb_desc, &dst_vb2, 12345678);
480 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
482 memset(&vp, 0, sizeof(vp));
483 vp.dwX = 64;
484 vp.dwY = 64;
485 vp.dwWidth = 128;
486 vp.dwHeight = 128;
487 vp.dvMinZ = 0.0f;
488 vp.dvMaxZ = 1.0f;
489 hr = IDirect3DDevice7_SetViewport(device, &vp);
490 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
492 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
493 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
494 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb2, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
495 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
497 hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
498 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
499 ok(compare_vec4(&dst_data[0], +1.280e+2f, +1.280e+2f, +0.000e+0f, +1.000e+0f, 4096),
500 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
501 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
502 ok(compare_vec4(&dst_data[1], +1.920e+2f, +6.400e+1f, +1.000e+0f, +1.000e+0f, 4096),
503 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
504 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
505 ok(compare_vec4(&dst_data[2], +6.400e+1f, +1.920e+2f, +5.000e-1f, +1.000e+0f, 4096),
506 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
507 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
508 ok(compare_vec4(&dst_data[3], +1.600e+2f, +1.600e+2f, +2.500e-1f, +1.000e+0f, 4096),
509 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
510 dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
511 hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
512 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
514 hr = IDirect3DVertexBuffer7_Lock(dst_vb2, 0, (void **)&dst_data2, NULL);
515 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
516 /* Small thing without much practical meaning, but I stumbled upon it,
517 * so let's check for it: If the output vertex buffer has no RHW value,
518 * the RHW value of the last vertex is written into the next vertex. */
519 ok(compare_vec3(&dst_data2[4], +1.000e+0f, +0.000e+0f, +0.000e+0f, 4096),
520 "Got unexpected vertex 4 {%.8e, %.8e, %.8e}.\n",
521 dst_data2[4].x, dst_data2[4].y, dst_data2[4].z);
522 hr = IDirect3DVertexBuffer7_Unlock(dst_vb2);
523 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
525 /* Try a more complicated viewport, same vertices. */
526 memset(&vp, 0, sizeof(vp));
527 vp.dwX = 10;
528 vp.dwY = 5;
529 vp.dwWidth = 246;
530 vp.dwHeight = 130;
531 vp.dvMinZ = -2.0f;
532 vp.dvMaxZ = 4.0f;
533 hr = IDirect3DDevice7_SetViewport(device, &vp);
534 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
536 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
537 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
539 hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
540 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
541 ok(compare_vec4(&dst_data[0], +1.330e+2f, +7.000e+1f, -2.000e+0f, +1.000e+0f, 4096),
542 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
543 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
544 ok(compare_vec4(&dst_data[1], +2.560e+2f, +5.000e+0f, +4.000e+0f, +1.000e+0f, 4096),
545 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
546 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
547 ok(compare_vec4(&dst_data[2], +1.000e+1f, +1.350e+2f, +1.000e+0f, +1.000e+0f, 4096),
548 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
549 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
550 ok(compare_vec4(&dst_data[3], +1.945e+2f, +1.025e+2f, -5.000e-1f, +1.000e+0f, 4096),
551 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
552 dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
553 hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
554 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
556 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &world);
557 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
558 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &view);
559 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
560 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &proj);
561 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
563 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
564 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
566 hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
567 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
568 ok(compare_vec4(&dst_data[0], +2.560e+2f, +7.000e+1f, -2.000e+0f, +3.333e-1f, 4096),
569 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
570 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
571 ok(compare_vec4(&dst_data[1], +2.560e+2f, +7.813e+1f, -2.750e+0f, +1.250e-1f, 4096),
572 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
573 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
574 ok(compare_vec4(&dst_data[2], +2.560e+2f, +4.400e+1f, +4.000e-1f, +4.000e-1f, 4096),
575 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
576 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
577 ok(compare_vec4(&dst_data[3], +2.560e+2f, +8.182e+1f, -3.091e+0f, +3.636e-1f, 4096),
578 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
579 dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
580 hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
581 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
583 IDirect3DVertexBuffer7_Release(dst_vb2);
584 IDirect3DVertexBuffer7_Release(dst_vb1);
585 IDirect3DVertexBuffer7_Release(src_vb);
586 IDirect3D7_Release(d3d7);
587 IDirect3DDevice7_Release(device);
588 DestroyWindow(window);
591 static void test_coop_level_create_device_window(void)
593 HWND focus_window, device_window;
594 IDirectDraw7 *ddraw;
595 HRESULT hr;
597 focus_window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
598 0, 0, 640, 480, 0, 0, 0, 0);
599 ddraw = create_ddraw();
600 ok(!!ddraw, "Failed to create a ddraw object.\n");
602 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
603 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
604 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
605 ok(!device_window, "Unexpected device window found.\n");
606 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
607 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
608 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
609 ok(!device_window, "Unexpected device window found.\n");
610 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
611 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
612 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
613 ok(!device_window, "Unexpected device window found.\n");
614 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
615 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
616 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
617 ok(!device_window, "Unexpected device window found.\n");
618 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
619 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
620 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
621 ok(!device_window, "Unexpected device window found.\n");
623 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
624 if (broken(hr == DDERR_INVALIDPARAMS))
626 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
627 IDirectDraw7_Release(ddraw);
628 DestroyWindow(focus_window);
629 return;
632 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
633 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
634 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
635 ok(!device_window, "Unexpected device window found.\n");
636 hr = IDirectDraw7_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
637 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
638 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
639 ok(!device_window, "Unexpected device window found.\n");
641 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
642 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
643 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
644 ok(!device_window, "Unexpected device window found.\n");
645 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
646 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
647 ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
648 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
649 ok(!!device_window, "Device window not found.\n");
651 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
652 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
653 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
654 ok(!device_window, "Unexpected device window found.\n");
655 hr = IDirectDraw7_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
656 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
657 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
658 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
659 ok(!!device_window, "Device window not found.\n");
661 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
662 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
663 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
664 ok(!device_window, "Unexpected device window found.\n");
665 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
666 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
667 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
668 ok(!device_window, "Unexpected device window found.\n");
669 hr = IDirectDraw7_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
670 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
671 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
672 ok(!device_window, "Unexpected device window found.\n");
673 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
674 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
675 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
676 ok(!!device_window, "Device window not found.\n");
678 IDirectDraw7_Release(ddraw);
679 DestroyWindow(focus_window);
682 static void test_clipper_blt(void)
684 IDirectDrawSurface7 *src_surface, *dst_surface;
685 RECT client_rect, src_rect;
686 IDirectDrawClipper *clipper;
687 DDSURFACEDESC2 surface_desc;
688 unsigned int i, j, x, y;
689 IDirectDraw7 *ddraw;
690 RGNDATA *rgn_data;
691 D3DCOLOR color;
692 ULONG refcount;
693 HRGN r1, r2;
694 HWND window;
695 DDBLTFX fx;
696 HRESULT hr;
697 DWORD *ptr;
698 DWORD ret;
700 static const DWORD src_data[] =
702 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
703 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
704 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
706 static const D3DCOLOR expected1[] =
708 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
709 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
710 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
711 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
713 /* Nvidia on Windows seems to have an off-by-one error
714 * when processing source rectangles. Our left = 1 and
715 * right = 5 input reads from x = {1, 2, 3}. x = 4 is
716 * read as well, but only for the edge pixels on the
717 * output image. The bug happens on the y axis as well,
718 * but we only read one row there, and all source rows
719 * contain the same data. This bug is not dependent on
720 * the presence of a clipper. */
721 static const D3DCOLOR expected1_broken[] =
723 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
724 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
725 0x00000000, 0x00000000, 0x00ff0000, 0x00ff0000,
726 0x00000000, 0x00000000, 0x0000ff00, 0x00ff0000,
728 static const D3DCOLOR expected2[] =
730 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
731 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
732 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
733 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
736 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
737 10, 10, 640, 480, 0, 0, 0, 0);
738 ShowWindow(window, SW_SHOW);
739 ddraw = create_ddraw();
740 ok(!!ddraw, "Failed to create a ddraw object.\n");
742 ret = GetClientRect(window, &client_rect);
743 ok(ret, "Failed to get client rect.\n");
744 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
745 ok(ret, "Failed to map client rect.\n");
747 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
748 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
750 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
751 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
752 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
753 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
754 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
755 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
756 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
757 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
758 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
759 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
760 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
761 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
762 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
763 ok(rgn_data->rdh.nCount >= 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
764 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
765 "Got unexpected bounding rect {%d, %d, %d, %d}, expected {%d, %d, %d, %d}.\n",
766 rgn_data->rdh.rcBound.left, rgn_data->rdh.rcBound.top,
767 rgn_data->rdh.rcBound.right, rgn_data->rdh.rcBound.bottom,
768 client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
769 HeapFree(GetProcessHeap(), 0, rgn_data);
771 r1 = CreateRectRgn(0, 0, 320, 240);
772 ok(!!r1, "Failed to create region.\n");
773 r2 = CreateRectRgn(320, 240, 640, 480);
774 ok(!!r2, "Failed to create region.\n");
775 CombineRgn(r1, r1, r2, RGN_OR);
776 ret = GetRegionData(r1, 0, NULL);
777 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
778 ret = GetRegionData(r1, ret, rgn_data);
779 ok(!!ret, "Failed to get region data.\n");
781 DeleteObject(r2);
782 DeleteObject(r1);
784 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
785 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
786 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
787 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
788 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
789 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
791 HeapFree(GetProcessHeap(), 0, rgn_data);
793 memset(&surface_desc, 0, sizeof(surface_desc));
794 surface_desc.dwSize = sizeof(surface_desc);
795 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
796 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
797 surface_desc.dwWidth = 640;
798 surface_desc.dwHeight = 480;
799 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
800 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
801 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
802 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
803 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
804 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
806 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
807 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
808 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
809 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
811 memset(&fx, 0, sizeof(fx));
812 fx.dwSize = sizeof(fx);
813 hr = IDirectDrawSurface7_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
814 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
815 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
816 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
818 hr = IDirectDrawSurface7_Lock(src_surface, NULL, &surface_desc, 0, NULL);
819 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
820 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
821 ptr = surface_desc.lpSurface;
822 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
823 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
824 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
825 hr = IDirectDrawSurface7_Unlock(src_surface, NULL);
826 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
828 hr = IDirectDrawSurface7_SetClipper(dst_surface, clipper);
829 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
831 SetRect(&src_rect, 1, 1, 5, 2);
832 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
833 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
834 for (i = 0; i < 4; ++i)
836 for (j = 0; j < 4; ++j)
838 x = 80 * ((2 * j) + 1);
839 y = 60 * ((2 * i) + 1);
840 color = get_surface_color(dst_surface, x, y);
841 ok(compare_color(color, expected1[i * 4 + j], 1)
842 || broken(compare_color(color, expected1_broken[i * 4 + j], 1)),
843 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
847 U5(fx).dwFillColor = 0xff0000ff;
848 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
849 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
850 for (i = 0; i < 4; ++i)
852 for (j = 0; j < 4; ++j)
854 x = 80 * ((2 * j) + 1);
855 y = 60 * ((2 * i) + 1);
856 color = get_surface_color(dst_surface, x, y);
857 ok(compare_color(color, expected2[i * 4 + j], 1),
858 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
862 hr = IDirectDrawSurface7_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
863 ok(hr == DDERR_BLTFASTCANTCLIP, "Got unexpected hr %#x.\n", hr);
865 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
866 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
867 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
868 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
869 DestroyWindow(window);
870 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
871 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
872 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
873 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
874 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
875 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
876 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
877 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
878 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
879 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
880 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
881 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
883 IDirectDrawSurface7_Release(dst_surface);
884 IDirectDrawSurface7_Release(src_surface);
885 refcount = IDirectDrawClipper_Release(clipper);
886 ok(!refcount, "Clipper has %u references left.\n", refcount);
887 IDirectDraw7_Release(ddraw);
890 static void test_coop_level_d3d_state(void)
892 IDirectDrawSurface7 *rt, *surface;
893 IDirect3DDevice7 *device;
894 IDirectDraw7 *ddraw;
895 IDirect3D7 *d3d;
896 D3DCOLOR color;
897 DWORD value;
898 HWND window;
899 HRESULT hr;
901 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
902 0, 0, 640, 480, 0, 0, 0, 0);
903 if (!(device = create_device(window, DDSCL_NORMAL)))
905 skip("Failed to create a 3D device, skipping test.\n");
906 DestroyWindow(window);
907 return;
910 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
911 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
912 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
913 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
914 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
915 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
916 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
917 ok(!value, "Got unexpected alpha blend enable state %#x.\n", value);
918 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
919 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
920 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
921 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
922 color = get_surface_color(rt, 320, 240);
923 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
925 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
926 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
927 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
928 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
929 IDirect3D7_Release(d3d);
930 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
931 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
932 hr = IDirectDrawSurface7_IsLost(rt);
933 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
934 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
935 ok(SUCCEEDED(hr), "Failed to restore surfaces, hr %#x.\n", hr);
936 IDirectDraw7_Release(ddraw);
938 hr = IDirect3DDevice7_GetRenderTarget(device, &surface);
939 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
940 ok(surface == rt, "Got unexpected surface %p.\n", surface);
941 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
942 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
943 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
944 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
945 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
946 ok(!!value, "Got unexpected alpha blend enable state %#x.\n", value);
947 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
948 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
949 color = get_surface_color(rt, 320, 240);
950 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
952 IDirectDrawSurface7_Release(surface);
953 IDirectDrawSurface7_Release(rt);
954 IDirect3DDevice7_Release(device);
955 DestroyWindow(window);
958 static void test_surface_interface_mismatch(void)
960 IDirectDraw7 *ddraw = NULL;
961 IDirect3D7 *d3d = NULL;
962 IDirectDrawSurface7 *surface = NULL, *ds;
963 IDirectDrawSurface3 *surface3 = NULL;
964 IDirect3DDevice7 *device = NULL;
965 DDSURFACEDESC2 surface_desc;
966 DDPIXELFORMAT z_fmt;
967 ULONG refcount;
968 HRESULT hr;
969 D3DCOLOR color;
970 HWND window;
972 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
973 0, 0, 640, 480, 0, 0, 0, 0);
974 ddraw = create_ddraw();
975 ok(!!ddraw, "Failed to create a ddraw object.\n");
976 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
977 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
979 memset(&surface_desc, 0, sizeof(surface_desc));
980 surface_desc.dwSize = sizeof(surface_desc);
981 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
982 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
983 surface_desc.dwWidth = 640;
984 surface_desc.dwHeight = 480;
986 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
987 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
989 hr = IDirectDrawSurface7_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
990 ok(SUCCEEDED(hr), "Failed to QI IDirectDrawSurface3, hr %#x.\n", hr);
992 if (FAILED(IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d)))
994 skip("D3D interface is not available, skipping test.\n");
995 goto cleanup;
998 memset(&z_fmt, 0, sizeof(z_fmt));
999 hr = IDirect3D7_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
1000 if (FAILED(hr) || !z_fmt.dwSize)
1002 skip("No depth buffer formats available, skipping test.\n");
1003 goto cleanup;
1006 memset(&surface_desc, 0, sizeof(surface_desc));
1007 surface_desc.dwSize = sizeof(surface_desc);
1008 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
1009 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1010 U4(surface_desc).ddpfPixelFormat = z_fmt;
1011 surface_desc.dwWidth = 640;
1012 surface_desc.dwHeight = 480;
1013 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL);
1014 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
1015 if (FAILED(hr))
1016 goto cleanup;
1018 /* Using a different surface interface version still works */
1019 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
1020 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
1021 refcount = IDirectDrawSurface7_Release(ds);
1022 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
1023 if (FAILED(hr))
1024 goto cleanup;
1026 /* Here too */
1027 hr = IDirect3D7_CreateDevice(d3d, &IID_IDirect3DHALDevice, (IDirectDrawSurface7 *)surface3, &device);
1028 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
1029 if (FAILED(hr))
1030 goto cleanup;
1032 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
1033 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1034 color = get_surface_color(surface, 320, 240);
1035 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1037 cleanup:
1038 if (surface3) IDirectDrawSurface3_Release(surface3);
1039 if (surface) IDirectDrawSurface7_Release(surface);
1040 if (device) IDirect3DDevice7_Release(device);
1041 if (d3d) IDirect3D7_Release(d3d);
1042 if (ddraw) IDirectDraw7_Release(ddraw);
1043 DestroyWindow(window);
1046 static void test_coop_level_threaded(void)
1048 struct create_window_thread_param p;
1049 IDirectDraw7 *ddraw;
1050 HRESULT hr;
1052 ddraw = create_ddraw();
1053 ok(!!ddraw, "Failed to create a ddraw object.\n");
1054 create_window_thread(&p);
1056 hr = IDirectDraw7_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1057 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1059 IDirectDraw7_Release(ddraw);
1060 destroy_window_thread(&p);
1063 static void test_depth_blit(void)
1065 IDirect3DDevice7 *device;
1066 static struct
1068 float x, y, z;
1069 DWORD color;
1071 quad1[] =
1073 { -1.0, 1.0, 0.50f, 0xff00ff00},
1074 { 1.0, 1.0, 0.50f, 0xff00ff00},
1075 { -1.0, -1.0, 0.50f, 0xff00ff00},
1076 { 1.0, -1.0, 0.50f, 0xff00ff00},
1078 static const D3DCOLOR expected_colors[4][4] =
1080 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1081 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1082 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1083 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1085 DDSURFACEDESC2 ddsd_new, ddsd_existing;
1087 IDirectDrawSurface7 *ds1, *ds2, *ds3, *rt;
1088 RECT src_rect, dst_rect;
1089 unsigned int i, j;
1090 D3DCOLOR color;
1091 HRESULT hr;
1092 IDirect3D7 *d3d;
1093 IDirectDraw7 *ddraw;
1094 DDBLTFX fx;
1095 HWND window;
1097 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1098 0, 0, 640, 480, 0, 0, 0, 0);
1099 if (!(device = create_device(window, DDSCL_NORMAL)))
1101 skip("Failed to create a 3D device, skipping test.\n");
1102 DestroyWindow(window);
1103 return;
1106 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1107 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
1108 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1109 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
1110 IDirect3D7_Release(d3d);
1112 ds1 = get_depth_stencil(device);
1114 memset(&ddsd_new, 0, sizeof(ddsd_new));
1115 ddsd_new.dwSize = sizeof(ddsd_new);
1116 memset(&ddsd_existing, 0, sizeof(ddsd_existing));
1117 ddsd_existing.dwSize = sizeof(ddsd_existing);
1118 hr = IDirectDrawSurface7_GetSurfaceDesc(ds1, &ddsd_existing);
1119 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
1120 ddsd_new.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1121 ddsd_new.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1122 ddsd_new.dwWidth = ddsd_existing.dwWidth;
1123 ddsd_new.dwHeight = ddsd_existing.dwHeight;
1124 U4(ddsd_new).ddpfPixelFormat = U4(ddsd_existing).ddpfPixelFormat;
1125 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd_new, &ds2, NULL);
1126 ok(SUCCEEDED(hr), "Failed to create a z buffer, hr %#x.\n", hr);
1127 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd_new, &ds3, NULL);
1128 ok(SUCCEEDED(hr), "Failed to create a z buffer, hr %#x.\n", hr);
1129 IDirectDraw7_Release(ddraw);
1131 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
1132 ok(SUCCEEDED(hr), "Failed to enable z testing, hr %#x.\n", hr);
1133 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
1134 ok(SUCCEEDED(hr), "Failed to set the z function, hr %#x.\n", hr);
1135 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
1136 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
1138 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
1139 ok(SUCCEEDED(hr), "Failed to clear the z buffer, hr %#x.\n", hr);
1141 /* Partial blit. */
1142 SetRect(&src_rect, 0, 0, 320, 240);
1143 SetRect(&dst_rect, 0, 0, 320, 240);
1144 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1145 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1146 /* Different locations. */
1147 SetRect(&src_rect, 0, 0, 320, 240);
1148 SetRect(&dst_rect, 320, 240, 640, 480);
1149 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1150 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1151 /* Streched. */
1152 SetRect(&src_rect, 0, 0, 320, 240);
1153 SetRect(&dst_rect, 0, 0, 640, 480);
1154 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1155 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1156 /* Flipped. */
1157 SetRect(&src_rect, 0, 480, 640, 0);
1158 SetRect(&dst_rect, 0, 0, 640, 480);
1159 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1160 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1161 SetRect(&src_rect, 0, 0, 640, 480);
1162 SetRect(&dst_rect, 0, 480, 640, 0);
1163 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1164 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1165 /* Full, explicit. */
1166 SetRect(&src_rect, 0, 0, 640, 480);
1167 SetRect(&dst_rect, 0, 0, 640, 480);
1168 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1169 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1170 /* Depth -> color blit: Succeeds on Win7 + Radeon HD 5700, fails on WinXP + Radeon X1600 */
1172 /* Depth blit inside a BeginScene / EndScene pair */
1173 hr = IDirect3DDevice7_BeginScene(device);
1174 ok(SUCCEEDED(hr), "Failed to start scene, hr %#x.\n", hr);
1175 /* From the current depth stencil */
1176 hr = IDirectDrawSurface7_Blt(ds2, NULL, ds1, NULL, DDBLT_WAIT, NULL);
1177 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1178 /* To the current depth stencil */
1179 hr = IDirectDrawSurface7_Blt(ds1, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1180 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1181 /* Between unbound surfaces */
1182 hr = IDirectDrawSurface7_Blt(ds3, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1183 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1184 hr = IDirect3DDevice7_EndScene(device);
1185 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1187 /* Avoid changing the depth stencil, it doesn't work properly on Windows.
1188 * Instead use DDBLT_DEPTHFILL to clear the depth stencil. Unfortunately
1189 * drivers disagree on the meaning of dwFillDepth. Only 0 seems to produce
1190 * a reliable result(z = 0.0) */
1191 memset(&fx, 0, sizeof(fx));
1192 fx.dwSize = sizeof(fx);
1193 hr = IDirectDrawSurface7_Blt(ds2, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
1194 ok(SUCCEEDED(hr), "Failed to clear the source z buffer, hr %#x.\n", hr);
1196 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET, 0xffff0000, 1.0f, 0);
1197 ok(SUCCEEDED(hr), "Failed to clear the color and z buffers, hr %#x.\n", hr);
1198 SetRect(&dst_rect, 0, 0, 320, 240);
1199 hr = IDirectDrawSurface7_Blt(ds1, &dst_rect, ds2, NULL, DDBLT_WAIT, NULL);
1200 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1201 IDirectDrawSurface7_Release(ds3);
1202 IDirectDrawSurface7_Release(ds2);
1203 IDirectDrawSurface7_Release(ds1);
1205 hr = IDirect3DDevice7_BeginScene(device);
1206 ok(SUCCEEDED(hr), "Failed to start scene, hr %#x.\n", hr);
1207 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
1208 quad1, 4, 0);
1209 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1210 hr = IDirect3DDevice7_EndScene(device);
1211 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1213 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1214 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1215 for (i = 0; i < 4; ++i)
1217 for (j = 0; j < 4; ++j)
1219 unsigned int x = 80 * ((2 * j) + 1);
1220 unsigned int y = 60 * ((2 * i) + 1);
1221 color = get_surface_color(rt, x, y);
1222 ok(compare_color(color, expected_colors[i][j], 1),
1223 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
1227 IDirectDrawSurface7_Release(rt);
1228 IDirect3DDevice7_Release(device);
1229 DestroyWindow(window);
1232 static void test_texture_load_ckey(void)
1234 HWND window;
1235 IDirect3DDevice7 *device;
1236 IDirectDraw7 *ddraw;
1237 IDirectDrawSurface7 *src;
1238 IDirectDrawSurface7 *dst;
1239 DDSURFACEDESC2 ddsd;
1240 HRESULT hr;
1241 DDCOLORKEY ckey;
1242 IDirect3D7 *d3d;
1244 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1245 0, 0, 640, 480, 0, 0, 0, 0);
1246 if (!(device = create_device(window, DDSCL_NORMAL)))
1248 skip("Failed to create a 3D device, skipping test.\n");
1249 DestroyWindow(window);
1250 return;
1253 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1254 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
1255 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1256 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
1257 IDirect3D7_Release(d3d);
1259 memset(&ddsd, 0, sizeof(ddsd));
1260 ddsd.dwSize = sizeof(ddsd);
1261 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
1262 ddsd.dwHeight = 128;
1263 ddsd.dwWidth = 128;
1264 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
1265 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &src, NULL);
1266 ok(SUCCEEDED(hr), "Failed to create source texture, hr %#x.\n", hr);
1267 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1268 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &dst, NULL);
1269 ok(SUCCEEDED(hr), "Failed to create destination texture, hr %#x.\n", hr);
1271 /* No surface has a color key */
1272 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1273 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1274 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0xdeadbeef;
1275 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1276 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1277 ok(ckey.dwColorSpaceLowValue == 0xdeadbeef, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1278 ok(ckey.dwColorSpaceHighValue == 0xdeadbeef, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1280 /* Source surface has a color key */
1281 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
1282 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
1283 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1284 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1285 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1286 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1287 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1288 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1289 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1291 /* Both surfaces have a color key: Dest ckey is overwritten */
1292 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x000000ff;
1293 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1294 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1295 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1296 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1297 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1298 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1299 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1300 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1302 /* Only the destination has a color key: It is deleted. This behavior differs from
1303 * IDirect3DTexture(2)::Load */
1304 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, NULL);
1305 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1306 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
1307 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1308 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1309 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1310 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1311 todo_wine ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1313 IDirectDrawSurface7_Release(dst);
1314 IDirectDrawSurface7_Release(src);
1315 IDirectDraw7_Release(ddraw);
1316 IDirect3DDevice7_Release(device);
1317 DestroyWindow(window);
1320 static void test_zenable(void)
1322 static struct
1324 struct vec4 position;
1325 D3DCOLOR diffuse;
1327 tquad[] =
1329 {{ 0.0f, 480.0f, -0.5f, 1.0f}, 0xff00ff00},
1330 {{ 0.0f, 0.0f, -0.5f, 1.0f}, 0xff00ff00},
1331 {{640.0f, 480.0f, 1.5f, 1.0f}, 0xff00ff00},
1332 {{640.0f, 0.0f, 1.5f, 1.0f}, 0xff00ff00},
1334 IDirect3DDevice7 *device;
1335 IDirectDrawSurface7 *rt;
1336 D3DCOLOR color;
1337 HWND window;
1338 HRESULT hr;
1339 UINT x, y;
1340 UINT i, j;
1342 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1343 0, 0, 640, 480, 0, 0, 0, 0);
1344 if (!(device = create_device(window, DDSCL_NORMAL)))
1346 skip("Failed to create a 3D device, skipping test.\n");
1347 DestroyWindow(window);
1348 return;
1351 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1352 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
1354 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 0.0f, 0);
1355 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1356 hr = IDirect3DDevice7_BeginScene(device);
1357 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1358 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_DIFFUSE, tquad, 4, 0);
1359 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1360 hr = IDirect3DDevice7_EndScene(device);
1361 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1363 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1364 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1365 for (i = 0; i < 4; ++i)
1367 for (j = 0; j < 4; ++j)
1369 x = 80 * ((2 * j) + 1);
1370 y = 60 * ((2 * i) + 1);
1371 color = get_surface_color(rt, x, y);
1372 ok(compare_color(color, 0x0000ff00, 1),
1373 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1376 IDirectDrawSurface7_Release(rt);
1378 IDirect3DDevice7_Release(device);
1379 DestroyWindow(window);
1382 static void test_ck_rgba(void)
1384 static struct
1386 struct vec4 position;
1387 struct vec2 texcoord;
1389 tquad[] =
1391 {{ 0.0f, 480.0f, 0.25f, 1.0f}, {0.0f, 0.0f}},
1392 {{ 0.0f, 0.0f, 0.25f, 1.0f}, {0.0f, 1.0f}},
1393 {{640.0f, 480.0f, 0.25f, 1.0f}, {1.0f, 0.0f}},
1394 {{640.0f, 0.0f, 0.25f, 1.0f}, {1.0f, 1.0f}},
1395 {{ 0.0f, 480.0f, 0.75f, 1.0f}, {0.0f, 0.0f}},
1396 {{ 0.0f, 0.0f, 0.75f, 1.0f}, {0.0f, 1.0f}},
1397 {{640.0f, 480.0f, 0.75f, 1.0f}, {1.0f, 0.0f}},
1398 {{640.0f, 0.0f, 0.75f, 1.0f}, {1.0f, 1.0f}},
1400 static const struct
1402 D3DCOLOR fill_color;
1403 BOOL color_key;
1404 BOOL blend;
1405 D3DCOLOR result1, result1_broken;
1406 D3DCOLOR result2, result2_broken;
1408 tests[] =
1410 /* r200 on Windows doesn't check the alpha component when applying the color
1411 * key, so the key matches on every texel. */
1412 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1413 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1414 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1415 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1416 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00ff0000, 0x00807f00, 0x000000ff},
1417 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x00ff0000, 0x0000ff00, 0x000000ff},
1418 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00, 0x00807f00, 0x00807f00},
1419 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1422 IDirectDrawSurface7 *texture;
1423 DDSURFACEDESC2 surface_desc;
1424 IDirect3DDevice7 *device;
1425 IDirectDrawSurface7 *rt;
1426 IDirectDraw7 *ddraw;
1427 IDirect3D7 *d3d;
1428 D3DCOLOR color;
1429 HWND window;
1430 DDBLTFX fx;
1431 HRESULT hr;
1432 UINT i;
1434 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1435 0, 0, 640, 480, 0, 0, 0, 0);
1436 if (!(device = create_device(window, DDSCL_NORMAL)))
1438 skip("Failed to create a 3D device, skipping test.\n");
1439 DestroyWindow(window);
1440 return;
1443 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1444 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1445 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1446 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1447 IDirect3D7_Release(d3d);
1449 memset(&surface_desc, 0, sizeof(surface_desc));
1450 surface_desc.dwSize = sizeof(surface_desc);
1451 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1452 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1453 surface_desc.dwWidth = 256;
1454 surface_desc.dwHeight = 256;
1455 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1456 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1457 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1458 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1459 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1460 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1461 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1462 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1463 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1464 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
1465 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1467 hr = IDirect3DDevice7_SetTexture(device, 0, texture);
1468 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1469 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1470 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1471 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1472 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1474 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1475 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1477 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
1479 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1480 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1481 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1482 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1484 memset(&fx, 0, sizeof(fx));
1485 fx.dwSize = sizeof(fx);
1486 U5(fx).dwFillColor = tests[i].fill_color;
1487 hr = IDirectDrawSurface7_Blt(texture, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1488 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1490 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 1.0f, 0);
1491 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1492 hr = IDirect3DDevice7_BeginScene(device);
1493 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1494 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1495 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1496 hr = IDirect3DDevice7_EndScene(device);
1497 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1499 color = get_surface_color(rt, 320, 240);
1500 ok(compare_color(color, tests[i].result1, 1) || compare_color(color, tests[i].result1_broken, 1),
1501 "Expected color 0x%08x for test %u, got 0x%08x.\n",
1502 tests[i].result1, i, color);
1504 U5(fx).dwFillColor = 0xff0000ff;
1505 hr = IDirectDrawSurface7_Blt(texture, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1506 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1508 hr = IDirect3DDevice7_BeginScene(device);
1509 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1510 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[4], 4, 0);
1511 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1512 hr = IDirect3DDevice7_EndScene(device);
1513 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1515 /* This tests that fragments that are masked out by the color key are
1516 * discarded, instead of just fully transparent. */
1517 color = get_surface_color(rt, 320, 240);
1518 ok(compare_color(color, tests[i].result2, 1) || compare_color(color, tests[i].result2_broken, 1),
1519 "Expected color 0x%08x for test %u, got 0x%08x.\n",
1520 tests[i].result2, i, color);
1523 IDirectDrawSurface7_Release(rt);
1524 IDirectDrawSurface7_Release(texture);
1525 IDirectDraw7_Release(ddraw);
1526 IDirect3DDevice7_Release(device);
1527 DestroyWindow(window);
1530 static void test_ck_default(void)
1532 static struct
1534 struct vec4 position;
1535 struct vec2 texcoord;
1537 tquad[] =
1539 {{ 0.0f, 480.0f, 0.0f, 1.0f}, {0.0f, 0.0f}},
1540 {{ 0.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 1.0f}},
1541 {{640.0f, 480.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
1542 {{640.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
1544 IDirectDrawSurface7 *surface, *rt;
1545 DDSURFACEDESC2 surface_desc;
1546 IDirect3DDevice7 *device;
1547 IDirectDraw7 *ddraw;
1548 IDirect3D7 *d3d;
1549 D3DCOLOR color;
1550 DWORD value;
1551 HWND window;
1552 DDBLTFX fx;
1553 HRESULT hr;
1555 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1556 0, 0, 640, 480, 0, 0, 0, 0);
1558 if (!(device = create_device(window, DDSCL_NORMAL)))
1560 skip("Failed to create a 3D device, skipping test.\n");
1561 DestroyWindow(window);
1562 return;
1565 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1566 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1567 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1568 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1569 IDirect3D7_Release(d3d);
1571 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1572 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1574 memset(&surface_desc, 0, sizeof(surface_desc));
1575 surface_desc.dwSize = sizeof(surface_desc);
1576 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1577 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1578 surface_desc.dwWidth = 256;
1579 surface_desc.dwHeight = 256;
1580 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1581 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
1582 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1583 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1584 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1585 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1586 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
1587 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
1588 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1589 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1590 hr = IDirect3DDevice7_SetTexture(device, 0, surface);
1591 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1593 memset(&fx, 0, sizeof(fx));
1594 fx.dwSize = sizeof(fx);
1595 U5(fx).dwFillColor = 0x000000ff;
1596 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1597 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
1599 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
1600 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1601 hr = IDirect3DDevice7_BeginScene(device);
1602 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1603 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1604 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1605 ok(!value, "Got unexpected color keying state %#x.\n", value);
1606 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1607 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1608 hr = IDirect3DDevice7_EndScene(device);
1609 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1610 color = get_surface_color(rt, 320, 240);
1611 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1613 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
1614 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1615 hr = IDirect3DDevice7_BeginScene(device);
1616 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1617 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
1618 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1619 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1620 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1621 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1622 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1623 ok(!!value, "Got unexpected color keying state %#x.\n", value);
1624 hr = IDirect3DDevice7_EndScene(device);
1625 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1626 color = get_surface_color(rt, 320, 240);
1627 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1629 IDirectDrawSurface7_Release(surface);
1630 IDirectDrawSurface7_Release(rt);
1631 IDirect3DDevice7_Release(device);
1632 IDirectDraw7_Release(ddraw);
1633 DestroyWindow(window);
1636 static void test_ck_complex(void)
1638 IDirectDrawSurface7 *surface, *mipmap, *tmp;
1639 D3DDEVICEDESC7 device_desc;
1640 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
1641 DDSURFACEDESC2 surface_desc;
1642 IDirect3DDevice7 *device;
1643 DDCOLORKEY color_key;
1644 IDirectDraw7 *ddraw;
1645 IDirect3D7 *d3d;
1646 unsigned int i;
1647 ULONG refcount;
1648 HWND window;
1649 HRESULT hr;
1651 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1652 0, 0, 640, 480, 0, 0, 0, 0);
1653 if (!(device = create_device(window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
1655 skip("Failed to create a 3D device, skipping test.\n");
1656 DestroyWindow(window);
1657 return;
1659 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
1660 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
1661 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1662 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1663 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1664 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1665 IDirect3D7_Release(d3d);
1667 memset(&surface_desc, 0, sizeof(surface_desc));
1668 surface_desc.dwSize = sizeof(surface_desc);
1669 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1670 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1671 surface_desc.dwWidth = 128;
1672 surface_desc.dwHeight = 128;
1673 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1674 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1676 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1677 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1678 color_key.dwColorSpaceLowValue = 0x0000ff00;
1679 color_key.dwColorSpaceHighValue = 0x0000ff00;
1680 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1681 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1682 memset(&color_key, 0, sizeof(color_key));
1683 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1684 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1685 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1686 color_key.dwColorSpaceLowValue);
1687 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1688 color_key.dwColorSpaceHighValue);
1690 mipmap = surface;
1691 IDirectDrawSurface_AddRef(mipmap);
1692 for (i = 0; i < 7; ++i)
1694 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
1695 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
1696 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1697 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1699 color_key.dwColorSpaceLowValue = 0x000000ff;
1700 color_key.dwColorSpaceHighValue = 0x000000ff;
1701 hr = IDirectDrawSurface7_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1702 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x, i %u.\n", hr, i);
1704 IDirectDrawSurface_Release(mipmap);
1705 mipmap = tmp;
1708 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
1709 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
1710 IDirectDrawSurface_Release(mipmap);
1711 refcount = IDirectDrawSurface7_Release(surface);
1712 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1714 memset(&surface_desc, 0, sizeof(surface_desc));
1715 surface_desc.dwSize = sizeof(surface_desc);
1716 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
1717 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
1718 U5(surface_desc).dwBackBufferCount = 1;
1719 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1720 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1722 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1723 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1724 color_key.dwColorSpaceLowValue = 0x0000ff00;
1725 color_key.dwColorSpaceHighValue = 0x0000ff00;
1726 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1727 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1728 memset(&color_key, 0, sizeof(color_key));
1729 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1730 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1731 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1732 color_key.dwColorSpaceLowValue);
1733 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1734 color_key.dwColorSpaceHighValue);
1736 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &tmp);
1737 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
1739 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1740 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1741 color_key.dwColorSpaceLowValue = 0x0000ff00;
1742 color_key.dwColorSpaceHighValue = 0x0000ff00;
1743 hr = IDirectDrawSurface7_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1744 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1745 memset(&color_key, 0, sizeof(color_key));
1746 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1747 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1748 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1749 color_key.dwColorSpaceLowValue);
1750 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1751 color_key.dwColorSpaceHighValue);
1753 IDirectDrawSurface_Release(tmp);
1755 refcount = IDirectDrawSurface7_Release(surface);
1756 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1758 if (!(device_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP))
1760 skip("Device does not support cubemaps.\n");
1761 goto cleanup;
1763 memset(&surface_desc, 0, sizeof(surface_desc));
1764 surface_desc.dwSize = sizeof(surface_desc);
1765 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1766 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1767 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
1768 surface_desc.dwWidth = 128;
1769 surface_desc.dwHeight = 128;
1770 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1771 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1773 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1774 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1775 color_key.dwColorSpaceLowValue = 0x0000ff00;
1776 color_key.dwColorSpaceHighValue = 0x0000ff00;
1777 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1778 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1780 caps.dwCaps2 = DDSCAPS2_CUBEMAP_NEGATIVEZ;
1781 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
1782 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
1784 hr = IDirectDrawSurface7_GetColorKey(mipmap, DDCKEY_SRCBLT, &color_key);
1785 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1786 color_key.dwColorSpaceLowValue = 0x000000ff;
1787 color_key.dwColorSpaceHighValue = 0x000000ff;
1788 hr = IDirectDrawSurface7_SetColorKey(mipmap, DDCKEY_SRCBLT, &color_key);
1789 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1791 color_key.dwColorSpaceLowValue = 0;
1792 color_key.dwColorSpaceHighValue = 0;
1793 hr = IDirectDrawSurface7_GetColorKey(mipmap, DDCKEY_SRCBLT, &color_key);
1794 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1795 ok(color_key.dwColorSpaceLowValue == 0x000000ff, "Got unexpected value 0x%08x.\n",
1796 color_key.dwColorSpaceLowValue);
1797 ok(color_key.dwColorSpaceHighValue == 0x000000ff, "Got unexpected value 0x%08x.\n",
1798 color_key.dwColorSpaceHighValue);
1800 IDirectDrawSurface_AddRef(mipmap);
1801 for (i = 0; i < 7; ++i)
1803 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
1804 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
1805 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1806 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1808 color_key.dwColorSpaceLowValue = 0x000000ff;
1809 color_key.dwColorSpaceHighValue = 0x000000ff;
1810 hr = IDirectDrawSurface7_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1811 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x, i %u.\n", hr, i);
1813 IDirectDrawSurface_Release(mipmap);
1814 mipmap = tmp;
1817 IDirectDrawSurface7_Release(mipmap);
1819 refcount = IDirectDrawSurface7_Release(surface);
1820 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1822 cleanup:
1823 IDirectDraw7_Release(ddraw);
1824 refcount = IDirect3DDevice7_Release(device);
1825 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1826 DestroyWindow(window);
1829 struct qi_test
1831 REFIID iid;
1832 REFIID refcount_iid;
1833 HRESULT hr;
1836 static void test_qi(const char *test_name, IUnknown *base_iface,
1837 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
1839 ULONG refcount, expected_refcount;
1840 IUnknown *iface1, *iface2;
1841 HRESULT hr;
1842 UINT i, j;
1844 for (i = 0; i < entry_count; ++i)
1846 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
1847 ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
1848 if (SUCCEEDED(hr))
1850 for (j = 0; j < entry_count; ++j)
1852 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
1853 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
1854 if (SUCCEEDED(hr))
1856 expected_refcount = 0;
1857 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
1858 ++expected_refcount;
1859 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
1860 ++expected_refcount;
1861 refcount = IUnknown_Release(iface2);
1862 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
1863 refcount, test_name, i, j, expected_refcount);
1867 expected_refcount = 0;
1868 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
1869 ++expected_refcount;
1870 refcount = IUnknown_Release(iface1);
1871 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
1872 refcount, test_name, i, expected_refcount);
1877 static void test_surface_qi(void)
1879 static const struct qi_test tests[] =
1881 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
1882 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
1883 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
1884 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1885 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
1886 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
1887 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
1888 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
1889 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
1890 {&IID_IDirect3DDevice7, NULL, E_NOINTERFACE},
1891 {&IID_IDirect3DDevice3, NULL, E_NOINTERFACE},
1892 {&IID_IDirect3DDevice2, NULL, E_NOINTERFACE},
1893 {&IID_IDirect3DDevice, NULL, E_NOINTERFACE},
1894 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
1895 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
1896 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
1897 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
1898 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
1899 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
1900 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
1901 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
1902 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
1903 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
1904 {&IID_IDirect3D, NULL, E_NOINTERFACE},
1905 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
1906 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
1907 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
1908 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
1909 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
1910 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
1911 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
1912 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
1913 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
1914 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
1915 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
1916 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
1917 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
1918 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
1919 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
1920 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
1921 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
1922 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
1925 IDirectDrawSurface7 *surface;
1926 DDSURFACEDESC2 surface_desc;
1927 IDirect3DDevice7 *device;
1928 IDirectDraw7 *ddraw;
1929 HWND window;
1930 HRESULT hr;
1932 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1933 0, 0, 640, 480, 0, 0, 0, 0);
1934 /* Try to create a D3D device to see if the ddraw implementation supports
1935 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
1936 * doesn't support e.g. the IDirect3DTexture interfaces. */
1937 if (!(device = create_device(window, DDSCL_NORMAL)))
1939 skip("Failed to create a 3D device, skipping test.\n");
1940 DestroyWindow(window);
1941 return;
1943 IDirect3DDevice_Release(device);
1944 ddraw = create_ddraw();
1945 ok(!!ddraw, "Failed to create a ddraw object.\n");
1946 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1947 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1949 memset(&surface_desc, 0, sizeof(surface_desc));
1950 surface_desc.dwSize = sizeof(surface_desc);
1951 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1952 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1953 surface_desc.dwWidth = 512;
1954 surface_desc.dwHeight = 512;
1955 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1956 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1958 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface7, tests, sizeof(tests) / sizeof(*tests));
1960 IDirectDrawSurface7_Release(surface);
1961 IDirectDraw7_Release(ddraw);
1962 DestroyWindow(window);
1965 static void test_device_qi(void)
1967 static const struct qi_test tests[] =
1969 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
1970 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
1971 {&IID_IDirectDrawGammaControl, NULL, E_NOINTERFACE},
1972 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1973 {&IID_IDirectDrawSurface7, NULL, E_NOINTERFACE},
1974 {&IID_IDirectDrawSurface4, NULL, E_NOINTERFACE},
1975 {&IID_IDirectDrawSurface3, NULL, E_NOINTERFACE},
1976 {&IID_IDirectDrawSurface2, NULL, E_NOINTERFACE},
1977 {&IID_IDirectDrawSurface, NULL, E_NOINTERFACE},
1978 {&IID_IDirect3DDevice7, &IID_IDirect3DDevice7, S_OK },
1979 {&IID_IDirect3DDevice3, NULL, E_NOINTERFACE},
1980 {&IID_IDirect3DDevice2, NULL, E_NOINTERFACE},
1981 {&IID_IDirect3DDevice, NULL, E_NOINTERFACE},
1982 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
1983 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
1984 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
1985 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
1986 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
1987 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
1988 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
1989 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
1990 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
1991 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
1992 {&IID_IDirect3D, NULL, E_NOINTERFACE},
1993 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
1994 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
1995 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
1996 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
1997 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
1998 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
1999 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
2000 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
2001 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
2002 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
2003 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
2004 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
2005 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
2006 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
2007 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
2008 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
2009 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
2010 {&IID_IUnknown, &IID_IDirect3DDevice7, S_OK },
2013 IDirect3DDevice7 *device;
2014 HWND window;
2016 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2017 0, 0, 640, 480, 0, 0, 0, 0);
2018 if (!(device = create_device(window, DDSCL_NORMAL)))
2020 skip("Failed to create a 3D device, skipping test.\n");
2021 DestroyWindow(window);
2022 return;
2025 test_qi("device_qi", (IUnknown *)device, &IID_IDirect3DDevice7, tests, sizeof(tests) / sizeof(*tests));
2027 IDirect3DDevice7_Release(device);
2028 DestroyWindow(window);
2031 static void test_wndproc(void)
2033 LONG_PTR proc, ddraw_proc;
2034 IDirectDraw7 *ddraw;
2035 WNDCLASSA wc = {0};
2036 HWND window;
2037 HRESULT hr;
2038 ULONG ref;
2040 static struct message messages[] =
2042 {WM_WINDOWPOSCHANGING, FALSE, 0},
2043 {WM_MOVE, FALSE, 0},
2044 {WM_SIZE, FALSE, 0},
2045 {WM_WINDOWPOSCHANGING, FALSE, 0},
2046 {WM_ACTIVATE, FALSE, 0},
2047 {WM_SETFOCUS, FALSE, 0},
2048 {0, FALSE, 0},
2051 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
2052 ddraw = create_ddraw();
2053 ok(!!ddraw, "Failed to create a ddraw object.\n");
2055 wc.lpfnWndProc = test_proc;
2056 wc.lpszClassName = "ddraw_test_wndproc_wc";
2057 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2059 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
2060 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
2062 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2063 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2064 (LONG_PTR)test_proc, proc);
2065 expect_messages = messages;
2066 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2067 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2068 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2069 expect_messages = NULL;
2070 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2071 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2072 (LONG_PTR)test_proc, proc);
2073 ref = IDirectDraw7_Release(ddraw);
2074 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2075 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2076 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2077 (LONG_PTR)test_proc, proc);
2079 /* DDSCL_NORMAL doesn't. */
2080 ddraw = create_ddraw();
2081 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2082 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2083 (LONG_PTR)test_proc, proc);
2084 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2085 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2086 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2087 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2088 (LONG_PTR)test_proc, proc);
2089 ref = IDirectDraw7_Release(ddraw);
2090 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2091 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2092 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2093 (LONG_PTR)test_proc, proc);
2095 /* The original window proc is only restored by ddraw if the current
2096 * window proc matches the one ddraw set. This also affects switching
2097 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
2098 ddraw = create_ddraw();
2099 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2100 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2101 (LONG_PTR)test_proc, proc);
2102 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2103 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2104 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2105 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2106 (LONG_PTR)test_proc, proc);
2107 ddraw_proc = proc;
2108 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2109 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2110 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2111 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2112 (LONG_PTR)test_proc, proc);
2113 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2114 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2115 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2116 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2117 (LONG_PTR)test_proc, proc);
2118 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2119 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2120 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2121 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2122 (LONG_PTR)DefWindowProcA, proc);
2123 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2124 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2125 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc);
2126 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2127 (LONG_PTR)DefWindowProcA, proc);
2128 ref = IDirectDraw7_Release(ddraw);
2129 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2130 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2131 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2132 (LONG_PTR)test_proc, proc);
2134 ddraw = create_ddraw();
2135 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2136 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2137 (LONG_PTR)test_proc, proc);
2138 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2139 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2140 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2141 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2142 (LONG_PTR)test_proc, proc);
2143 ref = IDirectDraw7_Release(ddraw);
2144 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2145 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2146 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2147 (LONG_PTR)DefWindowProcA, proc);
2149 fix_wndproc(window, (LONG_PTR)test_proc);
2150 expect_messages = NULL;
2151 DestroyWindow(window);
2152 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2155 static void test_window_style(void)
2157 LONG style, exstyle, tmp, expected_style;
2158 RECT fullscreen_rect, r;
2159 IDirectDraw7 *ddraw;
2160 HWND window;
2161 HRESULT hr;
2162 ULONG ref;
2163 BOOL ret;
2165 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2166 0, 0, 100, 100, 0, 0, 0, 0);
2167 ddraw = create_ddraw();
2168 ok(!!ddraw, "Failed to create a ddraw object.\n");
2170 style = GetWindowLongA(window, GWL_STYLE);
2171 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
2172 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2174 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2175 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2177 tmp = GetWindowLongA(window, GWL_STYLE);
2178 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2179 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2180 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2182 GetWindowRect(window, &r);
2183 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2184 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2185 r.left, r.top, r.right, r.bottom);
2186 GetClientRect(window, &r);
2187 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2189 ret = SetForegroundWindow(GetDesktopWindow());
2190 ok(ret, "Failed to set foreground window.\n");
2192 tmp = GetWindowLongA(window, GWL_STYLE);
2193 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2194 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2195 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2197 ret = SetForegroundWindow(window);
2198 ok(ret, "Failed to set foreground window.\n");
2199 /* Windows 7 (but not Vista and XP) shows the window when it receives focus. Hide it again,
2200 * the next tests expect this. */
2201 ShowWindow(window, SW_HIDE);
2203 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2204 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2206 tmp = GetWindowLongA(window, GWL_STYLE);
2207 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2208 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2209 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2211 ShowWindow(window, SW_SHOW);
2212 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2213 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2215 tmp = GetWindowLongA(window, GWL_STYLE);
2216 expected_style = style | WS_VISIBLE;
2217 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2218 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2219 expected_style = exstyle | WS_EX_TOPMOST;
2220 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2222 ret = SetForegroundWindow(GetDesktopWindow());
2223 ok(ret, "Failed to set foreground window.\n");
2224 tmp = GetWindowLongA(window, GWL_STYLE);
2225 expected_style = style | WS_VISIBLE | WS_MINIMIZE;
2226 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2227 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2228 expected_style = exstyle | WS_EX_TOPMOST;
2229 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2231 ref = IDirectDraw7_Release(ddraw);
2232 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2234 DestroyWindow(window);
2237 static void test_redundant_mode_set(void)
2239 DDSURFACEDESC2 surface_desc = {0};
2240 IDirectDraw7 *ddraw;
2241 HWND window;
2242 HRESULT hr;
2243 RECT r, s;
2244 ULONG ref;
2246 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2247 0, 0, 100, 100, 0, 0, 0, 0);
2248 ddraw = create_ddraw();
2249 ok(!!ddraw, "Failed to create a ddraw object.\n");
2250 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2251 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2253 surface_desc.dwSize = sizeof(surface_desc);
2254 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
2255 ok(SUCCEEDED(hr), "GetDipslayMode failed, hr %#x.\n", hr);
2257 hr = IDirectDraw7_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2258 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
2259 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2261 GetWindowRect(window, &r);
2262 r.right /= 2;
2263 r.bottom /= 2;
2264 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
2265 GetWindowRect(window, &s);
2266 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2267 r.left, r.top, r.right, r.bottom,
2268 s.left, s.top, s.right, s.bottom);
2270 hr = IDirectDraw7_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2271 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
2272 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2274 GetWindowRect(window, &s);
2275 ok(EqualRect(&r, &s), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2276 r.left, r.top, r.right, r.bottom,
2277 s.left, s.top, s.right, s.bottom);
2279 ref = IDirectDraw7_Release(ddraw);
2280 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2282 DestroyWindow(window);
2285 static SIZE screen_size, screen_size2;
2287 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2289 if (message == WM_SIZE)
2291 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2292 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2295 return test_proc(hwnd, message, wparam, lparam);
2298 static LRESULT CALLBACK mode_set_proc2(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2300 if (message == WM_SIZE)
2302 screen_size2.cx = GetSystemMetrics(SM_CXSCREEN);
2303 screen_size2.cy = GetSystemMetrics(SM_CYSCREEN);
2306 return test_proc(hwnd, message, wparam, lparam);
2309 struct test_coop_level_mode_set_enum_param
2311 DWORD ddraw_width, ddraw_height, user32_width, user32_height;
2314 static HRESULT CALLBACK test_coop_level_mode_set_enum_cb(DDSURFACEDESC2 *surface_desc, void *context)
2316 struct test_coop_level_mode_set_enum_param *param = context;
2318 if (U1(U4(*surface_desc).ddpfPixelFormat).dwRGBBitCount != registry_mode.dmBitsPerPel)
2319 return DDENUMRET_OK;
2320 if (surface_desc->dwWidth == registry_mode.dmPelsWidth
2321 && surface_desc->dwHeight == registry_mode.dmPelsHeight)
2322 return DDENUMRET_OK;
2324 if (!param->ddraw_width)
2326 param->ddraw_width = surface_desc->dwWidth;
2327 param->ddraw_height = surface_desc->dwHeight;
2328 return DDENUMRET_OK;
2330 if (surface_desc->dwWidth == param->ddraw_width && surface_desc->dwHeight == param->ddraw_height)
2331 return DDENUMRET_OK;
2333 param->user32_width = surface_desc->dwWidth;
2334 param->user32_height = surface_desc->dwHeight;
2335 return DDENUMRET_CANCEL;
2338 static void test_coop_level_mode_set(void)
2340 IDirectDrawSurface7 *primary;
2341 RECT registry_rect, ddraw_rect, user32_rect, r;
2342 IDirectDraw7 *ddraw;
2343 DDSURFACEDESC2 ddsd;
2344 WNDCLASSA wc = {0};
2345 HWND window, window2;
2346 HRESULT hr;
2347 ULONG ref;
2348 MSG msg;
2349 struct test_coop_level_mode_set_enum_param param;
2350 DEVMODEW devmode;
2351 BOOL ret;
2352 LONG change_ret;
2354 static const struct message exclusive_messages[] =
2356 {WM_WINDOWPOSCHANGING, FALSE, 0},
2357 {WM_WINDOWPOSCHANGED, FALSE, 0},
2358 {WM_SIZE, FALSE, 0},
2359 {WM_DISPLAYCHANGE, FALSE, 0},
2360 {0, FALSE, 0},
2362 static const struct message exclusive_focus_loss_messages[] =
2364 {WM_ACTIVATE, TRUE, WA_INACTIVE},
2365 {WM_DISPLAYCHANGE, FALSE, 0},
2366 {WM_WINDOWPOSCHANGING, FALSE, 0},
2367 /* Like d3d8 and d3d9 ddraw seems to use SW_SHOWMINIMIZED instead of
2368 * SW_MINIMIZED, causing a recursive window activation that does not
2369 * produce the same result in Wine yet. Ignore the difference for now.
2370 * {WM_ACTIVATE, TRUE, 0x200000 | WA_ACTIVE}, */
2371 {WM_WINDOWPOSCHANGED, FALSE, 0},
2372 {WM_MOVE, FALSE, 0},
2373 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2374 {WM_ACTIVATEAPP, TRUE, FALSE},
2375 {0, FALSE, 0},
2377 static const struct message exclusive_focus_restore_messages[] =
2379 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* From the ShowWindow(SW_RESTORE). */
2380 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Generated by ddraw, matches d3d9 behavior. */
2381 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching previous message. */
2382 {WM_SIZE, FALSE, 0}, /* DefWindowProc. */
2383 {WM_DISPLAYCHANGE, FALSE, 0}, /* Ddraw restores mode. */
2384 /* Native redundantly sets the window size here. */
2385 {WM_ACTIVATEAPP, TRUE, TRUE}, /* End of ddraw's hooks. */
2386 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching the one from ShowWindow. */
2387 {WM_MOVE, FALSE, 0}, /* DefWindowProc. */
2388 {WM_SIZE, TRUE, SIZE_RESTORED}, /* DefWindowProc. */
2389 {0, FALSE, 0},
2391 static const struct message sc_restore_messages[] =
2393 {WM_SYSCOMMAND, TRUE, SC_RESTORE},
2394 {WM_WINDOWPOSCHANGING, FALSE, 0},
2395 {WM_WINDOWPOSCHANGED, FALSE, 0},
2396 {WM_SIZE, TRUE, SIZE_RESTORED},
2397 {0, FALSE, 0},
2399 static const struct message sc_minimize_messages[] =
2401 {WM_SYSCOMMAND, TRUE, SC_MINIMIZE},
2402 {WM_WINDOWPOSCHANGING, FALSE, 0},
2403 {WM_WINDOWPOSCHANGED, FALSE, 0},
2404 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2405 {0, FALSE, 0},
2407 static const struct message sc_maximize_messages[] =
2409 {WM_SYSCOMMAND, TRUE, SC_MAXIMIZE},
2410 {WM_WINDOWPOSCHANGING, FALSE, 0},
2411 {WM_WINDOWPOSCHANGED, FALSE, 0},
2412 {WM_SIZE, TRUE, SIZE_MAXIMIZED},
2413 {0, FALSE, 0},
2416 static const struct message normal_messages[] =
2418 {WM_DISPLAYCHANGE, FALSE, 0},
2419 {0, FALSE, 0},
2422 ddraw = create_ddraw();
2423 ok(!!ddraw, "Failed to create a ddraw object.\n");
2425 memset(&param, 0, sizeof(param));
2426 hr = IDirectDraw7_EnumDisplayModes(ddraw, 0, NULL, &param, test_coop_level_mode_set_enum_cb);
2427 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
2428 ref = IDirectDraw7_Release(ddraw);
2429 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2431 if (!param.user32_height)
2433 skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
2434 return;
2437 SetRect(&registry_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2438 SetRect(&ddraw_rect, 0, 0, param.ddraw_width, param.ddraw_height);
2439 SetRect(&user32_rect, 0, 0, param.user32_width, param.user32_height);
2441 memset(&devmode, 0, sizeof(devmode));
2442 devmode.dmSize = sizeof(devmode);
2443 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2444 devmode.dmPelsWidth = param.user32_width;
2445 devmode.dmPelsHeight = param.user32_height;
2446 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2447 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2449 ddraw = create_ddraw();
2450 ok(!!ddraw, "Failed to create a ddraw object.\n");
2452 wc.lpfnWndProc = mode_set_proc;
2453 wc.lpszClassName = "ddraw_test_wndproc_wc";
2454 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2455 wc.lpfnWndProc = mode_set_proc2;
2456 wc.lpszClassName = "ddraw_test_wndproc_wc2";
2457 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2459 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
2460 0, 0, 100, 100, 0, 0, 0, 0);
2461 window2 = CreateWindowA("ddraw_test_wndproc_wc2", "ddraw_test", WS_OVERLAPPEDWINDOW,
2462 0, 0, 100, 100, 0, 0, 0, 0);
2464 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2465 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2467 GetWindowRect(window, &r);
2468 ok(EqualRect(&r, &user32_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2469 user32_rect.left, user32_rect.top, user32_rect.right, user32_rect.bottom,
2470 r.left, r.top, r.right, r.bottom);
2472 memset(&ddsd, 0, sizeof(ddsd));
2473 ddsd.dwSize = sizeof(ddsd);
2474 ddsd.dwFlags = DDSD_CAPS;
2475 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2477 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2478 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2479 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2480 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2481 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2482 param.user32_width, ddsd.dwWidth);
2483 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2484 param.user32_height, ddsd.dwHeight);
2486 GetWindowRect(window, &r);
2487 ok(EqualRect(&r, &user32_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2488 user32_rect.left, user32_rect.top, user32_rect.right, user32_rect.bottom,
2489 r.left, r.top, r.right, r.bottom);
2491 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2492 expect_messages = exclusive_messages;
2493 screen_size.cx = 0;
2494 screen_size.cy = 0;
2496 hr = IDirectDrawSurface7_IsLost(primary);
2497 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2498 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2499 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2500 hr = IDirectDrawSurface7_IsLost(primary);
2501 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2503 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2504 expect_messages = NULL;
2505 ok(screen_size.cx == param.ddraw_width && screen_size.cy == param.ddraw_height,
2506 "Expected screen size %ux%u, got %ux%u.\n",
2507 param.ddraw_width, param.ddraw_height, screen_size.cx, screen_size.cy);
2509 GetWindowRect(window, &r);
2510 ok(EqualRect(&r, &ddraw_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2511 ddraw_rect.left, ddraw_rect.top, ddraw_rect.right, ddraw_rect.bottom,
2512 r.left, r.top, r.right, r.bottom);
2514 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2515 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2516 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2517 param.user32_width, ddsd.dwWidth);
2518 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2519 param.user32_height, ddsd.dwHeight);
2520 IDirectDrawSurface7_Release(primary);
2522 memset(&ddsd, 0, sizeof(ddsd));
2523 ddsd.dwSize = sizeof(ddsd);
2524 ddsd.dwFlags = DDSD_CAPS;
2525 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2527 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2528 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2529 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2530 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2531 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2532 param.ddraw_width, ddsd.dwWidth);
2533 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2534 param.ddraw_height, ddsd.dwHeight);
2536 GetWindowRect(window, &r);
2537 ok(EqualRect(&r, &ddraw_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2538 ddraw_rect.left, ddraw_rect.top, ddraw_rect.right, ddraw_rect.bottom,
2539 r.left, r.top, r.right, r.bottom);
2541 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2542 expect_messages = exclusive_messages;
2543 screen_size.cx = 0;
2544 screen_size.cy = 0;
2546 hr = IDirectDrawSurface7_IsLost(primary);
2547 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2548 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2549 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2550 hr = IDirectDrawSurface7_IsLost(primary);
2551 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2553 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2554 expect_messages = NULL;
2555 ok(screen_size.cx == param.user32_width && screen_size.cy == param.user32_height,
2556 "Expected screen size %ux%u, got %ux%u.\n",
2557 param.user32_width, param.user32_height, screen_size.cx, screen_size.cy);
2559 GetWindowRect(window, &r);
2560 ok(EqualRect(&r, &user32_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2561 user32_rect.left, user32_rect.top, user32_rect.right, user32_rect.bottom,
2562 r.left, r.top, r.right, r.bottom);
2564 expect_messages = exclusive_focus_loss_messages;
2565 ret = SetForegroundWindow(GetDesktopWindow());
2566 ok(ret, "Failed to set foreground window.\n");
2567 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2568 memset(&devmode, 0, sizeof(devmode));
2569 devmode.dmSize = sizeof(devmode);
2570 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2571 ok(ret, "Failed to get display mode.\n");
2572 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2573 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
2574 devmode.dmPelsWidth, devmode.dmPelsHeight);
2576 expect_messages = exclusive_focus_restore_messages;
2577 ShowWindow(window, SW_RESTORE);
2578 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2580 GetWindowRect(window, &r);
2581 ok(EqualRect(&r, &ddraw_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2582 ddraw_rect.left, ddraw_rect.top, ddraw_rect.right, ddraw_rect.bottom,
2583 r.left, r.top, r.right, r.bottom);
2584 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2585 ok(ret, "Failed to get display mode.\n");
2586 ok(devmode.dmPelsWidth == param.ddraw_width
2587 && devmode.dmPelsHeight == param.ddraw_height, "Got unexpect screen size %ux%u.\n",
2588 devmode.dmPelsWidth, devmode.dmPelsHeight);
2590 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2591 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2592 /* Normally the primary should be restored here. Unfortunately this causes the
2593 * GetSurfaceDesc call after the next display mode change to crash on the Windows 8
2594 * testbot. Another Restore call would presumably avoid the crash, but it also moots
2595 * the point of the GetSurfaceDesc call. */
2597 expect_messages = sc_minimize_messages;
2598 SendMessageA(window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
2599 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2600 expect_messages = NULL;
2602 expect_messages = sc_restore_messages;
2603 SendMessageA(window, WM_SYSCOMMAND, SC_RESTORE, 0);
2604 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2605 expect_messages = NULL;
2607 expect_messages = sc_maximize_messages;
2608 SendMessageA(window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
2609 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2610 expect_messages = NULL;
2612 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2613 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2615 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2616 expect_messages = exclusive_messages;
2617 screen_size.cx = 0;
2618 screen_size.cy = 0;
2620 hr = IDirectDrawSurface7_IsLost(primary);
2621 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2622 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
2623 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2624 hr = IDirectDrawSurface7_IsLost(primary);
2625 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2627 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2628 expect_messages = NULL;
2629 ok(screen_size.cx == registry_mode.dmPelsWidth
2630 && screen_size.cy == registry_mode.dmPelsHeight,
2631 "Expected screen size %ux%u, got %ux%u.\n",
2632 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size.cx, screen_size.cy);
2634 GetWindowRect(window, &r);
2635 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2636 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2637 r.left, r.top, r.right, r.bottom);
2639 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2640 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2641 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2642 param.ddraw_width, ddsd.dwWidth);
2643 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2644 param.ddraw_height, ddsd.dwHeight);
2645 IDirectDrawSurface7_Release(primary);
2647 /* For Wine. */
2648 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
2649 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2651 memset(&ddsd, 0, sizeof(ddsd));
2652 ddsd.dwSize = sizeof(ddsd);
2653 ddsd.dwFlags = DDSD_CAPS;
2654 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2656 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2657 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2658 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2659 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2660 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2661 registry_mode.dmPelsWidth, ddsd.dwWidth);
2662 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2663 registry_mode.dmPelsHeight, ddsd.dwHeight);
2665 GetWindowRect(window, &r);
2666 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2667 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2668 r.left, r.top, r.right, r.bottom);
2670 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2671 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2673 GetWindowRect(window, &r);
2674 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2675 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2676 r.left, r.top, r.right, r.bottom);
2678 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2679 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2680 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2681 registry_mode.dmPelsWidth, ddsd.dwWidth);
2682 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2683 registry_mode.dmPelsHeight, ddsd.dwHeight);
2684 IDirectDrawSurface7_Release(primary);
2686 memset(&ddsd, 0, sizeof(ddsd));
2687 ddsd.dwSize = sizeof(ddsd);
2688 ddsd.dwFlags = DDSD_CAPS;
2689 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2691 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2692 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2693 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2694 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2695 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2696 registry_mode.dmPelsWidth, ddsd.dwWidth);
2697 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2698 registry_mode.dmPelsHeight, ddsd.dwHeight);
2700 GetWindowRect(window, &r);
2701 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2702 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2703 r.left, r.top, r.right, r.bottom);
2705 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2706 expect_messages = normal_messages;
2707 screen_size.cx = 0;
2708 screen_size.cy = 0;
2710 hr = IDirectDrawSurface7_IsLost(primary);
2711 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2712 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2713 devmode.dmPelsWidth = param.user32_width;
2714 devmode.dmPelsHeight = param.user32_height;
2715 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2716 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2717 hr = IDirectDrawSurface7_IsLost(primary);
2718 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2720 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2721 expect_messages = NULL;
2722 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2724 GetWindowRect(window, &r);
2725 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2726 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2727 r.left, r.top, r.right, r.bottom);
2729 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2730 expect_messages = normal_messages;
2731 screen_size.cx = 0;
2732 screen_size.cy = 0;
2734 hr = IDirectDrawSurface7_Restore(primary);
2735 todo_wine ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2736 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2737 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2738 hr = IDirectDrawSurface7_Restore(primary);
2739 todo_wine ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2740 hr = IDirectDrawSurface7_IsLost(primary);
2741 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2743 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2744 expect_messages = NULL;
2745 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2747 GetWindowRect(window, &r);
2748 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2749 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2750 r.left, r.top, r.right, r.bottom);
2752 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2753 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2754 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2755 registry_mode.dmPelsWidth, ddsd.dwWidth);
2756 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2757 registry_mode.dmPelsHeight, ddsd.dwHeight);
2758 IDirectDrawSurface7_Release(primary);
2760 memset(&ddsd, 0, sizeof(ddsd));
2761 ddsd.dwSize = sizeof(ddsd);
2762 ddsd.dwFlags = DDSD_CAPS;
2763 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2765 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2766 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2767 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2768 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2769 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2770 param.ddraw_width, ddsd.dwWidth);
2771 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2772 param.ddraw_height, ddsd.dwHeight);
2774 GetWindowRect(window, &r);
2775 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2776 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2777 r.left, r.top, r.right, r.bottom);
2779 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2780 expect_messages = normal_messages;
2781 screen_size.cx = 0;
2782 screen_size.cy = 0;
2784 hr = IDirectDrawSurface7_IsLost(primary);
2785 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2786 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
2787 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2788 hr = IDirectDrawSurface7_IsLost(primary);
2789 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2791 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2792 expect_messages = NULL;
2793 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2795 GetWindowRect(window, &r);
2796 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2797 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2798 r.left, r.top, r.right, r.bottom);
2800 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2801 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2802 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2803 param.ddraw_width, ddsd.dwWidth);
2804 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2805 param.ddraw_height, ddsd.dwHeight);
2806 IDirectDrawSurface7_Release(primary);
2808 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2809 ok(ret, "Failed to get display mode.\n");
2810 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2811 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
2812 "Expected resolution %ux%u, got %ux%u.\n",
2813 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
2814 devmode.dmPelsWidth, devmode.dmPelsHeight);
2815 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
2816 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2818 memset(&ddsd, 0, sizeof(ddsd));
2819 ddsd.dwSize = sizeof(ddsd);
2820 ddsd.dwFlags = DDSD_CAPS;
2821 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2823 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2824 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2825 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2826 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2827 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2828 registry_mode.dmPelsWidth, ddsd.dwWidth);
2829 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2830 registry_mode.dmPelsHeight, ddsd.dwHeight);
2832 GetWindowRect(window, &r);
2833 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2834 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2835 r.left, r.top, r.right, r.bottom);
2837 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
2838 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
2839 * not DDSCL_FULLSCREEN. */
2840 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2841 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2843 GetWindowRect(window, &r);
2844 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2845 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2846 r.left, r.top, r.right, r.bottom);
2848 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2849 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2850 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2851 registry_mode.dmPelsWidth, ddsd.dwWidth);
2852 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2853 registry_mode.dmPelsHeight, ddsd.dwHeight);
2854 IDirectDrawSurface7_Release(primary);
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);
2870 GetWindowRect(window, &r);
2871 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2872 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2873 r.left, r.top, r.right, r.bottom);
2875 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2876 expect_messages = normal_messages;
2877 screen_size.cx = 0;
2878 screen_size.cy = 0;
2880 hr = IDirectDrawSurface7_IsLost(primary);
2881 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2882 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2883 devmode.dmPelsWidth = param.user32_width;
2884 devmode.dmPelsHeight = param.user32_height;
2885 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2886 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2887 hr = IDirectDrawSurface7_IsLost(primary);
2888 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected 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 && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2894 GetWindowRect(window, &r);
2895 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2896 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2897 r.left, r.top, r.right, r.bottom);
2899 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2900 expect_messages = normal_messages;
2901 screen_size.cx = 0;
2902 screen_size.cy = 0;
2904 hr = IDirectDrawSurface7_Restore(primary);
2905 todo_wine ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2906 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2907 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2908 hr = IDirectDrawSurface7_Restore(primary);
2909 todo_wine ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2910 hr = IDirectDrawSurface7_IsLost(primary);
2911 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2913 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2914 expect_messages = NULL;
2915 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2917 GetWindowRect(window, &r);
2918 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2919 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2920 r.left, r.top, r.right, r.bottom);
2922 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2923 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2924 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2925 registry_mode.dmPelsWidth, ddsd.dwWidth);
2926 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2927 registry_mode.dmPelsHeight, ddsd.dwHeight);
2928 IDirectDrawSurface7_Release(primary);
2930 memset(&ddsd, 0, sizeof(ddsd));
2931 ddsd.dwSize = sizeof(ddsd);
2932 ddsd.dwFlags = DDSD_CAPS;
2933 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2935 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2936 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2937 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2938 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2939 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2940 param.ddraw_width, ddsd.dwWidth);
2941 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2942 param.ddraw_height, ddsd.dwHeight);
2944 GetWindowRect(window, &r);
2945 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2946 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2947 r.left, r.top, r.right, r.bottom);
2949 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2950 expect_messages = normal_messages;
2951 screen_size.cx = 0;
2952 screen_size.cy = 0;
2954 hr = IDirectDrawSurface7_IsLost(primary);
2955 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2956 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
2957 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2958 hr = IDirectDrawSurface7_IsLost(primary);
2959 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected 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", screen_size.cx, screen_size.cy);
2965 GetWindowRect(window, &r);
2966 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2967 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
2968 r.left, r.top, r.right, r.bottom);
2970 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2971 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2972 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2973 param.ddraw_width, ddsd.dwWidth);
2974 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2975 param.ddraw_height, ddsd.dwHeight);
2976 IDirectDrawSurface7_Release(primary);
2978 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2979 ok(ret, "Failed to get display mode.\n");
2980 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2981 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
2982 "Expected resolution %ux%u, got %ux%u.\n",
2983 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
2984 devmode.dmPelsWidth, devmode.dmPelsHeight);
2985 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
2986 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2988 memset(&ddsd, 0, sizeof(ddsd));
2989 ddsd.dwSize = sizeof(ddsd);
2990 ddsd.dwFlags = DDSD_CAPS;
2991 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2993 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2994 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2995 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2996 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2997 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2998 registry_mode.dmPelsWidth, ddsd.dwWidth);
2999 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3000 registry_mode.dmPelsHeight, ddsd.dwHeight);
3001 IDirectDrawSurface7_Release(primary);
3003 GetWindowRect(window, &r);
3004 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3005 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
3006 r.left, r.top, r.right, r.bottom);
3008 /* Changing the coop level from EXCLUSIVE to NORMAL restores the screen resolution */
3009 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3010 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3011 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3012 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3014 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3015 expect_messages = exclusive_messages;
3016 screen_size.cx = 0;
3017 screen_size.cy = 0;
3019 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3020 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3022 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3023 expect_messages = NULL;
3024 ok(screen_size.cx == registry_mode.dmPelsWidth
3025 && screen_size.cy == registry_mode.dmPelsHeight,
3026 "Expected screen size %ux%u, got %ux%u.\n",
3027 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3028 screen_size.cx, screen_size.cy);
3030 GetWindowRect(window, &r);
3031 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3032 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
3033 r.left, r.top, r.right, r.bottom);
3035 memset(&ddsd, 0, sizeof(ddsd));
3036 ddsd.dwSize = sizeof(ddsd);
3037 ddsd.dwFlags = DDSD_CAPS;
3038 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3040 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3041 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3042 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3043 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3044 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3045 registry_mode.dmPelsWidth, ddsd.dwWidth);
3046 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3047 registry_mode.dmPelsHeight, ddsd.dwHeight);
3048 IDirectDrawSurface7_Release(primary);
3050 /* The screen restore is a property of DDSCL_EXCLUSIVE */
3051 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3052 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3053 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3054 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3056 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3057 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3059 memset(&ddsd, 0, sizeof(ddsd));
3060 ddsd.dwSize = sizeof(ddsd);
3061 ddsd.dwFlags = DDSD_CAPS;
3062 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3064 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3065 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3066 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3067 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3068 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3069 param.ddraw_width, ddsd.dwWidth);
3070 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3071 param.ddraw_height, ddsd.dwHeight);
3072 IDirectDrawSurface7_Release(primary);
3074 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
3075 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3077 /* If the window is changed at the same time, messages are sent to the new window. */
3078 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3079 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3080 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3081 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3083 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3084 expect_messages = exclusive_messages;
3085 screen_size.cx = 0;
3086 screen_size.cy = 0;
3087 screen_size2.cx = 0;
3088 screen_size2.cy = 0;
3090 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3091 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3093 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3094 expect_messages = NULL;
3095 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n",
3096 screen_size.cx, screen_size.cy);
3097 ok(screen_size2.cx == registry_mode.dmPelsWidth && screen_size2.cy == registry_mode.dmPelsHeight,
3098 "Expected screen size 2 %ux%u, got %ux%u.\n",
3099 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size2.cx, screen_size2.cy);
3101 GetWindowRect(window, &r);
3102 ok(EqualRect(&r, &ddraw_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3103 ddraw_rect.left, ddraw_rect.top, ddraw_rect.right, ddraw_rect.bottom,
3104 r.left, r.top, r.right, r.bottom);
3105 GetWindowRect(window2, &r);
3106 ok(EqualRect(&r, &registry_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3107 registry_rect.left, registry_rect.top, registry_rect.right, registry_rect.bottom,
3108 r.left, r.top, r.right, r.bottom);
3110 memset(&ddsd, 0, sizeof(ddsd));
3111 ddsd.dwSize = sizeof(ddsd);
3112 ddsd.dwFlags = DDSD_CAPS;
3113 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3115 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3116 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3117 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3118 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3119 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3120 registry_mode.dmPelsWidth, ddsd.dwWidth);
3121 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3122 registry_mode.dmPelsHeight, ddsd.dwHeight);
3123 IDirectDrawSurface7_Release(primary);
3125 ref = IDirectDraw7_Release(ddraw);
3126 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3128 GetWindowRect(window, &r);
3129 ok(EqualRect(&r, &ddraw_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3130 ddraw_rect.left, ddraw_rect.top, ddraw_rect.right, ddraw_rect.bottom,
3131 r.left, r.top, r.right, r.bottom);
3133 expect_messages = NULL;
3134 DestroyWindow(window);
3135 DestroyWindow(window2);
3136 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
3137 UnregisterClassA("ddraw_test_wndproc_wc2", GetModuleHandleA(NULL));
3140 static void test_coop_level_mode_set_multi(void)
3142 IDirectDraw7 *ddraw1, *ddraw2;
3143 UINT w, h;
3144 HWND window;
3145 HRESULT hr;
3146 ULONG ref;
3148 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3149 0, 0, 100, 100, 0, 0, 0, 0);
3150 ddraw1 = create_ddraw();
3151 ok(!!ddraw1, "Failed to create a ddraw object.\n");
3153 /* With just a single ddraw object, the display mode is restored on
3154 * release. */
3155 hr = set_display_mode(ddraw1, 800, 600);
3156 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3157 w = GetSystemMetrics(SM_CXSCREEN);
3158 ok(w == 800, "Got unexpected screen width %u.\n", w);
3159 h = GetSystemMetrics(SM_CYSCREEN);
3160 ok(h == 600, "Got unexpected screen height %u.\n", h);
3162 ref = IDirectDraw7_Release(ddraw1);
3163 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3164 w = GetSystemMetrics(SM_CXSCREEN);
3165 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3166 h = GetSystemMetrics(SM_CYSCREEN);
3167 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3169 /* When there are multiple ddraw objects, the display mode is restored to
3170 * the initial mode, before the first SetDisplayMode() call. */
3171 ddraw1 = create_ddraw();
3172 hr = set_display_mode(ddraw1, 800, 600);
3173 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3174 w = GetSystemMetrics(SM_CXSCREEN);
3175 ok(w == 800, "Got unexpected screen width %u.\n", w);
3176 h = GetSystemMetrics(SM_CYSCREEN);
3177 ok(h == 600, "Got unexpected screen height %u.\n", h);
3179 ddraw2 = create_ddraw();
3180 hr = set_display_mode(ddraw2, 640, 480);
3181 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3182 w = GetSystemMetrics(SM_CXSCREEN);
3183 ok(w == 640, "Got unexpected screen width %u.\n", w);
3184 h = GetSystemMetrics(SM_CYSCREEN);
3185 ok(h == 480, "Got unexpected screen height %u.\n", h);
3187 ref = IDirectDraw7_Release(ddraw2);
3188 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3189 w = GetSystemMetrics(SM_CXSCREEN);
3190 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3191 h = GetSystemMetrics(SM_CYSCREEN);
3192 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3194 ref = IDirectDraw7_Release(ddraw1);
3195 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3196 w = GetSystemMetrics(SM_CXSCREEN);
3197 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3198 h = GetSystemMetrics(SM_CYSCREEN);
3199 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3201 /* Regardless of release ordering. */
3202 ddraw1 = create_ddraw();
3203 hr = set_display_mode(ddraw1, 800, 600);
3204 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3205 w = GetSystemMetrics(SM_CXSCREEN);
3206 ok(w == 800, "Got unexpected screen width %u.\n", w);
3207 h = GetSystemMetrics(SM_CYSCREEN);
3208 ok(h == 600, "Got unexpected screen height %u.\n", h);
3210 ddraw2 = create_ddraw();
3211 hr = set_display_mode(ddraw2, 640, 480);
3212 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3213 w = GetSystemMetrics(SM_CXSCREEN);
3214 ok(w == 640, "Got unexpected screen width %u.\n", w);
3215 h = GetSystemMetrics(SM_CYSCREEN);
3216 ok(h == 480, "Got unexpected screen height %u.\n", h);
3218 ref = IDirectDraw7_Release(ddraw1);
3219 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3220 w = GetSystemMetrics(SM_CXSCREEN);
3221 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3222 h = GetSystemMetrics(SM_CYSCREEN);
3223 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3225 ref = IDirectDraw7_Release(ddraw2);
3226 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3227 w = GetSystemMetrics(SM_CXSCREEN);
3228 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3229 h = GetSystemMetrics(SM_CYSCREEN);
3230 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3232 /* But only for ddraw objects that called SetDisplayMode(). */
3233 ddraw1 = create_ddraw();
3234 ddraw2 = create_ddraw();
3235 hr = set_display_mode(ddraw2, 640, 480);
3236 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3237 w = GetSystemMetrics(SM_CXSCREEN);
3238 ok(w == 640, "Got unexpected screen width %u.\n", w);
3239 h = GetSystemMetrics(SM_CYSCREEN);
3240 ok(h == 480, "Got unexpected screen height %u.\n", h);
3242 ref = IDirectDraw7_Release(ddraw1);
3243 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3244 w = GetSystemMetrics(SM_CXSCREEN);
3245 ok(w == 640, "Got unexpected screen width %u.\n", w);
3246 h = GetSystemMetrics(SM_CYSCREEN);
3247 ok(h == 480, "Got unexpected screen height %u.\n", h);
3249 ref = IDirectDraw7_Release(ddraw2);
3250 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3251 w = GetSystemMetrics(SM_CXSCREEN);
3252 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3253 h = GetSystemMetrics(SM_CYSCREEN);
3254 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3256 /* If there's a ddraw object that's currently in exclusive mode, it blocks
3257 * restoring the display mode. */
3258 ddraw1 = create_ddraw();
3259 hr = set_display_mode(ddraw1, 800, 600);
3260 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3261 w = GetSystemMetrics(SM_CXSCREEN);
3262 ok(w == 800, "Got unexpected screen width %u.\n", w);
3263 h = GetSystemMetrics(SM_CYSCREEN);
3264 ok(h == 600, "Got unexpected screen height %u.\n", h);
3266 ddraw2 = create_ddraw();
3267 hr = set_display_mode(ddraw2, 640, 480);
3268 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3269 w = GetSystemMetrics(SM_CXSCREEN);
3270 ok(w == 640, "Got unexpected screen width %u.\n", w);
3271 h = GetSystemMetrics(SM_CYSCREEN);
3272 ok(h == 480, "Got unexpected screen height %u.\n", h);
3274 hr = IDirectDraw7_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3275 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3277 ref = IDirectDraw7_Release(ddraw1);
3278 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3279 w = GetSystemMetrics(SM_CXSCREEN);
3280 ok(w == 640, "Got unexpected screen width %u.\n", w);
3281 h = GetSystemMetrics(SM_CYSCREEN);
3282 ok(h == 480, "Got unexpected screen height %u.\n", h);
3284 ref = IDirectDraw7_Release(ddraw2);
3285 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3286 w = GetSystemMetrics(SM_CXSCREEN);
3287 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3288 h = GetSystemMetrics(SM_CYSCREEN);
3289 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3291 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
3292 ddraw1 = create_ddraw();
3293 hr = set_display_mode(ddraw1, 800, 600);
3294 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3295 w = GetSystemMetrics(SM_CXSCREEN);
3296 ok(w == 800, "Got unexpected screen width %u.\n", w);
3297 h = GetSystemMetrics(SM_CYSCREEN);
3298 ok(h == 600, "Got unexpected screen height %u.\n", h);
3300 hr = IDirectDraw7_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3301 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3303 ddraw2 = create_ddraw();
3304 hr = set_display_mode(ddraw2, 640, 480);
3305 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
3307 ref = IDirectDraw7_Release(ddraw1);
3308 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3309 w = GetSystemMetrics(SM_CXSCREEN);
3310 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3311 h = GetSystemMetrics(SM_CYSCREEN);
3312 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3314 ref = IDirectDraw7_Release(ddraw2);
3315 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3316 w = GetSystemMetrics(SM_CXSCREEN);
3317 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3318 h = GetSystemMetrics(SM_CYSCREEN);
3319 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3321 DestroyWindow(window);
3324 static void test_initialize(void)
3326 IDirectDraw7 *ddraw;
3327 HRESULT hr;
3329 ddraw = create_ddraw();
3330 ok(!!ddraw, "Failed to create a ddraw object.\n");
3332 hr = IDirectDraw7_Initialize(ddraw, NULL);
3333 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
3334 IDirectDraw7_Release(ddraw);
3336 CoInitialize(NULL);
3337 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw7, (void **)&ddraw);
3338 ok(SUCCEEDED(hr), "Failed to create IDirectDraw7 instance, hr %#x.\n", hr);
3339 hr = IDirectDraw7_Initialize(ddraw, NULL);
3340 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
3341 hr = IDirectDraw7_Initialize(ddraw, NULL);
3342 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
3343 IDirectDraw7_Release(ddraw);
3344 CoUninitialize();
3347 static void test_coop_level_surf_create(void)
3349 IDirectDrawSurface7 *surface;
3350 IDirectDraw7 *ddraw;
3351 DDSURFACEDESC2 ddsd;
3352 HRESULT hr;
3354 ddraw = create_ddraw();
3355 ok(!!ddraw, "Failed to create a ddraw object.\n");
3357 memset(&ddsd, 0, sizeof(ddsd));
3358 ddsd.dwSize = sizeof(ddsd);
3359 ddsd.dwFlags = DDSD_CAPS;
3360 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3361 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
3362 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
3364 IDirectDraw7_Release(ddraw);
3367 static void test_vb_discard(void)
3369 static const struct vec4 quad[] =
3371 { 0.0f, 480.0f, 0.0f, 1.0f},
3372 { 0.0f, 0.0f, 0.0f, 1.0f},
3373 {640.0f, 480.0f, 0.0f, 1.0f},
3374 {640.0f, 0.0f, 0.0f, 1.0f},
3377 IDirect3DDevice7 *device;
3378 IDirect3D7 *d3d;
3379 IDirect3DVertexBuffer7 *buffer;
3380 HWND window;
3381 HRESULT hr;
3382 D3DVERTEXBUFFERDESC desc;
3383 BYTE *data;
3384 static const unsigned int vbsize = 16;
3385 unsigned int i;
3387 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3388 0, 0, 640, 480, 0, 0, 0, 0);
3390 if (!(device = create_device(window, DDSCL_NORMAL)))
3392 skip("Failed to create a 3D device, skipping test.\n");
3393 DestroyWindow(window);
3394 return;
3397 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
3398 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
3400 memset(&desc, 0, sizeof(desc));
3401 desc.dwSize = sizeof(desc);
3402 desc.dwCaps = D3DVBCAPS_WRITEONLY;
3403 desc.dwFVF = D3DFVF_XYZRHW;
3404 desc.dwNumVertices = vbsize;
3405 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &buffer, 0);
3406 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
3408 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3409 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3410 memcpy(data, quad, sizeof(quad));
3411 hr = IDirect3DVertexBuffer7_Unlock(buffer);
3412 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3414 hr = IDirect3DDevice7_BeginScene(device);
3415 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3416 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
3417 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3418 hr = IDirect3DDevice7_EndScene(device);
3419 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3421 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3422 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3423 memset(data, 0xaa, sizeof(struct vec4) * vbsize);
3424 hr = IDirect3DVertexBuffer7_Unlock(buffer);
3425 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3427 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3428 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3429 for (i = 0; i < sizeof(struct vec4) * vbsize; i++)
3431 if (data[i] != 0xaa)
3433 ok(FALSE, "Vertex buffer data byte %u is 0x%02x, expected 0xaa\n", i, data[i]);
3434 break;
3437 hr = IDirect3DVertexBuffer7_Unlock(buffer);
3438 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3440 IDirect3DVertexBuffer7_Release(buffer);
3441 IDirect3D7_Release(d3d);
3442 IDirect3DDevice7_Release(device);
3443 DestroyWindow(window);
3446 static void test_coop_level_multi_window(void)
3448 HWND window1, window2;
3449 IDirectDraw7 *ddraw;
3450 HRESULT hr;
3452 window1 = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
3453 0, 0, 640, 480, 0, 0, 0, 0);
3454 window2 = CreateWindowA("static", "ddraw_test2", WS_OVERLAPPEDWINDOW,
3455 0, 0, 640, 480, 0, 0, 0, 0);
3456 ddraw = create_ddraw();
3457 ok(!!ddraw, "Failed to create a ddraw object.\n");
3459 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
3460 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3461 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3462 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3463 ok(IsWindow(window1), "Window 1 was destroyed.\n");
3464 ok(IsWindow(window2), "Window 2 was destroyed.\n");
3466 IDirectDraw7_Release(ddraw);
3467 DestroyWindow(window2);
3468 DestroyWindow(window1);
3471 static void test_draw_strided(void)
3473 static struct vec3 position[] =
3475 {-1.0, -1.0, 0.0},
3476 {-1.0, 1.0, 0.0},
3477 { 1.0, 1.0, 0.0},
3478 { 1.0, -1.0, 0.0},
3480 static DWORD diffuse[] =
3482 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
3484 static WORD indices[] =
3486 0, 1, 2, 2, 3, 0
3489 IDirectDrawSurface7 *rt;
3490 IDirect3DDevice7 *device;
3491 D3DCOLOR color;
3492 HWND window;
3493 HRESULT hr;
3494 D3DDRAWPRIMITIVESTRIDEDDATA strided;
3496 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3497 0, 0, 640, 480, 0, 0, 0, 0);
3499 if (!(device = create_device(window, DDSCL_NORMAL)))
3501 skip("Failed to create a 3D device, skipping test.\n");
3502 DestroyWindow(window);
3503 return;
3506 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
3507 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3509 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
3510 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
3511 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 1.0f, 0);
3512 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
3513 hr = IDirect3DDevice7_BeginScene(device);
3514 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3516 memset(&strided, 0x55, sizeof(strided));
3517 strided.position.lpvData = position;
3518 strided.position.dwStride = sizeof(*position);
3519 strided.diffuse.lpvData = diffuse;
3520 strided.diffuse.dwStride = sizeof(*diffuse);
3521 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device, D3DPT_TRIANGLELIST, D3DFVF_XYZ | D3DFVF_DIFFUSE,
3522 &strided, 4, indices, 6, 0);
3523 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3525 hr = IDirect3DDevice7_EndScene(device);
3526 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3528 color = get_surface_color(rt, 320, 240);
3529 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
3531 IDirectDrawSurface7_Release(rt);
3532 IDirect3DDevice7_Release(device);
3533 DestroyWindow(window);
3536 static void test_lighting(void)
3538 static D3DMATRIX mat =
3540 1.0f, 0.0f, 0.0f, 0.0f,
3541 0.0f, 1.0f, 0.0f, 0.0f,
3542 0.0f, 0.0f, 1.0f, 0.0f,
3543 0.0f, 0.0f, 0.0f, 1.0f,
3545 mat_singular =
3547 1.0f, 0.0f, 1.0f, 0.0f,
3548 0.0f, 1.0f, 0.0f, 0.0f,
3549 1.0f, 0.0f, 1.0f, 0.0f,
3550 0.0f, 0.0f, 0.5f, 1.0f,
3552 mat_transf =
3554 0.0f, 0.0f, 1.0f, 0.0f,
3555 0.0f, 1.0f, 0.0f, 0.0f,
3556 -1.0f, 0.0f, 0.0f, 0.0f,
3557 10.f, 10.0f, 10.0f, 1.0f,
3559 mat_nonaffine =
3561 1.0f, 0.0f, 0.0f, 0.0f,
3562 0.0f, 1.0f, 0.0f, 0.0f,
3563 0.0f, 0.0f, 1.0f, -1.0f,
3564 10.f, 10.0f, 10.0f, 0.0f,
3566 static struct
3568 struct vec3 position;
3569 DWORD diffuse;
3571 unlitquad[] =
3573 {{-1.0f, -1.0f, 0.1f}, 0xffff0000},
3574 {{-1.0f, 0.0f, 0.1f}, 0xffff0000},
3575 {{ 0.0f, 0.0f, 0.1f}, 0xffff0000},
3576 {{ 0.0f, -1.0f, 0.1f}, 0xffff0000},
3578 litquad[] =
3580 {{-1.0f, 0.0f, 0.1f}, 0xff00ff00},
3581 {{-1.0f, 1.0f, 0.1f}, 0xff00ff00},
3582 {{ 0.0f, 1.0f, 0.1f}, 0xff00ff00},
3583 {{ 0.0f, 0.0f, 0.1f}, 0xff00ff00},
3585 static struct
3587 struct vec3 position;
3588 struct vec3 normal;
3589 DWORD diffuse;
3591 unlitnquad[] =
3593 {{0.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3594 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3595 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3596 {{1.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3598 litnquad[] =
3600 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3601 {{0.0f, 1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3602 {{1.0f, 1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3603 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3605 nquad[] =
3607 {{-1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3608 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3609 {{ 1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3610 {{ 1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3612 rotatedquad[] =
3614 {{-10.0f, -11.0f, 11.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3615 {{-10.0f, -9.0f, 11.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3616 {{-10.0f, -9.0f, 9.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3617 {{-10.0f, -11.0f, 9.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3619 translatedquad[] =
3621 {{-11.0f, -11.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3622 {{-11.0f, -9.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3623 {{ -9.0f, -9.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3624 {{ -9.0f, -11.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3626 static WORD indices[] = {0, 1, 2, 2, 3, 0};
3627 static const struct
3629 D3DMATRIX *world_matrix;
3630 void *quad;
3631 DWORD expected;
3632 const char *message;
3634 tests[] =
3636 {&mat, nquad, 0x000000ff, "Lit quad with light"},
3637 {&mat_singular, nquad, 0x000000ff, "Lit quad with singular world matrix"},
3638 {&mat_transf, rotatedquad, 0x000000ff, "Lit quad with transformation matrix"},
3639 {&mat_nonaffine, translatedquad, 0x00000000, "Lit quad with non-affine matrix"},
3642 HWND window;
3643 IDirect3DDevice7 *device;
3644 IDirectDrawSurface7 *rt;
3645 HRESULT hr;
3646 DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
3647 DWORD nfvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL;
3648 D3DCOLOR color;
3649 ULONG refcount;
3650 unsigned int i;
3652 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3653 0, 0, 640, 480, 0, 0, 0, 0);
3654 if (!(device = create_device(window, DDSCL_NORMAL)))
3656 skip("Failed to create a 3D device, skipping test.\n");
3657 DestroyWindow(window);
3658 return;
3661 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
3662 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3664 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
3665 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
3667 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
3668 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
3669 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
3670 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
3671 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
3672 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
3673 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
3674 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
3675 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
3676 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
3677 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
3678 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
3679 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
3680 ok(SUCCEEDED(hr), "Failed to disable stencil buffering, hr %#x.\n", hr);
3681 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
3682 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
3684 hr = IDirect3DDevice7_BeginScene(device);
3685 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3687 /* No lights are defined... That means, lit vertices should be entirely black. */
3688 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
3689 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
3690 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, unlitquad, 4,
3691 indices, 6, 0);
3692 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3694 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
3695 ok(SUCCEEDED(hr), "Failed to enable lighting, hr %#x.\n", hr);
3696 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, litquad, 4,
3697 indices, 6, 0);
3698 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3700 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
3701 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
3702 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, unlitnquad, 4,
3703 indices, 6, 0);
3704 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3706 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
3707 ok(SUCCEEDED(hr), "Failed to enable lighting, hr %#x.\n", hr);
3708 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, litnquad, 4,
3709 indices, 6, 0);
3710 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3712 hr = IDirect3DDevice7_EndScene(device);
3713 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3715 color = get_surface_color(rt, 160, 360);
3716 ok(color == 0x00ff0000, "Unlit quad without normals has color 0x%08x, expected 0x00ff0000.\n", color);
3717 color = get_surface_color(rt, 160, 120);
3718 ok(color == 0x00000000, "Lit quad without normals has color 0x%08x, expected 0x00000000.\n", color);
3719 color = get_surface_color(rt, 480, 360);
3720 ok(color == 0x000000ff, "Unlit quad with normals has color 0x%08x, expected 0x000000ff.\n", color);
3721 color = get_surface_color(rt, 480, 120);
3722 ok(color == 0x00000000, "Lit quad with normals has color 0x%08x, expected 0x00000000.\n", color);
3724 hr = IDirect3DDevice7_LightEnable(device, 0, TRUE);
3725 ok(SUCCEEDED(hr), "Failed to enable light 0, hr %#x.\n", hr);
3727 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
3729 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, tests[i].world_matrix);
3730 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
3732 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
3733 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
3735 hr = IDirect3DDevice7_BeginScene(device);
3736 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3738 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, tests[i].quad,
3739 4, indices, 6, 0);
3740 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3742 hr = IDirect3DDevice7_EndScene(device);
3743 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3745 color = get_surface_color(rt, 320, 240);
3746 ok(color == tests[i].expected, "%s has color 0x%08x.\n", tests[i].message, color);
3749 IDirectDrawSurface7_Release(rt);
3751 refcount = IDirect3DDevice7_Release(device);
3752 ok(!refcount, "Device has %u references left.\n", refcount);
3753 DestroyWindow(window);
3756 static void test_specular_lighting(void)
3758 static const unsigned int vertices_side = 5;
3759 const unsigned int indices_count = (vertices_side - 1) * (vertices_side - 1) * 2 * 3;
3760 static const DWORD fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3761 static D3DMATRIX mat =
3763 1.0f, 0.0f, 0.0f, 0.0f,
3764 0.0f, 1.0f, 0.0f, 0.0f,
3765 0.0f, 0.0f, 1.0f, 0.0f,
3766 0.0f, 0.0f, 0.0f, 1.0f,
3768 static D3DLIGHT7 directional =
3770 D3DLIGHT_DIRECTIONAL,
3771 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3772 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
3773 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3774 {{0.0f}, {0.0f}, {0.0f}},
3775 {{0.0f}, {0.0f}, {1.0f}},
3777 point =
3779 D3DLIGHT_POINT,
3780 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3781 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
3782 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3783 {{0.0f}, {0.0f}, {0.0f}},
3784 {{0.0f}, {0.0f}, {0.0f}},
3785 100.0f,
3786 0.0f,
3787 0.0f, 0.0f, 1.0f,
3789 spot =
3791 D3DLIGHT_SPOT,
3792 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3793 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
3794 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3795 {{0.0f}, {0.0f}, {0.0f}},
3796 {{0.0f}, {0.0f}, {1.0f}},
3797 100.0f,
3798 1.0f,
3799 0.0f, 0.0f, 1.0f,
3800 M_PI / 12.0f, M_PI / 3.0f
3802 /* The chosen range value makes the test fail when using a manhattan
3803 * distance metric vs the correct euclidean distance. */
3804 point_range =
3806 D3DLIGHT_POINT,
3807 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3808 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
3809 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3810 {{0.0f}, {0.0f}, {0.0f}},
3811 {{0.0f}, {0.0f}, {0.0f}},
3812 1.2f,
3813 0.0f,
3814 0.0f, 0.0f, 1.0f,
3816 static const struct expected_color
3818 unsigned int x, y;
3819 D3DCOLOR color;
3821 expected_directional[] =
3823 {160, 120, 0x00ffffff},
3824 {320, 120, 0x00ffffff},
3825 {480, 120, 0x00ffffff},
3826 {160, 240, 0x00ffffff},
3827 {320, 240, 0x00ffffff},
3828 {480, 240, 0x00ffffff},
3829 {160, 360, 0x00ffffff},
3830 {320, 360, 0x00ffffff},
3831 {480, 360, 0x00ffffff},
3833 expected_directional_local[] =
3835 {160, 120, 0x003c3c3c},
3836 {320, 120, 0x00717171},
3837 {480, 120, 0x003c3c3c},
3838 {160, 240, 0x00717171},
3839 {320, 240, 0x00ffffff},
3840 {480, 240, 0x00717171},
3841 {160, 360, 0x003c3c3c},
3842 {320, 360, 0x00717171},
3843 {480, 360, 0x003c3c3c},
3845 expected_point[] =
3847 {160, 120, 0x00282828},
3848 {320, 120, 0x005a5a5a},
3849 {480, 120, 0x00282828},
3850 {160, 240, 0x005a5a5a},
3851 {320, 240, 0x00ffffff},
3852 {480, 240, 0x005a5a5a},
3853 {160, 360, 0x00282828},
3854 {320, 360, 0x005a5a5a},
3855 {480, 360, 0x00282828},
3857 expected_point_local[] =
3859 {160, 120, 0x00000000},
3860 {320, 120, 0x00070707},
3861 {480, 120, 0x00000000},
3862 {160, 240, 0x00070707},
3863 {320, 240, 0x00ffffff},
3864 {480, 240, 0x00070707},
3865 {160, 360, 0x00000000},
3866 {320, 360, 0x00070707},
3867 {480, 360, 0x00000000},
3869 expected_spot[] =
3871 {160, 120, 0x00000000},
3872 {320, 120, 0x00141414},
3873 {480, 120, 0x00000000},
3874 {160, 240, 0x00141414},
3875 {320, 240, 0x00ffffff},
3876 {480, 240, 0x00141414},
3877 {160, 360, 0x00000000},
3878 {320, 360, 0x00141414},
3879 {480, 360, 0x00000000},
3881 expected_spot_local[] =
3883 {160, 120, 0x00000000},
3884 {320, 120, 0x00020202},
3885 {480, 120, 0x00000000},
3886 {160, 240, 0x00020202},
3887 {320, 240, 0x00ffffff},
3888 {480, 240, 0x00020202},
3889 {160, 360, 0x00000000},
3890 {320, 360, 0x00020202},
3891 {480, 360, 0x00000000},
3893 expected_point_range[] =
3895 {160, 120, 0x00000000},
3896 {320, 120, 0x005a5a5a},
3897 {480, 120, 0x00000000},
3898 {160, 240, 0x005a5a5a},
3899 {320, 240, 0x00ffffff},
3900 {480, 240, 0x005a5a5a},
3901 {160, 360, 0x00000000},
3902 {320, 360, 0x005a5a5a},
3903 {480, 360, 0x00000000},
3905 static const struct
3907 D3DLIGHT7 *light;
3908 BOOL local_viewer;
3909 const struct expected_color *expected;
3910 unsigned int expected_count;
3912 tests[] =
3914 {&directional, FALSE, expected_directional,
3915 sizeof(expected_directional) / sizeof(expected_directional[0])},
3916 {&directional, TRUE, expected_directional_local,
3917 sizeof(expected_directional_local) / sizeof(expected_directional_local[0])},
3918 {&point, FALSE, expected_point,
3919 sizeof(expected_point) / sizeof(expected_point[0])},
3920 {&point, TRUE, expected_point_local,
3921 sizeof(expected_point_local) / sizeof(expected_point_local[0])},
3922 {&spot, FALSE, expected_spot,
3923 sizeof(expected_spot) / sizeof(expected_spot[0])},
3924 {&spot, TRUE, expected_spot_local,
3925 sizeof(expected_spot_local) / sizeof(expected_spot_local[0])},
3926 {&point_range, FALSE, expected_point_range,
3927 sizeof(expected_point_range) / sizeof(expected_point_range[0])},
3929 IDirect3DDevice7 *device;
3930 IDirectDrawSurface7 *rt;
3931 D3DMATERIAL7 material;
3932 D3DCOLOR color;
3933 ULONG refcount;
3934 HWND window;
3935 HRESULT hr;
3936 unsigned int i, j, x, y;
3937 struct
3939 struct vec3 position;
3940 struct vec3 normal;
3941 } *quad;
3942 WORD *indices;
3944 quad = HeapAlloc(GetProcessHeap(), 0, vertices_side * vertices_side * sizeof(*quad));
3945 indices = HeapAlloc(GetProcessHeap(), 0, indices_count * sizeof(*indices));
3946 for (i = 0, y = 0; y < vertices_side; ++y)
3948 for (x = 0; x < vertices_side; ++x)
3950 quad[i].position.x = x * 2.0f / (vertices_side - 1) - 1.0f;
3951 quad[i].position.y = y * 2.0f / (vertices_side - 1) - 1.0f;
3952 quad[i].position.z = 1.0f;
3953 quad[i].normal.x = 0.0f;
3954 quad[i].normal.y = 0.0f;
3955 quad[i++].normal.z = -1.0f;
3958 for (i = 0, y = 0; y < (vertices_side - 1); ++y)
3960 for (x = 0; x < (vertices_side - 1); ++x)
3962 indices[i++] = y * vertices_side + x + 1;
3963 indices[i++] = y * vertices_side + x;
3964 indices[i++] = (y + 1) * vertices_side + x;
3965 indices[i++] = y * vertices_side + x + 1;
3966 indices[i++] = (y + 1) * vertices_side + x;
3967 indices[i++] = (y + 1) * vertices_side + x + 1;
3971 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3972 0, 0, 640, 480, 0, 0, 0, 0);
3973 if (!(device = create_device(window, DDSCL_NORMAL)))
3975 skip("Failed to create a 3D device, skipping test.\n");
3976 DestroyWindow(window);
3977 return;
3980 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
3981 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3983 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
3984 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
3985 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
3986 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
3987 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
3988 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
3989 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
3990 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
3991 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
3992 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
3993 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
3994 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
3996 memset(&material, 0, sizeof(material));
3997 U1(U2(material).specular).r = 1.0f;
3998 U2(U2(material).specular).g = 1.0f;
3999 U3(U2(material).specular).b = 1.0f;
4000 U4(U2(material).specular).a = 1.0f;
4001 U4(material).power = 30.0f;
4002 hr = IDirect3DDevice7_SetMaterial(device, &material);
4003 ok(SUCCEEDED(hr), "Failed to set material, hr %#x.\n", hr);
4005 hr = IDirect3DDevice7_LightEnable(device, 0, TRUE);
4006 ok(SUCCEEDED(hr), "Failed to enable light 0, hr %#x.\n", hr);
4007 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, TRUE);
4008 ok(SUCCEEDED(hr), "Failed to enable specular lighting, hr %#x.\n", hr);
4010 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
4012 hr = IDirect3DDevice7_SetLight(device, 0, tests[i].light);
4013 ok(SUCCEEDED(hr), "Failed to set light parameters, hr %#x.\n", hr);
4015 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LOCALVIEWER, tests[i].local_viewer);
4016 ok(SUCCEEDED(hr), "Failed to set local viewer state, hr %#x.\n", hr);
4018 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
4019 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
4021 hr = IDirect3DDevice7_BeginScene(device);
4022 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4024 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, quad,
4025 vertices_side * vertices_side, indices, indices_count, 0);
4026 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4028 hr = IDirect3DDevice7_EndScene(device);
4029 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4031 for (j = 0; j < tests[i].expected_count; ++j)
4033 color = get_surface_color(rt, tests[i].expected[j].x, tests[i].expected[j].y);
4034 ok(compare_color(color, tests[i].expected[j].color, 1),
4035 "Expected color 0x%08x at location (%u, %u), got 0x%08x, case %u.\n",
4036 tests[i].expected[j].color, tests[i].expected[j].x,
4037 tests[i].expected[j].y, color, i);
4041 IDirectDrawSurface7_Release(rt);
4043 refcount = IDirect3DDevice7_Release(device);
4044 ok(!refcount, "Device has %u references left.\n", refcount);
4045 DestroyWindow(window);
4046 HeapFree(GetProcessHeap(), 0, indices);
4047 HeapFree(GetProcessHeap(), 0, quad);
4050 static void test_clear_rect_count(void)
4052 IDirectDrawSurface7 *rt;
4053 IDirect3DDevice7 *device;
4054 D3DCOLOR color;
4055 HWND window;
4056 HRESULT hr;
4057 D3DRECT rect = {{0}, {0}, {640}, {480}};
4059 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4060 0, 0, 640, 480, 0, 0, 0, 0);
4061 if (!(device = create_device(window, DDSCL_NORMAL)))
4063 skip("Failed to create a 3D device, skipping test.\n");
4064 DestroyWindow(window);
4065 return;
4068 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
4069 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4071 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ffffff, 1.0f, 0);
4072 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4073 hr = IDirect3DDevice7_Clear(device, 0, &rect, D3DCLEAR_TARGET, 0x00ff0000, 1.0f, 0);
4074 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4076 color = get_surface_color(rt, 320, 240);
4077 ok(compare_color(color, 0x00ffffff, 1) || broken(compare_color(color, 0x00ff0000, 1)),
4078 "Clear with count = 0, rect != NULL has color %#08x.\n", color);
4080 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ffffff, 1.0f, 0);
4081 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4082 hr = IDirect3DDevice7_Clear(device, 1, NULL, D3DCLEAR_TARGET, 0x0000ff00, 1.0f, 0);
4083 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4085 color = get_surface_color(rt, 320, 240);
4086 ok(compare_color(color, 0x0000ff00, 1),
4087 "Clear with count = 1, rect = NULL has color %#08x.\n", color);
4089 IDirectDrawSurface7_Release(rt);
4090 IDirect3DDevice7_Release(device);
4091 DestroyWindow(window);
4094 static BOOL test_mode_restored(IDirectDraw7 *ddraw, HWND window)
4096 DDSURFACEDESC2 ddsd1, ddsd2;
4097 HRESULT hr;
4099 memset(&ddsd1, 0, sizeof(ddsd1));
4100 ddsd1.dwSize = sizeof(ddsd1);
4101 hr = IDirectDraw7_GetDisplayMode(ddraw, &ddsd1);
4102 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
4104 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4105 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4106 hr = set_display_mode(ddraw, 640, 480);
4107 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
4108 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4109 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4111 memset(&ddsd2, 0, sizeof(ddsd2));
4112 ddsd2.dwSize = sizeof(ddsd2);
4113 hr = IDirectDraw7_GetDisplayMode(ddraw, &ddsd2);
4114 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
4115 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
4116 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
4118 return ddsd1.dwWidth == ddsd2.dwWidth && ddsd1.dwHeight == ddsd2.dwHeight;
4121 static void test_coop_level_versions(void)
4123 HWND window;
4124 IDirectDraw *ddraw;
4125 HRESULT hr;
4126 BOOL restored;
4127 IDirectDrawSurface *surface;
4128 IDirectDraw7 *ddraw7;
4129 DDSURFACEDESC ddsd;
4131 window = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
4132 0, 0, 640, 480, 0, 0, 0, 0);
4134 ddraw7 = create_ddraw();
4135 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4136 /* Newly created ddraw objects restore the mode on ddraw2+::SetCooperativeLevel(NORMAL) */
4137 restored = test_mode_restored(ddraw7, window);
4138 ok(restored, "Display mode not restored in new ddraw object\n");
4140 /* A failing ddraw1::SetCooperativeLevel call does not have an effect */
4141 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4142 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4144 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4145 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
4146 restored = test_mode_restored(ddraw7, window);
4147 ok(restored, "Display mode not restored after bad ddraw1::SetCooperativeLevel call\n");
4149 /* A successful one does */
4150 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4151 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4152 restored = test_mode_restored(ddraw7, window);
4153 ok(!restored, "Display mode restored after good ddraw1::SetCooperativeLevel call\n");
4155 IDirectDraw_Release(ddraw);
4156 IDirectDraw7_Release(ddraw7);
4158 ddraw7 = create_ddraw();
4159 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4160 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4161 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4163 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_SETFOCUSWINDOW);
4164 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4165 restored = test_mode_restored(ddraw7, window);
4166 ok(!restored, "Display mode restored after ddraw1::SetCooperativeLevel(SETFOCUSWINDOW) call\n");
4168 IDirectDraw_Release(ddraw);
4169 IDirectDraw7_Release(ddraw7);
4171 /* A failing call does not restore the ddraw2+ behavior */
4172 ddraw7 = create_ddraw();
4173 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4174 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4175 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4177 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4178 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4179 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4180 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
4181 restored = test_mode_restored(ddraw7, window);
4182 ok(!restored, "Display mode restored after good-bad ddraw1::SetCooperativeLevel() call sequence\n");
4184 IDirectDraw_Release(ddraw);
4185 IDirectDraw7_Release(ddraw7);
4187 /* Neither does a sequence of successful calls with the new interface */
4188 ddraw7 = create_ddraw();
4189 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4190 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4191 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4193 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4194 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4195 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4196 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4197 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
4198 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4200 restored = test_mode_restored(ddraw7, window);
4201 ok(!restored, "Display mode restored after ddraw1-ddraw7 SetCooperativeLevel() call sequence\n");
4202 IDirectDraw_Release(ddraw);
4203 IDirectDraw7_Release(ddraw7);
4205 /* ddraw1::CreateSurface does not triger the ddraw1 behavior */
4206 ddraw7 = create_ddraw();
4207 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4208 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4209 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4211 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
4212 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4214 memset(&ddsd, 0, sizeof(ddsd));
4215 ddsd.dwSize = sizeof(ddsd);
4216 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
4217 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4218 ddsd.dwWidth = ddsd.dwHeight = 8;
4219 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
4220 ok(SUCCEEDED(hr), "CreateSurface failed, hr %#x.\n", hr);
4221 IDirectDrawSurface_Release(surface);
4222 restored = test_mode_restored(ddraw7, window);
4223 ok(restored, "Display mode not restored after ddraw1::CreateSurface() call\n");
4225 IDirectDraw_Release(ddraw);
4226 IDirectDraw7_Release(ddraw7);
4227 DestroyWindow(window);
4230 static void test_fog_special(void)
4232 static struct
4234 struct vec3 position;
4235 D3DCOLOR diffuse;
4237 quad[] =
4239 {{ -1.0f, 1.0f, 0.0f}, 0xff00ff00},
4240 {{ 1.0f, 1.0f, 1.0f}, 0xff00ff00},
4241 {{ -1.0f, -1.0f, 0.0f}, 0xff00ff00},
4242 {{ 1.0f, -1.0f, 1.0f}, 0xff00ff00},
4244 static const struct
4246 DWORD vertexmode, tablemode;
4247 D3DCOLOR color_left, color_right;
4249 tests[] =
4251 {D3DFOG_LINEAR, D3DFOG_NONE, 0x00ff0000, 0x00ff0000},
4252 {D3DFOG_NONE, D3DFOG_LINEAR, 0x0000ff00, 0x00ff0000},
4254 union
4256 float f;
4257 DWORD d;
4258 } conv;
4259 D3DCOLOR color;
4260 HRESULT hr;
4261 unsigned int i;
4262 HWND window;
4263 IDirect3DDevice7 *device;
4264 IDirectDrawSurface7 *rt;
4266 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4267 0, 0, 640, 480, 0, 0, 0, 0);
4269 if (!(device = create_device(window, DDSCL_NORMAL)))
4271 skip("Failed to create a 3D device, skipping test.\n");
4272 DestroyWindow(window);
4273 return;
4276 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
4277 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4279 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
4280 ok(SUCCEEDED(hr), "Failed to enable fog, hr %#x.\n", hr);
4281 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0xffff0000);
4282 ok(SUCCEEDED(hr), "Failed to set fog color, hr %#x.\n", hr);
4283 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
4284 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
4285 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
4286 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
4288 conv.f = 0.5f;
4289 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGSTART, conv.d);
4290 ok(SUCCEEDED(hr), "Failed to set fog start, hr %#x.\n", hr);
4291 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGEND, conv.d);
4292 ok(SUCCEEDED(hr), "Failed to set fog end, hr %#x.\n", hr);
4294 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
4296 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x000000ff, 1.0f, 0);
4297 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4299 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, tests[i].vertexmode);
4300 ok(SUCCEEDED(hr), "Failed to set fogvertexmode, hr %#x.\n", hr);
4301 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, tests[i].tablemode);
4302 ok(SUCCEEDED(hr), "Failed to set fogtablemode, hr %#x.\n", hr);
4304 hr = IDirect3DDevice7_BeginScene(device);
4305 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4306 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, 4, 0);
4307 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4308 hr = IDirect3DDevice7_EndScene(device);
4309 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4311 color = get_surface_color(rt, 310, 240);
4312 ok(compare_color(color, tests[i].color_left, 1),
4313 "Expected left color 0x%08x, got 0x%08x, case %u.\n", tests[i].color_left, color, i);
4314 color = get_surface_color(rt, 330, 240);
4315 ok(compare_color(color, tests[i].color_right, 1),
4316 "Expected right color 0x%08x, got 0x%08x, case %u.\n", tests[i].color_right, color, i);
4319 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
4320 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
4322 IDirectDrawSurface7_Release(rt);
4323 IDirect3DDevice7_Release(device);
4324 DestroyWindow(window);
4327 static void test_lighting_interface_versions(void)
4329 IDirect3DDevice7 *device;
4330 IDirectDrawSurface7 *rt;
4331 D3DCOLOR color;
4332 HWND window;
4333 HRESULT hr;
4334 DWORD rs;
4335 unsigned int i;
4336 ULONG ref;
4337 D3DMATERIAL7 material;
4338 static D3DVERTEX quad[] =
4340 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4341 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4342 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4343 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4346 #define FVF_COLORVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_SPECULAR)
4347 static struct
4349 struct vec3 position;
4350 struct vec3 normal;
4351 DWORD diffuse, specular;
4353 quad2[] =
4355 {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4356 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4357 {{-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4358 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4361 static D3DLVERTEX lquad[] =
4363 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4364 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4365 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4366 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4369 #define FVF_LVERTEX2 (D3DFVF_LVERTEX & ~D3DFVF_RESERVED1)
4370 static struct
4372 struct vec3 position;
4373 DWORD diffuse, specular;
4374 struct vec2 texcoord;
4376 lquad2[] =
4378 {{-1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
4379 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
4380 {{-1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
4381 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
4384 static D3DTLVERTEX tlquad[] =
4386 {{ 0.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4387 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4388 {{ 640.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4389 {{ 640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4392 static const struct
4394 DWORD vertextype;
4395 void *data;
4396 DWORD d3drs_lighting, d3drs_specular;
4397 DWORD draw_flags;
4398 D3DCOLOR color;
4400 tests[] =
4402 /* Lighting is enabled when D3DFVF_XYZ is used and D3DRENDERSTATE_LIGHTING is
4403 * enabled. D3DDP_DONOTLIGHT is ignored. Lighting is also enabled when normals
4404 * are not available
4406 * Note that the specular result is 0x00000000 when lighting is on even if the
4407 * input vertex has specular color because D3DRENDERSTATE_COLORVERTEX is not
4408 * enabled */
4410 /* 0 */
4411 { D3DFVF_VERTEX, quad, FALSE, FALSE, 0, 0x00ffffff},
4412 { D3DFVF_VERTEX, quad, TRUE, FALSE, 0, 0x0000ff00},
4413 { D3DFVF_VERTEX, quad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
4414 { D3DFVF_VERTEX, quad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
4415 { D3DFVF_VERTEX, quad, FALSE, TRUE, 0, 0x00ffffff},
4416 { D3DFVF_VERTEX, quad, TRUE, TRUE, 0, 0x0000ff00},
4417 { D3DFVF_VERTEX, quad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
4418 { D3DFVF_VERTEX, quad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
4420 /* 8 */
4421 { FVF_COLORVERTEX, quad2, FALSE, FALSE, 0, 0x00ff0000},
4422 { FVF_COLORVERTEX, quad2, TRUE, FALSE, 0, 0x0000ff00},
4423 { FVF_COLORVERTEX, quad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4424 { FVF_COLORVERTEX, quad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
4425 { FVF_COLORVERTEX, quad2, FALSE, TRUE, 0, 0x00ff8080},
4426 { FVF_COLORVERTEX, quad2, TRUE, TRUE, 0, 0x0000ff00},
4427 { FVF_COLORVERTEX, quad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4428 { FVF_COLORVERTEX, quad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
4430 /* 16 */
4431 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, 0, 0x00ff0000},
4432 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, 0, 0x0000ff00},
4433 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4434 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
4435 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, 0, 0x00ff8080},
4436 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, 0, 0x0000ff00},
4437 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4438 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
4440 /* 24 */
4441 { FVF_LVERTEX2, lquad2, FALSE, FALSE, 0, 0x00ff0000},
4442 { FVF_LVERTEX2, lquad2, TRUE, FALSE, 0, 0x0000ff00},
4443 { FVF_LVERTEX2, lquad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4444 { FVF_LVERTEX2, lquad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
4445 { FVF_LVERTEX2, lquad2, FALSE, TRUE, 0, 0x00ff8080},
4446 { FVF_LVERTEX2, lquad2, TRUE, TRUE, 0, 0x0000ff00},
4447 { FVF_LVERTEX2, lquad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4448 { FVF_LVERTEX2, lquad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
4450 /* 32 */
4451 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, 0, 0x000000ff},
4452 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, 0, 0x000000ff},
4453 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
4454 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
4455 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, 0, 0x008080ff},
4456 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, 0, 0x008080ff},
4457 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
4458 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
4461 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4462 0, 0, 640, 480, 0, 0, 0, 0);
4464 if (!(device = create_device(window, DDSCL_NORMAL)))
4466 skip("Failed to create a 3D device, skipping test.\n");
4467 DestroyWindow(window);
4468 return;
4471 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
4472 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4474 memset(&material, 0, sizeof(material));
4475 U2(U3(material).emissive).g = 1.0f;
4476 hr = IDirect3DDevice7_SetMaterial(device, &material);
4477 ok(SUCCEEDED(hr), "Failed set material, hr %#x.\n", hr);
4478 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
4479 ok(SUCCEEDED(hr), "Failed to disable z test, hr %#x.\n", hr);
4481 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &rs);
4482 ok(SUCCEEDED(hr), "Failed to get lighting render state, hr %#x.\n", hr);
4483 ok(rs == TRUE, "Initial D3DRENDERSTATE_LIGHTING is %#x, expected TRUE.\n", rs);
4484 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, &rs);
4485 ok(SUCCEEDED(hr), "Failed to get specularenable render state, hr %#x.\n", hr);
4486 ok(rs == FALSE, "Initial D3DRENDERSTATE_SPECULARENABLE is %#x, expected FALSE.\n", rs);
4488 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
4490 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff202020, 0.0f, 0);
4491 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
4493 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, tests[i].d3drs_lighting);
4494 ok(SUCCEEDED(hr), "Failed to set lighting render state, hr %#x.\n", hr);
4495 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE,
4496 tests[i].d3drs_specular);
4497 ok(SUCCEEDED(hr), "Failed to set specularenable render state, hr %#x.\n", hr);
4499 hr = IDirect3DDevice7_BeginScene(device);
4500 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4501 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
4502 tests[i].vertextype, tests[i].data, 4, tests[i].draw_flags | D3DDP_WAIT);
4503 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4504 hr = IDirect3DDevice7_EndScene(device);
4505 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4507 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &rs);
4508 ok(SUCCEEDED(hr), "Failed to get lighting render state, hr %#x.\n", hr);
4509 ok(rs == tests[i].d3drs_lighting, "D3DRENDERSTATE_LIGHTING is %#x, expected %#x.\n",
4510 rs, tests[i].d3drs_lighting);
4512 color = get_surface_color(rt, 320, 240);
4513 ok(compare_color(color, tests[i].color, 1),
4514 "Got unexpected color 0x%08x, expected 0x%08x, test %u.\n",
4515 color, tests[i].color, i);
4518 IDirectDrawSurface7_Release(rt);
4519 ref = IDirect3DDevice7_Release(device);
4520 ok(ref == 0, "Device not properly released, refcount %u.\n", ref);
4521 DestroyWindow(window);
4524 static struct
4526 BOOL received;
4527 IDirectDraw7 *ddraw;
4528 HWND window;
4529 DWORD coop_level;
4530 } activateapp_testdata;
4532 static LRESULT CALLBACK activateapp_test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
4534 if (message == WM_ACTIVATEAPP)
4536 if (activateapp_testdata.ddraw)
4538 HRESULT hr;
4539 activateapp_testdata.received = FALSE;
4540 hr = IDirectDraw7_SetCooperativeLevel(activateapp_testdata.ddraw,
4541 activateapp_testdata.window, activateapp_testdata.coop_level);
4542 ok(SUCCEEDED(hr), "Recursive SetCooperativeLevel call failed, hr %#x.\n", hr);
4543 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP during recursive SetCooperativeLevel call.\n");
4545 activateapp_testdata.received = TRUE;
4548 return DefWindowProcA(hwnd, message, wparam, lparam);
4551 static void test_coop_level_activateapp(void)
4553 IDirectDraw7 *ddraw;
4554 HRESULT hr;
4555 HWND window;
4556 WNDCLASSA wc = {0};
4557 DDSURFACEDESC2 ddsd;
4558 IDirectDrawSurface7 *surface;
4560 ddraw = create_ddraw();
4561 ok(!!ddraw, "Failed to create a ddraw object.\n");
4563 wc.lpfnWndProc = activateapp_test_proc;
4564 wc.lpszClassName = "ddraw_test_wndproc_wc";
4565 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4567 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
4568 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
4570 /* Exclusive with window already active. */
4571 SetForegroundWindow(window);
4572 activateapp_testdata.received = FALSE;
4573 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4574 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4575 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP although window was already active.\n");
4576 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4577 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4579 /* Exclusive with window not active. */
4580 SetForegroundWindow(GetDesktopWindow());
4581 activateapp_testdata.received = FALSE;
4582 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4583 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4584 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4585 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4586 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4588 /* Normal with window not active, then exclusive with the same window. */
4589 SetForegroundWindow(GetDesktopWindow());
4590 activateapp_testdata.received = FALSE;
4591 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4592 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4593 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP when setting DDSCL_NORMAL.\n");
4594 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4595 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4596 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4597 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4598 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4600 /* Recursive set of DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. */
4601 SetForegroundWindow(GetDesktopWindow());
4602 activateapp_testdata.received = FALSE;
4603 activateapp_testdata.ddraw = ddraw;
4604 activateapp_testdata.window = window;
4605 activateapp_testdata.coop_level = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
4606 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4607 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4608 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4609 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4610 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4612 /* The recursive call seems to have some bad effect on native ddraw, despite (apparently)
4613 * succeeding. Another switch to exclusive and back to normal is needed to release the
4614 * window properly. Without doing this, SetCooperativeLevel(EXCLUSIVE) will not send
4615 * WM_ACTIVATEAPP messages. */
4616 activateapp_testdata.ddraw = NULL;
4617 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4618 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4619 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4620 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4622 /* Setting DDSCL_NORMAL with recursive invocation. */
4623 SetForegroundWindow(GetDesktopWindow());
4624 activateapp_testdata.received = FALSE;
4625 activateapp_testdata.ddraw = ddraw;
4626 activateapp_testdata.window = window;
4627 activateapp_testdata.coop_level = DDSCL_NORMAL;
4628 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4629 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4630 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4632 /* DDraw is in exlusive mode now. */
4633 memset(&ddsd, 0, sizeof(ddsd));
4634 ddsd.dwSize = sizeof(ddsd);
4635 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
4636 U5(ddsd).dwBackBufferCount = 1;
4637 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
4638 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
4639 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4640 IDirectDrawSurface7_Release(surface);
4642 /* Recover again, just to be sure. */
4643 activateapp_testdata.ddraw = NULL;
4644 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4645 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4646 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4647 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4649 DestroyWindow(window);
4650 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
4651 IDirectDraw7_Release(ddraw);
4654 static void test_texturemanage(void)
4656 IDirectDraw7 *ddraw;
4657 HRESULT hr;
4658 DDSURFACEDESC2 ddsd;
4659 IDirectDrawSurface7 *surface;
4660 unsigned int i;
4661 DDCAPS hal_caps, hel_caps;
4662 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
4663 static const struct
4665 DWORD caps_in, caps2_in;
4666 HRESULT hr;
4667 DWORD caps_out, caps2_out;
4669 tests[] =
4671 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4672 ~0U, ~0U},
4673 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4674 ~0U, ~0U},
4675 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4676 ~0U, ~0U},
4677 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4678 ~0U, ~0U},
4679 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DD_OK,
4680 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE},
4681 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DD_OK,
4682 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE},
4683 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
4684 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_LOCALVIDMEM, 0},
4685 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
4686 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0},
4688 {0, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4689 ~0U, ~0U},
4690 {0, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4691 ~0U, ~0U},
4692 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4693 ~0U, ~0U},
4694 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4695 ~0U, ~0U},
4696 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4697 ~0U, ~0U},
4698 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4699 ~0U, ~0U},
4700 {DDSCAPS_VIDEOMEMORY, 0, DD_OK,
4701 DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY, 0},
4702 {DDSCAPS_SYSTEMMEMORY, 0, DD_OK,
4703 DDSCAPS_SYSTEMMEMORY, 0},
4706 ddraw = create_ddraw();
4707 ok(!!ddraw, "Failed to create a ddraw object.\n");
4708 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4709 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4711 memset(&hal_caps, 0, sizeof(hal_caps));
4712 hal_caps.dwSize = sizeof(hal_caps);
4713 memset(&hel_caps, 0, sizeof(hel_caps));
4714 hel_caps.dwSize = sizeof(hel_caps);
4715 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, &hel_caps);
4716 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
4717 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps)
4719 skip("Managed textures not supported, skipping managed texture test.\n");
4720 IDirectDraw7_Release(ddraw);
4721 return;
4724 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
4726 memset(&ddsd, 0, sizeof(ddsd));
4727 ddsd.dwSize = sizeof(ddsd);
4728 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
4729 ddsd.ddsCaps.dwCaps = tests[i].caps_in;
4730 ddsd.ddsCaps.dwCaps2 = tests[i].caps2_in;
4731 ddsd.dwWidth = 4;
4732 ddsd.dwHeight = 4;
4734 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
4735 if (tests[i].hr == DD_OK && is_ddraw64 && (tests[i].caps_in & DDSCAPS_TEXTURE))
4736 todo_wine ok(hr == E_NOINTERFACE, "Test %u: Got unexpected hr %#x.\n", i, hr);
4737 else
4738 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, tests[i].hr);
4739 if (FAILED(hr))
4740 continue;
4742 memset(&ddsd, 0, sizeof(ddsd));
4743 ddsd.dwSize = sizeof(ddsd);
4744 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
4745 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4747 ok(ddsd.ddsCaps.dwCaps == tests[i].caps_out,
4748 "Input caps %#x, %#x, expected output caps %#x, got %#x, case %u.\n",
4749 tests[i].caps_in, tests[i].caps2_in, tests[i].caps_out, ddsd.ddsCaps.dwCaps, i);
4750 ok(ddsd.ddsCaps.dwCaps2 == tests[i].caps2_out,
4751 "Input caps %#x, %#x, expected output caps %#x, got %#x, case %u.\n",
4752 tests[i].caps_in, tests[i].caps2_in, tests[i].caps2_out, ddsd.ddsCaps.dwCaps2, i);
4754 IDirectDrawSurface7_Release(surface);
4757 IDirectDraw7_Release(ddraw);
4760 #define SUPPORT_DXT1 0x01
4761 #define SUPPORT_DXT2 0x02
4762 #define SUPPORT_DXT3 0x04
4763 #define SUPPORT_DXT4 0x08
4764 #define SUPPORT_DXT5 0x10
4765 #define SUPPORT_YUY2 0x20
4766 #define SUPPORT_UYVY 0x40
4768 static HRESULT WINAPI test_block_formats_creation_cb(DDPIXELFORMAT *fmt, void *ctx)
4770 DWORD *supported_fmts = ctx;
4772 if (!(fmt->dwFlags & DDPF_FOURCC))
4773 return DDENUMRET_OK;
4775 switch (fmt->dwFourCC)
4777 case MAKEFOURCC('D','X','T','1'):
4778 *supported_fmts |= SUPPORT_DXT1;
4779 break;
4780 case MAKEFOURCC('D','X','T','2'):
4781 *supported_fmts |= SUPPORT_DXT2;
4782 break;
4783 case MAKEFOURCC('D','X','T','3'):
4784 *supported_fmts |= SUPPORT_DXT3;
4785 break;
4786 case MAKEFOURCC('D','X','T','4'):
4787 *supported_fmts |= SUPPORT_DXT4;
4788 break;
4789 case MAKEFOURCC('D','X','T','5'):
4790 *supported_fmts |= SUPPORT_DXT5;
4791 break;
4792 case MAKEFOURCC('Y','U','Y','2'):
4793 *supported_fmts |= SUPPORT_YUY2;
4794 break;
4795 case MAKEFOURCC('U','Y','V','Y'):
4796 *supported_fmts |= SUPPORT_UYVY;
4797 break;
4798 default:
4799 break;
4802 return DDENUMRET_OK;
4805 static void test_block_formats_creation(void)
4807 HRESULT hr, expect_hr;
4808 unsigned int i, j, w, h;
4809 HWND window;
4810 IDirectDraw7 *ddraw;
4811 IDirect3D7 *d3d;
4812 IDirect3DDevice7 *device;
4813 IDirectDrawSurface7 *surface;
4814 DWORD supported_fmts = 0, supported_overlay_fmts = 0;
4815 DWORD num_fourcc_codes = 0, *fourcc_codes;
4816 DDSURFACEDESC2 ddsd;
4817 DDCAPS hal_caps;
4818 void *mem;
4820 static const struct
4822 DWORD fourcc;
4823 const char *name;
4824 DWORD support_flag;
4825 unsigned int block_width;
4826 unsigned int block_height;
4827 unsigned int block_size;
4828 BOOL create_size_checked, overlay;
4830 formats[] =
4832 {MAKEFOURCC('D','X','T','1'), "D3DFMT_DXT1", SUPPORT_DXT1, 4, 4, 8, TRUE, FALSE},
4833 {MAKEFOURCC('D','X','T','2'), "D3DFMT_DXT2", SUPPORT_DXT2, 4, 4, 16, TRUE, FALSE},
4834 {MAKEFOURCC('D','X','T','3'), "D3DFMT_DXT3", SUPPORT_DXT3, 4, 4, 16, TRUE, FALSE},
4835 {MAKEFOURCC('D','X','T','4'), "D3DFMT_DXT4", SUPPORT_DXT4, 4, 4, 16, TRUE, FALSE},
4836 {MAKEFOURCC('D','X','T','5'), "D3DFMT_DXT5", SUPPORT_DXT5, 4, 4, 16, TRUE, FALSE},
4837 {MAKEFOURCC('Y','U','Y','2'), "D3DFMT_YUY2", SUPPORT_YUY2, 2, 1, 4, FALSE, TRUE },
4838 {MAKEFOURCC('U','Y','V','Y'), "D3DFMT_UYVY", SUPPORT_UYVY, 2, 1, 4, FALSE, TRUE },
4840 static const struct
4842 DWORD caps, caps2;
4843 const char *name;
4844 BOOL overlay;
4846 types[] =
4848 /* DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY fails to create any fourcc
4849 * surface with DDERR_INVALIDPIXELFORMAT. Don't care about it for now.
4851 * Nvidia returns E_FAIL on DXTN DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY.
4852 * Other hw / drivers successfully create those surfaces. Ignore them, this
4853 * suggests that no game uses this, otherwise Nvidia would support it. */
4855 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0,
4856 "videomemory texture", FALSE
4859 DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY, 0,
4860 "videomemory overlay", TRUE
4863 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0,
4864 "systemmemory texture", FALSE
4867 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
4868 "managed texture", FALSE
4871 enum size_type
4873 SIZE_TYPE_ZERO,
4874 SIZE_TYPE_PITCH,
4875 SIZE_TYPE_SIZE,
4877 static const struct
4879 DWORD flags;
4880 enum size_type size_type;
4881 int rel_size;
4882 HRESULT hr;
4884 user_mem_tests[] =
4886 {DDSD_LINEARSIZE, SIZE_TYPE_ZERO, 0, DD_OK},
4887 {DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
4888 {DDSD_PITCH, SIZE_TYPE_ZERO, 0, DD_OK},
4889 {DDSD_PITCH, SIZE_TYPE_PITCH, 0, DD_OK},
4890 {DDSD_LPSURFACE, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
4891 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
4892 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_PITCH, 0, DDERR_INVALIDPARAMS},
4893 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
4894 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 1, DD_OK},
4895 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, -1, DDERR_INVALIDPARAMS},
4896 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
4897 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_PITCH, 0, DDERR_INVALIDPARAMS},
4898 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_SIZE, 0, DDERR_INVALIDPARAMS},
4899 {DDSD_LPSURFACE | DDSD_PITCH | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DDERR_INVALIDPARAMS},
4902 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4903 0, 0, 640, 480, 0, 0, 0, 0);
4905 if (!(device = create_device(window, DDSCL_NORMAL)))
4907 skip("Failed to create a 3D device, skipping test.\n");
4908 DestroyWindow(window);
4909 return;
4912 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
4913 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
4914 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **) &ddraw);
4915 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
4916 IDirect3D7_Release(d3d);
4918 hr = IDirect3DDevice7_EnumTextureFormats(device, test_block_formats_creation_cb,
4919 &supported_fmts);
4920 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
4922 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
4923 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
4924 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
4925 num_fourcc_codes * sizeof(*fourcc_codes));
4926 if (!fourcc_codes)
4927 goto cleanup;
4928 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
4929 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
4930 for (i = 0; i < num_fourcc_codes; i++)
4932 for (j = 0; j < sizeof(formats) / sizeof(*formats); j++)
4934 if (fourcc_codes[i] == formats[j].fourcc)
4935 supported_overlay_fmts |= formats[j].support_flag;
4938 HeapFree(GetProcessHeap(), 0, fourcc_codes);
4940 memset(&hal_caps, 0, sizeof(hal_caps));
4941 hal_caps.dwSize = sizeof(hal_caps);
4942 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
4943 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
4945 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 2 * 2 * 16 + 1);
4947 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
4949 for (j = 0; j < sizeof(types) / sizeof(*types); j++)
4951 BOOL support;
4953 if (formats[i].overlay != types[j].overlay
4954 || (types[j].overlay && !(hal_caps.dwCaps & DDCAPS_OVERLAY)))
4955 continue;
4957 if (formats[i].overlay)
4958 support = supported_overlay_fmts & formats[i].support_flag;
4959 else
4960 support = supported_fmts & formats[i].support_flag;
4962 for (w = 1; w <= 8; w++)
4964 for (h = 1; h <= 8; h++)
4966 BOOL block_aligned = TRUE;
4967 BOOL todo = FALSE;
4969 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
4970 block_aligned = FALSE;
4972 memset(&ddsd, 0, sizeof(ddsd));
4973 ddsd.dwSize = sizeof(ddsd);
4974 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
4975 ddsd.ddsCaps.dwCaps = types[j].caps;
4976 ddsd.ddsCaps.dwCaps2 = types[j].caps2;
4977 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
4978 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
4979 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
4980 ddsd.dwWidth = w;
4981 ddsd.dwHeight = h;
4983 /* TODO: Handle power of two limitations. I cannot test the pow2
4984 * behavior on windows because I have no hardware that doesn't at
4985 * least support np2_conditional. There's probably no HW that
4986 * supports DXTN textures but no conditional np2 textures. */
4987 if (!support && !(types[j].caps & DDSCAPS_SYSTEMMEMORY))
4988 expect_hr = DDERR_INVALIDPARAMS;
4989 else if (formats[i].create_size_checked && !block_aligned)
4991 expect_hr = DDERR_INVALIDPARAMS;
4992 if (!(types[j].caps & DDSCAPS_TEXTURE))
4993 todo = TRUE;
4995 else
4996 expect_hr = D3D_OK;
4998 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
4999 if (todo)
5000 todo_wine ok(hr == expect_hr,
5001 "Got unexpected hr %#x for format %s, resource type %s, size %ux%u, expected %#x.\n",
5002 hr, formats[i].name, types[j].name, w, h, expect_hr);
5003 else
5004 ok(hr == expect_hr,
5005 "Got unexpected hr %#x for format %s, resource type %s, size %ux%u, expected %#x.\n",
5006 hr, formats[i].name, types[j].name, w, h, expect_hr);
5008 if (SUCCEEDED(hr))
5009 IDirectDrawSurface7_Release(surface);
5014 if (formats[i].overlay)
5015 continue;
5017 for (j = 0; j < sizeof(user_mem_tests) / sizeof(*user_mem_tests); ++j)
5019 memset(&ddsd, 0, sizeof(ddsd));
5020 ddsd.dwSize = sizeof(ddsd);
5021 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | user_mem_tests[j].flags;
5022 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE;
5024 switch (user_mem_tests[j].size_type)
5026 case SIZE_TYPE_ZERO:
5027 U1(ddsd).dwLinearSize = 0;
5028 break;
5030 case SIZE_TYPE_PITCH:
5031 U1(ddsd).dwLinearSize = 2 * formats[i].block_size;
5032 break;
5034 case SIZE_TYPE_SIZE:
5035 U1(ddsd).dwLinearSize = 2 * 2 * formats[i].block_size;
5036 break;
5038 U1(ddsd).dwLinearSize += user_mem_tests[j].rel_size;
5040 ddsd.lpSurface = mem;
5041 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
5042 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
5043 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
5044 ddsd.dwWidth = 8;
5045 ddsd.dwHeight = 8;
5047 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5048 ok(hr == user_mem_tests[j].hr, "Test %u: Got unexpected hr %#x, format %s.\n", j, hr, formats[i].name);
5050 if (FAILED(hr))
5051 continue;
5053 memset(&ddsd, 0, sizeof(ddsd));
5054 ddsd.dwSize = sizeof(ddsd);
5055 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
5056 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", j, hr);
5057 ok(ddsd.dwFlags == (DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_LINEARSIZE),
5058 "Test %u: Got unexpected flags %#x.\n", j, ddsd.dwFlags);
5059 if (user_mem_tests[j].flags & DDSD_LPSURFACE)
5060 ok(U1(ddsd).dwLinearSize == ~0u, "Test %u: Got unexpected linear size %#x.\n",
5061 j, U1(ddsd).dwLinearSize);
5062 else
5063 ok(U1(ddsd).dwLinearSize == 2 * 2 * formats[i].block_size,
5064 "Test %u: Got unexpected linear size %#x, expected %#x.\n",
5065 j, U1(ddsd).dwLinearSize, 2 * 2 * formats[i].block_size);
5066 IDirectDrawSurface7_Release(surface);
5070 HeapFree(GetProcessHeap(), 0, mem);
5071 cleanup:
5072 IDirectDraw7_Release(ddraw);
5073 IDirect3DDevice7_Release(device);
5074 DestroyWindow(window);
5077 struct format_support_check
5079 const DDPIXELFORMAT *format;
5080 BOOL supported;
5083 static HRESULT WINAPI test_unsupported_formats_cb(DDPIXELFORMAT *fmt, void *ctx)
5085 struct format_support_check *format = ctx;
5087 if (!memcmp(format->format, fmt, sizeof(*fmt)))
5089 format->supported = TRUE;
5090 return DDENUMRET_CANCEL;
5093 return DDENUMRET_OK;
5096 static void test_unsupported_formats(void)
5098 HRESULT hr;
5099 BOOL expect_success;
5100 HWND window;
5101 IDirectDraw7 *ddraw;
5102 IDirect3D7 *d3d;
5103 IDirect3DDevice7 *device;
5104 IDirectDrawSurface7 *surface;
5105 DDSURFACEDESC2 ddsd;
5106 unsigned int i, j;
5107 DWORD expected_caps;
5108 static const struct
5110 const char *name;
5111 DDPIXELFORMAT fmt;
5113 formats[] =
5116 "D3DFMT_A8R8G8B8",
5118 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
5119 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
5123 "D3DFMT_P8",
5125 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
5126 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
5130 static const DWORD caps[] = {0, DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY};
5132 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5133 0, 0, 640, 480, 0, 0, 0, 0);
5135 if (!(device = create_device(window, DDSCL_NORMAL)))
5137 skip("Failed to create a 3D device, skipping test.\n");
5138 DestroyWindow(window);
5139 return;
5142 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
5143 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
5144 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **) &ddraw);
5145 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
5146 IDirect3D7_Release(d3d);
5148 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
5150 struct format_support_check check = {&formats[i].fmt, FALSE};
5151 hr = IDirect3DDevice7_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
5152 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
5154 for (j = 0; j < sizeof(caps) / sizeof(*caps); j++)
5156 memset(&ddsd, 0, sizeof(ddsd));
5157 ddsd.dwSize = sizeof(ddsd);
5158 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
5159 U4(ddsd).ddpfPixelFormat = formats[i].fmt;
5160 ddsd.dwWidth = 4;
5161 ddsd.dwHeight = 4;
5162 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | caps[j];
5164 if (caps[j] & DDSCAPS_VIDEOMEMORY && !check.supported)
5165 expect_success = FALSE;
5166 else
5167 expect_success = TRUE;
5169 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5170 ok(SUCCEEDED(hr) == expect_success,
5171 "Got unexpected hr %#x for format %s, caps %#x, expected %s.\n",
5172 hr, formats[i].name, caps[j], expect_success ? "success" : "failure");
5173 if (FAILED(hr))
5174 continue;
5176 memset(&ddsd, 0, sizeof(ddsd));
5177 ddsd.dwSize = sizeof(ddsd);
5178 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
5179 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5181 if (caps[j] & DDSCAPS_VIDEOMEMORY)
5182 expected_caps = DDSCAPS_VIDEOMEMORY;
5183 else if (caps[j] & DDSCAPS_SYSTEMMEMORY)
5184 expected_caps = DDSCAPS_SYSTEMMEMORY;
5185 else if (check.supported)
5186 expected_caps = DDSCAPS_VIDEOMEMORY;
5187 else
5188 expected_caps = DDSCAPS_SYSTEMMEMORY;
5190 ok(ddsd.ddsCaps.dwCaps & expected_caps,
5191 "Expected capability %#x, format %s, input cap %#x.\n",
5192 expected_caps, formats[i].name, caps[j]);
5194 IDirectDrawSurface7_Release(surface);
5198 IDirectDraw7_Release(ddraw);
5199 IDirect3DDevice7_Release(device);
5200 DestroyWindow(window);
5203 static void test_rt_caps(void)
5205 const GUID *devtype = &IID_IDirect3DHALDevice;
5206 PALETTEENTRY palette_entries[256];
5207 IDirectDrawPalette *palette;
5208 IDirectDraw7 *ddraw;
5209 BOOL hal_ok = FALSE;
5210 DDPIXELFORMAT z_fmt;
5211 IDirect3D7 *d3d;
5212 unsigned int i;
5213 ULONG refcount;
5214 HWND window;
5215 HRESULT hr;
5217 static const DDPIXELFORMAT p8_fmt =
5219 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
5220 {8}, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000},
5223 const struct
5225 const DDPIXELFORMAT *pf;
5226 DWORD caps_in;
5227 DWORD caps_out;
5228 HRESULT create_device_hr;
5229 HRESULT set_rt_hr, alternative_set_rt_hr;
5231 test_data[] =
5234 NULL,
5235 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
5236 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5237 D3D_OK,
5238 D3D_OK,
5239 D3D_OK,
5242 NULL,
5243 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5244 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5245 D3D_OK,
5246 D3D_OK,
5247 D3D_OK,
5250 NULL,
5251 DDSCAPS_OFFSCREENPLAIN,
5252 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5253 DDERR_INVALIDCAPS,
5254 DDERR_INVALIDCAPS,
5255 DDERR_INVALIDCAPS,
5258 NULL,
5259 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5260 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5261 D3DERR_SURFACENOTINVIDMEM,
5262 DDERR_INVALIDPARAMS,
5263 D3D_OK,
5266 NULL,
5267 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5268 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5269 DDERR_INVALIDCAPS,
5270 DDERR_INVALIDCAPS,
5271 DDERR_INVALIDCAPS,
5274 NULL,
5275 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
5276 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5277 D3D_OK,
5278 D3D_OK,
5279 D3D_OK,
5282 NULL,
5283 DDSCAPS_3DDEVICE,
5284 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5285 D3D_OK,
5286 D3D_OK,
5287 D3D_OK,
5290 NULL,
5292 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5293 DDERR_INVALIDCAPS,
5294 DDERR_INVALIDCAPS,
5295 DDERR_INVALIDCAPS,
5298 NULL,
5299 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5300 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5301 D3DERR_SURFACENOTINVIDMEM,
5302 DDERR_INVALIDPARAMS,
5303 D3D_OK,
5306 NULL,
5307 DDSCAPS_SYSTEMMEMORY,
5308 DDSCAPS_SYSTEMMEMORY,
5309 DDERR_INVALIDCAPS,
5310 DDERR_INVALIDCAPS,
5311 DDERR_INVALIDCAPS,
5314 &p8_fmt,
5316 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5317 DDERR_INVALIDCAPS,
5318 DDERR_INVALIDCAPS,
5319 DDERR_INVALIDCAPS,
5322 &p8_fmt,
5323 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5324 ~0U /* AMD r200 */,
5325 DDERR_NOPALETTEATTACHED,
5326 DDERR_INVALIDCAPS,
5327 DDERR_INVALIDCAPS,
5330 &p8_fmt,
5331 DDSCAPS_OFFSCREENPLAIN,
5332 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5333 DDERR_INVALIDCAPS,
5334 DDERR_INVALIDCAPS,
5335 DDERR_INVALIDCAPS,
5338 &p8_fmt,
5339 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5340 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5341 DDERR_NOPALETTEATTACHED,
5342 DDERR_INVALIDCAPS,
5343 DDERR_INVALIDCAPS,
5346 &p8_fmt,
5347 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5348 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5349 DDERR_INVALIDCAPS,
5350 DDERR_INVALIDCAPS,
5351 DDERR_INVALIDCAPS,
5354 &z_fmt,
5355 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
5356 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5357 DDERR_INVALIDCAPS,
5358 DDERR_INVALIDPIXELFORMAT,
5359 DDERR_INVALIDPIXELFORMAT,
5362 &z_fmt,
5363 DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5364 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5365 DDERR_INVALIDCAPS,
5366 DDERR_INVALIDPIXELFORMAT,
5367 DDERR_INVALIDPIXELFORMAT,
5370 &z_fmt,
5371 DDSCAPS_ZBUFFER,
5372 DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5373 DDERR_INVALIDCAPS,
5374 DDERR_INVALIDCAPS,
5375 DDERR_INVALIDCAPS,
5378 &z_fmt,
5379 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5380 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5381 DDERR_INVALIDCAPS,
5382 DDERR_INVALIDPARAMS,
5383 DDERR_INVALIDPIXELFORMAT,
5386 &z_fmt,
5387 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
5388 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
5389 DDERR_INVALIDCAPS,
5390 DDERR_INVALIDCAPS,
5391 DDERR_INVALIDCAPS,
5395 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5396 0, 0, 640, 480, 0, 0, 0, 0);
5397 ddraw = create_ddraw();
5398 ok(!!ddraw, "Failed to create a ddraw object.\n");
5399 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5400 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5402 if (FAILED(IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d)))
5404 skip("D3D interface is not available, skipping test.\n");
5405 goto done;
5408 hr = IDirect3D7_EnumDevices(d3d, enum_devtype_cb, &hal_ok);
5409 ok(SUCCEEDED(hr), "Failed to enumerate devices, hr %#x.\n", hr);
5410 if (hal_ok)
5411 devtype = &IID_IDirect3DTnLHalDevice;
5413 memset(&z_fmt, 0, sizeof(z_fmt));
5414 hr = IDirect3D7_EnumZBufferFormats(d3d, devtype, enum_z_fmt, &z_fmt);
5415 if (FAILED(hr) || !z_fmt.dwSize)
5417 skip("No depth buffer formats available, skipping test.\n");
5418 IDirect3D7_Release(d3d);
5419 goto done;
5422 memset(palette_entries, 0, sizeof(palette_entries));
5423 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
5424 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
5426 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
5428 IDirectDrawSurface7 *surface, *rt, *expected_rt, *tmp;
5429 DDSURFACEDESC2 surface_desc;
5430 IDirect3DDevice7 *device;
5432 memset(&surface_desc, 0, sizeof(surface_desc));
5433 surface_desc.dwSize = sizeof(surface_desc);
5434 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5435 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5436 if (test_data[i].pf)
5438 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
5439 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
5441 surface_desc.dwWidth = 640;
5442 surface_desc.dwHeight = 480;
5443 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5444 ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
5445 i, test_data[i].caps_in, hr);
5447 memset(&surface_desc, 0, sizeof(surface_desc));
5448 surface_desc.dwSize = sizeof(surface_desc);
5449 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
5450 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
5451 ok(test_data[i].caps_out == ~0U || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out,
5452 "Test %u: Got unexpected caps %#x, expected %#x.\n",
5453 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
5455 hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
5456 ok(hr == test_data[i].create_device_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n",
5457 i, hr, test_data[i].create_device_hr);
5458 if (FAILED(hr))
5460 if (hr == DDERR_NOPALETTEATTACHED)
5462 hr = IDirectDrawSurface7_SetPalette(surface, palette);
5463 ok(SUCCEEDED(hr), "Test %u: Failed to set palette, hr %#x.\n", i, hr);
5464 hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
5465 if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
5466 ok(hr == DDERR_INVALIDPIXELFORMAT, "Test %u: Got unexpected hr %#x.\n", i, hr);
5467 else
5468 ok(hr == D3DERR_SURFACENOTINVIDMEM, "Test %u: Got unexpected hr %#x.\n", i, hr);
5470 IDirectDrawSurface7_Release(surface);
5472 memset(&surface_desc, 0, sizeof(surface_desc));
5473 surface_desc.dwSize = sizeof(surface_desc);
5474 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5475 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
5476 surface_desc.dwWidth = 640;
5477 surface_desc.dwHeight = 480;
5478 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5479 ok(SUCCEEDED(hr), "Test %u: Failed to create surface, hr %#x.\n", i, hr);
5481 hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
5482 ok(SUCCEEDED(hr), "Test %u: Failed to create device, hr %#x.\n", i, hr);
5485 memset(&surface_desc, 0, sizeof(surface_desc));
5486 surface_desc.dwSize = sizeof(surface_desc);
5487 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5488 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5489 if (test_data[i].pf)
5491 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
5492 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
5494 surface_desc.dwWidth = 640;
5495 surface_desc.dwHeight = 480;
5496 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &rt, NULL);
5497 ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
5498 i, test_data[i].caps_in, hr);
5500 hr = IDirect3DDevice7_SetRenderTarget(device, rt, 0);
5501 ok(hr == test_data[i].set_rt_hr || broken(hr == test_data[i].alternative_set_rt_hr),
5502 "Test %u: Got unexpected hr %#x, expected %#x.\n",
5503 i, hr, test_data[i].set_rt_hr);
5504 if (SUCCEEDED(hr) || hr == DDERR_INVALIDPIXELFORMAT)
5505 expected_rt = rt;
5506 else
5507 expected_rt = surface;
5509 hr = IDirect3DDevice7_GetRenderTarget(device, &tmp);
5510 ok(SUCCEEDED(hr), "Test %u: Failed to get render target, hr %#x.\n", i, hr);
5511 ok(tmp == expected_rt, "Test %u: Got unexpected rt %p.\n", i, tmp);
5513 IDirectDrawSurface7_Release(tmp);
5514 IDirectDrawSurface7_Release(rt);
5515 refcount = IDirect3DDevice7_Release(device);
5516 ok(refcount == 0, "Test %u: The device was not properly freed, refcount %u.\n", i, refcount);
5517 refcount = IDirectDrawSurface7_Release(surface);
5518 ok(refcount == 0, "Test %u: The surface was not properly freed, refcount %u.\n", i, refcount);
5521 IDirectDrawPalette_Release(palette);
5522 IDirect3D7_Release(d3d);
5524 done:
5525 refcount = IDirectDraw7_Release(ddraw);
5526 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5527 DestroyWindow(window);
5530 static void test_primary_caps(void)
5532 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
5533 IDirectDrawSurface7 *surface;
5534 DDSURFACEDESC2 surface_desc;
5535 IDirectDraw7 *ddraw;
5536 unsigned int i;
5537 ULONG refcount;
5538 HWND window;
5539 HRESULT hr;
5541 static const struct
5543 DWORD coop_level;
5544 DWORD caps_in;
5545 DWORD back_buffer_count;
5546 HRESULT hr;
5547 DWORD caps_out;
5549 test_data[] =
5552 DDSCL_NORMAL,
5553 DDSCAPS_PRIMARYSURFACE,
5554 ~0u,
5555 DD_OK,
5556 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE,
5559 DDSCL_NORMAL,
5560 DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE,
5561 ~0u,
5562 DDERR_INVALIDCAPS,
5563 ~0u,
5566 DDSCL_NORMAL,
5567 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
5568 ~0u,
5569 DDERR_INVALIDCAPS,
5570 ~0u,
5573 DDSCL_NORMAL,
5574 DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER,
5575 ~0u,
5576 DDERR_INVALIDCAPS,
5577 ~0u,
5580 DDSCL_NORMAL,
5581 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP,
5582 ~0u,
5583 DDERR_INVALIDCAPS,
5584 ~0u,
5587 DDSCL_NORMAL,
5588 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX,
5589 ~0u,
5590 DDERR_INVALIDCAPS,
5591 ~0u,
5594 DDSCL_NORMAL,
5595 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5596 ~0u,
5597 DDERR_INVALIDCAPS,
5598 ~0u,
5601 DDSCL_NORMAL,
5602 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5604 DDERR_INVALIDCAPS,
5605 ~0u,
5608 DDSCL_NORMAL,
5609 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5611 DDERR_NOEXCLUSIVEMODE,
5612 ~0u,
5615 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5616 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5618 DDERR_INVALIDCAPS,
5619 ~0u,
5622 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5623 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5625 DD_OK,
5626 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX,
5629 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5630 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER,
5632 DDERR_INVALIDCAPS,
5633 ~0u,
5636 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5637 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_BACKBUFFER,
5639 DDERR_INVALIDCAPS,
5640 ~0u,
5644 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5645 0, 0, 640, 480, 0, 0, 0, 0);
5646 ddraw = create_ddraw();
5647 ok(!!ddraw, "Failed to create a ddraw object.\n");
5649 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
5651 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, test_data[i].coop_level);
5652 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5654 memset(&surface_desc, 0, sizeof(surface_desc));
5655 surface_desc.dwSize = sizeof(surface_desc);
5656 surface_desc.dwFlags = DDSD_CAPS;
5657 if (test_data[i].back_buffer_count != ~0u)
5658 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
5659 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5660 U5(surface_desc).dwBackBufferCount = test_data[i].back_buffer_count;
5661 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5662 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
5663 if (FAILED(hr))
5664 continue;
5666 memset(&surface_desc, 0, sizeof(surface_desc));
5667 surface_desc.dwSize = sizeof(surface_desc);
5668 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
5669 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
5670 ok((surface_desc.ddsCaps.dwCaps & ~placement) == test_data[i].caps_out,
5671 "Test %u: Got unexpected caps %#x, expected %#x.\n",
5672 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
5674 IDirectDrawSurface7_Release(surface);
5677 refcount = IDirectDraw7_Release(ddraw);
5678 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5679 DestroyWindow(window);
5682 static void test_surface_lock(void)
5684 IDirectDraw7 *ddraw;
5685 IDirect3D7 *d3d = NULL;
5686 IDirectDrawSurface7 *surface;
5687 IDirect3DDevice7 *device;
5688 HRESULT hr;
5689 HWND window;
5690 unsigned int i;
5691 DDSURFACEDESC2 ddsd;
5692 ULONG refcount;
5693 DDPIXELFORMAT z_fmt;
5694 BOOL hal_ok = FALSE;
5695 const GUID *devtype = &IID_IDirect3DHALDevice;
5696 D3DDEVICEDESC7 device_desc;
5697 BOOL cubemap_supported;
5698 static const struct
5700 DWORD caps;
5701 DWORD caps2;
5702 const char *name;
5704 tests[] =
5707 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
5709 "videomemory offscreenplain"
5712 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5714 "systemmemory offscreenplain"
5717 DDSCAPS_PRIMARYSURFACE,
5719 "primary"
5722 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
5724 "videomemory texture"
5727 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
5728 DDSCAPS2_OPAQUE,
5729 "opaque videomemory texture"
5732 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
5734 "systemmemory texture"
5737 DDSCAPS_TEXTURE,
5738 DDSCAPS2_TEXTUREMANAGE,
5739 "managed texture"
5742 DDSCAPS_TEXTURE,
5743 DDSCAPS2_D3DTEXTUREMANAGE,
5744 "managed texture"
5747 DDSCAPS_TEXTURE,
5748 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_OPAQUE,
5749 "opaque managed texture"
5752 DDSCAPS_TEXTURE,
5753 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_OPAQUE,
5754 "opaque managed texture"
5757 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5759 "render target"
5762 DDSCAPS_ZBUFFER,
5764 "Z buffer"
5767 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY,
5768 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
5769 "videomemory cube"
5772 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY,
5773 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_OPAQUE,
5774 "opaque videomemory cube"
5777 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_SYSTEMMEMORY,
5778 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
5779 "systemmemory cube"
5782 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
5783 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
5784 "managed cube"
5787 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
5788 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
5789 "managed cube"
5792 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
5793 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_OPAQUE,
5794 "opaque managed cube"
5797 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
5798 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_OPAQUE,
5799 "opaque managed cube"
5803 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5804 0, 0, 640, 480, 0, 0, 0, 0);
5805 ddraw = create_ddraw();
5806 ok(!!ddraw, "Failed to create a ddraw object.\n");
5807 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5808 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5810 if (FAILED(IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d)))
5812 skip("D3D interface is not available, skipping test.\n");
5813 goto done;
5816 hr = IDirect3D7_EnumDevices(d3d, enum_devtype_cb, &hal_ok);
5817 ok(SUCCEEDED(hr), "Failed to enumerate devices, hr %#x.\n", hr);
5818 if (hal_ok)
5819 devtype = &IID_IDirect3DTnLHalDevice;
5821 memset(&z_fmt, 0, sizeof(z_fmt));
5822 hr = IDirect3D7_EnumZBufferFormats(d3d, devtype, enum_z_fmt, &z_fmt);
5823 if (FAILED(hr) || !z_fmt.dwSize)
5825 skip("No depth buffer formats available, skipping test.\n");
5826 goto done;
5829 memset(&ddsd, 0, sizeof(ddsd));
5830 ddsd.dwSize = sizeof(ddsd);
5831 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5832 ddsd.dwWidth = 64;
5833 ddsd.dwHeight = 64;
5834 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
5835 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5836 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5838 hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
5839 ok(SUCCEEDED(hr), "Failed to create device, hr %#x.\n", hr);
5840 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
5841 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5842 cubemap_supported = !!(device_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP);
5843 IDirect3DDevice7_Release(device);
5845 IDirectDrawSurface7_Release(surface);
5847 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
5849 if (!cubemap_supported && tests[i].caps2 & DDSCAPS2_CUBEMAP)
5850 continue;
5852 memset(&ddsd, 0, sizeof(ddsd));
5853 ddsd.dwSize = sizeof(ddsd);
5854 ddsd.dwFlags = DDSD_CAPS;
5855 if (!(tests[i].caps & DDSCAPS_PRIMARYSURFACE))
5857 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
5858 ddsd.dwWidth = 64;
5859 ddsd.dwHeight = 64;
5861 if (tests[i].caps & DDSCAPS_ZBUFFER)
5863 ddsd.dwFlags |= DDSD_PIXELFORMAT;
5864 U4(ddsd).ddpfPixelFormat = z_fmt;
5866 ddsd.ddsCaps.dwCaps = tests[i].caps;
5867 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
5869 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5870 ok(SUCCEEDED(hr), "Failed to create surface, type %s, hr %#x.\n", tests[i].name, hr);
5872 memset(&ddsd, 0, sizeof(ddsd));
5873 ddsd.dwSize = sizeof(ddsd);
5874 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
5875 ok(SUCCEEDED(hr), "Failed to lock surface, type %s, hr %#x.\n", tests[i].name, hr);
5876 if (SUCCEEDED(hr))
5878 hr = IDirectDrawSurface7_Unlock(surface, NULL);
5879 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
5882 IDirectDrawSurface7_Release(surface);
5885 done:
5886 if (d3d)
5887 IDirect3D7_Release(d3d);
5888 refcount = IDirectDraw7_Release(ddraw);
5889 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5890 DestroyWindow(window);
5893 static void test_surface_discard(void)
5895 IDirect3DDevice7 *device;
5896 IDirect3D7 *d3d;
5897 IDirectDraw7 *ddraw;
5898 HRESULT hr;
5899 HWND window;
5900 DDSURFACEDESC2 ddsd;
5901 IDirectDrawSurface7 *surface, *target;
5902 void *addr;
5903 static const struct
5905 DWORD caps, caps2;
5906 BOOL discard;
5908 tests[] =
5910 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, TRUE},
5911 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
5912 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, TRUE},
5913 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
5914 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE},
5915 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
5916 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE},
5917 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
5919 unsigned int i;
5921 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5922 0, 0, 640, 480, 0, 0, 0, 0);
5924 if (!(device = create_device(window, DDSCL_NORMAL)))
5926 skip("Failed to create a 3D device, skipping test.\n");
5927 DestroyWindow(window);
5928 return;
5930 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
5931 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
5932 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
5933 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
5934 hr = IDirect3DDevice7_GetRenderTarget(device, &target);
5935 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
5937 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
5939 BOOL discarded;
5941 memset(&ddsd, 0, sizeof(ddsd));
5942 ddsd.dwSize = sizeof(ddsd);
5943 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5944 ddsd.ddsCaps.dwCaps = tests[i].caps;
5945 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
5946 ddsd.dwWidth = 64;
5947 ddsd.dwHeight = 64;
5948 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5949 ok(SUCCEEDED(hr), "Failed to create offscreen surface, hr %#x, case %u.\n", hr, i);
5951 memset(&ddsd, 0, sizeof(ddsd));
5952 ddsd.dwSize = sizeof(ddsd);
5953 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, 0, NULL);
5954 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5955 addr = ddsd.lpSurface;
5956 hr = IDirectDrawSurface7_Unlock(surface, NULL);
5957 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5959 memset(&ddsd, 0, sizeof(ddsd));
5960 ddsd.dwSize = sizeof(ddsd);
5961 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
5962 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5963 discarded = ddsd.lpSurface != addr;
5964 hr = IDirectDrawSurface7_Unlock(surface, NULL);
5965 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5967 hr = IDirectDrawSurface7_Blt(target, NULL, surface, NULL, DDBLT_WAIT, NULL);
5968 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
5970 memset(&ddsd, 0, sizeof(ddsd));
5971 ddsd.dwSize = sizeof(ddsd);
5972 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
5973 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5974 discarded |= ddsd.lpSurface != addr;
5975 hr = IDirectDrawSurface7_Unlock(surface, NULL);
5976 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5978 IDirectDrawSurface7_Release(surface);
5980 /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler,
5981 * AMD r500, evergreen). Windows XP, at least on AMD r200, does not. */
5982 ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i);
5985 IDirectDrawSurface7_Release(target);
5986 IDirectDraw7_Release(ddraw);
5987 IDirect3D7_Release(d3d);
5988 IDirect3DDevice7_Release(device);
5989 DestroyWindow(window);
5992 static void test_flip(void)
5994 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
5995 IDirectDrawSurface7 *primary, *backbuffer1, *backbuffer2, *backbuffer3, *surface;
5996 DDSCAPS2 caps = {DDSCAPS_FLIP, 0, 0, {0}};
5997 DDSURFACEDESC2 surface_desc;
5998 BOOL sysmem_primary;
5999 IDirectDraw7 *ddraw;
6000 D3DCOLOR color;
6001 ULONG refcount;
6002 HWND window;
6003 DDBLTFX fx;
6004 HRESULT hr;
6006 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6007 0, 0, 640, 480, 0, 0, 0, 0);
6008 ddraw = create_ddraw();
6009 ok(!!ddraw, "Failed to create a ddraw object.\n");
6011 hr = set_display_mode(ddraw, 640, 480);
6012 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
6013 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6014 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6016 memset(&surface_desc, 0, sizeof(surface_desc));
6017 surface_desc.dwSize = sizeof(surface_desc);
6018 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
6019 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
6020 U5(surface_desc).dwBackBufferCount = 3;
6021 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
6022 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6024 memset(&surface_desc, 0, sizeof(surface_desc));
6025 surface_desc.dwSize = sizeof(surface_desc);
6026 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &surface_desc);
6027 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6028 ok((surface_desc.ddsCaps.dwCaps & ~placement)
6029 == (DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX),
6030 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
6031 sysmem_primary = surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
6033 hr = IDirectDrawSurface7_GetAttachedSurface(primary, &caps, &backbuffer1);
6034 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
6035 memset(&surface_desc, 0, sizeof(surface_desc));
6036 surface_desc.dwSize = sizeof(surface_desc);
6037 hr = IDirectDrawSurface7_GetSurfaceDesc(backbuffer1, &surface_desc);
6038 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6039 ok(!U5(surface_desc).dwBackBufferCount, "Got unexpected back buffer count %u.\n", U5(surface_desc).dwBackBufferCount);
6040 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_BACKBUFFER),
6041 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
6043 hr = IDirectDrawSurface7_GetAttachedSurface(backbuffer1, &caps, &backbuffer2);
6044 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
6045 memset(&surface_desc, 0, sizeof(surface_desc));
6046 surface_desc.dwSize = sizeof(surface_desc);
6047 hr = IDirectDrawSurface7_GetSurfaceDesc(backbuffer2, &surface_desc);
6048 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6049 ok(!U5(surface_desc).dwBackBufferCount, "Got unexpected back buffer count %u.\n", U5(surface_desc).dwBackBufferCount);
6050 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX),
6051 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
6053 hr = IDirectDrawSurface7_GetAttachedSurface(backbuffer2, &caps, &backbuffer3);
6054 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
6055 memset(&surface_desc, 0, sizeof(surface_desc));
6056 surface_desc.dwSize = sizeof(surface_desc);
6057 hr = IDirectDrawSurface7_GetSurfaceDesc(backbuffer3, &surface_desc);
6058 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6059 ok(!U5(surface_desc).dwBackBufferCount, "Got unexpected back buffer count %u.\n", U5(surface_desc).dwBackBufferCount);
6060 ok((surface_desc.ddsCaps.dwCaps & ~placement) == (DDSCAPS_FLIP | DDSCAPS_COMPLEX),
6061 "Got unexpected caps %#x.\n", surface_desc.ddsCaps.dwCaps);
6063 hr = IDirectDrawSurface7_GetAttachedSurface(backbuffer3, &caps, &surface);
6064 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
6065 ok(surface == primary, "Got unexpected surface %p, expected %p.\n", surface, primary);
6066 IDirectDrawSurface7_Release(surface);
6068 memset(&surface_desc, 0, sizeof(surface_desc));
6069 surface_desc.dwSize = sizeof(surface_desc);
6070 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6071 surface_desc.ddsCaps.dwCaps = 0;
6072 surface_desc.dwWidth = 640;
6073 surface_desc.dwHeight = 480;
6074 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6075 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6076 hr = IDirectDrawSurface7_Flip(primary, surface, DDFLIP_WAIT);
6077 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
6078 IDirectDrawSurface7_Release(surface);
6080 hr = IDirectDrawSurface7_Flip(primary, primary, DDFLIP_WAIT);
6081 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
6082 hr = IDirectDrawSurface7_Flip(backbuffer1, NULL, DDFLIP_WAIT);
6083 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
6084 hr = IDirectDrawSurface7_Flip(backbuffer2, NULL, DDFLIP_WAIT);
6085 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
6086 hr = IDirectDrawSurface7_Flip(backbuffer3, NULL, DDFLIP_WAIT);
6087 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
6089 memset(&fx, 0, sizeof(fx));
6090 fx.dwSize = sizeof(fx);
6091 U5(fx).dwFillColor = 0xffff0000;
6092 hr = IDirectDrawSurface7_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6093 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
6094 U5(fx).dwFillColor = 0xff00ff00;
6095 hr = IDirectDrawSurface7_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6096 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
6097 U5(fx).dwFillColor = 0xff0000ff;
6098 hr = IDirectDrawSurface7_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6099 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
6101 hr = IDirectDrawSurface7_Flip(primary, NULL, DDFLIP_WAIT);
6102 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
6103 color = get_surface_color(backbuffer1, 320, 240);
6104 /* The testbot seems to just copy the contents of one surface to all the
6105 * others, instead of properly flipping. */
6106 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
6107 "Got unexpected color 0x%08x.\n", color);
6108 color = get_surface_color(backbuffer2, 320, 240);
6109 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
6110 U5(fx).dwFillColor = 0xffff0000;
6111 hr = IDirectDrawSurface7_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6112 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
6114 hr = IDirectDrawSurface7_Flip(primary, NULL, DDFLIP_WAIT);
6115 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
6116 color = get_surface_color(backbuffer1, 320, 240);
6117 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
6118 "Got unexpected color 0x%08x.\n", color);
6119 color = get_surface_color(backbuffer2, 320, 240);
6120 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
6121 U5(fx).dwFillColor = 0xff00ff00;
6122 hr = IDirectDrawSurface7_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6123 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
6125 hr = IDirectDrawSurface7_Flip(primary, NULL, DDFLIP_WAIT);
6126 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
6127 color = get_surface_color(backbuffer1, 320, 240);
6128 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
6129 "Got unexpected color 0x%08x.\n", color);
6130 color = get_surface_color(backbuffer2, 320, 240);
6131 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
6132 U5(fx).dwFillColor = 0xff0000ff;
6133 hr = IDirectDrawSurface7_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6134 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
6136 hr = IDirectDrawSurface7_Flip(primary, backbuffer1, DDFLIP_WAIT);
6137 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
6138 color = get_surface_color(backbuffer2, 320, 240);
6139 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
6140 "Got unexpected color 0x%08x.\n", color);
6141 color = get_surface_color(backbuffer3, 320, 240);
6142 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
6143 U5(fx).dwFillColor = 0xffff0000;
6144 hr = IDirectDrawSurface7_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6145 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
6147 hr = IDirectDrawSurface7_Flip(primary, backbuffer2, DDFLIP_WAIT);
6148 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
6149 color = get_surface_color(backbuffer1, 320, 240);
6150 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
6151 color = get_surface_color(backbuffer3, 320, 240);
6152 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
6153 "Got unexpected color 0x%08x.\n", color);
6154 U5(fx).dwFillColor = 0xff00ff00;
6155 hr = IDirectDrawSurface7_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6156 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
6158 hr = IDirectDrawSurface7_Flip(primary, backbuffer3, DDFLIP_WAIT);
6159 ok(SUCCEEDED(hr), "Failed to flip, hr %#x.\n", hr);
6160 color = get_surface_color(backbuffer1, 320, 240);
6161 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
6162 "Got unexpected color 0x%08x.\n", color);
6163 color = get_surface_color(backbuffer2, 320, 240);
6164 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
6166 IDirectDrawSurface7_Release(backbuffer3);
6167 IDirectDrawSurface7_Release(backbuffer2);
6168 IDirectDrawSurface7_Release(backbuffer1);
6169 IDirectDrawSurface7_Release(primary);
6170 refcount = IDirectDraw7_Release(ddraw);
6171 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
6172 DestroyWindow(window);
6175 static void reset_ddsd(DDSURFACEDESC2 *ddsd)
6177 memset(ddsd, 0, sizeof(*ddsd));
6178 ddsd->dwSize = sizeof(*ddsd);
6181 static void test_set_surface_desc(void)
6183 IDirectDraw7 *ddraw;
6184 HWND window;
6185 HRESULT hr;
6186 DDSURFACEDESC2 ddsd;
6187 IDirectDrawSurface7 *surface;
6188 BYTE data[16*16*4];
6189 ULONG ref;
6190 unsigned int i;
6191 static const struct
6193 DWORD caps, caps2;
6194 BOOL supported;
6195 const char *name;
6197 invalid_caps_tests[] =
6199 {DDSCAPS_VIDEOMEMORY, 0, FALSE, "videomemory plain"},
6200 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, TRUE, "systemmemory texture"},
6201 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE, "managed texture"},
6202 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE, "managed texture"},
6203 {DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY, 0, FALSE, "systemmemory primary"},
6206 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6207 0, 0, 640, 480, 0, 0, 0, 0);
6208 ddraw = create_ddraw();
6209 ok(!!ddraw, "Failed to create a ddraw object.\n");
6210 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6211 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6213 reset_ddsd(&ddsd);
6214 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
6215 ddsd.dwWidth = 8;
6216 ddsd.dwHeight = 8;
6217 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6218 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6219 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6220 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6221 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6222 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6223 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6225 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6226 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6228 reset_ddsd(&ddsd);
6229 ddsd.dwFlags = DDSD_LPSURFACE;
6230 ddsd.lpSurface = data;
6231 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6232 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6234 /* Redundantly setting the same lpSurface is not an error. */
6235 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6236 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6238 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6239 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6240 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
6241 ok(ddsd.lpSurface == NULL, "lpSurface is %p, expected NULL.\n", ddsd.lpSurface);
6243 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, 0, NULL);
6244 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6245 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
6246 ok(ddsd.lpSurface == data, "lpSurface is %p, expected %p.\n", data, data);
6247 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6248 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6250 reset_ddsd(&ddsd);
6251 ddsd.dwFlags = DDSD_LPSURFACE;
6252 ddsd.lpSurface = data;
6253 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 1);
6254 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with flags=1 returned %#x.\n", hr);
6256 ddsd.lpSurface = NULL;
6257 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6258 ok(hr == DDERR_INVALIDPARAMS, "Setting lpSurface=NULL returned %#x.\n", hr);
6260 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, NULL, 0);
6261 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with NULL desc returned %#x.\n", hr);
6263 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6264 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6265 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
6266 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
6267 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#x.\n", 0);
6269 /* Setting the caps is an error. This also means the original description cannot be reapplied. */
6270 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6271 ok(hr == DDERR_INVALIDPARAMS, "Setting the original desc returned %#x.\n", hr);
6273 ddsd.dwFlags = DDSD_CAPS;
6274 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6275 ok(hr == DDERR_INVALIDPARAMS, "Setting DDSD_CAPS returned %#x.\n", hr);
6277 /* dwCaps = 0 is allowed, but ignored. Caps2 can be anything and is ignored too. */
6278 ddsd.dwFlags = DDSD_CAPS | DDSD_LPSURFACE;
6279 ddsd.lpSurface = data;
6280 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6281 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
6282 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6283 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6284 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
6285 ddsd.ddsCaps.dwCaps = 0;
6286 ddsd.ddsCaps.dwCaps2 = 0xdeadbeef;
6287 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6288 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6290 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6291 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6292 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
6293 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
6294 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#x.\n", 0);
6296 /* Setting the height is allowed, but it cannot be set to 0, and only if LPSURFACE is set too. */
6297 reset_ddsd(&ddsd);
6298 ddsd.dwFlags = DDSD_HEIGHT;
6299 ddsd.dwHeight = 16;
6300 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6301 ok(hr == DDERR_INVALIDPARAMS, "Setting height without lpSurface returned %#x.\n", hr);
6303 ddsd.lpSurface = data;
6304 ddsd.dwFlags = DDSD_HEIGHT | DDSD_LPSURFACE;
6305 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6306 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6308 ddsd.dwHeight = 0;
6309 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6310 ok(hr == DDERR_INVALIDPARAMS, "Setting height=0 returned %#x.\n", hr);
6312 reset_ddsd(&ddsd);
6313 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6314 ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr);
6315 ok(ddsd.dwWidth == 8, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
6316 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
6318 /* Pitch and width can be set, but only together, and only with LPSURFACE. They must not be 0. */
6319 reset_ddsd(&ddsd);
6320 ddsd.dwFlags = DDSD_PITCH;
6321 U1(ddsd).lPitch = 8 * 4;
6322 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6323 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch without lpSurface or width returned %#x.\n", hr);
6325 ddsd.dwFlags = DDSD_WIDTH;
6326 ddsd.dwWidth = 16;
6327 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6328 ok(hr == DDERR_INVALIDPARAMS, "Setting width without lpSurface or pitch returned %#x.\n", hr);
6330 ddsd.dwFlags = DDSD_PITCH | DDSD_LPSURFACE;
6331 ddsd.lpSurface = data;
6332 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6333 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch and lpSurface without width returned %#x.\n", hr);
6335 ddsd.dwFlags = DDSD_WIDTH | DDSD_LPSURFACE;
6336 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6337 ok(hr == DDERR_INVALIDPARAMS, "Setting width and lpSurface without pitch returned %#x.\n", hr);
6339 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6340 U1(ddsd).lPitch = 16 * 4;
6341 ddsd.dwWidth = 16;
6342 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6343 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6345 reset_ddsd(&ddsd);
6346 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6347 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6348 ok(ddsd.dwWidth == 16, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
6349 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
6350 ok(U1(ddsd).lPitch == 16 * 4, "SetSurfaceDesc: Expected pitch 64, got %u.\n", U1(ddsd).lPitch);
6352 /* The pitch must be 32 bit aligned and > 0, but is not verified for sanity otherwise.
6354 * VMware rejects those calls, but all real drivers accept it. Mark the VMware behavior broken. */
6355 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6356 U1(ddsd).lPitch = 4 * 4;
6357 ddsd.lpSurface = data;
6358 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6359 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
6361 U1(ddsd).lPitch = 4;
6362 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6363 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
6365 U1(ddsd).lPitch = 16 * 4 + 1;
6366 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6367 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
6369 U1(ddsd).lPitch = 16 * 4 + 3;
6370 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6371 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
6373 U1(ddsd).lPitch = -4;
6374 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6375 ok(hr == DDERR_INVALIDPARAMS, "Setting negative pitch returned %#x.\n", hr);
6377 U1(ddsd).lPitch = 16 * 4;
6378 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6379 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6381 reset_ddsd(&ddsd);
6382 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6383 U1(ddsd).lPitch = 0;
6384 ddsd.dwWidth = 16;
6385 ddsd.lpSurface = data;
6386 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6387 ok(hr == DDERR_INVALIDPARAMS, "Setting zero pitch returned %#x.\n", hr);
6389 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6390 U1(ddsd).lPitch = 16 * 4;
6391 ddsd.dwWidth = 0;
6392 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6393 ok(hr == DDERR_INVALIDPARAMS, "Setting zero width returned %#x.\n", hr);
6395 /* Setting the pixelformat without LPSURFACE is an error, but with LPSURFACE it works. */
6396 ddsd.dwFlags = DDSD_PIXELFORMAT;
6397 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6398 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6399 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6400 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6401 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6402 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6403 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6404 ok(hr == DDERR_INVALIDPARAMS, "Setting the pixel format returned %#x.\n", hr);
6406 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_LPSURFACE;
6407 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6408 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6410 /* Can't set color keys. */
6411 reset_ddsd(&ddsd);
6412 ddsd.dwFlags = DDSD_CKSRCBLT;
6413 ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff0000;
6414 ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff0000;
6415 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6416 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
6418 ddsd.dwFlags = DDSD_CKSRCBLT | DDSD_LPSURFACE;
6419 ddsd.lpSurface = data;
6420 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6421 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
6423 IDirectDrawSurface7_Release(surface);
6425 /* SetSurfaceDesc needs systemmemory surfaces.
6427 * As a sidenote, fourcc surfaces aren't allowed in sysmem, thus testing DDSD_LINEARSIZE is moot. */
6428 for (i = 0; i < sizeof(invalid_caps_tests) / sizeof(*invalid_caps_tests); i++)
6430 reset_ddsd(&ddsd);
6431 ddsd.dwFlags = DDSD_CAPS;
6432 ddsd.ddsCaps.dwCaps = invalid_caps_tests[i].caps;
6433 ddsd.ddsCaps.dwCaps2 = invalid_caps_tests[i].caps2;
6434 if (!(invalid_caps_tests[i].caps & DDSCAPS_PRIMARYSURFACE))
6436 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6437 ddsd.dwWidth = 8;
6438 ddsd.dwHeight = 8;
6439 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6440 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6441 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6442 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6443 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6444 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6447 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6448 if (is_ddraw64 && (invalid_caps_tests[i].caps & DDSCAPS_TEXTURE))
6449 todo_wine ok(hr == E_NOINTERFACE, "Test %u: Got unexpected hr %#x.\n", i, hr);
6450 else
6451 ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWHW, "Test %u: Got unexpected hr %#x.\n", i, hr);
6452 if (FAILED(hr))
6453 continue;
6455 reset_ddsd(&ddsd);
6456 ddsd.dwFlags = DDSD_LPSURFACE;
6457 ddsd.lpSurface = data;
6458 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6459 if (invalid_caps_tests[i].supported)
6461 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6463 else
6465 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
6466 invalid_caps_tests[i].name, hr);
6468 /* Check priority of error conditions. */
6469 ddsd.dwFlags = DDSD_WIDTH;
6470 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6471 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
6472 invalid_caps_tests[i].name, hr);
6475 IDirectDrawSurface7_Release(surface);
6478 ref = IDirectDraw7_Release(ddraw);
6479 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
6480 DestroyWindow(window);
6483 static void test_user_memory_getdc(void)
6485 IDirectDraw7 *ddraw;
6486 HWND window;
6487 HRESULT hr;
6488 DDSURFACEDESC2 ddsd;
6489 IDirectDrawSurface7 *surface;
6490 DWORD data[16][16];
6491 ULONG ref;
6492 HDC dc;
6493 unsigned int x, y;
6495 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6496 0, 0, 640, 480, 0, 0, 0, 0);
6497 ddraw = create_ddraw();
6498 ok(!!ddraw, "Failed to create a ddraw object.\n");
6499 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6500 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6502 reset_ddsd(&ddsd);
6503 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
6504 ddsd.dwWidth = 16;
6505 ddsd.dwHeight = 16;
6506 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6507 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6508 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6509 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6510 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6511 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6512 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6513 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6514 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6516 memset(data, 0xaa, sizeof(data));
6517 reset_ddsd(&ddsd);
6518 ddsd.dwFlags = DDSD_LPSURFACE;
6519 ddsd.lpSurface = data;
6520 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6521 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6523 hr = IDirectDrawSurface7_GetDC(surface, &dc);
6524 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
6525 BitBlt(dc, 0, 0, 16, 8, NULL, 0, 0, WHITENESS);
6526 BitBlt(dc, 0, 8, 16, 8, NULL, 0, 0, BLACKNESS);
6527 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
6528 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
6530 ok(data[0][0] == 0xffffffff, "Expected color 0xffffffff, got %#x.\n", data[0][0]);
6531 ok(data[15][15] == 0x00000000, "Expected color 0x00000000, got %#x.\n", data[15][15]);
6533 ddsd.dwFlags = DDSD_LPSURFACE | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH;
6534 ddsd.lpSurface = data;
6535 ddsd.dwWidth = 4;
6536 ddsd.dwHeight = 8;
6537 U1(ddsd).lPitch = sizeof(*data);
6538 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6539 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6541 memset(data, 0xaa, sizeof(data));
6542 hr = IDirectDrawSurface7_GetDC(surface, &dc);
6543 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
6544 BitBlt(dc, 0, 0, 4, 8, NULL, 0, 0, BLACKNESS);
6545 BitBlt(dc, 1, 1, 2, 2, NULL, 0, 0, WHITENESS);
6546 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
6547 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
6549 for (y = 0; y < 4; y++)
6551 for (x = 0; x < 4; x++)
6553 if ((x == 1 || x == 2) && (y == 1 || y == 2))
6554 ok(data[y][x] == 0xffffffff, "Expected color 0xffffffff on position %ux%u, got %#x.\n",
6555 x, y, data[y][x]);
6556 else
6557 ok(data[y][x] == 0x00000000, "Expected color 0x00000000 on position %ux%u, got %#x.\n",
6558 x, y, data[y][x]);
6561 ok(data[0][5] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 5x0, got %#x.\n",
6562 data[0][5]);
6563 ok(data[7][3] == 0x00000000, "Expected color 0x00000000 on position 3x7, got %#x.\n",
6564 data[7][3]);
6565 ok(data[7][4] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 4x7, got %#x.\n",
6566 data[7][4]);
6567 ok(data[8][0] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 0x8, got %#x.\n",
6568 data[8][0]);
6570 IDirectDrawSurface7_Release(surface);
6571 ref = IDirectDraw7_Release(ddraw);
6572 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
6573 DestroyWindow(window);
6576 static void test_sysmem_overlay(void)
6578 IDirectDraw7 *ddraw;
6579 HWND window;
6580 HRESULT hr;
6581 DDSURFACEDESC2 ddsd;
6582 IDirectDrawSurface7 *surface;
6583 ULONG ref;
6585 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6586 0, 0, 640, 480, 0, 0, 0, 0);
6587 ddraw = create_ddraw();
6588 ok(!!ddraw, "Failed to create a ddraw object.\n");
6589 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6590 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6592 reset_ddsd(&ddsd);
6593 ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
6594 ddsd.dwWidth = 16;
6595 ddsd.dwHeight = 16;
6596 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OVERLAY;
6597 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6598 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6599 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6600 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6601 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6602 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6603 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6604 ok(hr == DDERR_NOOVERLAYHW, "Got unexpected hr %#x.\n", hr);
6606 ref = IDirectDraw7_Release(ddraw);
6607 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
6608 DestroyWindow(window);
6611 static void test_primary_palette(void)
6613 DDSCAPS2 surface_caps = {DDSCAPS_FLIP, 0, 0, {0}};
6614 IDirectDrawSurface7 *primary, *backbuffer;
6615 PALETTEENTRY palette_entries[256];
6616 IDirectDrawPalette *palette, *tmp;
6617 DDSURFACEDESC2 surface_desc;
6618 IDirectDraw7 *ddraw;
6619 DWORD palette_caps;
6620 ULONG refcount;
6621 HWND window;
6622 HRESULT hr;
6624 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6625 0, 0, 640, 480, 0, 0, 0, 0);
6626 ddraw = create_ddraw();
6627 ok(!!ddraw, "Failed to create a ddraw object.\n");
6628 if (FAILED(IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
6630 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
6631 IDirectDraw7_Release(ddraw);
6632 DestroyWindow(window);
6633 return;
6635 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6636 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6638 memset(&surface_desc, 0, sizeof(surface_desc));
6639 surface_desc.dwSize = sizeof(surface_desc);
6640 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
6641 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
6642 U5(surface_desc).dwBackBufferCount = 1;
6643 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
6644 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6645 hr = IDirectDrawSurface7_GetAttachedSurface(primary, &surface_caps, &backbuffer);
6646 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
6648 memset(palette_entries, 0, sizeof(palette_entries));
6649 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_entries, &palette, NULL);
6650 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
6651 refcount = get_refcount((IUnknown *)palette);
6652 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6654 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
6655 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
6656 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
6658 hr = IDirectDrawSurface7_SetPalette(primary, palette);
6659 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6661 /* The Windows 8 testbot attaches the palette to the backbuffer as well,
6662 * and is generally somewhat broken with respect to 8 bpp / palette
6663 * handling. */
6664 if (SUCCEEDED(IDirectDrawSurface7_GetPalette(backbuffer, &tmp)))
6666 win_skip("Broken palette handling detected, skipping tests.\n");
6667 IDirectDrawPalette_Release(tmp);
6668 IDirectDrawPalette_Release(palette);
6669 /* The Windows 8 testbot keeps extra references to the primary and
6670 * backbuffer while in 8 bpp mode. */
6671 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
6672 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
6673 goto done;
6676 refcount = get_refcount((IUnknown *)palette);
6677 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
6679 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
6680 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
6681 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE | DDPCAPS_ALLOW256),
6682 "Got unexpected palette caps %#x.\n", palette_caps);
6684 hr = IDirectDrawSurface7_SetPalette(primary, NULL);
6685 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6686 refcount = get_refcount((IUnknown *)palette);
6687 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6689 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
6690 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
6691 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
6693 hr = IDirectDrawSurface7_SetPalette(primary, palette);
6694 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6695 refcount = get_refcount((IUnknown *)palette);
6696 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
6698 hr = IDirectDrawSurface7_GetPalette(primary, &tmp);
6699 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
6700 ok(tmp == palette, "Got unexpected palette %p, expected %p.\n", tmp, palette);
6701 IDirectDrawPalette_Release(tmp);
6702 hr = IDirectDrawSurface7_GetPalette(backbuffer, &tmp);
6703 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
6705 refcount = IDirectDrawPalette_Release(palette);
6706 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6707 refcount = IDirectDrawPalette_Release(palette);
6708 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6710 /* Note that this only seems to work when the palette is attached to the
6711 * primary surface. When attached to a regular surface, attempting to get
6712 * the palette here will cause an access violation. */
6713 hr = IDirectDrawSurface7_GetPalette(primary, &tmp);
6714 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
6716 done:
6717 refcount = IDirectDrawSurface7_Release(backbuffer);
6718 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6719 refcount = IDirectDrawSurface7_Release(primary);
6720 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6721 refcount = IDirectDraw7_Release(ddraw);
6722 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6723 DestroyWindow(window);
6726 static HRESULT WINAPI surface_counter(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
6728 UINT *surface_count = context;
6730 ++(*surface_count);
6731 IDirectDrawSurface_Release(surface);
6733 return DDENUMRET_OK;
6736 static void test_surface_attachment(void)
6738 IDirectDrawSurface7 *surface1, *surface2, *surface3, *surface4;
6739 IDirectDrawSurface *surface1v1, *surface2v1;
6740 DDSCAPS2 caps = {DDSCAPS_TEXTURE, 0, 0, {0}};
6741 DDSURFACEDESC2 surface_desc;
6742 IDirectDraw7 *ddraw;
6743 UINT surface_count;
6744 ULONG refcount;
6745 HWND window;
6746 HRESULT hr;
6748 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6749 0, 0, 640, 480, 0, 0, 0, 0);
6750 ddraw = create_ddraw();
6751 ok(!!ddraw, "Failed to create a ddraw object.\n");
6752 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6753 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6755 memset(&surface_desc, 0, sizeof(surface_desc));
6756 surface_desc.dwSize = sizeof(surface_desc);
6757 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
6758 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
6759 U2(surface_desc).dwMipMapCount = 3;
6760 surface_desc.dwWidth = 128;
6761 surface_desc.dwHeight = 128;
6762 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL)))
6764 skip("Failed to create a texture, skipping tests.\n");
6765 IDirectDraw7_Release(ddraw);
6766 DestroyWindow(window);
6767 return;
6770 hr = IDirectDrawSurface7_GetAttachedSurface(surface1, &caps, &surface2);
6771 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
6772 hr = IDirectDrawSurface7_GetAttachedSurface(surface2, &caps, &surface3);
6773 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
6774 hr = IDirectDrawSurface7_GetAttachedSurface(surface3, &caps, &surface4);
6775 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
6777 surface_count = 0;
6778 IDirectDrawSurface7_EnumAttachedSurfaces(surface1, &surface_count, surface_counter);
6779 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
6780 surface_count = 0;
6781 IDirectDrawSurface7_EnumAttachedSurfaces(surface2, &surface_count, surface_counter);
6782 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
6783 surface_count = 0;
6784 IDirectDrawSurface7_EnumAttachedSurfaces(surface3, &surface_count, surface_counter);
6785 ok(!surface_count, "Got unexpected surface_count %u.\n", surface_count);
6787 memset(&surface_desc, 0, sizeof(surface_desc));
6788 surface_desc.dwSize = sizeof(surface_desc);
6789 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6790 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6791 surface_desc.dwWidth = 16;
6792 surface_desc.dwHeight = 16;
6793 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
6794 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6796 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
6797 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6798 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
6799 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6800 hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface4);
6801 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6802 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface3);
6803 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6804 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface4);
6805 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6806 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface2);
6807 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6809 IDirectDrawSurface7_Release(surface4);
6811 memset(&surface_desc, 0, sizeof(surface_desc));
6812 surface_desc.dwSize = sizeof(surface_desc);
6813 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6814 surface_desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6815 surface_desc.dwWidth = 16;
6816 surface_desc.dwHeight = 16;
6817 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
6818 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6820 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
6821 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6822 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
6823 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6824 hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface4);
6825 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6826 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface3);
6827 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6828 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface4);
6829 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6830 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface2);
6831 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6833 IDirectDrawSurface7_Release(surface4);
6834 IDirectDrawSurface7_Release(surface3);
6835 IDirectDrawSurface7_Release(surface2);
6836 IDirectDrawSurface7_Release(surface1);
6838 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6839 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6841 /* Try a single primary and two offscreen plain surfaces. */
6842 memset(&surface_desc, 0, sizeof(surface_desc));
6843 surface_desc.dwSize = sizeof(surface_desc);
6844 surface_desc.dwFlags = DDSD_CAPS;
6845 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
6846 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
6847 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6849 memset(&surface_desc, 0, sizeof(surface_desc));
6850 surface_desc.dwSize = sizeof(surface_desc);
6851 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6852 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6853 surface_desc.dwWidth = registry_mode.dmPelsWidth;
6854 surface_desc.dwHeight = registry_mode.dmPelsHeight;
6855 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
6856 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6858 memset(&surface_desc, 0, sizeof(surface_desc));
6859 surface_desc.dwSize = sizeof(surface_desc);
6860 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6861 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6862 surface_desc.dwWidth = registry_mode.dmPelsWidth;
6863 surface_desc.dwHeight = registry_mode.dmPelsHeight;
6864 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
6865 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6867 /* This one has a different size. */
6868 memset(&surface_desc, 0, sizeof(surface_desc));
6869 surface_desc.dwSize = sizeof(surface_desc);
6870 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6871 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
6872 surface_desc.dwWidth = 128;
6873 surface_desc.dwHeight = 128;
6874 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
6875 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6877 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
6878 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6879 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface1);
6880 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6881 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface3);
6882 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6883 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
6884 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6885 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
6886 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6888 IDirectDrawSurface7_Release(surface4);
6889 IDirectDrawSurface7_Release(surface3);
6890 IDirectDrawSurface7_Release(surface2);
6891 IDirectDrawSurface7_Release(surface1);
6893 /* Test DeleteAttachedSurface() and automatic detachment of attached surfaces on release. */
6894 memset(&surface_desc, 0, sizeof(surface_desc));
6895 surface_desc.dwSize = sizeof(surface_desc);
6896 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6897 surface_desc.dwWidth = 64;
6898 surface_desc.dwHeight = 64;
6899 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
6900 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
6901 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
6902 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
6903 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
6904 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
6905 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
6906 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
6907 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6908 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
6909 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6911 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
6912 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
6913 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = 16;
6914 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = 0x0000ffff;
6915 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
6916 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6918 hr = IDirectDrawSurface7_QueryInterface(surface1, &IID_IDirectDrawSurface, (void **)&surface1v1);
6919 ok(SUCCEEDED(hr), "Failed to get interface, hr %#x.\n", hr);
6920 hr = IDirectDrawSurface7_QueryInterface(surface2, &IID_IDirectDrawSurface, (void **)&surface2v1);
6921 ok(SUCCEEDED(hr), "Failed to get interface, hr %#x.\n", hr);
6923 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
6924 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
6925 refcount = get_refcount((IUnknown *)surface2);
6926 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
6927 refcount = get_refcount((IUnknown *)surface2v1);
6928 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6929 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
6930 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
6931 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
6932 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6933 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
6934 ok(hr == DDERR_SURFACENOTATTACHED, "Got unexpected hr %#x.\n", hr);
6936 /* Attaching while already attached to other surface. */
6937 hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface2);
6938 todo_wine ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
6939 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface3, 0, surface2);
6940 todo_wine ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
6941 IDirectDrawSurface7_Release(surface3);
6943 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface2);
6944 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
6945 refcount = get_refcount((IUnknown *)surface2);
6946 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6947 refcount = get_refcount((IUnknown *)surface2v1);
6948 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6950 /* DeleteAttachedSurface() when attaching via IDirectDrawSurface. */
6951 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
6952 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
6953 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface2);
6954 ok(hr == DDERR_SURFACENOTATTACHED, "Got unexpected hr %#x.\n", hr);
6955 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
6956 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
6957 refcount = IDirectDrawSurface7_Release(surface2);
6958 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6959 refcount = IDirectDrawSurface7_Release(surface1);
6960 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6962 /* Automatic detachment on release. */
6963 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
6964 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
6965 refcount = get_refcount((IUnknown *)surface2v1);
6966 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
6967 refcount = IDirectDrawSurface_Release(surface1v1);
6968 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6969 refcount = IDirectDrawSurface_Release(surface2v1);
6970 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6971 refcount = IDirectDraw7_Release(ddraw);
6972 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6973 DestroyWindow(window);
6976 static void test_private_data(void)
6978 IDirectDraw7 *ddraw;
6979 IDirectDrawSurface7 *surface, *surface2;
6980 DDSURFACEDESC2 surface_desc;
6981 ULONG refcount, refcount2, refcount3;
6982 IUnknown *ptr;
6983 DWORD size = sizeof(ptr);
6984 HRESULT hr;
6985 HWND window;
6986 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
6987 DWORD data[] = {1, 2, 3, 4};
6988 DDCAPS hal_caps;
6989 static const GUID ddraw_private_data_test_guid =
6991 0xfdb37466,
6992 0x428f,
6993 0x4edf,
6994 {0xa3,0x7f,0x9b,0x1d,0xf4,0x88,0xc5,0xfc}
6996 static const GUID ddraw_private_data_test_guid2 =
6998 0x2e5afac2,
6999 0x87b5,
7000 0x4c10,
7001 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
7004 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7005 0, 0, 640, 480, 0, 0, 0, 0);
7006 ddraw = create_ddraw();
7007 ok(!!ddraw, "Failed to create a ddraw object.\n");
7008 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7009 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7011 reset_ddsd(&surface_desc);
7012 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
7013 surface_desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
7014 surface_desc.dwHeight = 4;
7015 surface_desc.dwWidth = 4;
7016 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7017 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7019 /* NULL pointers are not valid, but don't cause a crash. */
7020 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL,
7021 sizeof(IUnknown *), DDSPD_IUNKNOWNPOINTER);
7022 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7023 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL, 0, 0);
7024 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7025 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL, 1, 0);
7026 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7028 /* DDSPD_IUNKNOWNPOINTER needs sizeof(IUnknown *) bytes of data. */
7029 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7030 0, DDSPD_IUNKNOWNPOINTER);
7031 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7032 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7033 5, DDSPD_IUNKNOWNPOINTER);
7034 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7035 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7036 sizeof(ddraw) * 2, DDSPD_IUNKNOWNPOINTER);
7037 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7039 /* Note that with a size != 0 and size != sizeof(IUnknown *) and
7040 * DDSPD_IUNKNOWNPOINTER set SetPrivateData in ddraw4 and ddraw7
7041 * erases the old content and returns an error. This behavior has
7042 * been fixed in d3d8 and d3d9. Unless an application is found
7043 * that depends on this we don't care about this behavior. */
7044 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7045 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7046 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7047 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7048 0, DDSPD_IUNKNOWNPOINTER);
7049 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7050 size = sizeof(ptr);
7051 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
7052 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7053 hr = IDirectDrawSurface7_FreePrivateData(surface, &ddraw_private_data_test_guid);
7054 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7056 refcount = get_refcount((IUnknown *)ddraw);
7057 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7058 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7059 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7060 refcount2 = get_refcount((IUnknown *)ddraw);
7061 ok(refcount2 == refcount + 1, "Got unexpected refcount %u.\n", refcount2);
7063 hr = IDirectDrawSurface7_FreePrivateData(surface, &ddraw_private_data_test_guid);
7064 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7065 refcount2 = get_refcount((IUnknown *)ddraw);
7066 ok(refcount2 == refcount, "Got unexpected refcount %u.\n", refcount2);
7068 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7069 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7070 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7071 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, surface,
7072 sizeof(surface), DDSPD_IUNKNOWNPOINTER);
7073 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7074 refcount2 = get_refcount((IUnknown *)ddraw);
7075 ok(refcount2 == refcount, "Got unexpected refcount %u.\n", refcount2);
7077 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7078 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7079 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7080 size = 2 * sizeof(ptr);
7081 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
7082 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7083 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
7084 refcount2 = get_refcount(ptr);
7085 /* Object is NOT addref'ed by the getter. */
7086 ok(ptr == (IUnknown *)ddraw, "Returned interface pointer is %p, expected %p.\n", ptr, ddraw);
7087 ok(refcount2 == refcount + 1, "Got unexpected refcount %u.\n", refcount2);
7089 ptr = (IUnknown *)0xdeadbeef;
7090 size = 1;
7091 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, &size);
7092 ok(hr == DDERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
7093 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
7094 size = 2 * sizeof(ptr);
7095 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, &size);
7096 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7097 ok(size == 2 * sizeof(ptr), "Got unexpected size %u.\n", size);
7098 size = 1;
7099 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
7100 ok(hr == DDERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
7101 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
7102 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7103 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid2, NULL, NULL);
7104 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7105 size = 0xdeadbabe;
7106 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid2, &ptr, &size);
7107 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7108 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7109 ok(size == 0xdeadbabe, "Got unexpected size %u.\n", size);
7110 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, NULL);
7111 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7113 refcount3 = IDirectDrawSurface7_Release(surface);
7114 ok(!refcount3, "Got unexpected refcount %u.\n", refcount3);
7116 /* Destroying the surface frees the reference held on the private data. It also frees
7117 * the reference the surface is holding on its creating object. */
7118 refcount2 = get_refcount((IUnknown *)ddraw);
7119 ok(refcount2 == refcount - 1, "Got unexpected refcount %u.\n", refcount2);
7121 memset(&hal_caps, 0, sizeof(hal_caps));
7122 hal_caps.dwSize = sizeof(hal_caps);
7123 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
7124 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7125 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) == (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)
7126 && !is_ddraw64)
7128 reset_ddsd(&surface_desc);
7129 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_MIPMAPCOUNT;
7130 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7131 surface_desc.dwHeight = 4;
7132 surface_desc.dwWidth = 4;
7133 U2(surface_desc).dwMipMapCount = 2;
7134 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7135 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7136 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &surface2);
7137 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
7139 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, data, sizeof(data), 0);
7140 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7141 hr = IDirectDrawSurface7_GetPrivateData(surface2, &ddraw_private_data_test_guid, NULL, NULL);
7142 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7144 IDirectDrawSurface7_Release(surface2);
7145 IDirectDrawSurface7_Release(surface);
7147 else
7148 skip("Mipmapped textures not supported, skipping mipmap private data test.\n");
7150 refcount = IDirectDraw7_Release(ddraw);
7151 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7152 DestroyWindow(window);
7155 static void test_pixel_format(void)
7157 HWND window, window2 = NULL;
7158 HDC hdc, hdc2 = NULL;
7159 HMODULE gl = NULL;
7160 int format, test_format;
7161 PIXELFORMATDESCRIPTOR pfd;
7162 IDirectDraw7 *ddraw = NULL;
7163 IDirectDrawClipper *clipper = NULL;
7164 DDSURFACEDESC2 ddsd;
7165 IDirectDrawSurface7 *primary = NULL;
7166 DDBLTFX fx;
7167 HRESULT hr;
7169 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
7170 100, 100, 160, 160, NULL, NULL, NULL, NULL);
7171 if (!window)
7173 skip("Failed to create window\n");
7174 return;
7177 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
7178 100, 100, 160, 160, NULL, NULL, NULL, NULL);
7180 hdc = GetDC(window);
7181 if (!hdc)
7183 skip("Failed to get DC\n");
7184 goto cleanup;
7187 if (window2)
7188 hdc2 = GetDC(window2);
7190 gl = LoadLibraryA("opengl32.dll");
7191 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
7193 format = GetPixelFormat(hdc);
7194 ok(format == 0, "new window has pixel format %d\n", format);
7196 ZeroMemory(&pfd, sizeof(pfd));
7197 pfd.nSize = sizeof(pfd);
7198 pfd.nVersion = 1;
7199 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
7200 pfd.iPixelType = PFD_TYPE_RGBA;
7201 pfd.iLayerType = PFD_MAIN_PLANE;
7202 format = ChoosePixelFormat(hdc, &pfd);
7203 if (format <= 0)
7205 skip("no pixel format available\n");
7206 goto cleanup;
7209 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
7211 skip("failed to set pixel format\n");
7212 goto cleanup;
7215 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
7217 skip("failed to set pixel format on second window\n");
7218 if (hdc2)
7220 ReleaseDC(window2, hdc2);
7221 hdc2 = NULL;
7225 ddraw = create_ddraw();
7226 ok(!!ddraw, "Failed to create a ddraw object.\n");
7228 test_format = GetPixelFormat(hdc);
7229 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7231 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7232 if (FAILED(hr))
7234 skip("Failed to set cooperative level, hr %#x.\n", hr);
7235 goto cleanup;
7238 test_format = GetPixelFormat(hdc);
7239 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7241 if (hdc2)
7243 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
7244 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
7245 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window2);
7246 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
7248 test_format = GetPixelFormat(hdc);
7249 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7251 test_format = GetPixelFormat(hdc2);
7252 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7255 memset(&ddsd, 0, sizeof(ddsd));
7256 ddsd.dwSize = sizeof(ddsd);
7257 ddsd.dwFlags = DDSD_CAPS;
7258 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7260 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
7261 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
7263 test_format = GetPixelFormat(hdc);
7264 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7266 if (hdc2)
7268 test_format = GetPixelFormat(hdc2);
7269 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7272 if (clipper)
7274 hr = IDirectDrawSurface7_SetClipper(primary, clipper);
7275 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
7277 test_format = GetPixelFormat(hdc);
7278 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7280 test_format = GetPixelFormat(hdc2);
7281 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7284 memset(&fx, 0, sizeof(fx));
7285 fx.dwSize = sizeof(fx);
7286 hr = IDirectDrawSurface7_Blt(primary, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7287 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
7289 test_format = GetPixelFormat(hdc);
7290 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7292 if (hdc2)
7294 test_format = GetPixelFormat(hdc2);
7295 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7298 cleanup:
7299 if (primary) IDirectDrawSurface7_Release(primary);
7300 if (clipper) IDirectDrawClipper_Release(clipper);
7301 if (ddraw) IDirectDraw7_Release(ddraw);
7302 if (gl) FreeLibrary(gl);
7303 if (hdc) ReleaseDC(window, hdc);
7304 if (hdc2) ReleaseDC(window2, hdc2);
7305 if (window) DestroyWindow(window);
7306 if (window2) DestroyWindow(window2);
7309 static void test_create_surface_pitch(void)
7311 IDirectDrawSurface7 *surface;
7312 DDSURFACEDESC2 surface_desc;
7313 IDirectDraw7 *ddraw;
7314 unsigned int i;
7315 ULONG refcount;
7316 HWND window;
7317 HRESULT hr;
7318 void *mem;
7320 static const struct
7322 DWORD caps;
7323 DWORD flags_in;
7324 DWORD pitch_in;
7325 HRESULT hr;
7326 DWORD flags_out;
7327 DWORD pitch_out32;
7328 DWORD pitch_out64;
7330 test_data[] =
7332 /* 0 */
7333 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7334 0, 0, DD_OK,
7335 DDSD_PITCH, 0x100, 0x100},
7336 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7337 DDSD_PITCH, 0x104, DD_OK,
7338 DDSD_PITCH, 0x100, 0x100},
7339 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7340 DDSD_PITCH, 0x0f8, DD_OK,
7341 DDSD_PITCH, 0x100, 0x100},
7342 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7343 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
7344 0, 0, 0 },
7345 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7346 0, 0, DD_OK,
7347 DDSD_PITCH, 0x100, 0x0fc},
7348 /* 5 */
7349 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7350 DDSD_PITCH, 0x104, DD_OK,
7351 DDSD_PITCH, 0x100, 0x0fc},
7352 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7353 DDSD_PITCH, 0x0f8, DD_OK,
7354 DDSD_PITCH, 0x100, 0x0fc},
7355 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7356 DDSD_PITCH | DDSD_LINEARSIZE, 0, DD_OK,
7357 DDSD_PITCH, 0x100, 0x0fc},
7358 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7359 DDSD_LPSURFACE, 0, DDERR_INVALIDPARAMS,
7360 0, 0, 0 },
7361 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7362 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DD_OK,
7363 DDSD_PITCH, 0x100, 0x100},
7364 /* 10 */
7365 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7366 DDSD_LPSURFACE | DDSD_PITCH, 0x0fe, DDERR_INVALIDPARAMS,
7367 0, 0, 0 },
7368 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7369 DDSD_LPSURFACE | DDSD_PITCH, 0x0fc, DD_OK,
7370 DDSD_PITCH, 0x0fc, 0x0fc},
7371 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7372 DDSD_LPSURFACE | DDSD_PITCH, 0x0f8, DDERR_INVALIDPARAMS,
7373 0, 0, 0 },
7374 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7375 DDSD_LPSURFACE | DDSD_LINEARSIZE, 0x100, DDERR_INVALIDPARAMS,
7376 0, 0, 0 },
7377 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7378 DDSD_LPSURFACE | DDSD_LINEARSIZE, 0x3f00, DDERR_INVALIDPARAMS,
7379 0, 0, 0 },
7380 /* 15 */
7381 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7382 DDSD_LPSURFACE | DDSD_PITCH | DDSD_LINEARSIZE, 0x100, DD_OK,
7383 DDSD_PITCH, 0x100, 0x100},
7384 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
7385 0, 0, DDERR_INVALIDCAPS,
7386 0, 0, 0 },
7387 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7388 0, 0, DD_OK,
7389 DDSD_PITCH, 0x100, 0 },
7390 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7391 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
7392 0, 0, 0 },
7393 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
7394 0, 0, DDERR_INVALIDCAPS,
7395 0, 0, 0 },
7396 /* 20 */
7397 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7398 0, 0, DD_OK,
7399 DDSD_PITCH, 0x100, 0 },
7400 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7401 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DD_OK,
7402 DDSD_PITCH, 0x100, 0 },
7404 DWORD flags_mask = DDSD_PITCH | DDSD_LPSURFACE | DDSD_LINEARSIZE;
7406 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7407 0, 0, 640, 480, 0, 0, 0, 0);
7408 ddraw = create_ddraw();
7409 ok(!!ddraw, "Failed to create a ddraw object.\n");
7410 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7411 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7413 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((63 * 4) + 8) * 63);
7415 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
7417 memset(&surface_desc, 0, sizeof(surface_desc));
7418 surface_desc.dwSize = sizeof(surface_desc);
7419 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | test_data[i].flags_in;
7420 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
7421 surface_desc.dwWidth = 63;
7422 surface_desc.dwHeight = 63;
7423 U1(surface_desc).lPitch = test_data[i].pitch_in;
7424 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7425 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
7426 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
7427 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7428 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7429 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7430 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7431 if (test_data[i].flags_in & DDSD_LPSURFACE)
7433 HRESULT expected_hr = SUCCEEDED(test_data[i].hr) ? DDERR_INVALIDPARAMS : test_data[i].hr;
7434 ok(hr == expected_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, expected_hr);
7435 surface_desc.lpSurface = mem;
7436 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7438 if ((test_data[i].caps & DDSCAPS_VIDEOMEMORY) && hr == DDERR_NODIRECTDRAWHW)
7439 continue;
7440 if (is_ddraw64 && (test_data[i].caps & DDSCAPS_TEXTURE) && SUCCEEDED(test_data[i].hr))
7441 todo_wine ok(hr == E_NOINTERFACE, "Test %u: Got unexpected hr %#x.\n", i, hr);
7442 else
7443 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
7444 if (FAILED(hr))
7445 continue;
7447 memset(&surface_desc, 0, sizeof(surface_desc));
7448 surface_desc.dwSize = sizeof(surface_desc);
7449 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
7450 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
7451 ok((surface_desc.dwFlags & flags_mask) == test_data[i].flags_out,
7452 "Test %u: Got unexpected flags %#x, expected %#x.\n",
7453 i, surface_desc.dwFlags & flags_mask, test_data[i].flags_out);
7454 /* The pitch for textures seems to be implementation specific. */
7455 if (!(test_data[i].caps & DDSCAPS_TEXTURE))
7457 if (is_ddraw64 && test_data[i].pitch_out32 != test_data[i].pitch_out64)
7458 todo_wine ok(U1(surface_desc).lPitch == test_data[i].pitch_out64,
7459 "Test %u: Got unexpected pitch %u, expected %u.\n",
7460 i, U1(surface_desc).lPitch, test_data[i].pitch_out64);
7461 else
7462 ok(U1(surface_desc).lPitch == test_data[i].pitch_out32,
7463 "Test %u: Got unexpected pitch %u, expected %u.\n",
7464 i, U1(surface_desc).lPitch, test_data[i].pitch_out32);
7466 ok(!surface_desc.lpSurface, "Test %u: Got unexpected lpSurface %p.\n", i, surface_desc.lpSurface);
7468 IDirectDrawSurface7_Release(surface);
7471 HeapFree(GetProcessHeap(), 0, mem);
7472 refcount = IDirectDraw7_Release(ddraw);
7473 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7474 DestroyWindow(window);
7477 static void test_mipmap(void)
7479 IDirectDrawSurface7 *surface, *surface2;
7480 DDSURFACEDESC2 surface_desc;
7481 IDirectDraw7 *ddraw;
7482 unsigned int i;
7483 ULONG refcount;
7484 HWND window;
7485 HRESULT hr;
7486 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
7487 DDCAPS hal_caps;
7489 static const struct
7491 DWORD flags;
7492 DWORD caps;
7493 DWORD width;
7494 DWORD height;
7495 DWORD mipmap_count_in;
7496 HRESULT hr;
7497 DWORD mipmap_count_out;
7499 tests[] =
7501 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 3, DD_OK, 3},
7502 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDPARAMS, 0},
7503 {0, DDSCAPS_TEXTURE | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 1},
7504 {0, DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDCAPS, 0},
7505 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 8},
7506 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 32, 64, 0, DD_OK, 7},
7509 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7510 0, 0, 640, 480, 0, 0, 0, 0);
7511 ddraw = create_ddraw();
7512 ok(!!ddraw, "Failed to create a ddraw object.\n");
7513 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7514 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7516 memset(&hal_caps, 0, sizeof(hal_caps));
7517 hal_caps.dwSize = sizeof(hal_caps);
7518 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
7519 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7520 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)
7521 || is_ddraw64)
7523 skip("Mipmapped textures not supported, skipping tests.\n");
7524 IDirectDraw7_Release(ddraw);
7525 DestroyWindow(window);
7526 return;
7529 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
7531 memset(&surface_desc, 0, sizeof(surface_desc));
7532 surface_desc.dwSize = sizeof(surface_desc);
7533 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | tests[i].flags;
7534 surface_desc.ddsCaps.dwCaps = tests[i].caps;
7535 surface_desc.dwWidth = tests[i].width;
7536 surface_desc.dwHeight = tests[i].height;
7537 if (tests[i].flags & DDSD_MIPMAPCOUNT)
7538 U2(surface_desc).dwMipMapCount = tests[i].mipmap_count_in;
7539 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7540 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x.\n", i, hr);
7541 if (FAILED(hr))
7542 continue;
7544 memset(&surface_desc, 0, sizeof(surface_desc));
7545 surface_desc.dwSize = sizeof(surface_desc);
7546 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
7547 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
7548 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
7549 "Test %u: Got unexpected flags %#x.\n", i, surface_desc.dwFlags);
7550 ok(U2(surface_desc).dwMipMapCount == tests[i].mipmap_count_out,
7551 "Test %u: Got unexpected mipmap count %u.\n", i, U2(surface_desc).dwMipMapCount);
7553 if (U2(surface_desc).dwMipMapCount > 1)
7555 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &surface2);
7556 ok(SUCCEEDED(hr), "Test %u: Failed to get attached surface, hr %#x.\n", i, hr);
7558 memset(&surface_desc, 0, sizeof(surface_desc));
7559 surface_desc.dwSize = sizeof(surface_desc);
7560 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, 0, NULL);
7561 ok(SUCCEEDED(hr), "Test %u: Failed to lock surface, hr %#x.\n", i, hr);
7562 memset(&surface_desc, 0, sizeof(surface_desc));
7563 surface_desc.dwSize = sizeof(surface_desc);
7564 hr = IDirectDrawSurface7_Lock(surface2, NULL, &surface_desc, 0, NULL);
7565 ok(SUCCEEDED(hr), "Test %u: Failed to lock surface, hr %#x.\n", i, hr);
7566 IDirectDrawSurface7_Unlock(surface2, NULL);
7567 IDirectDrawSurface7_Unlock(surface, NULL);
7569 IDirectDrawSurface7_Release(surface2);
7572 IDirectDrawSurface7_Release(surface);
7575 refcount = IDirectDraw7_Release(ddraw);
7576 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7577 DestroyWindow(window);
7580 static void test_palette_complex(void)
7582 IDirectDrawSurface7 *surface, *mipmap, *tmp;
7583 DDSURFACEDESC2 surface_desc;
7584 IDirectDraw7 *ddraw;
7585 IDirectDrawPalette *palette, *palette2;
7586 ULONG refcount;
7587 HWND window;
7588 HRESULT hr;
7589 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
7590 DDCAPS hal_caps;
7591 PALETTEENTRY palette_entries[256];
7592 unsigned int i;
7594 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7595 0, 0, 640, 480, 0, 0, 0, 0);
7596 ddraw = create_ddraw();
7597 ok(!!ddraw, "Failed to create a ddraw object.\n");
7598 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7599 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7601 memset(&hal_caps, 0, sizeof(hal_caps));
7602 hal_caps.dwSize = sizeof(hal_caps);
7603 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
7604 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7605 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)
7606 || is_ddraw64)
7608 skip("Mipmapped textures not supported, skipping mipmap palette test.\n");
7609 IDirectDraw7_Release(ddraw);
7610 DestroyWindow(window);
7611 return;
7614 memset(&surface_desc, 0, sizeof(surface_desc));
7615 surface_desc.dwSize = sizeof(surface_desc);
7616 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7617 surface_desc.dwWidth = 128;
7618 surface_desc.dwHeight = 128;
7619 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7620 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7621 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
7622 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
7623 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7624 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7626 memset(palette_entries, 0, sizeof(palette_entries));
7627 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7628 palette_entries, &palette, NULL);
7629 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7631 palette2 = (void *)0xdeadbeef;
7632 hr = IDirectDrawSurface7_GetPalette(surface, &palette2);
7633 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
7634 ok(!palette2, "Got unexpected palette %p.\n", palette2);
7635 hr = IDirectDrawSurface7_SetPalette(surface, palette);
7636 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7637 hr = IDirectDrawSurface7_GetPalette(surface, &palette2);
7638 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
7639 ok(palette == palette2, "Got unexpected palette %p.\n", palette2);
7640 IDirectDrawPalette_Release(palette2);
7642 mipmap = surface;
7643 IDirectDrawSurface7_AddRef(mipmap);
7644 for (i = 0; i < 7; ++i)
7646 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
7647 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
7648 palette2 = (void *)0xdeadbeef;
7649 hr = IDirectDrawSurface7_GetPalette(tmp, &palette2);
7650 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x, i %u.\n", hr, i);
7651 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
7653 hr = IDirectDrawSurface7_SetPalette(tmp, palette);
7654 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x, i %u.\n", hr, i);
7656 hr = IDirectDrawSurface7_GetPalette(tmp, &palette2);
7657 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x, i %u.\n", hr, i);
7658 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
7660 /* Ddraw7 uses the palette of the mipmap for GetDC, just like previous
7661 * ddraw versions. Combined with the test results above this means no
7662 * palette is available. So depending on the driver either GetDC fails
7663 * or the DIB color table contains random data. */
7665 IDirectDrawSurface7_Release(mipmap);
7666 mipmap = tmp;
7669 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
7670 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7671 IDirectDrawSurface7_Release(mipmap);
7672 refcount = IDirectDrawSurface7_Release(surface);
7673 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7675 /* Test DDERR_INVALIDPIXELFORMAT vs DDERR_NOTONMIPMAPSUBLEVEL. */
7676 memset(&surface_desc, 0, sizeof(surface_desc));
7677 surface_desc.dwSize = sizeof(surface_desc);
7678 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7679 surface_desc.dwWidth = 128;
7680 surface_desc.dwHeight = 128;
7681 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7682 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7683 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
7684 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
7685 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7686 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7687 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7688 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7689 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7691 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
7692 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
7693 hr = IDirectDrawSurface7_SetPalette(mipmap, palette);
7694 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x.\n", hr);
7696 IDirectDrawSurface7_Release(mipmap);
7697 refcount = IDirectDrawSurface7_Release(surface);
7698 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7699 refcount = IDirectDrawPalette_Release(palette);
7700 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7702 refcount = IDirectDraw7_Release(ddraw);
7703 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7704 DestroyWindow(window);
7707 static void test_p8_rgb_blit(void)
7709 IDirectDrawSurface7 *src, *dst;
7710 DDSURFACEDESC2 surface_desc;
7711 IDirectDraw7 *ddraw;
7712 IDirectDrawPalette *palette;
7713 ULONG refcount;
7714 HWND window;
7715 HRESULT hr;
7716 PALETTEENTRY palette_entries[256];
7717 unsigned int x;
7718 static const BYTE src_data[] = {0x10, 0x1, 0x2, 0x3, 0x4, 0x5, 0xff, 0x80};
7719 static const D3DCOLOR expected[] =
7721 0x00101010, 0x00010101, 0x00020202, 0x00030303,
7722 0x00040404, 0x00050505, 0x00ffffff, 0x00808080,
7724 D3DCOLOR color;
7726 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7727 0, 0, 640, 480, 0, 0, 0, 0);
7728 ddraw = create_ddraw();
7729 ok(!!ddraw, "Failed to create a ddraw object.\n");
7730 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7731 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7733 memset(palette_entries, 0, sizeof(palette_entries));
7734 palette_entries[1].peGreen = 0xff;
7735 palette_entries[2].peBlue = 0xff;
7736 palette_entries[3].peFlags = 0xff;
7737 palette_entries[4].peRed = 0xff;
7738 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7739 palette_entries, &palette, NULL);
7740 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7742 memset(&surface_desc, 0, sizeof(surface_desc));
7743 surface_desc.dwSize = sizeof(surface_desc);
7744 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7745 surface_desc.dwWidth = 8;
7746 surface_desc.dwHeight = 1;
7747 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7748 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7749 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
7750 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
7751 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
7752 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7754 memset(&surface_desc, 0, sizeof(surface_desc));
7755 surface_desc.dwSize = sizeof(surface_desc);
7756 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7757 surface_desc.dwWidth = 8;
7758 surface_desc.dwHeight = 1;
7759 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7760 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7761 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
7762 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
7763 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7764 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7765 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7766 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
7767 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
7768 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7770 memset(&surface_desc, 0, sizeof(surface_desc));
7771 surface_desc.dwSize = sizeof(surface_desc);
7772 hr = IDirectDrawSurface7_Lock(src, NULL, &surface_desc, 0, NULL);
7773 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
7774 memcpy(surface_desc.lpSurface, src_data, sizeof(src_data));
7775 hr = IDirectDrawSurface7_Unlock(src, NULL);
7776 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
7778 hr = IDirectDrawSurface7_SetPalette(src, palette);
7779 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7780 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_WAIT, NULL);
7781 /* The r500 Windows 7 driver returns E_NOTIMPL. r200 on Windows XP works.
7782 * The Geforce 7 driver on Windows Vista returns E_FAIL. Newer Nvidia GPUs work. */
7783 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL) || broken(hr == E_FAIL),
7784 "Failed to blit, hr %#x.\n", hr);
7786 if (SUCCEEDED(hr))
7788 for (x = 0; x < sizeof(expected) / sizeof(*expected); x++)
7790 color = get_surface_color(dst, x, 0);
7791 todo_wine ok(compare_color(color, expected[x], 0),
7792 "Pixel %u: Got color %#x, expected %#x.\n",
7793 x, color, expected[x]);
7797 IDirectDrawSurface7_Release(src);
7798 IDirectDrawSurface7_Release(dst);
7799 IDirectDrawPalette_Release(palette);
7801 refcount = IDirectDraw7_Release(ddraw);
7802 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7803 DestroyWindow(window);
7806 static void test_material(void)
7808 static const D3DCOLORVALUE null_color;
7809 IDirect3DDevice7 *device;
7810 D3DMATERIAL7 material;
7811 ULONG refcount;
7812 HWND window;
7813 HRESULT hr;
7815 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7816 0, 0, 640, 480, 0, 0, 0, 0);
7817 if (!(device = create_device(window, DDSCL_NORMAL)))
7819 skip("Failed to create a 3D device, skipping test.\n");
7820 DestroyWindow(window);
7821 return;
7824 hr = IDirect3DDevice7_GetMaterial(device, &material);
7825 ok(SUCCEEDED(hr), "Failed to get material, hr %#x.\n", hr);
7826 ok(!memcmp(&U(material).diffuse, &null_color, sizeof(null_color)),
7827 "Got unexpected diffuse color {%.8e, %.8e, %.8e, %.8e}.\n",
7828 U1(U(material).diffuse).r, U2(U(material).diffuse).g,
7829 U3(U(material).diffuse).b, U4(U(material).diffuse).a);
7830 ok(!memcmp(&U1(material).ambient, &null_color, sizeof(null_color)),
7831 "Got unexpected ambient color {%.8e, %.8e, %.8e, %.8e}.\n",
7832 U1(U1(material).ambient).r, U2(U1(material).ambient).g,
7833 U3(U1(material).ambient).b, U4(U1(material).ambient).a);
7834 ok(!memcmp(&U2(material).specular, &null_color, sizeof(null_color)),
7835 "Got unexpected specular color {%.8e, %.8e, %.8e, %.8e}.\n",
7836 U1(U2(material).specular).r, U2(U2(material).specular).g,
7837 U3(U2(material).specular).b, U4(U2(material).specular).a);
7838 ok(!memcmp(&U3(material).emissive, &null_color, sizeof(null_color)),
7839 "Got unexpected emissive color {%.8e, %.8e, %.8e, %.8e}.\n",
7840 U1(U3(material).emissive).r, U2(U3(material).emissive).g,
7841 U3(U3(material).emissive).b, U4(U3(material).emissive).a);
7842 ok(U4(material).power == 0.0f, "Got unexpected power %.8e.\n", U4(material).power);
7844 refcount = IDirect3DDevice7_Release(device);
7845 ok(!refcount, "Device has %u references left.\n", refcount);
7846 DestroyWindow(window);
7849 static void test_palette_gdi(void)
7851 IDirectDrawSurface7 *surface, *primary;
7852 DDSURFACEDESC2 surface_desc;
7853 IDirectDraw7 *ddraw;
7854 IDirectDrawPalette *palette, *palette2;
7855 ULONG refcount;
7856 HWND window;
7857 HRESULT hr;
7858 PALETTEENTRY palette_entries[256];
7859 UINT i;
7860 HDC dc;
7861 /* On the Windows 8 testbot palette index 0 of the onscreen palette is forced to
7862 * r = 0, g = 0, b = 0. Do not attempt to set it to something else as this is
7863 * not the point of this test. */
7864 static const RGBQUAD expected1[] =
7866 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
7867 {0x03, 0x00, 0x00, 0x00}, {0x15, 0x14, 0x13, 0x00},
7869 static const RGBQUAD expected2[] =
7871 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
7872 {0x03, 0x00, 0x00, 0x00}, {0x25, 0x24, 0x23, 0x00},
7874 static const RGBQUAD expected3[] =
7876 {0x00, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x40, 0x00},
7877 {0x00, 0x40, 0x00, 0x00}, {0x56, 0x34, 0x12, 0x00},
7879 HPALETTE ddraw_palette_handle;
7880 /* Similar to index 0, index 255 is r = 0xff, g = 0xff, b = 0xff on the Win8 VMs. */
7881 RGBQUAD rgbquad[255];
7882 static const RGBQUAD rgb_zero = {0, 0, 0, 0};
7884 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7885 0, 0, 640, 480, 0, 0, 0, 0);
7886 ddraw = create_ddraw();
7887 ok(!!ddraw, "Failed to create a ddraw object.\n");
7888 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7889 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7891 memset(&surface_desc, 0, sizeof(surface_desc));
7892 surface_desc.dwSize = sizeof(surface_desc);
7893 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7894 surface_desc.dwWidth = 16;
7895 surface_desc.dwHeight = 16;
7896 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7897 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7898 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
7899 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
7900 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7901 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7903 /* Avoid colors from the Windows default palette. */
7904 memset(palette_entries, 0, sizeof(palette_entries));
7905 palette_entries[1].peRed = 0x01;
7906 palette_entries[2].peGreen = 0x02;
7907 palette_entries[3].peBlue = 0x03;
7908 palette_entries[4].peRed = 0x13;
7909 palette_entries[4].peGreen = 0x14;
7910 palette_entries[4].peBlue = 0x15;
7911 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7912 palette_entries, &palette, NULL);
7913 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7915 /* If there is no palette assigned and the display mode is not 8 bpp, some
7916 * drivers refuse to create a DC while others allow it. If a DC is created,
7917 * the DIB color table is uninitialized and contains random colors. No error
7918 * is generated when trying to read pixels and random garbage is returned.
7920 * The most likely explanation is that if the driver creates a DC, it (or
7921 * the higher-level runtime) uses GetSystemPaletteEntries to find the
7922 * palette, but GetSystemPaletteEntries fails when bpp > 8 and the palette
7923 * contains uninitialized garbage. See comments below for the P8 case. */
7925 hr = IDirectDrawSurface7_SetPalette(surface, palette);
7926 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7927 hr = IDirectDrawSurface7_GetDC(surface, &dc);
7928 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7929 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
7930 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
7931 "Got unexpected palette %p, expected %p.\n",
7932 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
7934 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
7935 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
7936 for (i = 0; i < sizeof(expected1) / sizeof(*expected1); i++)
7938 ok(!memcmp(&rgbquad[i], &expected1[i], sizeof(rgbquad[i])),
7939 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7940 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7941 expected1[i].rgbRed, expected1[i].rgbGreen, expected1[i].rgbBlue);
7943 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
7945 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7946 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7947 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7950 /* Update the palette while the DC is in use. This does not modify the DC. */
7951 palette_entries[4].peRed = 0x23;
7952 palette_entries[4].peGreen = 0x24;
7953 palette_entries[4].peBlue = 0x25;
7954 hr = IDirectDrawPalette_SetEntries(palette, 0, 4, 1, &palette_entries[4]);
7955 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
7957 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
7958 ok(i == 1, "Expected count 1, got %u.\n", i);
7959 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
7960 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7961 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
7962 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
7964 /* Neither does re-setting the palette. */
7965 hr = IDirectDrawSurface7_SetPalette(surface, NULL);
7966 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7967 hr = IDirectDrawSurface7_SetPalette(surface, palette);
7968 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7970 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
7971 ok(i == 1, "Expected count 1, got %u.\n", i);
7972 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
7973 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7974 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
7975 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
7977 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
7978 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7980 /* Refresh the DC. This updates the palette. */
7981 hr = IDirectDrawSurface7_GetDC(surface, &dc);
7982 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7983 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
7984 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
7985 for (i = 0; i < sizeof(expected2) / sizeof(*expected2); i++)
7987 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
7988 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
7989 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
7990 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
7992 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
7994 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
7995 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
7996 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
7998 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
7999 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8001 refcount = IDirectDrawSurface7_Release(surface);
8002 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8004 if (FAILED(IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
8006 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
8007 IDirectDrawPalette_Release(palette);
8008 IDirectDraw7_Release(ddraw);
8009 DestroyWindow(window);
8010 return;
8012 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
8013 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
8014 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8016 memset(&surface_desc, 0, sizeof(surface_desc));
8017 surface_desc.dwSize = sizeof(surface_desc);
8018 surface_desc.dwFlags = DDSD_CAPS;
8019 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8020 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
8021 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8023 hr = IDirectDrawSurface7_SetPalette(primary, palette);
8024 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8025 hr = IDirectDrawSurface7_GetDC(primary, &dc);
8026 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8027 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
8028 /* Windows 2000 on the testbot assigns a different palette to the primary. Refrast? */
8029 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE) || broken(TRUE),
8030 "Got unexpected palette %p, expected %p.\n",
8031 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
8032 SelectPalette(dc, ddraw_palette_handle, FALSE);
8034 /* The primary uses the system palette. In exclusive mode, the system palette matches
8035 * the ddraw palette attached to the primary, so the result is what you would expect
8036 * from a regular surface. Tests for the interaction between the ddraw palette and
8037 * the system palette are not included pending an application that depends on this.
8038 * The relation between those causes problems on Windows Vista and newer for games
8039 * like Age of Empires or StarcCaft. Don't emulate it without a real need. */
8040 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
8041 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
8042 for (i = 0; i < sizeof(expected2) / sizeof(*expected2); i++)
8044 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8045 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8046 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8047 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8049 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
8051 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8052 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8053 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8055 hr = IDirectDrawSurface7_ReleaseDC(primary, dc);
8056 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8058 memset(&surface_desc, 0, sizeof(surface_desc));
8059 surface_desc.dwSize = sizeof(surface_desc);
8060 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8061 surface_desc.dwWidth = 16;
8062 surface_desc.dwHeight = 16;
8063 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8064 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8065 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8067 /* Here the offscreen surface appears to use the primary's palette,
8068 * but in all likelihood it is actually the system palette. */
8069 hr = IDirectDrawSurface7_GetDC(surface, &dc);
8070 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8071 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
8072 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
8073 for (i = 0; i < sizeof(expected2) / sizeof(*expected2); i++)
8075 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8076 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8077 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8078 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8080 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
8082 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8083 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8084 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8086 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
8087 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8089 /* On real hardware a change to the primary surface's palette applies immediately,
8090 * even on device contexts from offscreen surfaces that do not have their own
8091 * palette. On the testbot VMs this is not the case. Don't test this until we
8092 * know of an application that depends on this. */
8094 memset(palette_entries, 0, sizeof(palette_entries));
8095 palette_entries[1].peBlue = 0x40;
8096 palette_entries[2].peRed = 0x40;
8097 palette_entries[3].peGreen = 0x40;
8098 palette_entries[4].peRed = 0x12;
8099 palette_entries[4].peGreen = 0x34;
8100 palette_entries[4].peBlue = 0x56;
8101 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8102 palette_entries, &palette2, NULL);
8103 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8104 hr = IDirectDrawSurface7_SetPalette(surface, palette2);
8105 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8107 /* A palette assigned to the offscreen surface overrides the primary / system
8108 * palette. */
8109 hr = IDirectDrawSurface7_GetDC(surface, &dc);
8110 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8111 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
8112 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
8113 for (i = 0; i < sizeof(expected3) / sizeof(*expected3); i++)
8115 ok(!memcmp(&rgbquad[i], &expected3[i], sizeof(rgbquad[i])),
8116 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8117 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8118 expected3[i].rgbRed, expected3[i].rgbGreen, expected3[i].rgbBlue);
8120 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
8122 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8123 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8124 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8126 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
8127 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8129 refcount = IDirectDrawSurface7_Release(surface);
8130 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8132 /* The Windows 8 testbot keeps extra references to the primary and
8133 * backbuffer while in 8 bpp mode. */
8134 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
8135 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
8137 refcount = IDirectDrawSurface7_Release(primary);
8138 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8139 refcount = IDirectDrawPalette_Release(palette2);
8140 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8141 refcount = IDirectDrawPalette_Release(palette);
8142 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8143 refcount = IDirectDraw7_Release(ddraw);
8144 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8145 DestroyWindow(window);
8148 static void test_palette_alpha(void)
8150 IDirectDrawSurface7 *surface;
8151 DDSURFACEDESC2 surface_desc;
8152 IDirectDraw7 *ddraw;
8153 IDirectDrawPalette *palette;
8154 ULONG refcount;
8155 HWND window;
8156 HRESULT hr;
8157 PALETTEENTRY palette_entries[256];
8158 unsigned int i;
8159 static const struct
8161 DWORD caps, flags;
8162 BOOL attach_allowed;
8163 const char *name;
8165 test_data[] =
8167 {DDSCAPS_OFFSCREENPLAIN, DDSD_WIDTH | DDSD_HEIGHT, FALSE, "offscreenplain"},
8168 {DDSCAPS_TEXTURE, DDSD_WIDTH | DDSD_HEIGHT, TRUE, "texture"},
8169 {DDSCAPS_PRIMARYSURFACE, 0, FALSE, "primary"}
8172 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8173 0, 0, 640, 480, 0, 0, 0, 0);
8174 ddraw = create_ddraw();
8175 ok(!!ddraw, "Failed to create a ddraw object.\n");
8176 if (FAILED(IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
8178 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
8179 IDirectDraw7_Release(ddraw);
8180 DestroyWindow(window);
8181 return;
8183 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8184 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8186 memset(palette_entries, 0, sizeof(palette_entries));
8187 palette_entries[1].peFlags = 0x42;
8188 palette_entries[2].peFlags = 0xff;
8189 palette_entries[3].peFlags = 0x80;
8190 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
8191 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8193 memset(palette_entries, 0x66, sizeof(palette_entries));
8194 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
8195 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
8196 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8197 palette_entries[0].peFlags);
8198 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8199 palette_entries[1].peFlags);
8200 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
8201 palette_entries[2].peFlags);
8202 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
8203 palette_entries[3].peFlags);
8205 IDirectDrawPalette_Release(palette);
8207 memset(palette_entries, 0, sizeof(palette_entries));
8208 palette_entries[1].peFlags = 0x42;
8209 palette_entries[1].peRed = 0xff;
8210 palette_entries[2].peFlags = 0xff;
8211 palette_entries[3].peFlags = 0x80;
8212 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT | DDPCAPS_ALPHA,
8213 palette_entries, &palette, NULL);
8214 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8216 memset(palette_entries, 0x66, sizeof(palette_entries));
8217 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
8218 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
8219 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8220 palette_entries[0].peFlags);
8221 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8222 palette_entries[1].peFlags);
8223 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
8224 palette_entries[2].peFlags);
8225 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
8226 palette_entries[3].peFlags);
8228 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); i++)
8230 memset(&surface_desc, 0, sizeof(surface_desc));
8231 surface_desc.dwSize = sizeof(surface_desc);
8232 surface_desc.dwFlags = DDSD_CAPS | test_data[i].flags;
8233 surface_desc.dwWidth = 128;
8234 surface_desc.dwHeight = 128;
8235 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
8236 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8237 ok(SUCCEEDED(hr), "Failed to create %s surface, hr %#x.\n", test_data[i].name, hr);
8239 hr = IDirectDrawSurface7_SetPalette(surface, palette);
8240 if (test_data[i].attach_allowed)
8241 ok(SUCCEEDED(hr), "Failed to attach palette to %s surface, hr %#x.\n", test_data[i].name, hr);
8242 else
8243 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x, %s surface.\n", hr, test_data[i].name);
8245 if (SUCCEEDED(hr))
8247 HDC dc;
8248 RGBQUAD rgbquad;
8249 UINT retval;
8251 hr = IDirectDrawSurface7_GetDC(surface, &dc);
8252 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x, %s surface.\n", hr, test_data[i].name);
8253 retval = GetDIBColorTable(dc, 1, 1, &rgbquad);
8254 ok(retval == 1, "GetDIBColorTable returned unexpected result %u.\n", retval);
8255 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x, %s surface.\n",
8256 rgbquad.rgbRed, test_data[i].name);
8257 ok(rgbquad.rgbGreen == 0, "Expected rgbGreen = 0, got %#x, %s surface.\n",
8258 rgbquad.rgbGreen, test_data[i].name);
8259 ok(rgbquad.rgbBlue == 0, "Expected rgbBlue = 0, got %#x, %s surface.\n",
8260 rgbquad.rgbBlue, test_data[i].name);
8261 todo_wine ok(rgbquad.rgbReserved == 0, "Expected rgbReserved = 0, got %u, %s surface.\n",
8262 rgbquad.rgbReserved, test_data[i].name);
8263 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
8264 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8266 IDirectDrawSurface7_Release(surface);
8269 /* Test INVALIDSURFACETYPE vs INVALIDPIXELFORMAT. */
8270 memset(&surface_desc, 0, sizeof(surface_desc));
8271 surface_desc.dwSize = sizeof(surface_desc);
8272 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8273 surface_desc.dwWidth = 128;
8274 surface_desc.dwHeight = 128;
8275 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8276 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8277 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
8278 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
8279 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8280 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8281 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
8282 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8283 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8284 hr = IDirectDrawSurface7_SetPalette(surface, palette);
8285 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x.\n", hr);
8286 IDirectDrawSurface7_Release(surface);
8288 /* The Windows 8 testbot keeps extra references to the primary
8289 * while in 8 bpp mode. */
8290 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
8291 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
8293 refcount = IDirectDrawPalette_Release(palette);
8294 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8295 refcount = IDirectDraw7_Release(ddraw);
8296 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8297 DestroyWindow(window);
8300 static void test_vb_writeonly(void)
8302 IDirect3DDevice7 *device;
8303 IDirect3D7 *d3d;
8304 IDirect3DVertexBuffer7 *buffer;
8305 HWND window;
8306 HRESULT hr;
8307 D3DVERTEXBUFFERDESC desc;
8308 void *ptr;
8309 static const struct vec4 quad[] =
8311 { 0.0f, 480.0f, 0.0f, 1.0f},
8312 { 0.0f, 0.0f, 0.0f, 1.0f},
8313 {640.0f, 480.0f, 0.0f, 1.0f},
8314 {640.0f, 0.0f, 0.0f, 1.0f},
8317 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8318 0, 0, 640, 480, 0, 0, 0, 0);
8320 if (!(device = create_device(window, DDSCL_NORMAL)))
8322 skip("Failed to create a 3D device, skipping test.\n");
8323 DestroyWindow(window);
8324 return;
8327 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
8328 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
8330 memset(&desc, 0, sizeof(desc));
8331 desc.dwSize = sizeof(desc);
8332 desc.dwCaps = D3DVBCAPS_WRITEONLY;
8333 desc.dwFVF = D3DFVF_XYZRHW;
8334 desc.dwNumVertices = sizeof(quad) / sizeof(*quad);
8335 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &buffer, 0);
8336 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
8338 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, &ptr, NULL);
8339 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
8340 memcpy(ptr, quad, sizeof(quad));
8341 hr = IDirect3DVertexBuffer7_Unlock(buffer);
8342 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
8344 hr = IDirect3DDevice7_BeginScene(device);
8345 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8346 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
8347 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8348 hr = IDirect3DDevice7_EndScene(device);
8349 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8351 hr = IDirect3DVertexBuffer7_Lock(buffer, 0, &ptr, NULL);
8352 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
8353 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
8354 hr = IDirect3DVertexBuffer7_Unlock(buffer);
8355 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
8357 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_READONLY, &ptr, NULL);
8358 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
8359 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
8360 hr = IDirect3DVertexBuffer7_Unlock(buffer);
8361 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
8363 IDirect3DVertexBuffer7_Release(buffer);
8364 IDirect3D7_Release(d3d);
8365 IDirect3DDevice7_Release(device);
8366 DestroyWindow(window);
8369 static void test_lost_device(void)
8371 IDirectDrawSurface7 *surface;
8372 DDSURFACEDESC2 surface_desc;
8373 HWND window1, window2;
8374 IDirectDraw7 *ddraw;
8375 ULONG refcount;
8376 HRESULT hr;
8377 BOOL ret;
8379 window1 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8380 0, 0, 640, 480, 0, 0, 0, 0);
8381 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8382 0, 0, 640, 480, 0, 0, 0, 0);
8383 ddraw = create_ddraw();
8384 ok(!!ddraw, "Failed to create a ddraw object.\n");
8385 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8386 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8388 memset(&surface_desc, 0, sizeof(surface_desc));
8389 surface_desc.dwSize = sizeof(surface_desc);
8390 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
8391 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
8392 U5(surface_desc).dwBackBufferCount = 1;
8393 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8394 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8396 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8397 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8398 hr = IDirectDrawSurface7_IsLost(surface);
8399 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8400 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8401 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8403 ret = SetForegroundWindow(GetDesktopWindow());
8404 ok(ret, "Failed to set foreground window.\n");
8405 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8406 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8407 hr = IDirectDrawSurface7_IsLost(surface);
8408 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8409 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8410 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8412 ret = SetForegroundWindow(window1);
8413 ok(ret, "Failed to set foreground window.\n");
8414 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8415 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8416 hr = IDirectDrawSurface7_IsLost(surface);
8417 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8418 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8419 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8421 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
8422 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8423 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8424 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8425 hr = IDirectDrawSurface7_IsLost(surface);
8426 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8427 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8428 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8430 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
8431 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8432 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8433 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8434 hr = IDirectDrawSurface7_IsLost(surface);
8435 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8436 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8437 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8439 /* Trying to restore the primary will crash, probably because flippable
8440 * surfaces can't exist in DDSCL_NORMAL. */
8441 IDirectDrawSurface7_Release(surface);
8442 memset(&surface_desc, 0, sizeof(surface_desc));
8443 surface_desc.dwSize = sizeof(surface_desc);
8444 surface_desc.dwFlags = DDSD_CAPS;
8445 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8446 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8447 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8449 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8450 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8451 hr = IDirectDrawSurface7_IsLost(surface);
8452 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8454 ret = SetForegroundWindow(GetDesktopWindow());
8455 ok(ret, "Failed to set foreground window.\n");
8456 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8457 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8458 hr = IDirectDrawSurface7_IsLost(surface);
8459 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8461 ret = SetForegroundWindow(window1);
8462 ok(ret, "Failed to set foreground window.\n");
8463 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8464 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8465 hr = IDirectDrawSurface7_IsLost(surface);
8466 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8468 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8469 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8470 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8471 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8472 hr = IDirectDrawSurface7_IsLost(surface);
8473 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8475 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
8476 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8477 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8478 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8479 hr = IDirectDrawSurface7_IsLost(surface);
8480 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8482 IDirectDrawSurface7_Release(surface);
8483 memset(&surface_desc, 0, sizeof(surface_desc));
8484 surface_desc.dwSize = sizeof(surface_desc);
8485 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
8486 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
8487 U5(surface_desc).dwBackBufferCount = 1;
8488 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8489 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8491 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8492 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8493 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8494 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8495 hr = IDirectDrawSurface7_IsLost(surface);
8496 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8497 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8498 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8500 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL | DDSCL_FULLSCREEN);
8501 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8502 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8503 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8504 hr = IDirectDrawSurface7_IsLost(surface);
8505 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8506 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8507 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8509 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
8510 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8511 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8512 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8513 hr = IDirectDrawSurface7_IsLost(surface);
8514 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8515 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8516 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8518 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
8519 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8520 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8521 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8522 hr = IDirectDrawSurface7_IsLost(surface);
8523 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8524 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8525 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8527 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL | DDSCL_FULLSCREEN);
8528 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8529 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8530 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8531 hr = IDirectDrawSurface7_IsLost(surface);
8532 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8533 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8534 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8536 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8537 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8538 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8539 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8540 hr = IDirectDrawSurface7_IsLost(surface);
8541 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8542 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8543 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8545 IDirectDrawSurface7_Release(surface);
8546 refcount = IDirectDraw7_Release(ddraw);
8547 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8548 DestroyWindow(window2);
8549 DestroyWindow(window1);
8552 static void test_resource_priority(void)
8554 IDirectDrawSurface7 *surface, *mipmap;
8555 DDSURFACEDESC2 surface_desc;
8556 IDirectDraw7 *ddraw;
8557 ULONG refcount;
8558 HWND window;
8559 HRESULT hr;
8560 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
8561 DDCAPS hal_caps;
8562 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_MIPMAP;
8563 unsigned int i;
8564 DWORD priority;
8565 static const struct
8567 DWORD caps, caps2;
8568 const char *name;
8569 HRESULT hr;
8570 /* SetPriority on offscreenplain surfaces crashes on AMD GPUs on Win7. */
8571 BOOL crash;
8573 test_data[] =
8575 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, "vidmem texture", DDERR_INVALIDPARAMS, FALSE},
8576 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, "sysmem texture", DDERR_INVALIDPARAMS, FALSE},
8577 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, "managed texture", DD_OK, FALSE},
8578 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, "managed texture", DD_OK, FALSE},
8579 {DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP,
8580 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_TEXTUREMANAGE,
8581 "cubemap", DD_OK, FALSE},
8582 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, "vidmem offscreenplain", DDERR_INVALIDOBJECT, TRUE},
8583 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, "sysmem offscreenplain", DDERR_INVALIDOBJECT, TRUE},
8586 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8587 0, 0, 640, 480, 0, 0, 0, 0);
8588 ddraw = create_ddraw();
8589 ok(!!ddraw, "Failed to create a ddraw object.\n");
8590 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8591 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8593 memset(&hal_caps, 0, sizeof(hal_caps));
8594 hal_caps.dwSize = sizeof(hal_caps);
8595 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
8596 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8597 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps
8598 || !(hal_caps.ddsCaps.dwCaps & DDSCAPS2_TEXTUREMANAGE))
8600 skip("Required surface types not supported, skipping test.\n");
8601 goto done;
8604 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); i++)
8606 memset(&surface_desc, 0, sizeof(surface_desc));
8607 surface_desc.dwSize = sizeof(surface_desc);
8608 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
8609 surface_desc.dwWidth = 32;
8610 surface_desc.dwHeight = 32;
8611 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
8612 surface_desc.ddsCaps.dwCaps2 = test_data[i].caps2;
8613 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8614 if (is_ddraw64 && (test_data[i].caps & DDSCAPS_TEXTURE))
8616 todo_wine ok(hr == E_NOINTERFACE, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
8617 if (SUCCEEDED(hr))
8618 IDirectDrawSurface7_Release(surface);
8619 continue;
8621 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n", hr, test_data[i].name);
8623 /* Priority == NULL segfaults. */
8624 priority = 0xdeadbeef;
8625 hr = IDirectDrawSurface7_GetPriority(surface, &priority);
8626 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
8627 if (SUCCEEDED(test_data[i].hr))
8628 ok(priority == 0, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
8629 else
8630 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
8632 if (!test_data[i].crash)
8634 hr = IDirectDrawSurface7_SetPriority(surface, 1);
8635 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
8636 hr = IDirectDrawSurface7_GetPriority(surface, &priority);
8637 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
8638 if (SUCCEEDED(test_data[i].hr))
8640 ok(priority == 1, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
8641 hr = IDirectDrawSurface7_SetPriority(surface, 2);
8642 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
8644 else
8645 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
8648 if (test_data[i].caps2 & DDSCAPS2_CUBEMAP)
8650 caps.dwCaps2 = DDSCAPS2_CUBEMAP_NEGATIVEZ;
8651 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
8652 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
8653 /* IDirectDrawSurface7_SetPriority crashes when called on non-positive X surfaces on Windows */
8654 priority = 0xdeadbeef;
8655 hr = IDirectDrawSurface7_GetPriority(mipmap, &priority);
8656 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
8657 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
8659 IDirectDrawSurface7_Release(mipmap);
8662 IDirectDrawSurface7_Release(surface);
8665 if (is_ddraw64)
8666 goto done;
8668 memset(&surface_desc, 0, sizeof(surface_desc));
8669 surface_desc.dwSize = sizeof(surface_desc);
8670 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_MIPMAPCOUNT;
8671 surface_desc.dwWidth = 32;
8672 surface_desc.dwHeight = 32;
8673 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
8674 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
8675 U2(surface_desc).dwMipMapCount = 2;
8676 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8677 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8678 caps.dwCaps2 = 0;
8679 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
8680 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
8682 priority = 0xdeadbeef;
8683 hr = IDirectDrawSurface7_GetPriority(mipmap, &priority);
8684 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type managed mipmap.\n", hr);
8685 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type managed mipmap.\n", priority);
8686 /* SetPriority on the mipmap surface crashes. */
8687 hr = IDirectDrawSurface7_GetPriority(surface, &priority);
8688 ok(SUCCEEDED(hr), "Failed to get priority, hr %#x.\n", hr);
8689 ok(priority == 0, "Got unexpected priority %u, type managed mipmap.\n", priority);
8691 IDirectDrawSurface7_Release(mipmap);
8692 refcount = IDirectDrawSurface7_Release(surface);
8693 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8695 done:
8696 refcount = IDirectDraw7_Release(ddraw);
8697 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8698 DestroyWindow(window);
8701 static void test_surface_desc_lock(void)
8703 IDirectDrawSurface7 *surface;
8704 DDSURFACEDESC2 surface_desc;
8705 IDirectDraw7 *ddraw;
8706 ULONG refcount;
8707 HWND window;
8708 HRESULT hr;
8710 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8711 0, 0, 640, 480, 0, 0, 0, 0);
8712 ddraw = create_ddraw();
8713 ok(!!ddraw, "Failed to create a ddraw object.\n");
8714 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8715 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8717 memset(&surface_desc, 0, sizeof(surface_desc));
8718 surface_desc.dwSize = sizeof(surface_desc);
8719 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8720 surface_desc.dwWidth = 16;
8721 surface_desc.dwHeight = 16;
8722 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8723 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8724 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8726 memset(&surface_desc, 0xaa, sizeof(surface_desc));
8727 surface_desc.dwSize = sizeof(surface_desc);
8728 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
8729 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8730 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
8732 memset(&surface_desc, 0xaa, sizeof(surface_desc));
8733 surface_desc.dwSize = sizeof(surface_desc);
8734 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, 0, NULL);
8735 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
8736 ok(surface_desc.lpSurface != NULL, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
8737 memset(&surface_desc, 0xaa, sizeof(surface_desc));
8738 surface_desc.dwSize = sizeof(surface_desc);
8739 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
8740 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8741 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
8742 hr = IDirectDrawSurface7_Unlock(surface, NULL);
8743 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8745 memset(&surface_desc, 0xaa, sizeof(surface_desc));
8746 surface_desc.dwSize = sizeof(surface_desc);
8747 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
8748 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8749 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
8751 IDirectDrawSurface7_Release(surface);
8752 refcount = IDirectDraw7_Release(ddraw);
8753 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8754 DestroyWindow(window);
8757 static void test_fog_interpolation(void)
8759 HRESULT hr;
8760 IDirect3DDevice7 *device;
8761 IDirectDrawSurface7 *rt;
8762 ULONG refcount;
8763 HWND window;
8764 D3DCOLOR color;
8765 static struct
8767 struct vec3 position;
8768 D3DCOLOR diffuse;
8769 D3DCOLOR specular;
8771 quad[] =
8773 {{-1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff000000},
8774 {{-1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff000000},
8775 {{ 1.0f, -1.0f, 1.0f}, 0xffff0000, 0x00000000},
8776 {{ 1.0f, 1.0f, 1.0f}, 0xffff0000, 0x00000000},
8778 union
8780 DWORD d;
8781 float f;
8782 } conv;
8783 unsigned int i;
8784 static const struct
8786 D3DFOGMODE vfog, tfog;
8787 D3DSHADEMODE shade;
8788 D3DCOLOR middle_color;
8789 BOOL todo;
8791 tests[] =
8793 {D3DFOG_NONE, D3DFOG_NONE, D3DSHADE_FLAT, 0x00007f80, FALSE},
8794 {D3DFOG_NONE, D3DFOG_NONE, D3DSHADE_GOURAUD, 0x00007f80, FALSE},
8795 {D3DFOG_EXP, D3DFOG_NONE, D3DSHADE_FLAT, 0x00007f80, TRUE},
8796 {D3DFOG_EXP, D3DFOG_NONE, D3DSHADE_GOURAUD, 0x00007f80, TRUE},
8797 {D3DFOG_NONE, D3DFOG_EXP, D3DSHADE_FLAT, 0x0000ea15, FALSE},
8798 {D3DFOG_NONE, D3DFOG_EXP, D3DSHADE_GOURAUD, 0x0000ea15, FALSE},
8799 {D3DFOG_EXP, D3DFOG_EXP, D3DSHADE_FLAT, 0x0000ea15, FALSE},
8800 {D3DFOG_EXP, D3DFOG_EXP, D3DSHADE_GOURAUD, 0x0000ea15, FALSE},
8802 D3DDEVICEDESC7 caps;
8804 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8805 0, 0, 640, 480, 0, 0, 0, 0);
8807 if (!(device = create_device(window, DDSCL_NORMAL)))
8809 skip("Failed to create a 3D device, skipping test.\n");
8810 DestroyWindow(window);
8811 return;
8814 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
8815 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8816 hr = IDirect3DDevice7_GetCaps(device, &caps);
8817 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
8818 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE))
8819 skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping some fog tests\n");
8821 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
8822 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8823 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
8824 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8825 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
8826 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8827 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x0000ff00);
8828 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8829 conv.f = 5.0;
8830 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGDENSITY, conv.d);
8831 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8833 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
8834 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
8835 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
8836 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
8837 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x000000ff);
8838 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8840 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
8842 if(!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE) && tests[i].tfog)
8843 continue;
8845 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00808080, 0.0f, 0);
8846 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
8848 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SHADEMODE, tests[i].shade);
8849 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8850 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, tests[i].vfog);
8851 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8852 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, tests[i].tfog);
8853 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8854 hr = IDirect3DDevice7_BeginScene(device);
8855 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8856 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
8857 D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR, quad, 4, 0);
8858 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8859 hr = IDirect3DDevice7_EndScene(device);
8860 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8862 color = get_surface_color(rt, 0, 240);
8863 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x, case %u.\n", color, i);
8864 color = get_surface_color(rt, 320, 240);
8865 if (tests[i].todo)
8866 todo_wine ok(compare_color(color, tests[i].middle_color, 2),
8867 "Got unexpected color 0x%08x, case %u.\n", color, i);
8868 else
8869 ok(compare_color(color, tests[i].middle_color, 2),
8870 "Got unexpected color 0x%08x, case %u.\n", color, i);
8871 color = get_surface_color(rt, 639, 240);
8872 ok(compare_color(color, 0x0000fd02, 2), "Got unexpected color 0x%08x, case %u.\n", color, i);
8875 IDirectDrawSurface7_Release(rt);
8876 refcount = IDirect3DDevice7_Release(device);
8877 ok(!refcount, "Device has %u references left.\n", refcount);
8878 DestroyWindow(window);
8881 static void test_negative_fixedfunction_fog(void)
8883 HRESULT hr;
8884 IDirect3DDevice7 *device;
8885 IDirectDrawSurface7 *rt;
8886 ULONG refcount;
8887 HWND window;
8888 D3DCOLOR color;
8889 static struct
8891 struct vec3 position;
8892 D3DCOLOR diffuse;
8894 quad[] =
8896 {{-1.0f, -1.0f, -0.5f}, 0xffff0000},
8897 {{-1.0f, 1.0f, -0.5f}, 0xffff0000},
8898 {{ 1.0f, -1.0f, -0.5f}, 0xffff0000},
8899 {{ 1.0f, 1.0f, -0.5f}, 0xffff0000},
8901 static struct
8903 struct vec4 position;
8904 D3DCOLOR diffuse;
8906 tquad[] =
8908 {{ 0.0f, 0.0f, -0.5f, 1.0f}, 0xffff0000},
8909 {{640.0f, 0.0f, -0.5f, 1.0f}, 0xffff0000},
8910 {{ 0.0f, 480.0f, -0.5f, 1.0f}, 0xffff0000},
8911 {{640.0f, 480.0f, -0.5f, 1.0f}, 0xffff0000},
8913 unsigned int i;
8914 static D3DMATRIX zero =
8916 1.0f, 0.0f, 0.0f, 0.0f,
8917 0.0f, 1.0f, 0.0f, 0.0f,
8918 0.0f, 0.0f, 0.0f, 0.0f,
8919 0.0f, 0.0f, 0.0f, 1.0f
8921 static D3DMATRIX identity =
8923 1.0f, 0.0f, 0.0f, 0.0f,
8924 0.0f, 1.0f, 0.0f, 0.0f,
8925 0.0f, 0.0f, 1.0f, 0.0f,
8926 0.0f, 0.0f, 0.0f, 1.0f
8928 static const struct
8930 DWORD pos_type;
8931 void *quad;
8932 D3DMATRIX *matrix;
8933 union
8935 float f;
8936 DWORD d;
8937 } start, end;
8938 D3DFOGMODE vfog, tfog;
8939 DWORD color, color_broken, color_broken2;
8941 tests[] =
8943 /* Run the XYZRHW tests first. Depth clamping is broken after RHW draws on the testbot.
8945 * Geforce8+ GPUs on Windows abs() table fog, everything else does not. */
8946 {D3DFVF_XYZRHW, tquad, &identity, { 0.0f}, {1.0f}, D3DFOG_NONE, D3DFOG_LINEAR,
8947 0x00ff0000, 0x00808000, 0x00808000},
8948 /* r200 GPUs and presumably all d3d8 and older HW clamp the fog
8949 * parameters to 0.0 and 1.0 in the table fog case. */
8950 {D3DFVF_XYZRHW, tquad, &identity, {-1.0f}, {0.0f}, D3DFOG_NONE, D3DFOG_LINEAR,
8951 0x00808000, 0x00ff0000, 0x0000ff00},
8952 /* test_fog_interpolation shows that vertex fog evaluates the fog
8953 * equation in the vertex pipeline. Start = -1.0 && end = 0.0 shows
8954 * that the abs happens before the fog equation is evaluated.
8956 * Vertex fog abs() behavior is the same on all GPUs. */
8957 {D3DFVF_XYZ, quad, &zero, { 0.0f}, {1.0f}, D3DFOG_LINEAR, D3DFOG_NONE,
8958 0x00808000, 0x00808000, 0x00808000},
8959 {D3DFVF_XYZ, quad, &zero, {-1.0f}, {0.0f}, D3DFOG_LINEAR, D3DFOG_NONE,
8960 0x0000ff00, 0x0000ff00, 0x0000ff00},
8961 {D3DFVF_XYZ, quad, &zero, { 0.0f}, {1.0f}, D3DFOG_EXP, D3DFOG_NONE,
8962 0x009b6400, 0x009b6400, 0x009b6400},
8964 D3DDEVICEDESC7 caps;
8966 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8967 0, 0, 640, 480, 0, 0, 0, 0);
8969 if (!(device = create_device(window, DDSCL_NORMAL)))
8971 skip("Failed to create a 3D device, skipping test.\n");
8972 DestroyWindow(window);
8973 return;
8976 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
8977 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8978 hr = IDirect3DDevice7_GetCaps(device, &caps);
8979 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
8980 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE))
8981 skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping some fog tests.\n");
8983 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
8984 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8985 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
8986 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8987 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
8988 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8989 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x0000ff00);
8990 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8991 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
8992 ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
8994 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
8996 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE) && tests[i].tfog)
8997 continue;
8999 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0);
9000 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
9002 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, tests[i].matrix);
9003 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
9004 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGSTART, tests[i].start.d);
9005 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9006 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGEND, tests[i].end.d);
9007 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9008 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, tests[i].vfog);
9009 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9010 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, tests[i].tfog);
9011 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9013 hr = IDirect3DDevice7_BeginScene(device);
9014 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9015 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9016 tests[i].pos_type | D3DFVF_DIFFUSE, tests[i].quad, 4, 0);
9017 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9018 hr = IDirect3DDevice7_EndScene(device);
9019 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9021 color = get_surface_color(rt, 0, 240);
9022 ok(compare_color(color, tests[i].color, 2) || broken(compare_color(color, tests[i].color_broken, 2))
9023 || broken(compare_color(color, tests[i].color_broken2, 2)),
9024 "Got unexpected color 0x%08x, case %u.\n", color, i);
9027 IDirectDrawSurface7_Release(rt);
9028 refcount = IDirect3DDevice7_Release(device);
9029 ok(!refcount, "Device has %u references left.\n", refcount);
9030 DestroyWindow(window);
9033 static void test_table_fog_zw(void)
9035 HRESULT hr;
9036 IDirect3DDevice7 *device;
9037 IDirectDrawSurface7 *rt;
9038 ULONG refcount;
9039 HWND window;
9040 D3DCOLOR color;
9041 static struct
9043 struct vec4 position;
9044 D3DCOLOR diffuse;
9046 quad[] =
9048 {{ 0.0f, 0.0f, 0.0f, 0.0f}, 0xffff0000},
9049 {{640.0f, 0.0f, 0.0f, 0.0f}, 0xffff0000},
9050 {{ 0.0f, 480.0f, 0.0f, 0.0f}, 0xffff0000},
9051 {{640.0f, 480.0f, 0.0f, 0.0f}, 0xffff0000},
9053 static D3DMATRIX identity =
9055 1.0f, 0.0f, 0.0f, 0.0f,
9056 0.0f, 1.0f, 0.0f, 0.0f,
9057 0.0f, 0.0f, 1.0f, 0.0f,
9058 0.0f, 0.0f, 0.0f, 1.0f
9060 D3DDEVICEDESC7 caps;
9061 static const struct
9063 float z, w;
9064 D3DZBUFFERTYPE z_test;
9065 D3DCOLOR color;
9067 tests[] =
9069 {0.7f, 0.0f, D3DZB_TRUE, 0x004cb200},
9070 {0.7f, 0.0f, D3DZB_FALSE, 0x004cb200},
9071 {0.7f, 0.3f, D3DZB_TRUE, 0x004cb200},
9072 {0.7f, 0.3f, D3DZB_FALSE, 0x004cb200},
9073 {0.7f, 3.0f, D3DZB_TRUE, 0x004cb200},
9074 {0.7f, 3.0f, D3DZB_FALSE, 0x004cb200},
9075 {0.3f, 0.0f, D3DZB_TRUE, 0x00b24c00},
9076 {0.3f, 0.0f, D3DZB_FALSE, 0x00b24c00},
9078 unsigned int i;
9080 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9081 0, 0, 640, 480, 0, 0, 0, 0);
9083 if (!(device = create_device(window, DDSCL_NORMAL)))
9085 skip("Failed to create a 3D device, skipping test.\n");
9086 DestroyWindow(window);
9087 return;
9090 hr = IDirect3DDevice7_GetCaps(device, &caps);
9091 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
9092 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE))
9094 skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping POSITIONT table fog test.\n");
9095 goto done;
9097 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
9098 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9100 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
9101 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9102 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
9103 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9104 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x0000ff00);
9105 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9106 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
9107 ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
9108 /* Work around an AMD Windows driver bug. Needs a proj matrix applied redundantly. */
9109 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &identity);
9110 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
9111 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_LINEAR);
9112 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9114 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
9116 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x000000ff, 1.0f, 0);
9117 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
9119 quad[0].position.z = tests[i].z;
9120 quad[1].position.z = tests[i].z;
9121 quad[2].position.z = tests[i].z;
9122 quad[3].position.z = tests[i].z;
9123 quad[0].position.w = tests[i].w;
9124 quad[1].position.w = tests[i].w;
9125 quad[2].position.w = tests[i].w;
9126 quad[3].position.w = tests[i].w;
9127 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, tests[i].z_test);
9128 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9130 hr = IDirect3DDevice7_BeginScene(device);
9131 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9132 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9133 D3DFVF_XYZRHW | D3DFVF_DIFFUSE, quad, 4, 0);
9134 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9135 hr = IDirect3DDevice7_EndScene(device);
9136 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9138 color = get_surface_color(rt, 0, 240);
9139 ok(compare_color(color, tests[i].color, 2),
9140 "Got unexpected color 0x%08x, expected 0x%8x, case %u.\n", color, tests[i].color, i);
9143 IDirectDrawSurface7_Release(rt);
9144 done:
9145 refcount = IDirect3DDevice7_Release(device);
9146 ok(!refcount, "Device has %u references left.\n", refcount);
9147 DestroyWindow(window);
9150 static void test_signed_formats(void)
9152 HRESULT hr;
9153 IDirect3DDevice7 *device;
9154 IDirect3D7 *d3d;
9155 IDirectDraw7 *ddraw;
9156 IDirectDrawSurface7 *surface, *rt;
9157 DDSURFACEDESC2 surface_desc;
9158 ULONG refcount;
9159 HWND window;
9160 D3DCOLOR color, expected_color;
9161 static struct
9163 struct vec3 position;
9164 struct vec2 texcoord;
9166 quad[] =
9168 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
9169 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
9170 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
9171 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
9173 /* See test_signed_formats() in dlls/d3d9/tests/visual.c for an explanation
9174 * of these values. */
9175 static const USHORT content_v8u8[4][4] =
9177 {0x0000, 0x7f7f, 0x8880, 0x0000},
9178 {0x0080, 0x8000, 0x7f00, 0x007f},
9179 {0x193b, 0xe8c8, 0x0808, 0xf8f8},
9180 {0x4444, 0xc0c0, 0xa066, 0x22e0},
9182 static const DWORD content_x8l8v8u8[4][4] =
9184 {0x00000000, 0x00ff7f7f, 0x00008880, 0x00ff0000},
9185 {0x00000080, 0x00008000, 0x00007f00, 0x0000007f},
9186 {0x0041193b, 0x0051e8c8, 0x00040808, 0x00fff8f8},
9187 {0x00824444, 0x0000c0c0, 0x00c2a066, 0x009222e0},
9189 static const USHORT content_l6v5u5[4][4] =
9191 {0x0000, 0xfdef, 0x0230, 0xfc00},
9192 {0x0010, 0x0200, 0x01e0, 0x000f},
9193 {0x4067, 0x53b9, 0x0421, 0xffff},
9194 {0x8108, 0x0318, 0xc28c, 0x909c},
9196 static const struct
9198 const char *name;
9199 const void *content;
9200 SIZE_T pixel_size;
9201 BOOL blue;
9202 unsigned int slop, slop_broken;
9203 DDPIXELFORMAT format;
9205 formats[] =
9208 "D3DFMT_V8U8", content_v8u8, sizeof(WORD), FALSE, 1, 0,
9210 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV, 0,
9211 {16}, {0x000000ff}, {0x0000ff00}, {0x00000000}, {0x00000000}
9215 "D3DFMT_X8L8V8U8", content_x8l8v8u8, sizeof(DWORD), TRUE, 1, 0,
9217 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE, 0,
9218 {32}, {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}
9222 "D3DFMT_L6V5U5", content_l6v5u5, sizeof(WORD), TRUE, 4, 7,
9224 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE, 0,
9225 {16}, {0x0000001f}, {0x000003e0}, {0x0000fc00}, {0x00000000}
9229 /* No V16U16 or Q8W8V8U8 support in ddraw. */
9231 static const D3DCOLOR expected_colors[4][4] =
9233 {0x00808080, 0x00fefeff, 0x00010780, 0x008080ff},
9234 {0x00018080, 0x00800180, 0x0080fe80, 0x00fe8080},
9235 {0x00ba98a0, 0x004767a8, 0x00888881, 0x007878ff},
9236 {0x00c3c3c0, 0x003f3f80, 0x00e51fe1, 0x005fa2c8},
9238 unsigned int i, width, x, y;
9239 D3DDEVICEDESC7 device_desc;
9241 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9242 0, 0, 640, 480, 0, 0, 0, 0);
9244 if (!(device = create_device(window, DDSCL_NORMAL)))
9246 skip("Failed to create a 3D device, skipping test.\n");
9247 DestroyWindow(window);
9248 return;
9251 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
9252 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
9253 if (!(device_desc.dwTextureOpCaps & D3DTEXOPCAPS_BLENDFACTORALPHA))
9255 skip("D3DTOP_BLENDFACTORALPHA not supported, skipping bumpmap format tests.\n");
9256 goto done;
9259 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
9260 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
9261 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
9262 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
9263 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
9264 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9266 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
9267 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9269 /* dst = tex * 0.5 + 1.0 * (1.0 - 0.5) = tex * 0.5 + 0.5 */
9270 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x80ffffff);
9271 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9272 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_BLENDFACTORALPHA);
9273 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
9274 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
9275 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
9276 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
9277 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
9279 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
9281 for (width = 1; width < 5; width += 3)
9283 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
9284 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
9286 memset(&surface_desc, 0, sizeof(surface_desc));
9287 surface_desc.dwSize = sizeof(surface_desc);
9288 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
9289 surface_desc.dwWidth = width;
9290 surface_desc.dwHeight = 4;
9291 U4(surface_desc).ddpfPixelFormat = formats[i].format;
9292 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
9293 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9294 if (FAILED(hr))
9296 skip("%s textures not supported, skipping.\n", formats[i].name);
9297 continue;
9299 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, format %s.\n", hr, formats[i].name);
9300 hr = IDirect3DDevice7_SetTexture(device, 0, surface);
9301 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x, format %s.\n", hr, formats[i].name);
9303 memset(&surface_desc, 0, sizeof(surface_desc));
9304 surface_desc.dwSize = sizeof(surface_desc);
9305 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, 0, NULL);
9306 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, format %s.\n", hr, formats[i].name);
9307 for (y = 0; y < 4; y++)
9309 memcpy((char *)surface_desc.lpSurface + y * U1(surface_desc).lPitch,
9310 (char *)formats[i].content + y * 4 * formats[i].pixel_size,
9311 width * formats[i].pixel_size);
9313 hr = IDirectDrawSurface7_Unlock(surface, NULL);
9314 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, format %s.\n", hr, formats[i].name);
9316 hr = IDirect3DDevice7_BeginScene(device);
9317 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9318 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9319 D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
9320 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9321 hr = IDirect3DDevice7_EndScene(device);
9322 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9324 for (y = 0; y < 4; y++)
9326 for (x = 0; x < width; x++)
9328 expected_color = expected_colors[y][x];
9329 if (!formats[i].blue)
9330 expected_color |= 0x000000ff;
9332 color = get_surface_color(rt, 80 + 160 * x, 60 + 120 * y);
9333 ok(compare_color(color, expected_color, formats[i].slop)
9334 || broken(compare_color(color, expected_color, formats[i].slop_broken)),
9335 "Expected color 0x%08x, got 0x%08x, format %s, location %ux%u.\n",
9336 expected_color, color, formats[i].name, x, y);
9340 IDirectDrawSurface7_Release(surface);
9345 IDirectDrawSurface7_Release(rt);
9346 IDirectDraw7_Release(ddraw);
9347 IDirect3D7_Release(d3d);
9349 done:
9350 refcount = IDirect3DDevice7_Release(device);
9351 ok(!refcount, "Device has %u references left.\n", refcount);
9352 DestroyWindow(window);
9355 static void test_color_fill(void)
9357 HRESULT hr;
9358 IDirect3DDevice7 *device;
9359 IDirect3D7 *d3d;
9360 IDirectDraw7 *ddraw;
9361 IDirectDrawSurface7 *surface, *surface2;
9362 DDSURFACEDESC2 surface_desc;
9363 DDPIXELFORMAT z_fmt;
9364 ULONG refcount;
9365 HWND window;
9366 unsigned int i;
9367 DDBLTFX fx;
9368 RECT rect = {5, 5, 7, 7};
9369 DWORD *color;
9370 DWORD supported_fmts = 0, num_fourcc_codes, *fourcc_codes;
9371 DDCAPS hal_caps;
9372 static const struct
9374 DWORD caps, caps2;
9375 HRESULT colorfill_hr, depthfill_hr;
9376 BOOL rop_success;
9377 const char *name;
9378 DWORD result;
9379 BOOL check_result;
9380 DDPIXELFORMAT format;
9382 tests[] =
9385 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
9386 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain RGB", 0xdeadbeef, TRUE,
9388 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9389 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9393 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0,
9394 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain RGB", 0xdeadbeef, TRUE,
9396 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9397 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9401 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0,
9402 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem texture RGB", 0xdeadbeef, TRUE,
9404 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9405 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9409 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0,
9410 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem texture RGB", 0xdeadbeef, TRUE,
9412 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9413 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9417 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
9418 DD_OK, DDERR_INVALIDPARAMS, TRUE, "managed texture RGB", 0xdeadbeef, TRUE,
9420 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9421 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9425 DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY, 0,
9426 DDERR_INVALIDPARAMS, DD_OK, TRUE, "vidmem zbuffer", 0, FALSE,
9427 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
9430 DDSCAPS_ZBUFFER | DDSCAPS_SYSTEMMEMORY, 0,
9431 DDERR_INVALIDPARAMS, DD_OK, TRUE, "sysmem zbuffer", 0, FALSE,
9432 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
9435 /* Colorfill on YUV surfaces always returns DD_OK, but the content is
9436 * different afterwards. DX9+ GPUs set one of the two luminance values
9437 * in each block, but AMD and Nvidia GPUs disagree on which luminance
9438 * value they set. r200 (dx8) just sets the entire block to the clear
9439 * value. */
9440 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
9441 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain YUY2", 0, FALSE,
9443 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
9444 {0}, {0}, {0}, {0}, {0}
9448 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
9449 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain UYVY", 0, FALSE,
9451 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
9452 {0}, {0}, {0}, {0}, {0}
9456 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY, 0,
9457 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay YUY2", 0, FALSE,
9459 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
9460 {0}, {0}, {0}, {0}, {0}
9464 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY, 0,
9465 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay UYVY", 0, FALSE,
9467 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
9468 {0}, {0}, {0}, {0}, {0}
9472 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0,
9473 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "vidmem texture DXT1", 0, FALSE,
9475 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
9476 {0}, {0}, {0}, {0}, {0}
9480 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0,
9481 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "sysmem texture DXT1", 0, FALSE,
9483 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
9484 {0}, {0}, {0}, {0}, {0}
9488 /* The testbot fills this with 0x00 instead of the blue channel. The sysmem
9489 * surface works, presumably because it is handled by the runtime instead of
9490 * the driver. */
9491 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
9492 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain P8", 0xefefefef, FALSE,
9494 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
9495 {8}, {0}, {0}, {0}, {0}
9499 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0,
9500 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain P8", 0xefefefef, TRUE,
9502 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
9503 {8}, {0}, {0}, {0}, {0}
9507 static const struct
9509 DWORD rop;
9510 const char *name;
9511 HRESULT hr;
9513 rops[] =
9515 {SRCCOPY, "SRCCOPY", DD_OK},
9516 {SRCPAINT, "SRCPAINT", DDERR_NORASTEROPHW},
9517 {SRCAND, "SRCAND", DDERR_NORASTEROPHW},
9518 {SRCINVERT, "SRCINVERT", DDERR_NORASTEROPHW},
9519 {SRCERASE, "SRCERASE", DDERR_NORASTEROPHW},
9520 {NOTSRCCOPY, "NOTSRCCOPY", DDERR_NORASTEROPHW},
9521 {NOTSRCERASE, "NOTSRCERASE", DDERR_NORASTEROPHW},
9522 {MERGECOPY, "MERGECOPY", DDERR_NORASTEROPHW},
9523 {MERGEPAINT, "MERGEPAINT", DDERR_NORASTEROPHW},
9524 {PATCOPY, "PATCOPY", DDERR_NORASTEROPHW},
9525 {PATPAINT, "PATPAINT", DDERR_NORASTEROPHW},
9526 {PATINVERT, "PATINVERT", DDERR_NORASTEROPHW},
9527 {DSTINVERT, "DSTINVERT", DDERR_NORASTEROPHW},
9528 {BLACKNESS, "BLACKNESS", DD_OK},
9529 {WHITENESS, "WHITENESS", DD_OK},
9530 {0xaa0029, "0xaa0029", DDERR_NORASTEROPHW} /* noop */
9533 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9534 0, 0, 640, 480, 0, 0, 0, 0);
9536 if (!(device = create_device(window, DDSCL_NORMAL)))
9538 skip("Failed to create a 3D device, skipping test.\n");
9539 DestroyWindow(window);
9540 return;
9543 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
9544 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
9545 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
9546 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
9548 memset(&z_fmt, 0, sizeof(z_fmt));
9549 IDirect3D7_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
9550 if (!z_fmt.dwSize)
9551 skip("No Z buffer formats supported, skipping Z buffer colorfill test.\n");
9553 IDirect3DDevice7_EnumTextureFormats(device, test_block_formats_creation_cb, &supported_fmts);
9554 if (!(supported_fmts & SUPPORT_DXT1))
9555 skip("DXT1 textures not supported, skipping DXT1 colorfill test.\n");
9557 IDirect3D7_Release(d3d);
9559 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
9560 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
9561 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
9562 num_fourcc_codes * sizeof(*fourcc_codes));
9563 if (!fourcc_codes)
9564 goto done;
9565 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
9566 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
9567 for (i = 0; i < num_fourcc_codes; i++)
9569 if (fourcc_codes[i] == MAKEFOURCC('Y', 'U', 'Y', '2'))
9570 supported_fmts |= SUPPORT_YUY2;
9571 else if (fourcc_codes[i] == MAKEFOURCC('U', 'Y', 'V', 'Y'))
9572 supported_fmts |= SUPPORT_UYVY;
9574 HeapFree(GetProcessHeap(), 0, fourcc_codes);
9576 memset(&hal_caps, 0, sizeof(hal_caps));
9577 hal_caps.dwSize = sizeof(hal_caps);
9578 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
9579 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9581 if (!(supported_fmts & (SUPPORT_YUY2 | SUPPORT_UYVY)) || !(hal_caps.dwCaps & DDCAPS_OVERLAY))
9582 skip("Overlays or some YUV formats not supported, skipping YUV colorfill tests.\n");
9584 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
9586 /* Some Windows drivers modify dwFillColor when it is used on P8 or FourCC formats. */
9587 memset(&fx, 0, sizeof(fx));
9588 fx.dwSize = sizeof(fx);
9589 U5(fx).dwFillColor = 0xdeadbeef;
9591 memset(&surface_desc, 0, sizeof(surface_desc));
9592 surface_desc.dwSize = sizeof(surface_desc);
9593 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9594 surface_desc.dwWidth = 64;
9595 surface_desc.dwHeight = 64;
9596 U4(surface_desc).ddpfPixelFormat = tests[i].format;
9597 surface_desc.ddsCaps.dwCaps = tests[i].caps;
9598 surface_desc.ddsCaps.dwCaps2 = tests[i].caps2;
9600 if (tests[i].format.dwFourCC == MAKEFOURCC('D','X','T','1') && !(supported_fmts & SUPPORT_DXT1))
9601 continue;
9602 if (tests[i].format.dwFourCC == MAKEFOURCC('Y','U','Y','2') && !(supported_fmts & SUPPORT_YUY2))
9603 continue;
9604 if (tests[i].format.dwFourCC == MAKEFOURCC('U','Y','V','Y') && !(supported_fmts & SUPPORT_UYVY))
9605 continue;
9606 if (tests[i].caps & DDSCAPS_OVERLAY && !(hal_caps.dwCaps & DDCAPS_OVERLAY))
9607 continue;
9609 if (tests[i].caps & DDSCAPS_ZBUFFER)
9611 if (!z_fmt.dwSize)
9612 continue;
9614 U4(surface_desc).ddpfPixelFormat = z_fmt;
9617 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9618 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, surface %s.\n", hr, tests[i].name);
9620 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9621 if (tests[i].format.dwFourCC)
9622 todo_wine ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9623 hr, tests[i].colorfill_hr, tests[i].name);
9624 else
9625 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9626 hr, tests[i].colorfill_hr, tests[i].name);
9628 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9629 if (tests[i].format.dwFourCC)
9630 todo_wine ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9631 hr, tests[i].colorfill_hr, tests[i].name);
9632 else
9633 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9634 hr, tests[i].colorfill_hr, tests[i].name);
9636 if (SUCCEEDED(hr) && tests[i].check_result)
9638 memset(&surface_desc, 0, sizeof(surface_desc));
9639 surface_desc.dwSize = sizeof(surface_desc);
9640 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9641 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9642 color = surface_desc.lpSurface;
9643 ok(*color == tests[i].result, "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
9644 *color, tests[i].result, tests[i].name);
9645 hr = IDirectDrawSurface7_Unlock(surface, NULL);
9646 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9649 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9650 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9651 hr, tests[i].depthfill_hr, tests[i].name);
9652 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9653 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9654 hr, tests[i].depthfill_hr, tests[i].name);
9656 U5(fx).dwFillColor = 0xdeadbeef;
9657 fx.dwROP = BLACKNESS;
9658 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
9659 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
9660 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
9661 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
9662 U5(fx).dwFillColor, tests[i].name);
9664 if (SUCCEEDED(hr) && tests[i].check_result)
9666 memset(&surface_desc, 0, sizeof(surface_desc));
9667 surface_desc.dwSize = sizeof(surface_desc);
9668 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9669 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9670 color = surface_desc.lpSurface;
9671 ok(*color == 0, "Got clear result 0x%08x, expected 0x00000000, surface %s.\n",
9672 *color, tests[i].name);
9673 hr = IDirectDrawSurface7_Unlock(surface, NULL);
9674 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9677 fx.dwROP = WHITENESS;
9678 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
9679 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
9680 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
9681 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
9682 U5(fx).dwFillColor, tests[i].name);
9684 if (SUCCEEDED(hr) && tests[i].check_result)
9686 memset(&surface_desc, 0, sizeof(surface_desc));
9687 surface_desc.dwSize = sizeof(surface_desc);
9688 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9689 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9690 color = surface_desc.lpSurface;
9691 /* WHITENESS sets the alpha channel to 0x00. Ignore this for now. */
9692 ok((*color & 0x00ffffff) == 0x00ffffff, "Got clear result 0x%08x, expected 0xffffffff, surface %s.\n",
9693 *color, tests[i].name);
9694 hr = IDirectDrawSurface7_Unlock(surface, NULL);
9695 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9698 IDirectDrawSurface7_Release(surface);
9701 memset(&fx, 0, sizeof(fx));
9702 fx.dwSize = sizeof(fx);
9703 U5(fx).dwFillColor = 0xdeadbeef;
9704 fx.dwROP = WHITENESS;
9706 memset(&surface_desc, 0, sizeof(surface_desc));
9707 surface_desc.dwSize = sizeof(surface_desc);
9708 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9709 surface_desc.dwWidth = 64;
9710 surface_desc.dwHeight = 64;
9711 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9712 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
9713 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
9714 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9715 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9716 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
9717 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
9718 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9719 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9720 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
9721 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9723 /* No DDBLTFX. */
9724 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, NULL);
9725 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9726 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, NULL);
9727 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9729 /* Unused source rectangle. */
9730 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9731 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9732 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
9733 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9735 /* Unused source surface. */
9736 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9737 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9738 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
9739 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9740 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9741 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9742 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
9743 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9745 /* Inverted destination or source rectangle. */
9746 SetRect(&rect, 5, 7, 7, 5);
9747 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9748 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9749 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9750 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9751 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9752 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9753 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9754 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9755 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
9756 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9758 /* Negative rectangle. */
9759 SetRect(&rect, -1, -1, 5, 5);
9760 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9761 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9762 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9763 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9764 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9765 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9766 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9767 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9768 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
9769 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9771 /* Out of bounds rectangle. */
9772 SetRect(&rect, 0, 0, 65, 65);
9773 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9774 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9775 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
9776 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9778 /* Combine multiple flags. */
9779 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9780 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9781 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
9782 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9783 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
9784 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9786 for (i = 0; i < sizeof(rops) / sizeof(*rops); i++)
9788 fx.dwROP = rops[i].rop;
9789 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
9790 ok(hr == rops[i].hr, "Got unexpected hr %#x for rop %s.\n", hr, rops[i].name);
9793 IDirectDrawSurface7_Release(surface2);
9794 IDirectDrawSurface7_Release(surface);
9796 if (!z_fmt.dwSize)
9797 goto done;
9799 memset(&surface_desc, 0, sizeof(surface_desc));
9800 surface_desc.dwSize = sizeof(surface_desc);
9801 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9802 surface_desc.dwWidth = 64;
9803 surface_desc.dwHeight = 64;
9804 U4(surface_desc).ddpfPixelFormat = z_fmt;
9805 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
9806 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9807 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9808 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
9809 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9811 /* No DDBLTFX. */
9812 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, NULL);
9813 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9815 /* Unused source rectangle. */
9816 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9817 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9819 /* Unused source surface. */
9820 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9821 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9822 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9823 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9825 /* Inverted destination or source rectangle. */
9826 SetRect(&rect, 5, 7, 7, 5);
9827 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9828 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9829 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9830 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9831 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9832 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9833 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9834 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9836 /* Negative rectangle. */
9837 SetRect(&rect, -1, -1, 5, 5);
9838 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9839 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9840 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9841 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
9842 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9843 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9844 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9845 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9847 /* Out of bounds rectangle. */
9848 SetRect(&rect, 0, 0, 65, 65);
9849 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9850 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
9852 /* Combine multiple flags. */
9853 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9854 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
9856 IDirectDrawSurface7_Release(surface2);
9857 IDirectDrawSurface7_Release(surface);
9859 done:
9860 IDirectDraw7_Release(ddraw);
9861 refcount = IDirect3DDevice7_Release(device);
9862 ok(!refcount, "Device has %u references left.\n", refcount);
9863 DestroyWindow(window);
9866 static void test_texcoordindex(void)
9868 static D3DMATRIX mat =
9870 1.0f, 0.0f, 0.0f, 0.0f,
9871 0.0f, 0.0f, 0.0f, 0.0f,
9872 0.0f, 0.0f, 0.0f, 0.0f,
9873 0.0f, 0.0f, 0.0f, 0.0f,
9875 static struct
9877 struct vec3 pos;
9878 struct vec2 texcoord1;
9879 struct vec2 texcoord2;
9880 struct vec2 texcoord3;
9882 quad[] =
9884 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f}},
9885 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 0.0f}},
9886 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}},
9887 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}},
9889 static const DWORD fvf = D3DFVF_XYZ | D3DFVF_TEX3;
9890 IDirect3DDevice7 *device;
9891 IDirect3D7 *d3d;
9892 IDirectDraw7 *ddraw;
9893 IDirectDrawSurface7 *rt;
9894 HWND window;
9895 HRESULT hr;
9896 IDirectDrawSurface7 *texture1, *texture2;
9897 DDSURFACEDESC2 surface_desc;
9898 ULONG refcount;
9899 D3DCOLOR color;
9900 DWORD *ptr;
9902 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9903 0, 0, 640, 480, 0, 0, 0, 0);
9904 if (!(device = create_device(window, DDSCL_NORMAL)))
9906 skip("Failed to create a 3D device, skipping test.\n");
9907 DestroyWindow(window);
9908 return;
9911 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
9912 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
9913 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
9914 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
9915 IDirect3D7_Release(d3d);
9917 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
9918 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9920 memset(&surface_desc, 0, sizeof(surface_desc));
9921 surface_desc.dwSize = sizeof(surface_desc);
9922 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9923 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
9924 surface_desc.dwWidth = 2;
9925 surface_desc.dwHeight = 2;
9926 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9927 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
9928 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
9929 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9930 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9931 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
9932 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
9933 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture1, NULL);
9934 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9935 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture2, NULL);
9936 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9938 memset(&surface_desc, 0, sizeof(surface_desc));
9939 surface_desc.dwSize = sizeof(surface_desc);
9940 hr = IDirectDrawSurface7_Lock(texture1, 0, &surface_desc, 0, NULL);
9941 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
9942 ptr = surface_desc.lpSurface;
9943 ptr[0] = 0xff000000;
9944 ptr[1] = 0xff00ff00;
9945 ptr += surface_desc.lPitch / sizeof(*ptr);
9946 ptr[0] = 0xff0000ff;
9947 ptr[1] = 0xff00ffff;
9948 hr = IDirectDrawSurface7_Unlock(texture1, NULL);
9949 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9951 memset(&surface_desc, 0, sizeof(surface_desc));
9952 surface_desc.dwSize = sizeof(surface_desc);
9953 hr = IDirectDrawSurface7_Lock(texture2, 0, &surface_desc, 0, NULL);
9954 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
9955 ptr = surface_desc.lpSurface;
9956 ptr[0] = 0xff000000;
9957 ptr[1] = 0xff0000ff;
9958 ptr += surface_desc.lPitch / sizeof(*ptr);
9959 ptr[0] = 0xffff0000;
9960 ptr[1] = 0xffff00ff;
9961 hr = IDirectDrawSurface7_Unlock(texture2, 0);
9962 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9964 hr = IDirect3DDevice7_SetTexture(device, 0, texture1);
9965 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
9966 hr = IDirect3DDevice7_SetTexture(device, 1, texture2);
9967 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
9968 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
9969 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
9970 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
9971 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
9972 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
9973 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
9974 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_ADD);
9975 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
9976 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
9977 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
9978 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
9979 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
9980 hr = IDirect3DDevice7_SetTextureStageState(device, 2, D3DTSS_COLOROP, D3DTOP_DISABLE);
9981 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
9983 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_TEXCOORDINDEX, 1);
9984 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
9985 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXCOORDINDEX, 0);
9986 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
9988 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
9989 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
9991 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
9992 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
9994 hr = IDirect3DDevice7_BeginScene(device);
9995 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9996 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
9997 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9998 hr = IDirect3DDevice7_EndScene(device);
9999 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10001 color = get_surface_color(rt, 160, 120);
10002 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
10003 color = get_surface_color(rt, 480, 120);
10004 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
10005 color = get_surface_color(rt, 160, 360);
10006 ok(compare_color(color, 0x00ff0000, 2), "Got unexpected color 0x%08x.\n", color);
10007 color = get_surface_color(rt, 480, 360);
10008 ok(compare_color(color, 0x00ffffff, 2), "Got unexpected color 0x%08x.\n", color);
10010 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
10011 ok(SUCCEEDED(hr), "Failed to set texture transform flags, hr %#x.\n", hr);
10012 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_TEXTURE1, &mat);
10013 ok(SUCCEEDED(hr), "Failed to set transformation matrix, hr %#x.\n", hr);
10015 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
10016 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10018 hr = IDirect3DDevice7_BeginScene(device);
10019 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10020 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
10021 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10022 hr = IDirect3DDevice7_EndScene(device);
10023 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10025 color = get_surface_color(rt, 160, 120);
10026 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
10027 color = get_surface_color(rt, 480, 120);
10028 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
10029 color = get_surface_color(rt, 160, 360);
10030 ok(compare_color(color, 0x00000000, 2), "Got unexpected color 0x%08x.\n", color);
10031 color = get_surface_color(rt, 480, 360);
10032 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
10034 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
10035 ok(SUCCEEDED(hr), "Failed to set texture transform flags, hr %#x.\n", hr);
10036 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXCOORDINDEX, 2);
10037 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
10039 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
10040 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10042 hr = IDirect3DDevice7_BeginScene(device);
10043 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10044 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
10045 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10046 hr = IDirect3DDevice7_EndScene(device);
10047 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10049 color = get_surface_color(rt, 160, 120);
10050 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
10051 color = get_surface_color(rt, 480, 120);
10052 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
10053 color = get_surface_color(rt, 160, 360);
10054 ok(compare_color(color, 0x00ff00ff, 2), "Got unexpected color 0x%08x.\n", color);
10055 color = get_surface_color(rt, 480, 360);
10056 ok(compare_color(color, 0x00ffff00, 2), "Got unexpected color 0x%08x.\n", color);
10058 IDirectDrawSurface7_Release(texture1);
10059 IDirectDrawSurface7_Release(texture2);
10061 IDirectDrawSurface7_Release(rt);
10062 IDirectDraw_Release(ddraw);
10063 refcount = IDirect3DDevice7_Release(device);
10064 ok(!refcount, "Device has %u references left.\n", refcount);
10065 DestroyWindow(window);
10068 static void test_colorkey_precision(void)
10070 static struct
10072 struct vec3 pos;
10073 struct vec2 texcoord;
10075 quad[] =
10077 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
10078 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
10079 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
10080 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
10082 IDirect3DDevice7 *device;
10083 IDirect3D7 *d3d;
10084 IDirectDraw7 *ddraw;
10085 IDirectDrawSurface7 *rt;
10086 HWND window;
10087 HRESULT hr;
10088 IDirectDrawSurface7 *src, *dst, *texture;
10089 DDSURFACEDESC2 surface_desc, lock_desc;
10090 ULONG refcount;
10091 D3DCOLOR color;
10092 unsigned int t, c;
10093 DDCOLORKEY ckey;
10094 DDBLTFX fx;
10095 DWORD data[4] = {0}, color_mask;
10096 D3DDEVICEDESC7 device_desc;
10097 BOOL warp;
10098 static const struct
10100 unsigned int max, shift, bpp, clear;
10101 const char *name;
10102 DDPIXELFORMAT fmt;
10104 tests[] =
10107 255, 0, 4, 0x00345678, "D3DFMT_X8R8G8B8",
10109 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
10110 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
10115 63, 5, 2, 0x5678, "D3DFMT_R5G6B5, G channel",
10117 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
10118 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
10123 31, 0, 2, 0x5678, "D3DFMT_R5G6B5, B channel",
10125 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
10126 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
10131 15, 0, 2, 0x0678, "D3DFMT_A4R4G4B4",
10133 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
10134 {16}, {0x0f00}, {0x00f0}, {0x000f}, {0xf000}
10140 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
10141 0, 0, 640, 480, 0, 0, 0, 0);
10142 if (!(device = create_device(window, DDSCL_NORMAL)))
10144 skip("Failed to create a 3D device, skipping test.\n");
10145 DestroyWindow(window);
10146 return;
10149 /* The Windows 8 WARP driver has plenty of false negatives in X8R8G8B8
10150 * (color key doesn't match although the values are equal), and a false
10151 * positive when the color key is 0 and the texture contains the value 1.
10152 * I don't want to mark this broken unconditionally since this would
10153 * essentially disable the test on Windows. Try to detect WARP (and I
10154 * guess mismatch other SW renderers) by its ability to texture from
10155 * system memory. Also on random occasions 254 == 255 and 255 != 255.*/
10156 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
10157 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10158 warp = !!(device_desc.dwDevCaps & D3DDEVCAPS_TEXTURESYSTEMMEMORY);
10160 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
10161 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
10162 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
10163 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
10164 IDirect3D7_Release(d3d);
10165 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
10166 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10168 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
10169 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
10170 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
10171 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
10172 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
10173 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
10174 /* Multiply the texture read result with 0, that way the result color if the key doesn't
10175 * match is constant. In theory color keying works without reading the texture result
10176 * (meaning we could just op=arg1, arg1=tfactor), but the Geforce7 Windows driver begs
10177 * to differ. */
10178 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
10179 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
10180 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
10181 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10182 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
10183 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10184 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x00000000);
10185 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10187 memset(&fx, 0, sizeof(fx));
10188 fx.dwSize = sizeof(fx);
10189 memset(&lock_desc, 0, sizeof(lock_desc));
10190 lock_desc.dwSize = sizeof(lock_desc);
10192 for (t = 0; t < sizeof(tests) / sizeof(*tests); ++t)
10194 memset(&surface_desc, 0, sizeof(surface_desc));
10195 surface_desc.dwSize = sizeof(surface_desc);
10196 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10197 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10198 surface_desc.dwWidth = 4;
10199 surface_desc.dwHeight = 1;
10200 U4(surface_desc).ddpfPixelFormat = tests[t].fmt;
10201 /* Windows XP (at least with the r200 driver, other drivers untested) produces
10202 * garbage when doing color keyed texture->texture blits. */
10203 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
10204 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10205 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
10206 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10208 fx.dwFillColor = tests[t].clear;
10209 /* On the w8 testbot (WARP driver) the blit result has different values in the
10210 * X channel. */
10211 color_mask = U2(tests[t].fmt).dwRBitMask
10212 | U3(tests[t].fmt).dwGBitMask
10213 | U4(tests[t].fmt).dwBBitMask;
10215 for (c = 0; c <= tests[t].max; ++c)
10217 /* The idiotic Nvidia Windows driver can't change the color key on a d3d
10218 * texture after it has been set once... */
10219 surface_desc.dwFlags |= DDSD_CKSRCBLT;
10220 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
10221 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = c << tests[t].shift;
10222 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = c << tests[t].shift;
10223 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
10224 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10225 hr = IDirect3DDevice7_SetTexture(device, 0, texture);
10226 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
10228 hr = IDirectDrawSurface7_Blt(dst, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10229 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
10231 hr = IDirectDrawSurface7_Lock(src, NULL, &lock_desc, DDLOCK_WAIT, NULL);
10232 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10233 switch (tests[t].bpp)
10235 case 4:
10236 ((DWORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
10237 ((DWORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
10238 ((DWORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
10239 ((DWORD *)lock_desc.lpSurface)[3] = 0xffffffff;
10240 break;
10242 case 2:
10243 ((WORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
10244 ((WORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
10245 ((WORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
10246 ((WORD *)lock_desc.lpSurface)[3] = 0xffff;
10247 break;
10249 hr = IDirectDrawSurface7_Unlock(src, 0);
10250 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10251 hr = IDirectDrawSurface7_Blt(texture, NULL, src, NULL, DDBLT_WAIT, NULL);
10252 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
10254 ckey.dwColorSpaceLowValue = c << tests[t].shift;
10255 ckey.dwColorSpaceHighValue = c << tests[t].shift;
10256 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
10257 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10259 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_WAIT, NULL);
10260 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
10262 /* Don't make this read only, it somehow breaks the detection of the Nvidia bug below. */
10263 hr = IDirectDrawSurface7_Lock(dst, NULL, &lock_desc, DDLOCK_WAIT, NULL);
10264 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10265 switch (tests[t].bpp)
10267 case 4:
10268 data[0] = ((DWORD *)lock_desc.lpSurface)[0] & color_mask;
10269 data[1] = ((DWORD *)lock_desc.lpSurface)[1] & color_mask;
10270 data[2] = ((DWORD *)lock_desc.lpSurface)[2] & color_mask;
10271 data[3] = ((DWORD *)lock_desc.lpSurface)[3] & color_mask;
10272 break;
10274 case 2:
10275 data[0] = ((WORD *)lock_desc.lpSurface)[0] & color_mask;
10276 data[1] = ((WORD *)lock_desc.lpSurface)[1] & color_mask;
10277 data[2] = ((WORD *)lock_desc.lpSurface)[2] & color_mask;
10278 data[3] = ((WORD *)lock_desc.lpSurface)[3] & color_mask;
10279 break;
10281 hr = IDirectDrawSurface7_Unlock(dst, 0);
10282 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10284 if (!c)
10286 ok(data[0] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10287 tests[t].clear, data[0], tests[t].name, c);
10289 if (data[3] == tests[t].clear)
10291 /* My Geforce GTX 460 on Windows 7 misbehaves when A4R4G4B4 is blitted with color
10292 * keying: The blit takes ~0.5 seconds, and subsequent color keying draws are broken,
10293 * even when a different surface is used. The blit itself doesn't draw anything,
10294 * so we can detect the bug by looking at the otherwise unused 4th texel. It should
10295 * never be masked out by the key.
10297 * Also appears to affect the testbot in some way with R5G6B5. Color keying is
10298 * terrible on WARP. */
10299 skip("Nvidia A4R4G4B4 color keying blit bug detected, skipping.\n");
10300 IDirectDrawSurface7_Release(texture);
10301 IDirectDrawSurface7_Release(src);
10302 IDirectDrawSurface7_Release(dst);
10303 goto done;
10306 else
10307 ok(data[0] == (c - 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10308 (c - 1) << tests[t].shift, data[0], tests[t].name, c);
10310 ok(data[1] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10311 tests[t].clear, data[1], tests[t].name, c);
10313 if (c == tests[t].max)
10314 ok(data[2] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10315 tests[t].clear, data[2], tests[t].name, c);
10316 else
10317 ok(data[2] == (c + 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10318 (c + 1) << tests[t].shift, data[2], tests[t].name, c);
10320 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x0000ff00, 1.0f, 0);
10321 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10323 hr = IDirect3DDevice7_BeginScene(device);
10324 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10325 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
10326 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10327 hr = IDirect3DDevice7_EndScene(device);
10328 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10330 color = get_surface_color(rt, 80, 240);
10331 if (!c)
10332 ok(compare_color(color, 0x0000ff00, 1) || broken(warp && compare_color(color, 0x00000000, 1)),
10333 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10334 color, tests[t].name, c);
10335 else
10336 ok(compare_color(color, 0x00000000, 1) || broken(warp && compare_color(color, 0x0000ff00, 1)),
10337 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10338 color, tests[t].name, c);
10340 color = get_surface_color(rt, 240, 240);
10341 ok(compare_color(color, 0x0000ff00, 1) || broken(warp && compare_color(color, 0x00000000, 1)),
10342 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10343 color, tests[t].name, c);
10345 color = get_surface_color(rt, 400, 240);
10346 if (c == tests[t].max)
10347 ok(compare_color(color, 0x0000ff00, 1) || broken(warp && compare_color(color, 0x00000000, 1)),
10348 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10349 color, tests[t].name, c);
10350 else
10351 ok(compare_color(color, 0x00000000, 1) || broken(warp && compare_color(color, 0x0000ff00, 1)),
10352 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10353 color, tests[t].name, c);
10355 IDirectDrawSurface7_Release(texture);
10357 IDirectDrawSurface7_Release(src);
10358 IDirectDrawSurface7_Release(dst);
10360 done:
10362 IDirectDrawSurface7_Release(rt);
10363 IDirectDraw7_Release(ddraw);
10364 refcount = IDirect3DDevice7_Release(device);
10365 ok(!refcount, "Device has %u references left.\n", refcount);
10366 DestroyWindow(window);
10369 static void test_range_colorkey(void)
10371 IDirectDraw7 *ddraw;
10372 HWND window;
10373 HRESULT hr;
10374 IDirectDrawSurface7 *surface;
10375 DDSURFACEDESC2 surface_desc;
10376 ULONG refcount;
10377 DDCOLORKEY ckey;
10379 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
10380 0, 0, 640, 480, 0, 0, 0, 0);
10381 ddraw = create_ddraw();
10382 ok(!!ddraw, "Failed to create a ddraw object.\n");
10383 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10384 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
10386 memset(&surface_desc, 0, sizeof(surface_desc));
10387 surface_desc.dwSize = sizeof(surface_desc);
10388 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
10389 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
10390 surface_desc.dwWidth = 1;
10391 surface_desc.dwHeight = 1;
10392 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
10393 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
10394 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
10395 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
10396 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
10397 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0x00000000;
10399 /* Creating a surface with a range color key fails with DDERR_NOCOLORKEY. */
10400 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
10401 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
10402 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10403 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10405 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
10406 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
10407 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10408 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10410 /* Same for DDSCAPS_OFFSCREENPLAIN. */
10411 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10412 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
10413 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
10414 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10415 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10417 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
10418 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
10419 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10420 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10422 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
10423 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
10424 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10425 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10427 /* Setting a range color key without DDCKEY_COLORSPACE collapses the key. */
10428 ckey.dwColorSpaceLowValue = 0x00000000;
10429 ckey.dwColorSpaceHighValue = 0x00000001;
10430 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10431 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10433 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10434 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
10435 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
10436 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
10438 ckey.dwColorSpaceLowValue = 0x00000001;
10439 ckey.dwColorSpaceHighValue = 0x00000000;
10440 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10441 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10443 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10444 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
10445 ok(ckey.dwColorSpaceLowValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
10446 ok(ckey.dwColorSpaceHighValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
10448 /* DDCKEY_COLORSPACE is ignored if the key is a single value. */
10449 ckey.dwColorSpaceLowValue = 0x00000000;
10450 ckey.dwColorSpaceHighValue = 0x00000000;
10451 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10452 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10454 /* Using it with a range key results in DDERR_NOCOLORKEYHW. */
10455 ckey.dwColorSpaceLowValue = 0x00000001;
10456 ckey.dwColorSpaceHighValue = 0x00000000;
10457 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10458 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10459 ckey.dwColorSpaceLowValue = 0x00000000;
10460 ckey.dwColorSpaceHighValue = 0x00000001;
10461 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10462 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10463 /* Range destination keys don't work either. */
10464 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_DESTBLT | DDCKEY_COLORSPACE, &ckey);
10465 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10467 /* Just to show it's not because of A, R, and G having equal values. */
10468 ckey.dwColorSpaceLowValue = 0x00000000;
10469 ckey.dwColorSpaceHighValue = 0x01010101;
10470 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10471 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10473 /* None of these operations modified the key. */
10474 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10475 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
10476 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
10477 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
10479 IDirectDrawSurface7_Release(surface),
10480 refcount = IDirectDraw7_Release(ddraw);
10481 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
10482 DestroyWindow(window);
10485 static void test_shademode(void)
10487 IDirect3DVertexBuffer7 *vb_strip, *vb_list, *buffer;
10488 IDirect3DDevice7 *device;
10489 D3DVERTEXBUFFERDESC desc;
10490 IDirectDrawSurface7 *rt;
10491 DWORD color0, color1;
10492 void *data = NULL;
10493 IDirect3D7 *d3d;
10494 ULONG refcount;
10495 UINT i, count;
10496 HWND window;
10497 HRESULT hr;
10498 static const struct
10500 struct vec3 position;
10501 DWORD diffuse;
10503 quad_strip[] =
10505 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
10506 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
10507 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
10508 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
10510 quad_list[] =
10512 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
10513 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
10514 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
10516 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
10517 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
10518 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
10520 static const struct
10522 DWORD primtype;
10523 DWORD shademode;
10524 DWORD color0, color1;
10526 tests[] =
10528 {D3DPT_TRIANGLESTRIP, D3DSHADE_FLAT, 0x00ff0000, 0x0000ff00},
10529 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
10530 {D3DPT_TRIANGLESTRIP, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
10531 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
10532 {D3DPT_TRIANGLELIST, D3DSHADE_FLAT, 0x00ff0000, 0x000000ff},
10533 {D3DPT_TRIANGLELIST, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
10536 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
10537 0, 0, 640, 480, 0, 0, 0, 0);
10539 if (!(device = create_device(window, DDSCL_NORMAL)))
10541 skip("Failed to create a 3D device, skipping test.\n");
10542 DestroyWindow(window);
10543 return;
10546 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
10547 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
10548 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
10549 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10551 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
10552 ok(hr == D3D_OK, "Failed to disable lighting, hr %#x.\n", hr);
10553 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
10554 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
10556 memset(&desc, 0, sizeof(desc));
10557 desc.dwSize = sizeof(desc);
10558 desc.dwCaps = D3DVBCAPS_WRITEONLY;
10559 desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
10560 desc.dwNumVertices = sizeof(quad_strip) / sizeof(*quad_strip);
10561 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &vb_strip, 0);
10562 ok(hr == D3D_OK, "Failed to create vertex buffer, hr %#x.\n", hr);
10563 hr = IDirect3DVertexBuffer7_Lock(vb_strip, 0, &data, NULL);
10564 ok(hr == D3D_OK, "Failed to lock vertex buffer, hr %#x.\n", hr);
10565 memcpy(data, quad_strip, sizeof(quad_strip));
10566 hr = IDirect3DVertexBuffer7_Unlock(vb_strip);
10567 ok(hr == D3D_OK, "Failed to unlock vertex buffer, hr %#x.\n", hr);
10569 desc.dwNumVertices = sizeof(quad_list) / sizeof(*quad_list);
10570 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &vb_list, 0);
10571 ok(hr == D3D_OK, "Failed to create vertex buffer, hr %#x.\n", hr);
10572 hr = IDirect3DVertexBuffer7_Lock(vb_list, 0, &data, NULL);
10573 ok(hr == D3D_OK, "Failed to lock vertex buffer, hr %#x.\n", hr);
10574 memcpy(data, quad_list, sizeof(quad_list));
10575 hr = IDirect3DVertexBuffer7_Unlock(vb_list);
10576 ok(hr == D3D_OK, "Failed to unlock vertex buffer, hr %#x.\n", hr);
10578 /* Try it first with a TRIANGLESTRIP. Do it with different geometry because
10579 * the color fixups we have to do for FLAT shading will be dependent on that. */
10581 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
10583 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
10584 ok(hr == D3D_OK, "Failed to clear, hr %#x.\n", hr);
10586 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SHADEMODE, tests[i].shademode);
10587 ok(hr == D3D_OK, "Failed to set shade mode, hr %#x.\n", hr);
10589 hr = IDirect3DDevice7_BeginScene(device);
10590 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10591 buffer = tests[i].primtype == D3DPT_TRIANGLESTRIP ? vb_strip : vb_list;
10592 count = tests[i].primtype == D3DPT_TRIANGLESTRIP ? 4 : 6;
10593 hr = IDirect3DDevice7_DrawPrimitiveVB(device, tests[i].primtype, buffer, 0, count, 0);
10594 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10595 hr = IDirect3DDevice7_EndScene(device);
10596 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10598 color0 = get_surface_color(rt, 100, 100); /* Inside first triangle */
10599 color1 = get_surface_color(rt, 500, 350); /* Inside second triangle */
10601 /* For D3DSHADE_FLAT it should take the color of the first vertex of
10602 * each triangle. This requires EXT_provoking_vertex or similar
10603 * functionality being available. */
10604 /* PHONG should be the same as GOURAUD, since no hardware implements
10605 * this. */
10606 ok(compare_color(color0, tests[i].color0, 1), "Test %u shading has color0 %08x, expected %08x.\n",
10607 i, color0, tests[i].color0);
10608 ok(compare_color(color1, tests[i].color1, 1), "Test %u shading has color1 %08x, expected %08x.\n",
10609 i, color1, tests[i].color1);
10612 IDirect3DVertexBuffer7_Release(vb_strip);
10613 IDirect3DVertexBuffer7_Release(vb_list);
10614 IDirectDrawSurface7_Release(rt);
10615 IDirect3D7_Release(d3d);
10616 refcount = IDirect3DDevice7_Release(device);
10617 ok(!refcount, "Device has %u references left.\n", refcount);
10618 DestroyWindow(window);
10621 static void test_lockrect_invalid(void)
10623 unsigned int i, r;
10624 IDirectDraw7 *ddraw;
10625 IDirectDrawSurface7 *surface;
10626 HWND window;
10627 HRESULT hr;
10628 DDSURFACEDESC2 surface_desc;
10629 DDSURFACEDESC2 locked_desc;
10630 DDCAPS hal_caps;
10631 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
10632 static RECT valid[] =
10634 {60, 60, 68, 68},
10635 {60, 60, 60, 68},
10636 {60, 60, 68, 60},
10637 {120, 60, 128, 68},
10638 {60, 120, 68, 128},
10640 static RECT invalid[] =
10642 {68, 60, 60, 68}, /* left > right */
10643 {60, 68, 68, 60}, /* top > bottom */
10644 {-8, 60, 0, 68}, /* left < surface */
10645 {60, -8, 68, 0}, /* top < surface */
10646 {-16, 60, -8, 68}, /* right < surface */
10647 {60, -16, 68, -8}, /* bottom < surface */
10648 {60, 60, 136, 68}, /* right > surface */
10649 {60, 60, 68, 136}, /* bottom > surface */
10650 {136, 60, 144, 68}, /* left > surface */
10651 {60, 136, 68, 144}, /* top > surface */
10653 static const struct
10655 DWORD caps, caps2;
10656 const char *name;
10657 HRESULT hr;
10659 resources[] =
10661 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, "sysmem offscreenplain", DDERR_INVALIDPARAMS},
10662 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, "vidmem offscreenplain", DDERR_INVALIDPARAMS},
10663 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, "sysmem texture", DD_OK},
10664 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, "vidmem texture", DDERR_INVALIDPARAMS},
10665 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, "managed texture", DD_OK},
10668 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
10669 0, 0, 640, 480, 0, 0, 0, 0);
10670 ddraw = create_ddraw();
10671 ok(!!ddraw, "Failed to create a ddraw object.\n");
10672 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10673 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
10675 memset(&hal_caps, 0, sizeof(hal_caps));
10676 hal_caps.dwSize = sizeof(hal_caps);
10677 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
10678 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
10679 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps
10680 || !(hal_caps.ddsCaps.dwCaps & DDSCAPS2_TEXTUREMANAGE))
10682 skip("Required surface types not supported, skipping test.\n");
10683 goto done;
10686 for (r = 0; r < sizeof(resources) / sizeof(*resources); ++r)
10688 memset(&surface_desc, 0, sizeof(surface_desc));
10689 surface_desc.dwSize = sizeof(surface_desc);
10690 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10691 surface_desc.ddsCaps.dwCaps = resources[r].caps;
10692 surface_desc.ddsCaps.dwCaps2 = resources[r].caps2;
10693 surface_desc.dwWidth = 128;
10694 surface_desc.dwHeight = 128;
10695 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
10696 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
10697 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
10698 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xff0000;
10699 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x00ff00;
10700 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x0000ff;
10702 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10703 if (is_ddraw64 && (resources[r].caps & DDSCAPS_TEXTURE))
10705 todo_wine ok(hr == E_NOINTERFACE, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
10706 if (SUCCEEDED(hr))
10707 IDirectDrawSurface7_Release(surface);
10708 continue;
10710 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n", hr, resources[r].name);
10712 /* Crashes in ddraw7
10713 hr = IDirectDrawSurface7_Lock(surface, NULL, NULL, DDLOCK_WAIT, NULL);
10714 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
10717 for (i = 0; i < sizeof(valid) / sizeof(*valid); ++i)
10719 RECT *rect = &valid[i];
10721 memset(&locked_desc, 0, sizeof(locked_desc));
10722 locked_desc.dwSize = sizeof(locked_desc);
10724 hr = IDirectDrawSurface7_Lock(surface, rect, &locked_desc, DDLOCK_WAIT, NULL);
10725 ok(SUCCEEDED(hr), "Lock failed (%#x) for rect [%d, %d]->[%d, %d], type %s.\n",
10726 hr, rect->left, rect->top, rect->right, rect->bottom, resources[r].name);
10728 hr = IDirectDrawSurface7_Unlock(surface, NULL);
10729 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
10732 for (i = 0; i < sizeof(invalid) / sizeof(*invalid); ++i)
10734 RECT *rect = &invalid[i];
10736 memset(&locked_desc, 1, sizeof(locked_desc));
10737 locked_desc.dwSize = sizeof(locked_desc);
10739 hr = IDirectDrawSurface7_Lock(surface, rect, &locked_desc, DDLOCK_WAIT, NULL);
10740 if (SUCCEEDED(resources[r].hr))
10741 todo_wine ok(hr == resources[r].hr, "Lock returned %#x for rect [%d, %d]->[%d, %d], type %s.\n",
10742 hr, rect->left, rect->top, rect->right, rect->bottom, resources[r].name);
10743 else
10744 ok(hr == resources[r].hr, "Lock returned %#x for rect [%d, %d]->[%d, %d], type %s.\n",
10745 hr, rect->left, rect->top, rect->right, rect->bottom, resources[r].name);
10746 if (SUCCEEDED(hr))
10748 hr = IDirectDrawSurface7_Unlock(surface, NULL);
10749 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
10751 else
10752 ok(!locked_desc.lpSurface, "Got unexpected lpSurface %p.\n", locked_desc.lpSurface);
10755 hr = IDirectDrawSurface7_Lock(surface, NULL, &locked_desc, DDLOCK_WAIT, NULL);
10756 ok(SUCCEEDED(hr), "Lock(rect = NULL) failed, hr %#x, type %s.\n",
10757 hr, resources[r].name);
10758 hr = IDirectDrawSurface7_Lock(surface, NULL, &locked_desc, DDLOCK_WAIT, NULL);
10759 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = NULL) returned %#x, type %s.\n",
10760 hr, resources[r].name);
10761 hr = IDirectDrawSurface7_Unlock(surface, NULL);
10762 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
10764 hr = IDirectDrawSurface7_Lock(surface, &valid[0], &locked_desc, DDLOCK_WAIT, NULL);
10765 ok(SUCCEEDED(hr), "Lock(rect = [%d, %d]->[%d, %d]) failed (%#x).\n",
10766 valid[0].left, valid[0].top, valid[0].right, valid[0].bottom, hr);
10767 hr = IDirectDrawSurface7_Lock(surface, &valid[0], &locked_desc, DDLOCK_WAIT, NULL);
10768 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = [%d, %d]->[%d, %d]) failed (%#x).\n",
10769 valid[0].left, valid[0].top, valid[0].right, valid[0].bottom, hr);
10771 /* Locking a different rectangle returns DD_OK, but it seems to break the surface.
10772 * Afterwards unlocking the surface fails(NULL rectangle or both locked rectangles) */
10774 hr = IDirectDrawSurface7_Unlock(surface, NULL);
10775 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
10777 IDirectDrawSurface7_Release(surface);
10780 done:
10781 IDirectDraw7_Release(ddraw);
10782 DestroyWindow(window);
10785 static void test_yv12_overlay(void)
10787 IDirectDrawSurface7 *src_surface, *dst_surface;
10788 RECT rect = {13, 17, 14, 18};
10789 unsigned int offset, y;
10790 DDSURFACEDESC2 desc;
10791 unsigned char *base;
10792 IDirectDraw7 *ddraw;
10793 HWND window;
10794 HRESULT hr;
10796 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
10797 0, 0, 640, 480, 0, 0, 0, 0);
10798 ddraw = create_ddraw();
10799 ok(!!ddraw, "Failed to create a ddraw object.\n");
10800 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10801 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
10803 if (!(src_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
10805 skip("Failed to create a YV12 overlay, skipping test.\n");
10806 goto done;
10809 memset(&desc, 0, sizeof(desc));
10810 desc.dwSize = sizeof(desc);
10811 hr = IDirectDrawSurface7_Lock(src_surface, NULL, &desc, DDLOCK_WAIT, NULL);
10812 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10814 ok(desc.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH),
10815 "Got unexpected flags %#x.\n", desc.dwFlags);
10816 ok(desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_HWCODEC)
10817 || desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
10818 "Got unexpected caps %#x.\n", desc.ddsCaps.dwCaps);
10819 ok(desc.dwWidth == 256, "Got unexpected width %u.\n", desc.dwWidth);
10820 ok(desc.dwHeight == 256, "Got unexpected height %u.\n", desc.dwHeight);
10821 /* The overlay pitch seems to have 256 byte alignment. */
10822 ok(!(U1(desc).lPitch & 0xff), "Got unexpected pitch %u.\n", U1(desc).lPitch);
10824 /* Fill the surface with some data for the blit test. */
10825 base = desc.lpSurface;
10826 /* Luminance */
10827 for (y = 0; y < desc.dwHeight; ++y)
10829 memset(base + U1(desc).lPitch * y, 0x10, desc.dwWidth);
10831 /* V */
10832 for (; y < desc.dwHeight + desc.dwHeight / 4; ++y)
10834 memset(base + U1(desc).lPitch * y, 0x20, desc.dwWidth);
10836 /* U */
10837 for (; y < desc.dwHeight + desc.dwHeight / 2; ++y)
10839 memset(base + U1(desc).lPitch * y, 0x30, desc.dwWidth);
10842 hr = IDirectDrawSurface7_Unlock(src_surface, NULL);
10843 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10845 /* YV12 uses 2x2 blocks with 6 bytes per block (4*Y, 1*U, 1*V). Unlike
10846 * other block-based formats like DXT the entire Y channel is stored in
10847 * one big chunk of memory, followed by the chroma channels. So partial
10848 * locks do not really make sense. Show that they are allowed nevertheless
10849 * and the offset points into the luminance data. */
10850 hr = IDirectDrawSurface7_Lock(src_surface, &rect, &desc, DDLOCK_WAIT, NULL);
10851 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10852 offset = ((const unsigned char *)desc.lpSurface - base);
10853 ok(offset == rect.top * U1(desc).lPitch + rect.left, "Got unexpected offset %u, expected %u.\n",
10854 offset, rect.top * U1(desc).lPitch + rect.left);
10855 hr = IDirectDrawSurface7_Unlock(src_surface, NULL);
10856 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10858 if (!(dst_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
10860 /* Windows XP with a Radeon X1600 GPU refuses to create a second
10861 * overlay surface, DDERR_NOOVERLAYHW, making the blit tests moot. */
10862 skip("Failed to create a second YV12 surface, skipping blit test.\n");
10863 IDirectDrawSurface7_Release(src_surface);
10864 goto done;
10867 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, src_surface, NULL, DDBLT_WAIT, NULL);
10868 /* VMware rejects YV12 blits. This behavior has not been seen on real
10869 * hardware yet, so mark it broken. */
10870 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL), "Failed to blit, hr %#x.\n", hr);
10872 if (SUCCEEDED(hr))
10874 memset(&desc, 0, sizeof(desc));
10875 desc.dwSize = sizeof(desc);
10876 hr = IDirectDrawSurface7_Lock(dst_surface, NULL, &desc, DDLOCK_WAIT, NULL);
10877 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10879 base = desc.lpSurface;
10880 ok(base[0] == 0x10, "Got unexpected Y data 0x%02x.\n", base[0]);
10881 base += desc.dwHeight * U1(desc).lPitch;
10882 todo_wine ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]);
10883 base += desc.dwHeight / 4 * U1(desc).lPitch;
10884 todo_wine ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]);
10886 hr = IDirectDrawSurface7_Unlock(dst_surface, NULL);
10887 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10890 IDirectDrawSurface7_Release(dst_surface);
10891 IDirectDrawSurface7_Release(src_surface);
10892 done:
10893 IDirectDraw7_Release(ddraw);
10894 DestroyWindow(window);
10897 START_TEST(ddraw7)
10899 HMODULE module = GetModuleHandleA("ddraw.dll");
10900 IDirectDraw7 *ddraw;
10901 DEVMODEW current_mode;
10903 if (!(pDirectDrawCreateEx = (void *)GetProcAddress(module, "DirectDrawCreateEx")))
10905 win_skip("DirectDrawCreateEx not available, skipping tests.\n");
10906 return;
10909 if (!(ddraw = create_ddraw()))
10911 skip("Failed to create a ddraw object, skipping tests.\n");
10912 return;
10914 IDirectDraw7_Release(ddraw);
10916 memset(&current_mode, 0, sizeof(current_mode));
10917 current_mode.dmSize = sizeof(current_mode);
10918 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
10919 registry_mode.dmSize = sizeof(registry_mode);
10920 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
10921 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
10922 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
10924 skip("Current mode does not match registry mode, skipping test.\n");
10925 return;
10928 test_process_vertices();
10929 test_coop_level_create_device_window();
10930 test_clipper_blt();
10931 test_coop_level_d3d_state();
10932 test_surface_interface_mismatch();
10933 test_coop_level_threaded();
10934 test_depth_blit();
10935 test_texture_load_ckey();
10936 test_zenable();
10937 test_ck_rgba();
10938 test_ck_default();
10939 test_ck_complex();
10940 test_surface_qi();
10941 test_device_qi();
10942 test_wndproc();
10943 test_window_style();
10944 test_redundant_mode_set();
10945 test_coop_level_mode_set();
10946 test_coop_level_mode_set_multi();
10947 test_initialize();
10948 test_coop_level_surf_create();
10949 test_vb_discard();
10950 test_coop_level_multi_window();
10951 test_draw_strided();
10952 test_lighting();
10953 test_specular_lighting();
10954 test_clear_rect_count();
10955 test_coop_level_versions();
10956 test_fog_special();
10957 test_lighting_interface_versions();
10958 test_coop_level_activateapp();
10959 test_texturemanage();
10960 test_block_formats_creation();
10961 test_unsupported_formats();
10962 test_rt_caps();
10963 test_primary_caps();
10964 test_surface_lock();
10965 test_surface_discard();
10966 test_flip();
10967 test_set_surface_desc();
10968 test_user_memory_getdc();
10969 test_sysmem_overlay();
10970 test_primary_palette();
10971 test_surface_attachment();
10972 test_private_data();
10973 test_pixel_format();
10974 test_create_surface_pitch();
10975 test_mipmap();
10976 test_palette_complex();
10977 test_p8_rgb_blit();
10978 test_material();
10979 test_palette_gdi();
10980 test_palette_alpha();
10981 test_vb_writeonly();
10982 test_lost_device();
10983 test_resource_priority();
10984 test_surface_desc_lock();
10985 test_fog_interpolation();
10986 test_negative_fixedfunction_fog();
10987 test_table_fog_zw();
10988 test_signed_formats();
10989 test_color_fill();
10990 test_texcoordindex();
10991 test_colorkey_precision();
10992 test_range_colorkey();
10993 test_shademode();
10994 test_lockrect_invalid();
10995 test_yv12_overlay();