ddraw/tests: Cleanup and extend d3d7 ComputeSphereVisibility() tests.
[wine.git] / dlls / ddraw / tests / ddraw7.c
blob6a35cb85b04e1ba842ec93b7569e273b1fb9d4a5
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 HRESULT WINAPI GetSurfaceFromDC(HDC dc, struct IDirectDrawSurface **surface, HDC *device_dc);
29 static HRESULT (WINAPI *pDirectDrawCreateEx)(GUID *guid, void **ddraw, REFIID iid, IUnknown *outer_unknown);
30 static BOOL is_ddraw64 = sizeof(DWORD) != sizeof(DWORD *);
31 static DEVMODEW registry_mode;
33 static HRESULT (WINAPI *pDwmIsCompositionEnabled)(BOOL *);
35 struct vec2
37 float x, y;
40 struct vec3
42 float x, y, z;
45 struct vec4
47 float x, y, z, w;
50 struct create_window_thread_param
52 HWND window;
53 HANDLE window_created;
54 HANDLE destroy_window;
55 HANDLE thread;
58 static BOOL compare_float(float f, float g, unsigned int ulps)
60 int x = *(int *)&f;
61 int y = *(int *)&g;
63 if (x < 0)
64 x = INT_MIN - x;
65 if (y < 0)
66 y = INT_MIN - y;
68 if (abs(x - y) > ulps)
69 return FALSE;
71 return TRUE;
74 static BOOL compare_vec3(struct vec3 *vec, float x, float y, float z, unsigned int ulps)
76 return compare_float(vec->x, x, ulps)
77 && compare_float(vec->y, y, ulps)
78 && compare_float(vec->z, z, ulps);
81 static BOOL compare_vec4(const struct vec4 *vec, float x, float y, float z, float w, unsigned int ulps)
83 return compare_float(vec->x, x, ulps)
84 && compare_float(vec->y, y, ulps)
85 && compare_float(vec->z, z, ulps)
86 && compare_float(vec->w, w, ulps);
89 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
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 c1 >>= 8; c2 >>= 8;
95 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
96 c1 >>= 8; c2 >>= 8;
97 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
98 return TRUE;
101 static ULONG get_refcount(IUnknown *iface)
103 IUnknown_AddRef(iface);
104 return IUnknown_Release(iface);
107 static BOOL ddraw_is_warp(IDirectDraw7 *ddraw)
109 DDDEVICEIDENTIFIER2 identifier;
110 HRESULT hr;
112 if (!strcmp(winetest_platform, "wine"))
113 return FALSE;
115 hr = IDirectDraw7_GetDeviceIdentifier(ddraw, &identifier, 0);
116 ok(SUCCEEDED(hr), "Failed to get device identifier, hr %#x.\n", hr);
118 return !!strstr(identifier.szDriver, "warp");
121 static BOOL ddraw_is_nvidia(IDirectDraw7 *ddraw)
123 DDDEVICEIDENTIFIER2 identifier;
124 HRESULT hr;
126 if (!strcmp(winetest_platform, "wine"))
127 return FALSE;
129 hr = IDirectDraw7_GetDeviceIdentifier(ddraw, &identifier, 0);
130 ok(SUCCEEDED(hr), "Failed to get device identifier, hr %#x.\n", hr);
132 return identifier.dwVendorId == 0x10de;
135 static BOOL ddraw_is_intel(IDirectDraw7 *ddraw)
137 DDDEVICEIDENTIFIER2 identifier;
138 HRESULT hr;
140 if (!strcmp(winetest_platform, "wine"))
141 return FALSE;
143 hr = IDirectDraw7_GetDeviceIdentifier(ddraw, &identifier, 0);
144 ok(SUCCEEDED(hr), "Failed to get device identifier, hr %#x.\n", hr);
146 return identifier.dwVendorId == 0x8086;
149 static IDirectDrawSurface7 *create_overlay(IDirectDraw7 *ddraw,
150 unsigned int width, unsigned int height, DWORD format)
152 IDirectDrawSurface7 *surface;
153 DDSURFACEDESC2 desc;
155 memset(&desc, 0, sizeof(desc));
156 desc.dwSize = sizeof(desc);
157 desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
158 desc.dwWidth = width;
159 desc.dwHeight = height;
160 desc.ddsCaps.dwCaps = DDSCAPS_OVERLAY;
161 U4(desc).ddpfPixelFormat.dwSize = sizeof(U4(desc).ddpfPixelFormat);
162 U4(desc).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
163 U4(desc).ddpfPixelFormat.dwFourCC = format;
165 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &desc, &surface, NULL)))
166 return NULL;
167 return surface;
170 static DWORD WINAPI create_window_thread_proc(void *param)
172 struct create_window_thread_param *p = param;
173 DWORD res;
174 BOOL ret;
176 p->window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
177 0, 0, 640, 480, 0, 0, 0, 0);
178 ret = SetEvent(p->window_created);
179 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
181 for (;;)
183 MSG msg;
185 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
186 DispatchMessageA(&msg);
187 res = WaitForSingleObject(p->destroy_window, 100);
188 if (res == WAIT_OBJECT_0)
189 break;
190 if (res != WAIT_TIMEOUT)
192 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
193 break;
197 DestroyWindow(p->window);
199 return 0;
202 static void create_window_thread(struct create_window_thread_param *p)
204 DWORD res, tid;
206 p->window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
207 ok(!!p->window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
208 p->destroy_window = CreateEventA(NULL, FALSE, FALSE, NULL);
209 ok(!!p->destroy_window, "CreateEvent failed, last error %#x.\n", GetLastError());
210 p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
211 ok(!!p->thread, "Failed to create thread, last error %#x.\n", GetLastError());
212 res = WaitForSingleObject(p->window_created, INFINITE);
213 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
216 static void destroy_window_thread(struct create_window_thread_param *p)
218 SetEvent(p->destroy_window);
219 WaitForSingleObject(p->thread, INFINITE);
220 CloseHandle(p->destroy_window);
221 CloseHandle(p->window_created);
222 CloseHandle(p->thread);
225 static IDirectDrawSurface7 *get_depth_stencil(IDirect3DDevice7 *device)
227 IDirectDrawSurface7 *rt, *ret;
228 DDSCAPS2 caps = {DDSCAPS_ZBUFFER, 0, 0, {0}};
229 HRESULT hr;
231 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
232 ok(SUCCEEDED(hr), "Failed to get the render target, hr %#x.\n", hr);
233 hr = IDirectDrawSurface7_GetAttachedSurface(rt, &caps, &ret);
234 ok(SUCCEEDED(hr) || hr == DDERR_NOTFOUND, "Failed to get the z buffer, hr %#x.\n", hr);
235 IDirectDrawSurface7_Release(rt);
236 return ret;
239 static HRESULT set_display_mode(IDirectDraw7 *ddraw, DWORD width, DWORD height)
241 if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
242 return DD_OK;
243 return IDirectDraw7_SetDisplayMode(ddraw, width, height, 24, 0, 0);
246 static D3DCOLOR get_surface_color(IDirectDrawSurface7 *surface, UINT x, UINT y)
248 RECT rect = {x, y, x + 1, y + 1};
249 DDSURFACEDESC2 surface_desc;
250 D3DCOLOR color;
251 HRESULT hr;
253 memset(&surface_desc, 0, sizeof(surface_desc));
254 surface_desc.dwSize = sizeof(surface_desc);
256 hr = IDirectDrawSurface7_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY, NULL);
257 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
258 if (FAILED(hr))
259 return 0xdeadbeef;
261 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
263 hr = IDirectDrawSurface7_Unlock(surface, &rect);
264 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
266 return color;
269 static HRESULT CALLBACK enum_z_fmt(DDPIXELFORMAT *format, void *ctx)
271 DDPIXELFORMAT *z_fmt = ctx;
273 if (U1(*format).dwZBufferBitDepth > U1(*z_fmt).dwZBufferBitDepth)
274 *z_fmt = *format;
276 return DDENUMRET_OK;
279 static IDirectDraw7 *create_ddraw(void)
281 IDirectDraw7 *ddraw;
283 if (FAILED(pDirectDrawCreateEx(NULL, (void **)&ddraw, &IID_IDirectDraw7, NULL)))
284 return NULL;
286 return ddraw;
289 static HRESULT WINAPI enum_devtype_cb(char *desc_str, char *name, D3DDEVICEDESC7 *desc, void *ctx)
291 BOOL *hal_ok = ctx;
292 if (IsEqualGUID(&desc->deviceGUID, &IID_IDirect3DTnLHalDevice))
294 *hal_ok = TRUE;
295 return DDENUMRET_CANCEL;
297 return DDENUMRET_OK;
300 static IDirect3DDevice7 *create_device(HWND window, DWORD coop_level)
302 IDirectDrawSurface7 *surface, *ds;
303 IDirect3DDevice7 *device = NULL;
304 DDSURFACEDESC2 surface_desc;
305 DDPIXELFORMAT z_fmt;
306 IDirectDraw7 *ddraw;
307 IDirect3D7 *d3d7;
308 HRESULT hr;
309 BOOL hal_ok = FALSE;
310 const GUID *devtype = &IID_IDirect3DHALDevice;
312 if (!(ddraw = create_ddraw()))
313 return NULL;
315 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, coop_level);
316 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
318 memset(&surface_desc, 0, sizeof(surface_desc));
319 surface_desc.dwSize = sizeof(surface_desc);
320 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
321 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
322 surface_desc.dwWidth = 640;
323 surface_desc.dwHeight = 480;
325 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
326 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
328 if (coop_level & DDSCL_NORMAL)
330 IDirectDrawClipper *clipper;
332 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
333 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
334 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
335 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
336 hr = IDirectDrawSurface7_SetClipper(surface, clipper);
337 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\n", hr);
338 IDirectDrawClipper_Release(clipper);
341 hr = IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d7);
342 IDirectDraw7_Release(ddraw);
343 if (FAILED(hr))
345 IDirectDrawSurface7_Release(surface);
346 return NULL;
349 hr = IDirect3D7_EnumDevices(d3d7, enum_devtype_cb, &hal_ok);
350 ok(SUCCEEDED(hr), "Failed to enumerate devices, hr %#x.\n", hr);
351 if (hal_ok) devtype = &IID_IDirect3DTnLHalDevice;
353 memset(&z_fmt, 0, sizeof(z_fmt));
354 hr = IDirect3D7_EnumZBufferFormats(d3d7, devtype, enum_z_fmt, &z_fmt);
355 if (FAILED(hr) || !z_fmt.dwSize)
357 IDirect3D7_Release(d3d7);
358 IDirectDrawSurface7_Release(surface);
359 return NULL;
362 memset(&surface_desc, 0, sizeof(surface_desc));
363 surface_desc.dwSize = sizeof(surface_desc);
364 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
365 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
366 U4(surface_desc).ddpfPixelFormat = z_fmt;
367 surface_desc.dwWidth = 640;
368 surface_desc.dwHeight = 480;
369 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL);
370 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
371 if (FAILED(hr))
373 IDirect3D7_Release(d3d7);
374 IDirectDrawSurface7_Release(surface);
375 return NULL;
378 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
379 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
380 IDirectDrawSurface7_Release(ds);
381 if (FAILED(hr))
383 IDirect3D7_Release(d3d7);
384 IDirectDrawSurface7_Release(surface);
385 return NULL;
388 hr = IDirect3D7_CreateDevice(d3d7, devtype, surface, &device);
389 IDirect3D7_Release(d3d7);
390 IDirectDrawSurface7_Release(surface);
391 if (FAILED(hr))
392 return NULL;
394 return device;
397 struct message
399 UINT message;
400 BOOL check_wparam;
401 WPARAM expect_wparam;
404 static const struct message *expect_messages;
406 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
408 if (expect_messages && message == expect_messages->message)
410 if (expect_messages->check_wparam)
411 ok (wparam == expect_messages->expect_wparam,
412 "Got unexpected wparam %lx for message %x, expected %lx.\n",
413 wparam, message, expect_messages->expect_wparam);
415 ++expect_messages;
418 return DefWindowProcA(hwnd, message, wparam, lparam);
421 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
422 * interface. This prevents subsequent SetCooperativeLevel() calls on a
423 * different window from failing with DDERR_HWNDALREADYSET. */
424 static void fix_wndproc(HWND window, LONG_PTR proc)
426 IDirectDraw7 *ddraw;
427 HRESULT hr;
429 if (!(ddraw = create_ddraw()))
430 return;
432 SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
433 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
434 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
435 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
436 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
438 IDirectDraw7_Release(ddraw);
441 static void test_process_vertices(void)
443 IDirect3DVertexBuffer7 *src_vb, *dst_vb1, *dst_vb2;
444 D3DVERTEXBUFFERDESC vb_desc;
445 IDirect3DDevice7 *device;
446 struct vec4 *dst_data;
447 struct vec3 *dst_data2;
448 struct vec3 *src_data;
449 IDirect3D7 *d3d7;
450 D3DVIEWPORT7 vp;
451 HWND window;
452 HRESULT hr;
454 static D3DMATRIX world =
456 0.0f, 1.0f, 0.0f, 0.0f,
457 1.0f, 0.0f, 0.0f, 0.0f,
458 0.0f, 0.0f, 0.0f, 1.0f,
459 0.0f, 1.0f, 1.0f, 1.0f,
461 static D3DMATRIX view =
463 2.0f, 0.0f, 0.0f, 0.0f,
464 0.0f, -1.0f, 0.0f, 0.0f,
465 0.0f, 0.0f, 1.0f, 0.0f,
466 0.0f, 0.0f, 0.0f, 3.0f,
468 static D3DMATRIX proj =
470 1.0f, 0.0f, 0.0f, 1.0f,
471 0.0f, 1.0f, 1.0f, 0.0f,
472 0.0f, 1.0f, 1.0f, 0.0f,
473 1.0f, 0.0f, 0.0f, 1.0f,
476 window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
477 0, 0, 640, 480, 0, 0, 0, 0);
478 if (!(device = create_device(window, DDSCL_NORMAL)))
480 skip("Failed to create a 3D device, skipping test.\n");
481 DestroyWindow(window);
482 return;
485 hr = IDirect3DDevice7_GetDirect3D(device, &d3d7);
486 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
488 memset(&vb_desc, 0, sizeof(vb_desc));
489 vb_desc.dwSize = sizeof(vb_desc);
490 vb_desc.dwFVF = D3DFVF_XYZ;
491 vb_desc.dwNumVertices = 4;
492 hr = IDirect3D7_CreateVertexBuffer(d3d7, &vb_desc, &src_vb, 0);
493 ok(SUCCEEDED(hr), "Failed to create source vertex buffer, hr %#x.\n", hr);
495 hr = IDirect3DVertexBuffer7_Lock(src_vb, 0, (void **)&src_data, NULL);
496 ok(SUCCEEDED(hr), "Failed to lock source vertex buffer, hr %#x.\n", hr);
497 src_data[0].x = 0.0f;
498 src_data[0].y = 0.0f;
499 src_data[0].z = 0.0f;
500 src_data[1].x = 1.0f;
501 src_data[1].y = 1.0f;
502 src_data[1].z = 1.0f;
503 src_data[2].x = -1.0f;
504 src_data[2].y = -1.0f;
505 src_data[2].z = 0.5f;
506 src_data[3].x = 0.5f;
507 src_data[3].y = -0.5f;
508 src_data[3].z = 0.25f;
509 hr = IDirect3DVertexBuffer7_Unlock(src_vb);
510 ok(SUCCEEDED(hr), "Failed to unlock source vertex buffer, hr %#x.\n", hr);
512 memset(&vb_desc, 0, sizeof(vb_desc));
513 vb_desc.dwSize = sizeof(vb_desc);
514 vb_desc.dwFVF = D3DFVF_XYZRHW;
515 vb_desc.dwNumVertices = 4;
516 /* MSDN says that the last parameter must be 0 - check that. */
517 hr = IDirect3D7_CreateVertexBuffer(d3d7, &vb_desc, &dst_vb1, 4);
518 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
520 memset(&vb_desc, 0, sizeof(vb_desc));
521 vb_desc.dwSize = sizeof(vb_desc);
522 vb_desc.dwFVF = D3DFVF_XYZ;
523 vb_desc.dwNumVertices = 5;
524 /* MSDN says that the last parameter must be 0 - check that. */
525 hr = IDirect3D7_CreateVertexBuffer(d3d7, &vb_desc, &dst_vb2, 12345678);
526 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
528 memset(&vp, 0, sizeof(vp));
529 vp.dwX = 64;
530 vp.dwY = 64;
531 vp.dwWidth = 128;
532 vp.dwHeight = 128;
533 vp.dvMinZ = 0.0f;
534 vp.dvMaxZ = 1.0f;
535 hr = IDirect3DDevice7_SetViewport(device, &vp);
536 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
538 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
539 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
540 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb2, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
541 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
543 hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
544 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
545 ok(compare_vec4(&dst_data[0], +1.280e+2f, +1.280e+2f, +0.000e+0f, +1.000e+0f, 4096),
546 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
547 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
548 ok(compare_vec4(&dst_data[1], +1.920e+2f, +6.400e+1f, +1.000e+0f, +1.000e+0f, 4096),
549 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
550 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
551 ok(compare_vec4(&dst_data[2], +6.400e+1f, +1.920e+2f, +5.000e-1f, +1.000e+0f, 4096),
552 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
553 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
554 ok(compare_vec4(&dst_data[3], +1.600e+2f, +1.600e+2f, +2.500e-1f, +1.000e+0f, 4096),
555 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
556 dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
557 hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
558 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
560 hr = IDirect3DVertexBuffer7_Lock(dst_vb2, 0, (void **)&dst_data2, NULL);
561 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
562 /* Small thing without much practical meaning, but I stumbled upon it,
563 * so let's check for it: If the output vertex buffer has no RHW value,
564 * the RHW value of the last vertex is written into the next vertex. */
565 ok(compare_vec3(&dst_data2[4], +1.000e+0f, +0.000e+0f, +0.000e+0f, 4096),
566 "Got unexpected vertex 4 {%.8e, %.8e, %.8e}.\n",
567 dst_data2[4].x, dst_data2[4].y, dst_data2[4].z);
568 hr = IDirect3DVertexBuffer7_Unlock(dst_vb2);
569 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
571 /* Try a more complicated viewport, same vertices. */
572 memset(&vp, 0, sizeof(vp));
573 vp.dwX = 10;
574 vp.dwY = 5;
575 vp.dwWidth = 246;
576 vp.dwHeight = 130;
577 vp.dvMinZ = -2.0f;
578 vp.dvMaxZ = 4.0f;
579 hr = IDirect3DDevice7_SetViewport(device, &vp);
580 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
582 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
583 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
585 hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
586 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
587 ok(compare_vec4(&dst_data[0], +1.330e+2f, +7.000e+1f, -2.000e+0f, +1.000e+0f, 4096),
588 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
589 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
590 ok(compare_vec4(&dst_data[1], +2.560e+2f, +5.000e+0f, +4.000e+0f, +1.000e+0f, 4096),
591 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
592 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
593 ok(compare_vec4(&dst_data[2], +1.000e+1f, +1.350e+2f, +1.000e+0f, +1.000e+0f, 4096),
594 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
595 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
596 ok(compare_vec4(&dst_data[3], +1.945e+2f, +1.025e+2f, -5.000e-1f, +1.000e+0f, 4096),
597 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
598 dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
599 hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
600 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
602 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &world);
603 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
604 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &view);
605 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
606 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &proj);
607 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
609 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
610 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
612 hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
613 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
614 ok(compare_vec4(&dst_data[0], +2.560e+2f, +7.000e+1f, -2.000e+0f, +3.333e-1f, 4096),
615 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
616 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
617 ok(compare_vec4(&dst_data[1], +2.560e+2f, +7.813e+1f, -2.750e+0f, +1.250e-1f, 4096),
618 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
619 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
620 ok(compare_vec4(&dst_data[2], +2.560e+2f, +4.400e+1f, +4.000e-1f, +4.000e-1f, 4096),
621 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
622 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
623 ok(compare_vec4(&dst_data[3], +2.560e+2f, +8.182e+1f, -3.091e+0f, +3.636e-1f, 4096),
624 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
625 dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
626 hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
627 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
629 IDirect3DVertexBuffer7_Release(dst_vb2);
630 IDirect3DVertexBuffer7_Release(dst_vb1);
631 IDirect3DVertexBuffer7_Release(src_vb);
632 IDirect3D7_Release(d3d7);
633 IDirect3DDevice7_Release(device);
634 DestroyWindow(window);
637 static void test_coop_level_create_device_window(void)
639 HWND focus_window, device_window;
640 IDirectDraw7 *ddraw;
641 HRESULT hr;
643 focus_window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
644 0, 0, 640, 480, 0, 0, 0, 0);
645 ddraw = create_ddraw();
646 ok(!!ddraw, "Failed to create a ddraw object.\n");
648 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
649 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
650 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
651 ok(!device_window, "Unexpected device window found.\n");
652 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
653 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
654 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
655 ok(!device_window, "Unexpected device window found.\n");
656 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
657 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
658 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
659 ok(!device_window, "Unexpected device window found.\n");
660 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
661 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
662 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
663 ok(!device_window, "Unexpected device window found.\n");
664 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
665 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
666 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
667 ok(!device_window, "Unexpected device window found.\n");
669 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
670 if (broken(hr == DDERR_INVALIDPARAMS))
672 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
673 IDirectDraw7_Release(ddraw);
674 DestroyWindow(focus_window);
675 return;
678 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
679 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
680 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
681 ok(!device_window, "Unexpected device window found.\n");
682 hr = IDirectDraw7_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
683 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
684 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
685 ok(!device_window, "Unexpected device window found.\n");
687 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
688 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
689 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
690 ok(!device_window, "Unexpected device window found.\n");
691 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
692 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
693 ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
694 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
695 ok(!!device_window, "Device window not found.\n");
697 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
698 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
699 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
700 ok(!device_window, "Unexpected device window found.\n");
701 hr = IDirectDraw7_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
702 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
703 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
704 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
705 ok(!!device_window, "Device window not found.\n");
707 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
708 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
709 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
710 ok(!device_window, "Unexpected device window found.\n");
711 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
712 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
713 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
714 ok(!device_window, "Unexpected device window found.\n");
715 hr = IDirectDraw7_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
716 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
717 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
718 ok(!device_window, "Unexpected device window found.\n");
719 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
720 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
721 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
722 ok(!!device_window, "Device window not found.\n");
724 IDirectDraw7_Release(ddraw);
725 DestroyWindow(focus_window);
728 static void test_clipper_blt(void)
730 IDirectDrawSurface7 *src_surface, *dst_surface;
731 RECT client_rect, src_rect;
732 IDirectDrawClipper *clipper;
733 DDSURFACEDESC2 surface_desc;
734 unsigned int i, j, x, y;
735 IDirectDraw7 *ddraw;
736 RGNDATA *rgn_data;
737 D3DCOLOR color;
738 ULONG refcount;
739 HRGN r1, r2;
740 HWND window;
741 DDBLTFX fx;
742 HRESULT hr;
743 DWORD *ptr;
744 DWORD ret;
746 static const DWORD src_data[] =
748 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
749 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
750 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
752 static const D3DCOLOR expected1[] =
754 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
755 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
756 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
757 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
759 /* Nvidia on Windows seems to have an off-by-one error
760 * when processing source rectangles. Our left = 1 and
761 * right = 5 input reads from x = {1, 2, 3}. x = 4 is
762 * read as well, but only for the edge pixels on the
763 * output image. The bug happens on the y axis as well,
764 * but we only read one row there, and all source rows
765 * contain the same data. This bug is not dependent on
766 * the presence of a clipper. */
767 static const D3DCOLOR expected1_broken[] =
769 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
770 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
771 0x00000000, 0x00000000, 0x00ff0000, 0x00ff0000,
772 0x00000000, 0x00000000, 0x0000ff00, 0x00ff0000,
774 static const D3DCOLOR expected2[] =
776 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
777 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
778 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
779 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
782 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
783 10, 10, 640, 480, 0, 0, 0, 0);
784 ShowWindow(window, SW_SHOW);
785 ddraw = create_ddraw();
786 ok(!!ddraw, "Failed to create a ddraw object.\n");
788 ret = GetClientRect(window, &client_rect);
789 ok(ret, "Failed to get client rect.\n");
790 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
791 ok(ret, "Failed to map client rect.\n");
793 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
794 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
796 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
797 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
798 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
799 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
800 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
801 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
802 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
803 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
804 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
805 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
806 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
807 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
808 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
809 ok(rgn_data->rdh.nCount >= 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
810 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
811 "Got unexpected bounding rect %s, expected %s.\n",
812 wine_dbgstr_rect(&rgn_data->rdh.rcBound), wine_dbgstr_rect(&client_rect));
813 HeapFree(GetProcessHeap(), 0, rgn_data);
815 r1 = CreateRectRgn(0, 0, 320, 240);
816 ok(!!r1, "Failed to create region.\n");
817 r2 = CreateRectRgn(320, 240, 640, 480);
818 ok(!!r2, "Failed to create region.\n");
819 CombineRgn(r1, r1, r2, RGN_OR);
820 ret = GetRegionData(r1, 0, NULL);
821 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
822 ret = GetRegionData(r1, ret, rgn_data);
823 ok(!!ret, "Failed to get region data.\n");
825 DeleteObject(r2);
826 DeleteObject(r1);
828 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
829 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
830 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
831 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
832 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
833 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
835 HeapFree(GetProcessHeap(), 0, rgn_data);
837 memset(&surface_desc, 0, sizeof(surface_desc));
838 surface_desc.dwSize = sizeof(surface_desc);
839 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
840 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
841 surface_desc.dwWidth = 640;
842 surface_desc.dwHeight = 480;
843 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
844 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
845 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
846 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
847 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
848 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
850 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
851 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
852 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
853 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
855 memset(&fx, 0, sizeof(fx));
856 fx.dwSize = sizeof(fx);
857 hr = IDirectDrawSurface7_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
858 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
859 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
860 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
862 hr = IDirectDrawSurface7_Lock(src_surface, NULL, &surface_desc, 0, NULL);
863 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
864 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
865 ptr = surface_desc.lpSurface;
866 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
867 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
868 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
869 hr = IDirectDrawSurface7_Unlock(src_surface, NULL);
870 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
872 hr = IDirectDrawSurface7_SetClipper(dst_surface, clipper);
873 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
875 SetRect(&src_rect, 1, 1, 5, 2);
876 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
877 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
878 for (i = 0; i < 4; ++i)
880 for (j = 0; j < 4; ++j)
882 x = 80 * ((2 * j) + 1);
883 y = 60 * ((2 * i) + 1);
884 color = get_surface_color(dst_surface, x, y);
885 ok(compare_color(color, expected1[i * 4 + j], 1)
886 || broken(compare_color(color, expected1_broken[i * 4 + j], 1)),
887 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
891 U5(fx).dwFillColor = 0xff0000ff;
892 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
893 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
894 for (i = 0; i < 4; ++i)
896 for (j = 0; j < 4; ++j)
898 x = 80 * ((2 * j) + 1);
899 y = 60 * ((2 * i) + 1);
900 color = get_surface_color(dst_surface, x, y);
901 ok(compare_color(color, expected2[i * 4 + j], 1),
902 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
906 hr = IDirectDrawSurface7_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
907 ok(hr == DDERR_BLTFASTCANTCLIP, "Got unexpected hr %#x.\n", hr);
909 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
910 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
911 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
912 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
913 DestroyWindow(window);
914 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
915 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
916 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
917 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
918 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
919 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
920 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
921 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
922 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
923 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
924 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
925 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
927 IDirectDrawSurface7_Release(dst_surface);
928 IDirectDrawSurface7_Release(src_surface);
929 refcount = IDirectDrawClipper_Release(clipper);
930 ok(!refcount, "Clipper has %u references left.\n", refcount);
931 IDirectDraw7_Release(ddraw);
934 static void test_coop_level_d3d_state(void)
936 IDirectDrawSurface7 *rt, *surface;
937 IDirect3DDevice7 *device;
938 IDirectDraw7 *ddraw;
939 IDirect3D7 *d3d;
940 D3DCOLOR color;
941 DWORD value;
942 HWND window;
943 HRESULT hr;
945 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
946 0, 0, 640, 480, 0, 0, 0, 0);
947 if (!(device = create_device(window, DDSCL_NORMAL)))
949 skip("Failed to create a 3D device, skipping test.\n");
950 DestroyWindow(window);
951 return;
954 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
955 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
956 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
957 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
958 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
959 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
960 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
961 ok(!value, "Got unexpected alpha blend enable state %#x.\n", value);
962 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
963 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
964 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
965 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
966 color = get_surface_color(rt, 320, 240);
967 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
969 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
970 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
971 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
972 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
973 IDirect3D7_Release(d3d);
974 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
975 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
976 hr = IDirectDrawSurface7_IsLost(rt);
977 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
978 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
979 ok(SUCCEEDED(hr), "Failed to restore surfaces, hr %#x.\n", hr);
980 IDirectDraw7_Release(ddraw);
982 hr = IDirect3DDevice7_GetRenderTarget(device, &surface);
983 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
984 ok(surface == rt, "Got unexpected surface %p.\n", surface);
985 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
986 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
987 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
988 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
989 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
990 ok(!!value, "Got unexpected alpha blend enable state %#x.\n", value);
991 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
992 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
993 color = get_surface_color(rt, 320, 240);
994 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
996 IDirectDrawSurface7_Release(surface);
997 IDirectDrawSurface7_Release(rt);
998 IDirect3DDevice7_Release(device);
999 DestroyWindow(window);
1002 static void test_surface_interface_mismatch(void)
1004 IDirectDraw7 *ddraw = NULL;
1005 IDirect3D7 *d3d = NULL;
1006 IDirectDrawSurface7 *surface = NULL, *ds;
1007 IDirectDrawSurface3 *surface3 = NULL;
1008 IDirect3DDevice7 *device = NULL;
1009 DDSURFACEDESC2 surface_desc;
1010 DDPIXELFORMAT z_fmt;
1011 ULONG refcount;
1012 HRESULT hr;
1013 D3DCOLOR color;
1014 HWND window;
1016 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1017 0, 0, 640, 480, 0, 0, 0, 0);
1018 ddraw = create_ddraw();
1019 ok(!!ddraw, "Failed to create a ddraw object.\n");
1020 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1021 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1023 memset(&surface_desc, 0, sizeof(surface_desc));
1024 surface_desc.dwSize = sizeof(surface_desc);
1025 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1026 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
1027 surface_desc.dwWidth = 640;
1028 surface_desc.dwHeight = 480;
1030 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1031 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1033 hr = IDirectDrawSurface7_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
1034 ok(SUCCEEDED(hr), "Failed to QI IDirectDrawSurface3, hr %#x.\n", hr);
1036 if (FAILED(IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d)))
1038 skip("D3D interface is not available, skipping test.\n");
1039 goto cleanup;
1042 memset(&z_fmt, 0, sizeof(z_fmt));
1043 hr = IDirect3D7_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
1044 if (FAILED(hr) || !z_fmt.dwSize)
1046 skip("No depth buffer formats available, skipping test.\n");
1047 goto cleanup;
1050 memset(&surface_desc, 0, sizeof(surface_desc));
1051 surface_desc.dwSize = sizeof(surface_desc);
1052 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
1053 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1054 U4(surface_desc).ddpfPixelFormat = z_fmt;
1055 surface_desc.dwWidth = 640;
1056 surface_desc.dwHeight = 480;
1057 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL);
1058 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
1059 if (FAILED(hr))
1060 goto cleanup;
1062 /* Using a different surface interface version still works */
1063 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
1064 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
1065 refcount = IDirectDrawSurface7_Release(ds);
1066 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
1067 if (FAILED(hr))
1068 goto cleanup;
1070 /* Here too */
1071 hr = IDirect3D7_CreateDevice(d3d, &IID_IDirect3DHALDevice, (IDirectDrawSurface7 *)surface3, &device);
1072 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
1073 if (FAILED(hr))
1074 goto cleanup;
1076 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
1077 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1078 color = get_surface_color(surface, 320, 240);
1079 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1081 cleanup:
1082 if (surface3) IDirectDrawSurface3_Release(surface3);
1083 if (surface) IDirectDrawSurface7_Release(surface);
1084 if (device) IDirect3DDevice7_Release(device);
1085 if (d3d) IDirect3D7_Release(d3d);
1086 if (ddraw) IDirectDraw7_Release(ddraw);
1087 DestroyWindow(window);
1090 static void test_coop_level_threaded(void)
1092 struct create_window_thread_param p;
1093 IDirectDraw7 *ddraw;
1094 HRESULT hr;
1096 ddraw = create_ddraw();
1097 ok(!!ddraw, "Failed to create a ddraw object.\n");
1098 create_window_thread(&p);
1100 hr = IDirectDraw7_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1101 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1103 IDirectDraw7_Release(ddraw);
1104 destroy_window_thread(&p);
1107 static void test_depth_blit(void)
1109 IDirect3DDevice7 *device;
1110 static struct
1112 float x, y, z;
1113 DWORD color;
1115 quad1[] =
1117 { -1.0, 1.0, 0.50f, 0xff00ff00},
1118 { 1.0, 1.0, 0.50f, 0xff00ff00},
1119 { -1.0, -1.0, 0.50f, 0xff00ff00},
1120 { 1.0, -1.0, 0.50f, 0xff00ff00},
1122 static const D3DCOLOR expected_colors[4][4] =
1124 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1125 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1126 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1127 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1129 DDSURFACEDESC2 ddsd_new, ddsd_existing;
1131 IDirectDrawSurface7 *ds1, *ds2, *ds3, *rt;
1132 RECT src_rect, dst_rect;
1133 unsigned int i, j;
1134 D3DCOLOR color;
1135 HRESULT hr;
1136 IDirect3D7 *d3d;
1137 IDirectDraw7 *ddraw;
1138 DDBLTFX fx;
1139 HWND window;
1141 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1142 0, 0, 640, 480, 0, 0, 0, 0);
1143 if (!(device = create_device(window, DDSCL_NORMAL)))
1145 skip("Failed to create a 3D device, skipping test.\n");
1146 DestroyWindow(window);
1147 return;
1150 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1151 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
1152 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1153 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
1154 IDirect3D7_Release(d3d);
1156 ds1 = get_depth_stencil(device);
1158 memset(&ddsd_new, 0, sizeof(ddsd_new));
1159 ddsd_new.dwSize = sizeof(ddsd_new);
1160 memset(&ddsd_existing, 0, sizeof(ddsd_existing));
1161 ddsd_existing.dwSize = sizeof(ddsd_existing);
1162 hr = IDirectDrawSurface7_GetSurfaceDesc(ds1, &ddsd_existing);
1163 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
1164 ddsd_new.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1165 ddsd_new.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1166 ddsd_new.dwWidth = ddsd_existing.dwWidth;
1167 ddsd_new.dwHeight = ddsd_existing.dwHeight;
1168 U4(ddsd_new).ddpfPixelFormat = U4(ddsd_existing).ddpfPixelFormat;
1169 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd_new, &ds2, NULL);
1170 ok(SUCCEEDED(hr), "Failed to create a z buffer, hr %#x.\n", hr);
1171 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd_new, &ds3, NULL);
1172 ok(SUCCEEDED(hr), "Failed to create a z buffer, hr %#x.\n", hr);
1173 IDirectDraw7_Release(ddraw);
1175 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
1176 ok(SUCCEEDED(hr), "Failed to enable z testing, hr %#x.\n", hr);
1177 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
1178 ok(SUCCEEDED(hr), "Failed to set the z function, hr %#x.\n", hr);
1179 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
1180 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
1182 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
1183 ok(SUCCEEDED(hr), "Failed to clear the z buffer, hr %#x.\n", hr);
1185 /* Partial blit. */
1186 SetRect(&src_rect, 0, 0, 320, 240);
1187 SetRect(&dst_rect, 0, 0, 320, 240);
1188 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1189 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1190 /* Different locations. */
1191 SetRect(&src_rect, 0, 0, 320, 240);
1192 SetRect(&dst_rect, 320, 240, 640, 480);
1193 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1194 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1195 /* Stretched. */
1196 SetRect(&src_rect, 0, 0, 320, 240);
1197 SetRect(&dst_rect, 0, 0, 640, 480);
1198 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1199 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1200 /* Flipped. */
1201 SetRect(&src_rect, 0, 480, 640, 0);
1202 SetRect(&dst_rect, 0, 0, 640, 480);
1203 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1204 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1205 SetRect(&src_rect, 0, 0, 640, 480);
1206 SetRect(&dst_rect, 0, 480, 640, 0);
1207 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1208 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1209 /* Full, explicit. */
1210 SetRect(&src_rect, 0, 0, 640, 480);
1211 SetRect(&dst_rect, 0, 0, 640, 480);
1212 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1213 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1214 /* Depth -> color blit: Succeeds on Win7 + Radeon HD 5700, fails on WinXP + Radeon X1600 */
1216 /* Depth blit inside a BeginScene / EndScene pair */
1217 hr = IDirect3DDevice7_BeginScene(device);
1218 ok(SUCCEEDED(hr), "Failed to start scene, hr %#x.\n", hr);
1219 /* From the current depth stencil */
1220 hr = IDirectDrawSurface7_Blt(ds2, NULL, ds1, NULL, DDBLT_WAIT, NULL);
1221 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1222 /* To the current depth stencil */
1223 hr = IDirectDrawSurface7_Blt(ds1, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1224 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1225 /* Between unbound surfaces */
1226 hr = IDirectDrawSurface7_Blt(ds3, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1227 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1228 hr = IDirect3DDevice7_EndScene(device);
1229 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1231 /* Avoid changing the depth stencil, it doesn't work properly on Windows.
1232 * Instead use DDBLT_DEPTHFILL to clear the depth stencil. Unfortunately
1233 * drivers disagree on the meaning of dwFillDepth. Only 0 seems to produce
1234 * a reliable result(z = 0.0) */
1235 memset(&fx, 0, sizeof(fx));
1236 fx.dwSize = sizeof(fx);
1237 hr = IDirectDrawSurface7_Blt(ds2, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
1238 ok(SUCCEEDED(hr), "Failed to clear the source z buffer, hr %#x.\n", hr);
1240 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET, 0xffff0000, 1.0f, 0);
1241 ok(SUCCEEDED(hr), "Failed to clear the color and z buffers, hr %#x.\n", hr);
1242 SetRect(&dst_rect, 0, 0, 320, 240);
1243 hr = IDirectDrawSurface7_Blt(ds1, &dst_rect, ds2, NULL, DDBLT_WAIT, NULL);
1244 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1245 IDirectDrawSurface7_Release(ds3);
1246 IDirectDrawSurface7_Release(ds2);
1247 IDirectDrawSurface7_Release(ds1);
1249 hr = IDirect3DDevice7_BeginScene(device);
1250 ok(SUCCEEDED(hr), "Failed to start scene, hr %#x.\n", hr);
1251 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
1252 quad1, 4, 0);
1253 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1254 hr = IDirect3DDevice7_EndScene(device);
1255 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1257 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1258 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1259 for (i = 0; i < 4; ++i)
1261 for (j = 0; j < 4; ++j)
1263 unsigned int x = 80 * ((2 * j) + 1);
1264 unsigned int y = 60 * ((2 * i) + 1);
1265 color = get_surface_color(rt, x, y);
1266 ok(compare_color(color, expected_colors[i][j], 1),
1267 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
1271 IDirectDrawSurface7_Release(rt);
1272 IDirect3DDevice7_Release(device);
1273 DestroyWindow(window);
1276 static void test_texture_load_ckey(void)
1278 HWND window;
1279 IDirect3DDevice7 *device;
1280 IDirectDraw7 *ddraw;
1281 IDirectDrawSurface7 *src;
1282 IDirectDrawSurface7 *dst;
1283 DDSURFACEDESC2 ddsd;
1284 HRESULT hr;
1285 DDCOLORKEY ckey;
1286 IDirect3D7 *d3d;
1288 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1289 0, 0, 640, 480, 0, 0, 0, 0);
1290 if (!(device = create_device(window, DDSCL_NORMAL)))
1292 skip("Failed to create a 3D device, skipping test.\n");
1293 DestroyWindow(window);
1294 return;
1297 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1298 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
1299 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1300 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
1301 IDirect3D7_Release(d3d);
1303 memset(&ddsd, 0, sizeof(ddsd));
1304 ddsd.dwSize = sizeof(ddsd);
1305 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
1306 ddsd.dwHeight = 128;
1307 ddsd.dwWidth = 128;
1308 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
1309 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &src, NULL);
1310 ok(SUCCEEDED(hr), "Failed to create source texture, hr %#x.\n", hr);
1311 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1312 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &dst, NULL);
1313 ok(SUCCEEDED(hr), "Failed to create destination texture, hr %#x.\n", hr);
1315 /* No surface has a color key */
1316 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1317 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1318 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0xdeadbeef;
1319 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1320 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1321 ok(ckey.dwColorSpaceLowValue == 0xdeadbeef, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1322 ok(ckey.dwColorSpaceHighValue == 0xdeadbeef, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1324 /* Source surface has a color key */
1325 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
1326 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
1327 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1328 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1329 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1330 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1331 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1332 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1333 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1335 /* Both surfaces have a color key: Dest ckey is overwritten */
1336 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x000000ff;
1337 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1338 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1339 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1340 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1341 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1342 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1343 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1344 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1346 /* Only the destination has a color key: It is deleted. This behavior differs from
1347 * IDirect3DTexture(2)::Load */
1348 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, NULL);
1349 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1350 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
1351 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1352 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1353 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1354 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1355 todo_wine ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1357 IDirectDrawSurface7_Release(dst);
1358 IDirectDrawSurface7_Release(src);
1359 IDirectDraw7_Release(ddraw);
1360 IDirect3DDevice7_Release(device);
1361 DestroyWindow(window);
1364 static void test_zenable(void)
1366 static struct
1368 struct vec4 position;
1369 D3DCOLOR diffuse;
1371 tquad[] =
1373 {{ 0.0f, 480.0f, -0.5f, 1.0f}, 0xff00ff00},
1374 {{ 0.0f, 0.0f, -0.5f, 1.0f}, 0xff00ff00},
1375 {{640.0f, 480.0f, 1.5f, 1.0f}, 0xff00ff00},
1376 {{640.0f, 0.0f, 1.5f, 1.0f}, 0xff00ff00},
1378 IDirect3DDevice7 *device;
1379 IDirectDrawSurface7 *rt;
1380 D3DCOLOR color;
1381 HWND window;
1382 HRESULT hr;
1383 UINT x, y;
1384 UINT i, j;
1386 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1387 0, 0, 640, 480, 0, 0, 0, 0);
1388 if (!(device = create_device(window, DDSCL_NORMAL)))
1390 skip("Failed to create a 3D device, skipping test.\n");
1391 DestroyWindow(window);
1392 return;
1395 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1396 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
1398 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 0.0f, 0);
1399 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1400 hr = IDirect3DDevice7_BeginScene(device);
1401 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1402 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_DIFFUSE, tquad, 4, 0);
1403 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1404 hr = IDirect3DDevice7_EndScene(device);
1405 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1407 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1408 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1409 for (i = 0; i < 4; ++i)
1411 for (j = 0; j < 4; ++j)
1413 x = 80 * ((2 * j) + 1);
1414 y = 60 * ((2 * i) + 1);
1415 color = get_surface_color(rt, x, y);
1416 ok(compare_color(color, 0x0000ff00, 1),
1417 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1420 IDirectDrawSurface7_Release(rt);
1422 IDirect3DDevice7_Release(device);
1423 DestroyWindow(window);
1426 static void test_ck_rgba(void)
1428 static struct
1430 struct vec4 position;
1431 struct vec2 texcoord;
1433 tquad[] =
1435 {{ 0.0f, 480.0f, 0.25f, 1.0f}, {0.0f, 0.0f}},
1436 {{ 0.0f, 0.0f, 0.25f, 1.0f}, {0.0f, 1.0f}},
1437 {{640.0f, 480.0f, 0.25f, 1.0f}, {1.0f, 0.0f}},
1438 {{640.0f, 0.0f, 0.25f, 1.0f}, {1.0f, 1.0f}},
1439 {{ 0.0f, 480.0f, 0.75f, 1.0f}, {0.0f, 0.0f}},
1440 {{ 0.0f, 0.0f, 0.75f, 1.0f}, {0.0f, 1.0f}},
1441 {{640.0f, 480.0f, 0.75f, 1.0f}, {1.0f, 0.0f}},
1442 {{640.0f, 0.0f, 0.75f, 1.0f}, {1.0f, 1.0f}},
1444 static const struct
1446 D3DCOLOR fill_color;
1447 BOOL color_key;
1448 BOOL blend;
1449 D3DCOLOR result1, result1_broken;
1450 D3DCOLOR result2, result2_broken;
1452 tests[] =
1454 /* r200 on Windows doesn't check the alpha component when applying the color
1455 * key, so the key matches on every texel. */
1456 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1457 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1458 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1459 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1460 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00ff0000, 0x00807f00, 0x000000ff},
1461 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x00ff0000, 0x0000ff00, 0x000000ff},
1462 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00, 0x00807f00, 0x00807f00},
1463 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1466 IDirectDrawSurface7 *texture;
1467 DDSURFACEDESC2 surface_desc;
1468 IDirect3DDevice7 *device;
1469 IDirectDrawSurface7 *rt;
1470 IDirectDraw7 *ddraw;
1471 IDirect3D7 *d3d;
1472 D3DCOLOR color;
1473 HWND window;
1474 DDBLTFX fx;
1475 HRESULT hr;
1476 UINT i;
1478 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1479 0, 0, 640, 480, 0, 0, 0, 0);
1480 if (!(device = create_device(window, DDSCL_NORMAL)))
1482 skip("Failed to create a 3D device, skipping test.\n");
1483 DestroyWindow(window);
1484 return;
1487 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1488 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1489 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1490 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1491 IDirect3D7_Release(d3d);
1493 memset(&surface_desc, 0, sizeof(surface_desc));
1494 surface_desc.dwSize = sizeof(surface_desc);
1495 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1496 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1497 surface_desc.dwWidth = 256;
1498 surface_desc.dwHeight = 256;
1499 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1500 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1501 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1502 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1503 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1504 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1505 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1506 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1507 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1508 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
1509 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1511 hr = IDirect3DDevice7_SetTexture(device, 0, texture);
1512 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1513 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1514 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1515 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1516 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1518 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1519 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1521 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
1523 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1524 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1525 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1526 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1528 memset(&fx, 0, sizeof(fx));
1529 fx.dwSize = sizeof(fx);
1530 U5(fx).dwFillColor = tests[i].fill_color;
1531 hr = IDirectDrawSurface7_Blt(texture, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1532 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1534 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 1.0f, 0);
1535 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1536 hr = IDirect3DDevice7_BeginScene(device);
1537 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1538 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1539 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1540 hr = IDirect3DDevice7_EndScene(device);
1541 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1543 color = get_surface_color(rt, 320, 240);
1544 ok(compare_color(color, tests[i].result1, 1) || compare_color(color, tests[i].result1_broken, 1),
1545 "Expected color 0x%08x for test %u, got 0x%08x.\n",
1546 tests[i].result1, i, color);
1548 U5(fx).dwFillColor = 0xff0000ff;
1549 hr = IDirectDrawSurface7_Blt(texture, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1550 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1552 hr = IDirect3DDevice7_BeginScene(device);
1553 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1554 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[4], 4, 0);
1555 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1556 hr = IDirect3DDevice7_EndScene(device);
1557 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1559 /* This tests that fragments that are masked out by the color key are
1560 * discarded, instead of just fully transparent. */
1561 color = get_surface_color(rt, 320, 240);
1562 ok(compare_color(color, tests[i].result2, 1) || compare_color(color, tests[i].result2_broken, 1),
1563 "Expected color 0x%08x for test %u, got 0x%08x.\n",
1564 tests[i].result2, i, color);
1567 IDirectDrawSurface7_Release(rt);
1568 IDirectDrawSurface7_Release(texture);
1569 IDirectDraw7_Release(ddraw);
1570 IDirect3DDevice7_Release(device);
1571 DestroyWindow(window);
1574 static void test_ck_default(void)
1576 static struct
1578 struct vec4 position;
1579 struct vec2 texcoord;
1581 tquad[] =
1583 {{ 0.0f, 480.0f, 0.0f, 1.0f}, {0.0f, 0.0f}},
1584 {{ 0.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 1.0f}},
1585 {{640.0f, 480.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
1586 {{640.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
1588 IDirectDrawSurface7 *surface, *rt;
1589 DDSURFACEDESC2 surface_desc;
1590 IDirect3DDevice7 *device;
1591 IDirectDraw7 *ddraw;
1592 IDirect3D7 *d3d;
1593 D3DCOLOR color;
1594 DWORD value;
1595 HWND window;
1596 DDBLTFX fx;
1597 HRESULT hr;
1599 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1600 0, 0, 640, 480, 0, 0, 0, 0);
1602 if (!(device = create_device(window, DDSCL_NORMAL)))
1604 skip("Failed to create a 3D device, skipping test.\n");
1605 DestroyWindow(window);
1606 return;
1609 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1610 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1611 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1612 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1613 IDirect3D7_Release(d3d);
1615 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1616 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1618 memset(&surface_desc, 0, sizeof(surface_desc));
1619 surface_desc.dwSize = sizeof(surface_desc);
1620 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1621 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1622 surface_desc.dwWidth = 256;
1623 surface_desc.dwHeight = 256;
1624 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1625 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
1626 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1627 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1628 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1629 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1630 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
1631 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
1632 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1633 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1634 hr = IDirect3DDevice7_SetTexture(device, 0, surface);
1635 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1637 memset(&fx, 0, sizeof(fx));
1638 fx.dwSize = sizeof(fx);
1639 U5(fx).dwFillColor = 0x000000ff;
1640 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1641 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
1643 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
1644 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1645 hr = IDirect3DDevice7_BeginScene(device);
1646 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1647 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1648 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1649 ok(!value, "Got unexpected color keying state %#x.\n", value);
1650 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1651 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1652 hr = IDirect3DDevice7_EndScene(device);
1653 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1654 color = get_surface_color(rt, 320, 240);
1655 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1657 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
1658 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1659 hr = IDirect3DDevice7_BeginScene(device);
1660 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1661 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
1662 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1663 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1664 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1665 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1666 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1667 ok(!!value, "Got unexpected color keying state %#x.\n", value);
1668 hr = IDirect3DDevice7_EndScene(device);
1669 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1670 color = get_surface_color(rt, 320, 240);
1671 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1673 IDirectDrawSurface7_Release(surface);
1674 IDirectDrawSurface7_Release(rt);
1675 IDirect3DDevice7_Release(device);
1676 IDirectDraw7_Release(ddraw);
1677 DestroyWindow(window);
1680 static void test_ck_complex(void)
1682 IDirectDrawSurface7 *surface, *mipmap, *tmp;
1683 D3DDEVICEDESC7 device_desc;
1684 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
1685 DDSURFACEDESC2 surface_desc;
1686 IDirect3DDevice7 *device;
1687 DDCOLORKEY color_key;
1688 IDirectDraw7 *ddraw;
1689 IDirect3D7 *d3d;
1690 unsigned int i;
1691 ULONG refcount;
1692 HWND window;
1693 HRESULT hr;
1695 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1696 0, 0, 640, 480, 0, 0, 0, 0);
1697 if (!(device = create_device(window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
1699 skip("Failed to create a 3D device, skipping test.\n");
1700 DestroyWindow(window);
1701 return;
1703 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
1704 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
1705 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1706 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1707 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1708 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1709 IDirect3D7_Release(d3d);
1711 memset(&surface_desc, 0, sizeof(surface_desc));
1712 surface_desc.dwSize = sizeof(surface_desc);
1713 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1714 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1715 surface_desc.dwWidth = 128;
1716 surface_desc.dwHeight = 128;
1717 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1718 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1720 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1721 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1722 color_key.dwColorSpaceLowValue = 0x0000ff00;
1723 color_key.dwColorSpaceHighValue = 0x0000ff00;
1724 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1725 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1726 memset(&color_key, 0, sizeof(color_key));
1727 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1728 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1729 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1730 color_key.dwColorSpaceLowValue);
1731 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1732 color_key.dwColorSpaceHighValue);
1734 mipmap = surface;
1735 IDirectDrawSurface_AddRef(mipmap);
1736 for (i = 0; i < 7; ++i)
1738 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
1739 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
1740 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1741 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1743 color_key.dwColorSpaceLowValue = 0x000000ff;
1744 color_key.dwColorSpaceHighValue = 0x000000ff;
1745 hr = IDirectDrawSurface7_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1746 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x, i %u.\n", hr, i);
1748 IDirectDrawSurface_Release(mipmap);
1749 mipmap = tmp;
1752 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
1753 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
1754 IDirectDrawSurface_Release(mipmap);
1755 refcount = IDirectDrawSurface7_Release(surface);
1756 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1758 memset(&surface_desc, 0, sizeof(surface_desc));
1759 surface_desc.dwSize = sizeof(surface_desc);
1760 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
1761 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
1762 U5(surface_desc).dwBackBufferCount = 1;
1763 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1764 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1766 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1767 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1768 color_key.dwColorSpaceLowValue = 0x0000ff00;
1769 color_key.dwColorSpaceHighValue = 0x0000ff00;
1770 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1771 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1772 memset(&color_key, 0, sizeof(color_key));
1773 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1774 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1775 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1776 color_key.dwColorSpaceLowValue);
1777 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1778 color_key.dwColorSpaceHighValue);
1780 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &tmp);
1781 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
1783 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1784 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1785 color_key.dwColorSpaceLowValue = 0x0000ff00;
1786 color_key.dwColorSpaceHighValue = 0x0000ff00;
1787 hr = IDirectDrawSurface7_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1788 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1789 memset(&color_key, 0, sizeof(color_key));
1790 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1791 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1792 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1793 color_key.dwColorSpaceLowValue);
1794 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1795 color_key.dwColorSpaceHighValue);
1797 IDirectDrawSurface_Release(tmp);
1799 refcount = IDirectDrawSurface7_Release(surface);
1800 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1802 if (!(device_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP))
1804 skip("Device does not support cubemaps.\n");
1805 goto cleanup;
1807 memset(&surface_desc, 0, sizeof(surface_desc));
1808 surface_desc.dwSize = sizeof(surface_desc);
1809 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1810 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1811 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
1812 surface_desc.dwWidth = 128;
1813 surface_desc.dwHeight = 128;
1814 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1815 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1817 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1818 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1819 color_key.dwColorSpaceLowValue = 0x0000ff00;
1820 color_key.dwColorSpaceHighValue = 0x0000ff00;
1821 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1822 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1824 caps.dwCaps2 = DDSCAPS2_CUBEMAP_NEGATIVEZ;
1825 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
1826 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
1828 hr = IDirectDrawSurface7_GetColorKey(mipmap, DDCKEY_SRCBLT, &color_key);
1829 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1830 color_key.dwColorSpaceLowValue = 0x000000ff;
1831 color_key.dwColorSpaceHighValue = 0x000000ff;
1832 hr = IDirectDrawSurface7_SetColorKey(mipmap, DDCKEY_SRCBLT, &color_key);
1833 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1835 color_key.dwColorSpaceLowValue = 0;
1836 color_key.dwColorSpaceHighValue = 0;
1837 hr = IDirectDrawSurface7_GetColorKey(mipmap, DDCKEY_SRCBLT, &color_key);
1838 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1839 ok(color_key.dwColorSpaceLowValue == 0x000000ff, "Got unexpected value 0x%08x.\n",
1840 color_key.dwColorSpaceLowValue);
1841 ok(color_key.dwColorSpaceHighValue == 0x000000ff, "Got unexpected value 0x%08x.\n",
1842 color_key.dwColorSpaceHighValue);
1844 IDirectDrawSurface_AddRef(mipmap);
1845 for (i = 0; i < 7; ++i)
1847 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
1848 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
1849 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1850 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1852 color_key.dwColorSpaceLowValue = 0x000000ff;
1853 color_key.dwColorSpaceHighValue = 0x000000ff;
1854 hr = IDirectDrawSurface7_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1855 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x, i %u.\n", hr, i);
1857 IDirectDrawSurface_Release(mipmap);
1858 mipmap = tmp;
1861 IDirectDrawSurface7_Release(mipmap);
1863 refcount = IDirectDrawSurface7_Release(surface);
1864 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1866 cleanup:
1867 IDirectDraw7_Release(ddraw);
1868 refcount = IDirect3DDevice7_Release(device);
1869 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1870 DestroyWindow(window);
1873 struct qi_test
1875 REFIID iid;
1876 REFIID refcount_iid;
1877 HRESULT hr;
1880 static void test_qi(const char *test_name, IUnknown *base_iface,
1881 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
1883 ULONG refcount, expected_refcount;
1884 IUnknown *iface1, *iface2;
1885 HRESULT hr;
1886 UINT i, j;
1888 for (i = 0; i < entry_count; ++i)
1890 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
1891 ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
1892 if (SUCCEEDED(hr))
1894 for (j = 0; j < entry_count; ++j)
1896 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
1897 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
1898 if (SUCCEEDED(hr))
1900 expected_refcount = 0;
1901 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
1902 ++expected_refcount;
1903 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
1904 ++expected_refcount;
1905 refcount = IUnknown_Release(iface2);
1906 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
1907 refcount, test_name, i, j, expected_refcount);
1911 expected_refcount = 0;
1912 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
1913 ++expected_refcount;
1914 refcount = IUnknown_Release(iface1);
1915 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
1916 refcount, test_name, i, expected_refcount);
1921 static void test_surface_qi(void)
1923 static const struct qi_test tests[] =
1925 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
1926 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
1927 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
1928 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1929 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
1930 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
1931 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
1932 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
1933 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
1934 {&IID_IDirect3DDevice7, NULL, E_NOINTERFACE},
1935 {&IID_IDirect3DDevice3, NULL, E_NOINTERFACE},
1936 {&IID_IDirect3DDevice2, NULL, E_NOINTERFACE},
1937 {&IID_IDirect3DDevice, NULL, E_NOINTERFACE},
1938 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
1939 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
1940 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
1941 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
1942 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
1943 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
1944 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
1945 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
1946 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
1947 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
1948 {&IID_IDirect3D, NULL, E_NOINTERFACE},
1949 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
1950 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
1951 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
1952 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
1953 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
1954 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
1955 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
1956 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
1957 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
1958 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
1959 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
1960 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
1961 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
1962 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
1963 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
1964 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
1965 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
1966 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
1969 IDirectDrawSurface7 *surface;
1970 DDSURFACEDESC2 surface_desc;
1971 IDirect3DDevice7 *device;
1972 IDirectDraw7 *ddraw;
1973 HWND window;
1974 HRESULT hr;
1976 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1977 0, 0, 640, 480, 0, 0, 0, 0);
1978 /* Try to create a D3D device to see if the ddraw implementation supports
1979 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
1980 * doesn't support e.g. the IDirect3DTexture interfaces. */
1981 if (!(device = create_device(window, DDSCL_NORMAL)))
1983 skip("Failed to create a 3D device, skipping test.\n");
1984 DestroyWindow(window);
1985 return;
1987 IDirect3DDevice_Release(device);
1988 ddraw = create_ddraw();
1989 ok(!!ddraw, "Failed to create a ddraw object.\n");
1990 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1991 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1993 memset(&surface_desc, 0, sizeof(surface_desc));
1994 surface_desc.dwSize = sizeof(surface_desc);
1995 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1996 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1997 surface_desc.dwWidth = 512;
1998 surface_desc.dwHeight = 512;
1999 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, (IDirectDrawSurface7 **)0xdeadbeef, NULL);
2000 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
2001 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2002 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
2004 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface7, tests, sizeof(tests) / sizeof(*tests));
2006 IDirectDrawSurface7_Release(surface);
2007 IDirectDraw7_Release(ddraw);
2008 DestroyWindow(window);
2011 static void test_device_qi(void)
2013 static const struct qi_test tests[] =
2015 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
2016 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
2017 {&IID_IDirectDrawGammaControl, NULL, E_NOINTERFACE},
2018 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2019 {&IID_IDirectDrawSurface7, NULL, E_NOINTERFACE},
2020 {&IID_IDirectDrawSurface4, NULL, E_NOINTERFACE},
2021 {&IID_IDirectDrawSurface3, NULL, E_NOINTERFACE},
2022 {&IID_IDirectDrawSurface2, NULL, E_NOINTERFACE},
2023 {&IID_IDirectDrawSurface, NULL, E_NOINTERFACE},
2024 {&IID_IDirect3DDevice7, &IID_IDirect3DDevice7, S_OK },
2025 {&IID_IDirect3DDevice3, NULL, E_NOINTERFACE},
2026 {&IID_IDirect3DDevice2, NULL, E_NOINTERFACE},
2027 {&IID_IDirect3DDevice, NULL, E_NOINTERFACE},
2028 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
2029 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
2030 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
2031 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
2032 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
2033 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
2034 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
2035 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
2036 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
2037 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
2038 {&IID_IDirect3D, NULL, E_NOINTERFACE},
2039 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
2040 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
2041 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
2042 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
2043 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
2044 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
2045 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
2046 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
2047 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
2048 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
2049 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
2050 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
2051 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
2052 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
2053 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
2054 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
2055 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
2056 {&IID_IUnknown, &IID_IDirect3DDevice7, S_OK },
2059 IDirect3DDevice7 *device;
2060 HWND window;
2062 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2063 0, 0, 640, 480, 0, 0, 0, 0);
2064 if (!(device = create_device(window, DDSCL_NORMAL)))
2066 skip("Failed to create a 3D device, skipping test.\n");
2067 DestroyWindow(window);
2068 return;
2071 test_qi("device_qi", (IUnknown *)device, &IID_IDirect3DDevice7, tests, sizeof(tests) / sizeof(*tests));
2073 IDirect3DDevice7_Release(device);
2074 DestroyWindow(window);
2077 static void test_wndproc(void)
2079 LONG_PTR proc, ddraw_proc;
2080 IDirectDraw7 *ddraw;
2081 WNDCLASSA wc = {0};
2082 HWND window;
2083 HRESULT hr;
2084 ULONG ref;
2086 static struct message messages[] =
2088 {WM_WINDOWPOSCHANGING, FALSE, 0},
2089 {WM_MOVE, FALSE, 0},
2090 {WM_SIZE, FALSE, 0},
2091 {WM_WINDOWPOSCHANGING, FALSE, 0},
2092 {WM_ACTIVATE, FALSE, 0},
2093 {WM_SETFOCUS, FALSE, 0},
2094 {0, FALSE, 0},
2097 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
2098 ddraw = create_ddraw();
2099 ok(!!ddraw, "Failed to create a ddraw object.\n");
2101 wc.lpfnWndProc = test_proc;
2102 wc.lpszClassName = "ddraw_test_wndproc_wc";
2103 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2105 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
2106 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
2108 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2109 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2110 (LONG_PTR)test_proc, proc);
2111 expect_messages = messages;
2112 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2113 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2114 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2115 expect_messages = NULL;
2116 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2117 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2118 (LONG_PTR)test_proc, proc);
2119 ref = IDirectDraw7_Release(ddraw);
2120 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2121 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2122 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2123 (LONG_PTR)test_proc, proc);
2125 /* DDSCL_NORMAL doesn't. */
2126 ddraw = create_ddraw();
2127 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2128 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2129 (LONG_PTR)test_proc, proc);
2130 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2131 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2132 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2133 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2134 (LONG_PTR)test_proc, proc);
2135 ref = IDirectDraw7_Release(ddraw);
2136 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2137 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2138 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2139 (LONG_PTR)test_proc, proc);
2141 /* The original window proc is only restored by ddraw if the current
2142 * window proc matches the one ddraw set. This also affects switching
2143 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
2144 ddraw = create_ddraw();
2145 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2146 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2147 (LONG_PTR)test_proc, proc);
2148 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2149 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2150 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2151 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2152 (LONG_PTR)test_proc, proc);
2153 ddraw_proc = proc;
2154 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2155 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2156 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2157 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2158 (LONG_PTR)test_proc, proc);
2159 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2160 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2161 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2162 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2163 (LONG_PTR)test_proc, proc);
2164 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2165 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2166 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2167 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2168 (LONG_PTR)DefWindowProcA, proc);
2169 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2170 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2171 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc);
2172 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2173 (LONG_PTR)DefWindowProcA, proc);
2174 ref = IDirectDraw7_Release(ddraw);
2175 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2176 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2177 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2178 (LONG_PTR)test_proc, proc);
2180 ddraw = create_ddraw();
2181 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2182 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2183 (LONG_PTR)test_proc, proc);
2184 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2185 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2186 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2187 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2188 (LONG_PTR)test_proc, proc);
2189 ref = IDirectDraw7_Release(ddraw);
2190 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2191 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2192 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2193 (LONG_PTR)DefWindowProcA, proc);
2195 fix_wndproc(window, (LONG_PTR)test_proc);
2196 expect_messages = NULL;
2197 DestroyWindow(window);
2198 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2201 static void test_window_style(void)
2203 LONG style, exstyle, tmp, expected_style;
2204 RECT fullscreen_rect, r;
2205 IDirectDraw7 *ddraw;
2206 HWND window;
2207 HRESULT hr;
2208 ULONG ref;
2209 BOOL ret;
2211 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2212 0, 0, 100, 100, 0, 0, 0, 0);
2213 ddraw = create_ddraw();
2214 ok(!!ddraw, "Failed to create a ddraw object.\n");
2216 style = GetWindowLongA(window, GWL_STYLE);
2217 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
2218 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2220 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2221 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2223 tmp = GetWindowLongA(window, GWL_STYLE);
2224 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2225 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2226 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2228 GetWindowRect(window, &r);
2229 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
2230 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
2231 GetClientRect(window, &r);
2232 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2234 ret = SetForegroundWindow(GetDesktopWindow());
2235 ok(ret, "Failed to set foreground window.\n");
2237 tmp = GetWindowLongA(window, GWL_STYLE);
2238 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2239 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2240 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2242 ret = SetForegroundWindow(window);
2243 ok(ret, "Failed to set foreground window.\n");
2244 /* Windows 7 (but not Vista and XP) shows the window when it receives focus. Hide it again,
2245 * the next tests expect this. */
2246 ShowWindow(window, SW_HIDE);
2248 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2249 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2251 tmp = GetWindowLongA(window, GWL_STYLE);
2252 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2253 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2254 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2256 ShowWindow(window, SW_SHOW);
2257 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2258 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2260 tmp = GetWindowLongA(window, GWL_STYLE);
2261 expected_style = style | WS_VISIBLE;
2262 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2263 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2264 expected_style = exstyle | WS_EX_TOPMOST;
2265 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2267 ret = SetForegroundWindow(GetDesktopWindow());
2268 ok(ret, "Failed to set foreground window.\n");
2269 tmp = GetWindowLongA(window, GWL_STYLE);
2270 expected_style = style | WS_VISIBLE | WS_MINIMIZE;
2271 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2272 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2273 expected_style = exstyle | WS_EX_TOPMOST;
2274 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2276 ref = IDirectDraw7_Release(ddraw);
2277 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2279 DestroyWindow(window);
2282 static void test_redundant_mode_set(void)
2284 DDSURFACEDESC2 surface_desc = {0};
2285 IDirectDraw7 *ddraw;
2286 HWND window;
2287 HRESULT hr;
2288 RECT r, s;
2289 ULONG ref;
2291 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2292 0, 0, 100, 100, 0, 0, 0, 0);
2293 ddraw = create_ddraw();
2294 ok(!!ddraw, "Failed to create a ddraw object.\n");
2295 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2296 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2298 surface_desc.dwSize = sizeof(surface_desc);
2299 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
2300 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
2302 hr = IDirectDraw7_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2303 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
2304 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2306 GetWindowRect(window, &r);
2307 r.right /= 2;
2308 r.bottom /= 2;
2309 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
2310 GetWindowRect(window, &s);
2311 ok(EqualRect(&r, &s), "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2313 hr = IDirectDraw7_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2314 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
2315 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2317 GetWindowRect(window, &s);
2318 ok(EqualRect(&r, &s), "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2320 ref = IDirectDraw7_Release(ddraw);
2321 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2323 DestroyWindow(window);
2326 static SIZE screen_size, screen_size2;
2328 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2330 if (message == WM_SIZE)
2332 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2333 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2336 return test_proc(hwnd, message, wparam, lparam);
2339 static LRESULT CALLBACK mode_set_proc2(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2341 if (message == WM_SIZE)
2343 screen_size2.cx = GetSystemMetrics(SM_CXSCREEN);
2344 screen_size2.cy = GetSystemMetrics(SM_CYSCREEN);
2347 return test_proc(hwnd, message, wparam, lparam);
2350 struct test_coop_level_mode_set_enum_param
2352 DWORD ddraw_width, ddraw_height, user32_width, user32_height;
2355 static HRESULT CALLBACK test_coop_level_mode_set_enum_cb(DDSURFACEDESC2 *surface_desc, void *context)
2357 struct test_coop_level_mode_set_enum_param *param = context;
2359 if (U1(U4(*surface_desc).ddpfPixelFormat).dwRGBBitCount != registry_mode.dmBitsPerPel)
2360 return DDENUMRET_OK;
2361 if (surface_desc->dwWidth == registry_mode.dmPelsWidth
2362 && surface_desc->dwHeight == registry_mode.dmPelsHeight)
2363 return DDENUMRET_OK;
2365 if (!param->ddraw_width)
2367 param->ddraw_width = surface_desc->dwWidth;
2368 param->ddraw_height = surface_desc->dwHeight;
2369 return DDENUMRET_OK;
2371 if (surface_desc->dwWidth == param->ddraw_width && surface_desc->dwHeight == param->ddraw_height)
2372 return DDENUMRET_OK;
2374 param->user32_width = surface_desc->dwWidth;
2375 param->user32_height = surface_desc->dwHeight;
2376 return DDENUMRET_CANCEL;
2379 static void test_coop_level_mode_set(void)
2381 IDirectDrawSurface7 *primary;
2382 RECT registry_rect, ddraw_rect, user32_rect, r;
2383 IDirectDraw7 *ddraw;
2384 DDSURFACEDESC2 ddsd;
2385 WNDCLASSA wc = {0};
2386 HWND window, window2;
2387 HRESULT hr;
2388 ULONG ref;
2389 MSG msg;
2390 struct test_coop_level_mode_set_enum_param param;
2391 DEVMODEW devmode;
2392 BOOL ret;
2393 LONG change_ret;
2395 static const struct message exclusive_messages[] =
2397 {WM_WINDOWPOSCHANGING, FALSE, 0},
2398 {WM_WINDOWPOSCHANGED, FALSE, 0},
2399 {WM_SIZE, FALSE, 0},
2400 {WM_DISPLAYCHANGE, FALSE, 0},
2401 {0, FALSE, 0},
2403 static const struct message exclusive_focus_loss_messages[] =
2405 {WM_ACTIVATE, TRUE, WA_INACTIVE},
2406 {WM_DISPLAYCHANGE, FALSE, 0},
2407 {WM_WINDOWPOSCHANGING, FALSE, 0},
2408 /* Like d3d8 and d3d9 ddraw seems to use SW_SHOWMINIMIZED instead of
2409 * SW_MINIMIZED, causing a recursive window activation that does not
2410 * produce the same result in Wine yet. Ignore the difference for now.
2411 * {WM_ACTIVATE, TRUE, 0x200000 | WA_ACTIVE}, */
2412 {WM_WINDOWPOSCHANGED, FALSE, 0},
2413 {WM_MOVE, FALSE, 0},
2414 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2415 {WM_ACTIVATEAPP, TRUE, FALSE},
2416 {0, FALSE, 0},
2418 static const struct message exclusive_focus_restore_messages[] =
2420 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* From the ShowWindow(SW_RESTORE). */
2421 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Generated by ddraw, matches d3d9 behavior. */
2422 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching previous message. */
2423 {WM_SIZE, FALSE, 0}, /* DefWindowProc. */
2424 {WM_DISPLAYCHANGE, FALSE, 0}, /* Ddraw restores mode. */
2425 /* Native redundantly sets the window size here. */
2426 {WM_ACTIVATEAPP, TRUE, TRUE}, /* End of ddraw's hooks. */
2427 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching the one from ShowWindow. */
2428 {WM_MOVE, FALSE, 0}, /* DefWindowProc. */
2429 {WM_SIZE, TRUE, SIZE_RESTORED}, /* DefWindowProc. */
2430 {0, FALSE, 0},
2432 static const struct message sc_restore_messages[] =
2434 {WM_SYSCOMMAND, TRUE, SC_RESTORE},
2435 {WM_WINDOWPOSCHANGING, FALSE, 0},
2436 {WM_WINDOWPOSCHANGED, FALSE, 0},
2437 {WM_SIZE, TRUE, SIZE_RESTORED},
2438 {0, FALSE, 0},
2440 static const struct message sc_minimize_messages[] =
2442 {WM_SYSCOMMAND, TRUE, SC_MINIMIZE},
2443 {WM_WINDOWPOSCHANGING, FALSE, 0},
2444 {WM_WINDOWPOSCHANGED, FALSE, 0},
2445 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2446 {0, FALSE, 0},
2448 static const struct message sc_maximize_messages[] =
2450 {WM_SYSCOMMAND, TRUE, SC_MAXIMIZE},
2451 {WM_WINDOWPOSCHANGING, FALSE, 0},
2452 {WM_WINDOWPOSCHANGED, FALSE, 0},
2453 {WM_SIZE, TRUE, SIZE_MAXIMIZED},
2454 {0, FALSE, 0},
2457 static const struct message normal_messages[] =
2459 {WM_DISPLAYCHANGE, FALSE, 0},
2460 {0, FALSE, 0},
2463 ddraw = create_ddraw();
2464 ok(!!ddraw, "Failed to create a ddraw object.\n");
2466 memset(&param, 0, sizeof(param));
2467 hr = IDirectDraw7_EnumDisplayModes(ddraw, 0, NULL, &param, test_coop_level_mode_set_enum_cb);
2468 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
2469 ref = IDirectDraw7_Release(ddraw);
2470 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2472 if (!param.user32_height)
2474 skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
2475 return;
2478 SetRect(&registry_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2479 SetRect(&ddraw_rect, 0, 0, param.ddraw_width, param.ddraw_height);
2480 SetRect(&user32_rect, 0, 0, param.user32_width, param.user32_height);
2482 memset(&devmode, 0, sizeof(devmode));
2483 devmode.dmSize = sizeof(devmode);
2484 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2485 devmode.dmPelsWidth = param.user32_width;
2486 devmode.dmPelsHeight = param.user32_height;
2487 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2488 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2490 ddraw = create_ddraw();
2491 ok(!!ddraw, "Failed to create a ddraw object.\n");
2493 wc.lpfnWndProc = mode_set_proc;
2494 wc.lpszClassName = "ddraw_test_wndproc_wc";
2495 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2496 wc.lpfnWndProc = mode_set_proc2;
2497 wc.lpszClassName = "ddraw_test_wndproc_wc2";
2498 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2500 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
2501 0, 0, 100, 100, 0, 0, 0, 0);
2502 window2 = CreateWindowA("ddraw_test_wndproc_wc2", "ddraw_test", WS_OVERLAPPEDWINDOW,
2503 0, 0, 100, 100, 0, 0, 0, 0);
2505 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2506 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2508 GetWindowRect(window, &r);
2509 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2510 wine_dbgstr_rect(&r));
2512 memset(&ddsd, 0, sizeof(ddsd));
2513 ddsd.dwSize = sizeof(ddsd);
2514 ddsd.dwFlags = DDSD_CAPS;
2515 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2517 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2518 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2519 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2520 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2521 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2522 param.user32_width, ddsd.dwWidth);
2523 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2524 param.user32_height, ddsd.dwHeight);
2526 GetWindowRect(window, &r);
2527 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2528 wine_dbgstr_rect(&r));
2530 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2531 expect_messages = exclusive_messages;
2532 screen_size.cx = 0;
2533 screen_size.cy = 0;
2535 hr = IDirectDrawSurface7_IsLost(primary);
2536 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2537 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2538 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2539 hr = IDirectDrawSurface7_IsLost(primary);
2540 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2542 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2543 expect_messages = NULL;
2544 ok(screen_size.cx == param.ddraw_width && screen_size.cy == param.ddraw_height,
2545 "Expected screen size %ux%u, got %ux%u.\n",
2546 param.ddraw_width, param.ddraw_height, screen_size.cx, screen_size.cy);
2548 GetWindowRect(window, &r);
2549 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2550 wine_dbgstr_rect(&r));
2552 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2553 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2554 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2555 param.user32_width, ddsd.dwWidth);
2556 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2557 param.user32_height, ddsd.dwHeight);
2558 IDirectDrawSurface7_Release(primary);
2560 memset(&ddsd, 0, sizeof(ddsd));
2561 ddsd.dwSize = sizeof(ddsd);
2562 ddsd.dwFlags = DDSD_CAPS;
2563 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2565 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2566 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2567 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2568 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2569 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2570 param.ddraw_width, ddsd.dwWidth);
2571 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2572 param.ddraw_height, ddsd.dwHeight);
2574 GetWindowRect(window, &r);
2575 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2576 wine_dbgstr_rect(&r));
2578 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2579 expect_messages = exclusive_messages;
2580 screen_size.cx = 0;
2581 screen_size.cy = 0;
2583 hr = IDirectDrawSurface7_IsLost(primary);
2584 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2585 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2586 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2587 hr = IDirectDrawSurface7_IsLost(primary);
2588 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2590 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2591 expect_messages = NULL;
2592 ok(screen_size.cx == param.user32_width && screen_size.cy == param.user32_height,
2593 "Expected screen size %ux%u, got %ux%u.\n",
2594 param.user32_width, param.user32_height, screen_size.cx, screen_size.cy);
2596 GetWindowRect(window, &r);
2597 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2598 wine_dbgstr_rect(&r));
2600 expect_messages = exclusive_focus_loss_messages;
2601 ret = SetForegroundWindow(GetDesktopWindow());
2602 ok(ret, "Failed to set foreground window.\n");
2603 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2604 memset(&devmode, 0, sizeof(devmode));
2605 devmode.dmSize = sizeof(devmode);
2606 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2607 ok(ret, "Failed to get display mode.\n");
2608 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2609 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
2610 devmode.dmPelsWidth, devmode.dmPelsHeight);
2612 expect_messages = exclusive_focus_restore_messages;
2613 ShowWindow(window, SW_RESTORE);
2614 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2616 GetWindowRect(window, &r);
2617 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2618 wine_dbgstr_rect(&r));
2619 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2620 ok(ret, "Failed to get display mode.\n");
2621 ok(devmode.dmPelsWidth == param.ddraw_width
2622 && devmode.dmPelsHeight == param.ddraw_height, "Got unexpect screen size %ux%u.\n",
2623 devmode.dmPelsWidth, devmode.dmPelsHeight);
2625 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2626 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2627 /* Normally the primary should be restored here. Unfortunately this causes the
2628 * GetSurfaceDesc call after the next display mode change to crash on the Windows 8
2629 * testbot. Another Restore call would presumably avoid the crash, but it also moots
2630 * the point of the GetSurfaceDesc call. */
2632 expect_messages = sc_minimize_messages;
2633 SendMessageA(window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
2634 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2635 expect_messages = NULL;
2637 expect_messages = sc_restore_messages;
2638 SendMessageA(window, WM_SYSCOMMAND, SC_RESTORE, 0);
2639 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2640 expect_messages = NULL;
2642 expect_messages = sc_maximize_messages;
2643 SendMessageA(window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
2644 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2645 expect_messages = NULL;
2647 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2648 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2650 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2651 expect_messages = exclusive_messages;
2652 screen_size.cx = 0;
2653 screen_size.cy = 0;
2655 hr = IDirectDrawSurface7_IsLost(primary);
2656 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2657 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
2658 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2659 hr = IDirectDrawSurface7_IsLost(primary);
2660 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2662 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2663 expect_messages = NULL;
2664 ok(screen_size.cx == registry_mode.dmPelsWidth
2665 && screen_size.cy == registry_mode.dmPelsHeight,
2666 "Expected screen size %ux%u, got %ux%u.\n",
2667 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size.cx, screen_size.cy);
2669 GetWindowRect(window, &r);
2670 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2671 wine_dbgstr_rect(&r));
2673 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2674 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2675 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2676 param.ddraw_width, ddsd.dwWidth);
2677 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2678 param.ddraw_height, ddsd.dwHeight);
2679 IDirectDrawSurface7_Release(primary);
2681 /* For Wine. */
2682 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
2683 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2685 memset(&ddsd, 0, sizeof(ddsd));
2686 ddsd.dwSize = sizeof(ddsd);
2687 ddsd.dwFlags = DDSD_CAPS;
2688 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2690 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2691 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2692 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2693 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2694 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2695 registry_mode.dmPelsWidth, ddsd.dwWidth);
2696 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2697 registry_mode.dmPelsHeight, ddsd.dwHeight);
2699 GetWindowRect(window, &r);
2700 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2701 wine_dbgstr_rect(&r));
2703 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2704 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2706 GetWindowRect(window, &r);
2707 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2708 wine_dbgstr_rect(&r));
2710 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2711 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2712 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2713 registry_mode.dmPelsWidth, ddsd.dwWidth);
2714 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2715 registry_mode.dmPelsHeight, ddsd.dwHeight);
2716 IDirectDrawSurface7_Release(primary);
2718 memset(&ddsd, 0, sizeof(ddsd));
2719 ddsd.dwSize = sizeof(ddsd);
2720 ddsd.dwFlags = DDSD_CAPS;
2721 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2723 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2724 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2725 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2726 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2727 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2728 registry_mode.dmPelsWidth, ddsd.dwWidth);
2729 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2730 registry_mode.dmPelsHeight, ddsd.dwHeight);
2732 GetWindowRect(window, &r);
2733 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2734 wine_dbgstr_rect(&r));
2736 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2737 expect_messages = normal_messages;
2738 screen_size.cx = 0;
2739 screen_size.cy = 0;
2741 hr = IDirectDrawSurface7_IsLost(primary);
2742 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2743 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2744 devmode.dmPelsWidth = param.user32_width;
2745 devmode.dmPelsHeight = param.user32_height;
2746 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2747 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2748 hr = IDirectDrawSurface7_IsLost(primary);
2749 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2751 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2752 expect_messages = NULL;
2753 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2755 GetWindowRect(window, &r);
2756 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2757 wine_dbgstr_rect(&r));
2759 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2760 expect_messages = normal_messages;
2761 screen_size.cx = 0;
2762 screen_size.cy = 0;
2764 hr = IDirectDrawSurface7_Restore(primary);
2765 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2766 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2767 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2768 hr = IDirectDrawSurface7_Restore(primary);
2769 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2770 hr = IDirectDrawSurface7_IsLost(primary);
2771 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2773 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2774 expect_messages = NULL;
2775 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2777 GetWindowRect(window, &r);
2778 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2779 wine_dbgstr_rect(&r));
2781 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2782 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2783 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2784 registry_mode.dmPelsWidth, ddsd.dwWidth);
2785 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2786 registry_mode.dmPelsHeight, ddsd.dwHeight);
2787 IDirectDrawSurface7_Release(primary);
2789 memset(&ddsd, 0, sizeof(ddsd));
2790 ddsd.dwSize = sizeof(ddsd);
2791 ddsd.dwFlags = DDSD_CAPS;
2792 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2794 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2795 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2796 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2797 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2798 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2799 param.ddraw_width, ddsd.dwWidth);
2800 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2801 param.ddraw_height, ddsd.dwHeight);
2803 GetWindowRect(window, &r);
2804 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2805 wine_dbgstr_rect(&r));
2807 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2808 expect_messages = normal_messages;
2809 screen_size.cx = 0;
2810 screen_size.cy = 0;
2812 hr = IDirectDrawSurface7_IsLost(primary);
2813 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2814 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
2815 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2816 hr = IDirectDrawSurface7_IsLost(primary);
2817 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2819 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2820 expect_messages = NULL;
2821 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2823 GetWindowRect(window, &r);
2824 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2825 wine_dbgstr_rect(&r));
2827 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2828 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2829 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2830 param.ddraw_width, ddsd.dwWidth);
2831 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2832 param.ddraw_height, ddsd.dwHeight);
2833 IDirectDrawSurface7_Release(primary);
2835 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2836 ok(ret, "Failed to get display mode.\n");
2837 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2838 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
2839 "Expected resolution %ux%u, got %ux%u.\n",
2840 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
2841 devmode.dmPelsWidth, devmode.dmPelsHeight);
2842 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
2843 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2845 memset(&ddsd, 0, sizeof(ddsd));
2846 ddsd.dwSize = sizeof(ddsd);
2847 ddsd.dwFlags = DDSD_CAPS;
2848 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2850 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2851 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2852 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2853 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2854 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2855 registry_mode.dmPelsWidth, ddsd.dwWidth);
2856 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2857 registry_mode.dmPelsHeight, ddsd.dwHeight);
2859 GetWindowRect(window, &r);
2860 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2861 wine_dbgstr_rect(&r));
2863 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
2864 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
2865 * not DDSCL_FULLSCREEN. */
2866 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2867 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2869 GetWindowRect(window, &r);
2870 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2871 wine_dbgstr_rect(&r));
2873 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2874 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2875 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2876 registry_mode.dmPelsWidth, ddsd.dwWidth);
2877 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2878 registry_mode.dmPelsHeight, ddsd.dwHeight);
2879 IDirectDrawSurface7_Release(primary);
2881 memset(&ddsd, 0, sizeof(ddsd));
2882 ddsd.dwSize = sizeof(ddsd);
2883 ddsd.dwFlags = DDSD_CAPS;
2884 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2886 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2887 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2888 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2889 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2890 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2891 registry_mode.dmPelsWidth, ddsd.dwWidth);
2892 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2893 registry_mode.dmPelsHeight, ddsd.dwHeight);
2895 GetWindowRect(window, &r);
2896 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2897 wine_dbgstr_rect(&r));
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_IsLost(primary);
2905 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2906 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2907 devmode.dmPelsWidth = param.user32_width;
2908 devmode.dmPelsHeight = param.user32_height;
2909 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2910 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2911 hr = IDirectDrawSurface7_IsLost(primary);
2912 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2914 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2915 expect_messages = NULL;
2916 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2918 GetWindowRect(window, &r);
2919 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2920 wine_dbgstr_rect(&r));
2922 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2923 expect_messages = normal_messages;
2924 screen_size.cx = 0;
2925 screen_size.cy = 0;
2927 hr = IDirectDrawSurface7_Restore(primary);
2928 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2929 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2930 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2931 hr = IDirectDrawSurface7_Restore(primary);
2932 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2933 hr = IDirectDrawSurface7_IsLost(primary);
2934 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2936 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2937 expect_messages = NULL;
2938 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2940 GetWindowRect(window, &r);
2941 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2942 wine_dbgstr_rect(&r));
2944 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2945 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2946 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2947 registry_mode.dmPelsWidth, ddsd.dwWidth);
2948 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2949 registry_mode.dmPelsHeight, ddsd.dwHeight);
2950 IDirectDrawSurface7_Release(primary);
2952 memset(&ddsd, 0, sizeof(ddsd));
2953 ddsd.dwSize = sizeof(ddsd);
2954 ddsd.dwFlags = DDSD_CAPS;
2955 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2957 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2958 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2959 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2960 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2961 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2962 param.ddraw_width, ddsd.dwWidth);
2963 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2964 param.ddraw_height, ddsd.dwHeight);
2966 GetWindowRect(window, &r);
2967 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2968 wine_dbgstr_rect(&r));
2970 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2971 expect_messages = normal_messages;
2972 screen_size.cx = 0;
2973 screen_size.cy = 0;
2975 hr = IDirectDrawSurface7_IsLost(primary);
2976 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2977 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
2978 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2979 hr = IDirectDrawSurface7_IsLost(primary);
2980 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2982 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2983 expect_messages = NULL;
2984 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2986 GetWindowRect(window, &r);
2987 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2988 wine_dbgstr_rect(&r));
2990 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2991 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2992 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2993 param.ddraw_width, ddsd.dwWidth);
2994 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2995 param.ddraw_height, ddsd.dwHeight);
2996 IDirectDrawSurface7_Release(primary);
2998 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2999 ok(ret, "Failed to get display mode.\n");
3000 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3001 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3002 "Expected resolution %ux%u, got %ux%u.\n",
3003 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3004 devmode.dmPelsWidth, devmode.dmPelsHeight);
3005 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3006 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3008 memset(&ddsd, 0, sizeof(ddsd));
3009 ddsd.dwSize = sizeof(ddsd);
3010 ddsd.dwFlags = DDSD_CAPS;
3011 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3013 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3014 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3015 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3016 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3017 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3018 registry_mode.dmPelsWidth, ddsd.dwWidth);
3019 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3020 registry_mode.dmPelsHeight, ddsd.dwHeight);
3021 IDirectDrawSurface7_Release(primary);
3023 GetWindowRect(window, &r);
3024 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3025 wine_dbgstr_rect(&r));
3027 /* Changing the coop level from EXCLUSIVE to NORMAL restores the screen resolution */
3028 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3029 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3030 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3031 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3033 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3034 expect_messages = exclusive_messages;
3035 screen_size.cx = 0;
3036 screen_size.cy = 0;
3038 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3039 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3041 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3042 expect_messages = NULL;
3043 ok(screen_size.cx == registry_mode.dmPelsWidth
3044 && screen_size.cy == registry_mode.dmPelsHeight,
3045 "Expected screen size %ux%u, got %ux%u.\n",
3046 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3047 screen_size.cx, screen_size.cy);
3049 GetWindowRect(window, &r);
3050 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3051 wine_dbgstr_rect(&r));
3053 memset(&ddsd, 0, sizeof(ddsd));
3054 ddsd.dwSize = sizeof(ddsd);
3055 ddsd.dwFlags = DDSD_CAPS;
3056 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3058 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3059 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3060 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3061 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3062 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3063 registry_mode.dmPelsWidth, ddsd.dwWidth);
3064 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3065 registry_mode.dmPelsHeight, ddsd.dwHeight);
3066 IDirectDrawSurface7_Release(primary);
3068 /* The screen restore is a property of DDSCL_EXCLUSIVE */
3069 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3070 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3071 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3072 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3074 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3075 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3077 memset(&ddsd, 0, sizeof(ddsd));
3078 ddsd.dwSize = sizeof(ddsd);
3079 ddsd.dwFlags = DDSD_CAPS;
3080 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3082 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3083 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3084 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3085 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3086 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3087 param.ddraw_width, ddsd.dwWidth);
3088 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3089 param.ddraw_height, ddsd.dwHeight);
3090 IDirectDrawSurface7_Release(primary);
3092 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
3093 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3095 /* If the window is changed at the same time, messages are sent to the new window. */
3096 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3097 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3098 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3099 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3101 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3102 expect_messages = exclusive_messages;
3103 screen_size.cx = 0;
3104 screen_size.cy = 0;
3105 screen_size2.cx = 0;
3106 screen_size2.cy = 0;
3108 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3109 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3111 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3112 expect_messages = NULL;
3113 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n",
3114 screen_size.cx, screen_size.cy);
3115 ok(screen_size2.cx == registry_mode.dmPelsWidth && screen_size2.cy == registry_mode.dmPelsHeight,
3116 "Expected screen size 2 %ux%u, got %ux%u.\n",
3117 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size2.cx, screen_size2.cy);
3119 GetWindowRect(window, &r);
3120 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3121 wine_dbgstr_rect(&r));
3122 GetWindowRect(window2, &r);
3123 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3124 wine_dbgstr_rect(&r));
3126 memset(&ddsd, 0, sizeof(ddsd));
3127 ddsd.dwSize = sizeof(ddsd);
3128 ddsd.dwFlags = DDSD_CAPS;
3129 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3131 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3132 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3133 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3134 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3135 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3136 registry_mode.dmPelsWidth, ddsd.dwWidth);
3137 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3138 registry_mode.dmPelsHeight, ddsd.dwHeight);
3139 IDirectDrawSurface7_Release(primary);
3141 ref = IDirectDraw7_Release(ddraw);
3142 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3144 GetWindowRect(window, &r);
3145 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3146 wine_dbgstr_rect(&r));
3148 expect_messages = NULL;
3149 DestroyWindow(window);
3150 DestroyWindow(window2);
3151 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
3152 UnregisterClassA("ddraw_test_wndproc_wc2", GetModuleHandleA(NULL));
3155 static void test_coop_level_mode_set_multi(void)
3157 IDirectDraw7 *ddraw1, *ddraw2;
3158 UINT w, h;
3159 HWND window;
3160 HRESULT hr;
3161 ULONG ref;
3163 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3164 0, 0, 100, 100, 0, 0, 0, 0);
3165 ddraw1 = create_ddraw();
3166 ok(!!ddraw1, "Failed to create a ddraw object.\n");
3168 /* With just a single ddraw object, the display mode is restored on
3169 * release. */
3170 hr = set_display_mode(ddraw1, 800, 600);
3171 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3172 w = GetSystemMetrics(SM_CXSCREEN);
3173 ok(w == 800, "Got unexpected screen width %u.\n", w);
3174 h = GetSystemMetrics(SM_CYSCREEN);
3175 ok(h == 600, "Got unexpected screen height %u.\n", h);
3177 ref = IDirectDraw7_Release(ddraw1);
3178 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3179 w = GetSystemMetrics(SM_CXSCREEN);
3180 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3181 h = GetSystemMetrics(SM_CYSCREEN);
3182 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3184 /* When there are multiple ddraw objects, the display mode is restored to
3185 * the initial mode, before the first SetDisplayMode() call. */
3186 ddraw1 = create_ddraw();
3187 hr = set_display_mode(ddraw1, 800, 600);
3188 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3189 w = GetSystemMetrics(SM_CXSCREEN);
3190 ok(w == 800, "Got unexpected screen width %u.\n", w);
3191 h = GetSystemMetrics(SM_CYSCREEN);
3192 ok(h == 600, "Got unexpected screen height %u.\n", h);
3194 ddraw2 = create_ddraw();
3195 hr = set_display_mode(ddraw2, 640, 480);
3196 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3197 w = GetSystemMetrics(SM_CXSCREEN);
3198 ok(w == 640, "Got unexpected screen width %u.\n", w);
3199 h = GetSystemMetrics(SM_CYSCREEN);
3200 ok(h == 480, "Got unexpected screen height %u.\n", h);
3202 ref = IDirectDraw7_Release(ddraw2);
3203 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3204 w = GetSystemMetrics(SM_CXSCREEN);
3205 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3206 h = GetSystemMetrics(SM_CYSCREEN);
3207 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3209 ref = IDirectDraw7_Release(ddraw1);
3210 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3211 w = GetSystemMetrics(SM_CXSCREEN);
3212 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3213 h = GetSystemMetrics(SM_CYSCREEN);
3214 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3216 /* Regardless of release ordering. */
3217 ddraw1 = create_ddraw();
3218 hr = set_display_mode(ddraw1, 800, 600);
3219 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3220 w = GetSystemMetrics(SM_CXSCREEN);
3221 ok(w == 800, "Got unexpected screen width %u.\n", w);
3222 h = GetSystemMetrics(SM_CYSCREEN);
3223 ok(h == 600, "Got unexpected screen height %u.\n", h);
3225 ddraw2 = create_ddraw();
3226 hr = set_display_mode(ddraw2, 640, 480);
3227 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3228 w = GetSystemMetrics(SM_CXSCREEN);
3229 ok(w == 640, "Got unexpected screen width %u.\n", w);
3230 h = GetSystemMetrics(SM_CYSCREEN);
3231 ok(h == 480, "Got unexpected screen height %u.\n", h);
3233 ref = IDirectDraw7_Release(ddraw1);
3234 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3235 w = GetSystemMetrics(SM_CXSCREEN);
3236 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3237 h = GetSystemMetrics(SM_CYSCREEN);
3238 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3240 ref = IDirectDraw7_Release(ddraw2);
3241 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3242 w = GetSystemMetrics(SM_CXSCREEN);
3243 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3244 h = GetSystemMetrics(SM_CYSCREEN);
3245 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3247 /* But only for ddraw objects that called SetDisplayMode(). */
3248 ddraw1 = create_ddraw();
3249 ddraw2 = create_ddraw();
3250 hr = set_display_mode(ddraw2, 640, 480);
3251 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3252 w = GetSystemMetrics(SM_CXSCREEN);
3253 ok(w == 640, "Got unexpected screen width %u.\n", w);
3254 h = GetSystemMetrics(SM_CYSCREEN);
3255 ok(h == 480, "Got unexpected screen height %u.\n", h);
3257 ref = IDirectDraw7_Release(ddraw1);
3258 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3259 w = GetSystemMetrics(SM_CXSCREEN);
3260 ok(w == 640, "Got unexpected screen width %u.\n", w);
3261 h = GetSystemMetrics(SM_CYSCREEN);
3262 ok(h == 480, "Got unexpected screen height %u.\n", h);
3264 ref = IDirectDraw7_Release(ddraw2);
3265 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3266 w = GetSystemMetrics(SM_CXSCREEN);
3267 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3268 h = GetSystemMetrics(SM_CYSCREEN);
3269 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3271 /* If there's a ddraw object that's currently in exclusive mode, it blocks
3272 * restoring the display mode. */
3273 ddraw1 = create_ddraw();
3274 hr = set_display_mode(ddraw1, 800, 600);
3275 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3276 w = GetSystemMetrics(SM_CXSCREEN);
3277 ok(w == 800, "Got unexpected screen width %u.\n", w);
3278 h = GetSystemMetrics(SM_CYSCREEN);
3279 ok(h == 600, "Got unexpected screen height %u.\n", h);
3281 ddraw2 = create_ddraw();
3282 hr = set_display_mode(ddraw2, 640, 480);
3283 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3284 w = GetSystemMetrics(SM_CXSCREEN);
3285 ok(w == 640, "Got unexpected screen width %u.\n", w);
3286 h = GetSystemMetrics(SM_CYSCREEN);
3287 ok(h == 480, "Got unexpected screen height %u.\n", h);
3289 hr = IDirectDraw7_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3290 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3292 ref = IDirectDraw7_Release(ddraw1);
3293 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3294 w = GetSystemMetrics(SM_CXSCREEN);
3295 ok(w == 640, "Got unexpected screen width %u.\n", w);
3296 h = GetSystemMetrics(SM_CYSCREEN);
3297 ok(h == 480, "Got unexpected screen height %u.\n", h);
3299 ref = IDirectDraw7_Release(ddraw2);
3300 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3301 w = GetSystemMetrics(SM_CXSCREEN);
3302 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3303 h = GetSystemMetrics(SM_CYSCREEN);
3304 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3306 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
3307 ddraw1 = create_ddraw();
3308 hr = set_display_mode(ddraw1, 800, 600);
3309 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3310 w = GetSystemMetrics(SM_CXSCREEN);
3311 ok(w == 800, "Got unexpected screen width %u.\n", w);
3312 h = GetSystemMetrics(SM_CYSCREEN);
3313 ok(h == 600, "Got unexpected screen height %u.\n", h);
3315 hr = IDirectDraw7_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3316 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3318 ddraw2 = create_ddraw();
3319 hr = set_display_mode(ddraw2, 640, 480);
3320 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
3322 ref = IDirectDraw7_Release(ddraw1);
3323 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3324 w = GetSystemMetrics(SM_CXSCREEN);
3325 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3326 h = GetSystemMetrics(SM_CYSCREEN);
3327 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3329 ref = IDirectDraw7_Release(ddraw2);
3330 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3331 w = GetSystemMetrics(SM_CXSCREEN);
3332 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3333 h = GetSystemMetrics(SM_CYSCREEN);
3334 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3336 DestroyWindow(window);
3339 static void test_initialize(void)
3341 IDirectDraw7 *ddraw;
3342 HRESULT hr;
3344 ddraw = create_ddraw();
3345 ok(!!ddraw, "Failed to create a ddraw object.\n");
3347 hr = IDirectDraw7_Initialize(ddraw, NULL);
3348 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
3349 IDirectDraw7_Release(ddraw);
3351 CoInitialize(NULL);
3352 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw7, (void **)&ddraw);
3353 ok(SUCCEEDED(hr), "Failed to create IDirectDraw7 instance, hr %#x.\n", hr);
3354 hr = IDirectDraw7_Initialize(ddraw, NULL);
3355 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
3356 hr = IDirectDraw7_Initialize(ddraw, NULL);
3357 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
3358 IDirectDraw7_Release(ddraw);
3359 CoUninitialize();
3362 static void test_coop_level_surf_create(void)
3364 IDirectDrawSurface7 *surface;
3365 IDirectDraw7 *ddraw;
3366 DDSURFACEDESC2 ddsd;
3367 HRESULT hr;
3369 ddraw = create_ddraw();
3370 ok(!!ddraw, "Failed to create a ddraw object.\n");
3372 memset(&ddsd, 0, sizeof(ddsd));
3373 ddsd.dwSize = sizeof(ddsd);
3374 ddsd.dwFlags = DDSD_CAPS;
3375 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3376 surface = (void *)0xdeadbeef;
3377 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
3378 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
3379 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
3381 IDirectDraw7_Release(ddraw);
3384 static void test_vb_discard(void)
3386 static const struct vec4 quad[] =
3388 { 0.0f, 480.0f, 0.0f, 1.0f},
3389 { 0.0f, 0.0f, 0.0f, 1.0f},
3390 {640.0f, 480.0f, 0.0f, 1.0f},
3391 {640.0f, 0.0f, 0.0f, 1.0f},
3394 IDirect3DDevice7 *device;
3395 IDirect3D7 *d3d;
3396 IDirect3DVertexBuffer7 *buffer;
3397 HWND window;
3398 HRESULT hr;
3399 D3DVERTEXBUFFERDESC desc;
3400 BYTE *data;
3401 static const unsigned int vbsize = 16;
3402 unsigned int i;
3404 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3405 0, 0, 640, 480, 0, 0, 0, 0);
3407 if (!(device = create_device(window, DDSCL_NORMAL)))
3409 skip("Failed to create a 3D device, skipping test.\n");
3410 DestroyWindow(window);
3411 return;
3414 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
3415 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
3417 memset(&desc, 0, sizeof(desc));
3418 desc.dwSize = sizeof(desc);
3419 desc.dwCaps = D3DVBCAPS_WRITEONLY;
3420 desc.dwFVF = D3DFVF_XYZRHW;
3421 desc.dwNumVertices = vbsize;
3422 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &buffer, 0);
3423 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
3425 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3426 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3427 memcpy(data, quad, sizeof(quad));
3428 hr = IDirect3DVertexBuffer7_Unlock(buffer);
3429 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3431 hr = IDirect3DDevice7_BeginScene(device);
3432 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3433 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
3434 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3435 hr = IDirect3DDevice7_EndScene(device);
3436 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3438 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3439 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3440 memset(data, 0xaa, sizeof(struct vec4) * vbsize);
3441 hr = IDirect3DVertexBuffer7_Unlock(buffer);
3442 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3444 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3445 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3446 for (i = 0; i < sizeof(struct vec4) * vbsize; i++)
3448 if (data[i] != 0xaa)
3450 ok(FALSE, "Vertex buffer data byte %u is 0x%02x, expected 0xaa\n", i, data[i]);
3451 break;
3454 hr = IDirect3DVertexBuffer7_Unlock(buffer);
3455 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3457 IDirect3DVertexBuffer7_Release(buffer);
3458 IDirect3D7_Release(d3d);
3459 IDirect3DDevice7_Release(device);
3460 DestroyWindow(window);
3463 static void test_coop_level_multi_window(void)
3465 HWND window1, window2;
3466 IDirectDraw7 *ddraw;
3467 HRESULT hr;
3469 window1 = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
3470 0, 0, 640, 480, 0, 0, 0, 0);
3471 window2 = CreateWindowA("static", "ddraw_test2", WS_OVERLAPPEDWINDOW,
3472 0, 0, 640, 480, 0, 0, 0, 0);
3473 ddraw = create_ddraw();
3474 ok(!!ddraw, "Failed to create a ddraw object.\n");
3476 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
3477 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3478 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3479 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3480 ok(IsWindow(window1), "Window 1 was destroyed.\n");
3481 ok(IsWindow(window2), "Window 2 was destroyed.\n");
3483 IDirectDraw7_Release(ddraw);
3484 DestroyWindow(window2);
3485 DestroyWindow(window1);
3488 static void test_draw_strided(void)
3490 static struct vec3 position[] =
3492 {-1.0, -1.0, 0.0},
3493 {-1.0, 1.0, 0.0},
3494 { 1.0, 1.0, 0.0},
3495 { 1.0, -1.0, 0.0},
3497 static DWORD diffuse[] =
3499 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
3501 static WORD indices[] =
3503 0, 1, 2, 2, 3, 0
3506 IDirectDrawSurface7 *rt;
3507 IDirect3DDevice7 *device;
3508 D3DCOLOR color;
3509 HWND window;
3510 HRESULT hr;
3511 D3DDRAWPRIMITIVESTRIDEDDATA strided;
3513 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3514 0, 0, 640, 480, 0, 0, 0, 0);
3516 if (!(device = create_device(window, DDSCL_NORMAL)))
3518 skip("Failed to create a 3D device, skipping test.\n");
3519 DestroyWindow(window);
3520 return;
3523 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
3524 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3526 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
3527 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
3528 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 1.0f, 0);
3529 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
3530 hr = IDirect3DDevice7_BeginScene(device);
3531 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3533 memset(&strided, 0x55, sizeof(strided));
3534 strided.position.lpvData = position;
3535 strided.position.dwStride = sizeof(*position);
3536 strided.diffuse.lpvData = diffuse;
3537 strided.diffuse.dwStride = sizeof(*diffuse);
3538 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device, D3DPT_TRIANGLELIST, D3DFVF_XYZ | D3DFVF_DIFFUSE,
3539 &strided, 4, indices, 6, 0);
3540 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3542 hr = IDirect3DDevice7_EndScene(device);
3543 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3545 color = get_surface_color(rt, 320, 240);
3546 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
3548 IDirectDrawSurface7_Release(rt);
3549 IDirect3DDevice7_Release(device);
3550 DestroyWindow(window);
3553 static void test_lighting(void)
3555 static D3DMATRIX mat =
3557 1.0f, 0.0f, 0.0f, 0.0f,
3558 0.0f, 1.0f, 0.0f, 0.0f,
3559 0.0f, 0.0f, 1.0f, 0.0f,
3560 0.0f, 0.0f, 0.0f, 1.0f,
3562 mat_singular =
3564 1.0f, 0.0f, 1.0f, 0.0f,
3565 0.0f, 1.0f, 0.0f, 0.0f,
3566 1.0f, 0.0f, 1.0f, 0.0f,
3567 0.0f, 0.0f, 0.5f, 1.0f,
3569 mat_transf =
3571 0.0f, 0.0f, 1.0f, 0.0f,
3572 0.0f, 1.0f, 0.0f, 0.0f,
3573 -1.0f, 0.0f, 0.0f, 0.0f,
3574 10.f, 10.0f, 10.0f, 1.0f,
3576 mat_nonaffine =
3578 1.0f, 0.0f, 0.0f, 0.0f,
3579 0.0f, 1.0f, 0.0f, 0.0f,
3580 0.0f, 0.0f, 1.0f, -1.0f,
3581 10.f, 10.0f, 10.0f, 0.0f,
3583 static struct
3585 struct vec3 position;
3586 DWORD diffuse;
3588 unlitquad[] =
3590 {{-1.0f, -1.0f, 0.1f}, 0xffff0000},
3591 {{-1.0f, 0.0f, 0.1f}, 0xffff0000},
3592 {{ 0.0f, 0.0f, 0.1f}, 0xffff0000},
3593 {{ 0.0f, -1.0f, 0.1f}, 0xffff0000},
3595 litquad[] =
3597 {{-1.0f, 0.0f, 0.1f}, 0xff00ff00},
3598 {{-1.0f, 1.0f, 0.1f}, 0xff00ff00},
3599 {{ 0.0f, 1.0f, 0.1f}, 0xff00ff00},
3600 {{ 0.0f, 0.0f, 0.1f}, 0xff00ff00},
3602 static struct
3604 struct vec3 position;
3605 struct vec3 normal;
3606 DWORD diffuse;
3608 unlitnquad[] =
3610 {{0.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3611 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3612 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3613 {{1.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3615 litnquad[] =
3617 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3618 {{0.0f, 1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3619 {{1.0f, 1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3620 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3622 nquad[] =
3624 {{-1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3625 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3626 {{ 1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3627 {{ 1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3629 rotatedquad[] =
3631 {{-10.0f, -11.0f, 11.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3632 {{-10.0f, -9.0f, 11.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3633 {{-10.0f, -9.0f, 9.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3634 {{-10.0f, -11.0f, 9.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3636 translatedquad[] =
3638 {{-11.0f, -11.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3639 {{-11.0f, -9.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3640 {{ -9.0f, -9.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3641 {{ -9.0f, -11.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3643 static WORD indices[] = {0, 1, 2, 2, 3, 0};
3644 static const struct
3646 D3DMATRIX *world_matrix;
3647 void *quad;
3648 DWORD expected;
3649 const char *message;
3651 tests[] =
3653 {&mat, nquad, 0x000000ff, "Lit quad with light"},
3654 {&mat_singular, nquad, 0x000000ff, "Lit quad with singular world matrix"},
3655 {&mat_transf, rotatedquad, 0x000000ff, "Lit quad with transformation matrix"},
3656 {&mat_nonaffine, translatedquad, 0x00000000, "Lit quad with non-affine matrix"},
3659 HWND window;
3660 IDirect3DDevice7 *device;
3661 IDirectDrawSurface7 *rt;
3662 HRESULT hr;
3663 DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
3664 DWORD nfvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL;
3665 D3DCOLOR color;
3666 ULONG refcount;
3667 unsigned int i;
3669 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3670 0, 0, 640, 480, 0, 0, 0, 0);
3671 if (!(device = create_device(window, DDSCL_NORMAL)))
3673 skip("Failed to create a 3D device, skipping test.\n");
3674 DestroyWindow(window);
3675 return;
3678 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
3679 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3681 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
3682 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
3684 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
3685 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
3686 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
3687 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
3688 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
3689 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
3690 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
3691 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
3692 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
3693 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
3694 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
3695 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
3696 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
3697 ok(SUCCEEDED(hr), "Failed to disable stencil buffering, hr %#x.\n", hr);
3698 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
3699 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
3701 hr = IDirect3DDevice7_BeginScene(device);
3702 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3704 /* No lights are defined... That means, lit vertices should be entirely black. */
3705 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
3706 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
3707 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, unlitquad, 4,
3708 indices, 6, 0);
3709 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3711 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
3712 ok(SUCCEEDED(hr), "Failed to enable lighting, hr %#x.\n", hr);
3713 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, litquad, 4,
3714 indices, 6, 0);
3715 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3717 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
3718 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
3719 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, unlitnquad, 4,
3720 indices, 6, 0);
3721 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3723 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
3724 ok(SUCCEEDED(hr), "Failed to enable lighting, hr %#x.\n", hr);
3725 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, litnquad, 4,
3726 indices, 6, 0);
3727 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3729 hr = IDirect3DDevice7_EndScene(device);
3730 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3732 color = get_surface_color(rt, 160, 360);
3733 ok(color == 0x00ff0000, "Unlit quad without normals has color 0x%08x, expected 0x00ff0000.\n", color);
3734 color = get_surface_color(rt, 160, 120);
3735 ok(color == 0x00000000, "Lit quad without normals has color 0x%08x, expected 0x00000000.\n", color);
3736 color = get_surface_color(rt, 480, 360);
3737 ok(color == 0x000000ff, "Unlit quad with normals has color 0x%08x, expected 0x000000ff.\n", color);
3738 color = get_surface_color(rt, 480, 120);
3739 ok(color == 0x00000000, "Lit quad with normals has color 0x%08x, expected 0x00000000.\n", color);
3741 hr = IDirect3DDevice7_LightEnable(device, 0, TRUE);
3742 ok(SUCCEEDED(hr), "Failed to enable light 0, hr %#x.\n", hr);
3744 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
3746 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, tests[i].world_matrix);
3747 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
3749 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
3750 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
3752 hr = IDirect3DDevice7_BeginScene(device);
3753 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3755 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, tests[i].quad,
3756 4, indices, 6, 0);
3757 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3759 hr = IDirect3DDevice7_EndScene(device);
3760 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3762 color = get_surface_color(rt, 320, 240);
3763 ok(color == tests[i].expected, "%s has color 0x%08x.\n", tests[i].message, color);
3766 IDirectDrawSurface7_Release(rt);
3768 refcount = IDirect3DDevice7_Release(device);
3769 ok(!refcount, "Device has %u references left.\n", refcount);
3770 DestroyWindow(window);
3773 static void test_specular_lighting(void)
3775 static const unsigned int vertices_side = 5;
3776 const unsigned int indices_count = (vertices_side - 1) * (vertices_side - 1) * 2 * 3;
3777 static const DWORD fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3778 static D3DMATRIX mat =
3780 1.0f, 0.0f, 0.0f, 0.0f,
3781 0.0f, 1.0f, 0.0f, 0.0f,
3782 0.0f, 0.0f, 1.0f, 0.0f,
3783 0.0f, 0.0f, 0.0f, 1.0f,
3785 static D3DLIGHT7 directional =
3787 D3DLIGHT_DIRECTIONAL,
3788 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3789 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
3790 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3791 {{0.0f}, {0.0f}, {0.0f}},
3792 {{0.0f}, {0.0f}, {1.0f}},
3794 point =
3796 D3DLIGHT_POINT,
3797 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3798 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
3799 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3800 {{0.0f}, {0.0f}, {0.0f}},
3801 {{0.0f}, {0.0f}, {0.0f}},
3802 100.0f,
3803 0.0f,
3804 0.0f, 0.0f, 1.0f,
3806 spot =
3808 D3DLIGHT_SPOT,
3809 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3810 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
3811 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3812 {{0.0f}, {0.0f}, {0.0f}},
3813 {{0.0f}, {0.0f}, {1.0f}},
3814 100.0f,
3815 1.0f,
3816 0.0f, 0.0f, 1.0f,
3817 M_PI / 12.0f, M_PI / 3.0f
3819 /* The chosen range value makes the test fail when using a manhattan
3820 * distance metric vs the correct euclidean distance. */
3821 point_range =
3823 D3DLIGHT_POINT,
3824 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3825 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
3826 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3827 {{0.0f}, {0.0f}, {0.0f}},
3828 {{0.0f}, {0.0f}, {0.0f}},
3829 1.2f,
3830 0.0f,
3831 0.0f, 0.0f, 1.0f,
3833 static const struct expected_color
3835 unsigned int x, y;
3836 D3DCOLOR color;
3838 expected_directional[] =
3840 {160, 120, 0x00ffffff},
3841 {320, 120, 0x00ffffff},
3842 {480, 120, 0x00ffffff},
3843 {160, 240, 0x00ffffff},
3844 {320, 240, 0x00ffffff},
3845 {480, 240, 0x00ffffff},
3846 {160, 360, 0x00ffffff},
3847 {320, 360, 0x00ffffff},
3848 {480, 360, 0x00ffffff},
3850 expected_directional_local[] =
3852 {160, 120, 0x003c3c3c},
3853 {320, 120, 0x00717171},
3854 {480, 120, 0x003c3c3c},
3855 {160, 240, 0x00717171},
3856 {320, 240, 0x00ffffff},
3857 {480, 240, 0x00717171},
3858 {160, 360, 0x003c3c3c},
3859 {320, 360, 0x00717171},
3860 {480, 360, 0x003c3c3c},
3862 expected_point[] =
3864 {160, 120, 0x00282828},
3865 {320, 120, 0x005a5a5a},
3866 {480, 120, 0x00282828},
3867 {160, 240, 0x005a5a5a},
3868 {320, 240, 0x00ffffff},
3869 {480, 240, 0x005a5a5a},
3870 {160, 360, 0x00282828},
3871 {320, 360, 0x005a5a5a},
3872 {480, 360, 0x00282828},
3874 expected_point_local[] =
3876 {160, 120, 0x00000000},
3877 {320, 120, 0x00070707},
3878 {480, 120, 0x00000000},
3879 {160, 240, 0x00070707},
3880 {320, 240, 0x00ffffff},
3881 {480, 240, 0x00070707},
3882 {160, 360, 0x00000000},
3883 {320, 360, 0x00070707},
3884 {480, 360, 0x00000000},
3886 expected_spot[] =
3888 {160, 120, 0x00000000},
3889 {320, 120, 0x00141414},
3890 {480, 120, 0x00000000},
3891 {160, 240, 0x00141414},
3892 {320, 240, 0x00ffffff},
3893 {480, 240, 0x00141414},
3894 {160, 360, 0x00000000},
3895 {320, 360, 0x00141414},
3896 {480, 360, 0x00000000},
3898 expected_spot_local[] =
3900 {160, 120, 0x00000000},
3901 {320, 120, 0x00020202},
3902 {480, 120, 0x00000000},
3903 {160, 240, 0x00020202},
3904 {320, 240, 0x00ffffff},
3905 {480, 240, 0x00020202},
3906 {160, 360, 0x00000000},
3907 {320, 360, 0x00020202},
3908 {480, 360, 0x00000000},
3910 expected_point_range[] =
3912 {160, 120, 0x00000000},
3913 {320, 120, 0x005a5a5a},
3914 {480, 120, 0x00000000},
3915 {160, 240, 0x005a5a5a},
3916 {320, 240, 0x00ffffff},
3917 {480, 240, 0x005a5a5a},
3918 {160, 360, 0x00000000},
3919 {320, 360, 0x005a5a5a},
3920 {480, 360, 0x00000000},
3922 static const struct
3924 D3DLIGHT7 *light;
3925 BOOL local_viewer;
3926 const struct expected_color *expected;
3927 unsigned int expected_count;
3929 tests[] =
3931 {&directional, FALSE, expected_directional,
3932 sizeof(expected_directional) / sizeof(expected_directional[0])},
3933 {&directional, TRUE, expected_directional_local,
3934 sizeof(expected_directional_local) / sizeof(expected_directional_local[0])},
3935 {&point, FALSE, expected_point,
3936 sizeof(expected_point) / sizeof(expected_point[0])},
3937 {&point, TRUE, expected_point_local,
3938 sizeof(expected_point_local) / sizeof(expected_point_local[0])},
3939 {&spot, FALSE, expected_spot,
3940 sizeof(expected_spot) / sizeof(expected_spot[0])},
3941 {&spot, TRUE, expected_spot_local,
3942 sizeof(expected_spot_local) / sizeof(expected_spot_local[0])},
3943 {&point_range, FALSE, expected_point_range,
3944 sizeof(expected_point_range) / sizeof(expected_point_range[0])},
3946 IDirect3DDevice7 *device;
3947 IDirectDrawSurface7 *rt;
3948 D3DMATERIAL7 material;
3949 D3DCOLOR color;
3950 ULONG refcount;
3951 HWND window;
3952 HRESULT hr;
3953 unsigned int i, j, x, y;
3954 struct
3956 struct vec3 position;
3957 struct vec3 normal;
3958 } *quad;
3959 WORD *indices;
3961 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3962 0, 0, 640, 480, 0, 0, 0, 0);
3963 if (!(device = create_device(window, DDSCL_NORMAL)))
3965 skip("Failed to create a 3D device, skipping test.\n");
3966 DestroyWindow(window);
3967 return;
3970 quad = HeapAlloc(GetProcessHeap(), 0, vertices_side * vertices_side * sizeof(*quad));
3971 indices = HeapAlloc(GetProcessHeap(), 0, indices_count * sizeof(*indices));
3972 for (i = 0, y = 0; y < vertices_side; ++y)
3974 for (x = 0; x < vertices_side; ++x)
3976 quad[i].position.x = x * 2.0f / (vertices_side - 1) - 1.0f;
3977 quad[i].position.y = y * 2.0f / (vertices_side - 1) - 1.0f;
3978 quad[i].position.z = 1.0f;
3979 quad[i].normal.x = 0.0f;
3980 quad[i].normal.y = 0.0f;
3981 quad[i++].normal.z = -1.0f;
3984 for (i = 0, y = 0; y < (vertices_side - 1); ++y)
3986 for (x = 0; x < (vertices_side - 1); ++x)
3988 indices[i++] = y * vertices_side + x + 1;
3989 indices[i++] = y * vertices_side + x;
3990 indices[i++] = (y + 1) * vertices_side + x;
3991 indices[i++] = y * vertices_side + x + 1;
3992 indices[i++] = (y + 1) * vertices_side + x;
3993 indices[i++] = (y + 1) * vertices_side + x + 1;
3997 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
3998 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4000 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
4001 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
4002 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
4003 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
4004 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
4005 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
4006 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
4007 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
4008 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
4009 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
4010 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
4011 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
4013 memset(&material, 0, sizeof(material));
4014 U1(U2(material).specular).r = 1.0f;
4015 U2(U2(material).specular).g = 1.0f;
4016 U3(U2(material).specular).b = 1.0f;
4017 U4(U2(material).specular).a = 1.0f;
4018 U4(material).power = 30.0f;
4019 hr = IDirect3DDevice7_SetMaterial(device, &material);
4020 ok(SUCCEEDED(hr), "Failed to set material, hr %#x.\n", hr);
4022 hr = IDirect3DDevice7_LightEnable(device, 0, TRUE);
4023 ok(SUCCEEDED(hr), "Failed to enable light 0, hr %#x.\n", hr);
4024 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, TRUE);
4025 ok(SUCCEEDED(hr), "Failed to enable specular lighting, hr %#x.\n", hr);
4027 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
4029 hr = IDirect3DDevice7_SetLight(device, 0, tests[i].light);
4030 ok(SUCCEEDED(hr), "Failed to set light parameters, hr %#x.\n", hr);
4032 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LOCALVIEWER, tests[i].local_viewer);
4033 ok(SUCCEEDED(hr), "Failed to set local viewer state, hr %#x.\n", hr);
4035 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
4036 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
4038 hr = IDirect3DDevice7_BeginScene(device);
4039 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4041 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, quad,
4042 vertices_side * vertices_side, indices, indices_count, 0);
4043 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4045 hr = IDirect3DDevice7_EndScene(device);
4046 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4048 for (j = 0; j < tests[i].expected_count; ++j)
4050 color = get_surface_color(rt, tests[i].expected[j].x, tests[i].expected[j].y);
4051 ok(compare_color(color, tests[i].expected[j].color, 1),
4052 "Expected color 0x%08x at location (%u, %u), got 0x%08x, case %u.\n",
4053 tests[i].expected[j].color, tests[i].expected[j].x,
4054 tests[i].expected[j].y, color, i);
4058 IDirectDrawSurface7_Release(rt);
4060 refcount = IDirect3DDevice7_Release(device);
4061 ok(!refcount, "Device has %u references left.\n", refcount);
4062 DestroyWindow(window);
4063 HeapFree(GetProcessHeap(), 0, indices);
4064 HeapFree(GetProcessHeap(), 0, quad);
4067 static void test_clear_rect_count(void)
4069 IDirectDrawSurface7 *rt;
4070 IDirect3DDevice7 *device;
4071 D3DCOLOR color;
4072 HWND window;
4073 HRESULT hr;
4074 D3DRECT rect = {{0}, {0}, {640}, {480}};
4076 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4077 0, 0, 640, 480, 0, 0, 0, 0);
4078 if (!(device = create_device(window, DDSCL_NORMAL)))
4080 skip("Failed to create a 3D device, skipping test.\n");
4081 DestroyWindow(window);
4082 return;
4085 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
4086 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4088 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ffffff, 1.0f, 0);
4089 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4090 hr = IDirect3DDevice7_Clear(device, 0, &rect, D3DCLEAR_TARGET, 0x00ff0000, 1.0f, 0);
4091 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4093 color = get_surface_color(rt, 320, 240);
4094 ok(compare_color(color, 0x00ffffff, 1) || broken(compare_color(color, 0x00ff0000, 1)),
4095 "Clear with count = 0, rect != NULL has color %#08x.\n", color);
4097 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ffffff, 1.0f, 0);
4098 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4099 hr = IDirect3DDevice7_Clear(device, 1, NULL, D3DCLEAR_TARGET, 0x0000ff00, 1.0f, 0);
4100 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4102 color = get_surface_color(rt, 320, 240);
4103 ok(compare_color(color, 0x0000ff00, 1),
4104 "Clear with count = 1, rect = NULL has color %#08x.\n", color);
4106 IDirectDrawSurface7_Release(rt);
4107 IDirect3DDevice7_Release(device);
4108 DestroyWindow(window);
4111 static BOOL test_mode_restored(IDirectDraw7 *ddraw, HWND window)
4113 DDSURFACEDESC2 ddsd1, ddsd2;
4114 HRESULT hr;
4116 memset(&ddsd1, 0, sizeof(ddsd1));
4117 ddsd1.dwSize = sizeof(ddsd1);
4118 hr = IDirectDraw7_GetDisplayMode(ddraw, &ddsd1);
4119 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
4121 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4122 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4123 hr = set_display_mode(ddraw, 640, 480);
4124 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
4125 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4126 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4128 memset(&ddsd2, 0, sizeof(ddsd2));
4129 ddsd2.dwSize = sizeof(ddsd2);
4130 hr = IDirectDraw7_GetDisplayMode(ddraw, &ddsd2);
4131 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
4132 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
4133 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
4135 return ddsd1.dwWidth == ddsd2.dwWidth && ddsd1.dwHeight == ddsd2.dwHeight;
4138 static void test_coop_level_versions(void)
4140 HWND window;
4141 IDirectDraw *ddraw;
4142 HRESULT hr;
4143 BOOL restored;
4144 IDirectDrawSurface *surface;
4145 IDirectDraw7 *ddraw7;
4146 DDSURFACEDESC ddsd;
4148 window = CreateWindowA("static", "ddraw_test1", WS_OVERLAPPEDWINDOW,
4149 0, 0, 640, 480, 0, 0, 0, 0);
4151 ddraw7 = create_ddraw();
4152 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4153 /* Newly created ddraw objects restore the mode on ddraw2+::SetCooperativeLevel(NORMAL) */
4154 restored = test_mode_restored(ddraw7, window);
4155 ok(restored, "Display mode not restored in new ddraw object\n");
4157 /* A failing ddraw1::SetCooperativeLevel call does not have an effect */
4158 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4159 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4161 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4162 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
4163 restored = test_mode_restored(ddraw7, window);
4164 ok(restored, "Display mode not restored after bad ddraw1::SetCooperativeLevel call\n");
4166 /* A successful one does */
4167 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4168 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4169 restored = test_mode_restored(ddraw7, window);
4170 ok(!restored, "Display mode restored after good ddraw1::SetCooperativeLevel call\n");
4172 IDirectDraw_Release(ddraw);
4173 IDirectDraw7_Release(ddraw7);
4175 ddraw7 = create_ddraw();
4176 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4177 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4178 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4180 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_SETFOCUSWINDOW);
4181 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4182 restored = test_mode_restored(ddraw7, window);
4183 ok(!restored, "Display mode restored after ddraw1::SetCooperativeLevel(SETFOCUSWINDOW) call\n");
4185 IDirectDraw_Release(ddraw);
4186 IDirectDraw7_Release(ddraw7);
4188 /* A failing call does not restore the ddraw2+ behavior */
4189 ddraw7 = create_ddraw();
4190 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4191 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4192 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4194 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4195 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4196 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4197 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
4198 restored = test_mode_restored(ddraw7, window);
4199 ok(!restored, "Display mode restored after good-bad ddraw1::SetCooperativeLevel() call sequence\n");
4201 IDirectDraw_Release(ddraw);
4202 IDirectDraw7_Release(ddraw7);
4204 /* Neither does a sequence of successful calls with the new interface */
4205 ddraw7 = create_ddraw();
4206 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4207 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4208 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4210 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4211 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4212 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4213 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4214 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
4215 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4217 restored = test_mode_restored(ddraw7, window);
4218 ok(!restored, "Display mode restored after ddraw1-ddraw7 SetCooperativeLevel() call sequence\n");
4219 IDirectDraw_Release(ddraw);
4220 IDirectDraw7_Release(ddraw7);
4222 /* ddraw1::CreateSurface does not triger the ddraw1 behavior */
4223 ddraw7 = create_ddraw();
4224 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4225 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4226 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4228 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
4229 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4231 memset(&ddsd, 0, sizeof(ddsd));
4232 ddsd.dwSize = sizeof(ddsd);
4233 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
4234 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4235 ddsd.dwWidth = ddsd.dwHeight = 8;
4236 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
4237 ok(SUCCEEDED(hr), "CreateSurface failed, hr %#x.\n", hr);
4238 IDirectDrawSurface_Release(surface);
4239 restored = test_mode_restored(ddraw7, window);
4240 ok(restored, "Display mode not restored after ddraw1::CreateSurface() call\n");
4242 IDirectDraw_Release(ddraw);
4243 IDirectDraw7_Release(ddraw7);
4244 DestroyWindow(window);
4247 static void test_fog_special(void)
4249 static struct
4251 struct vec3 position;
4252 D3DCOLOR diffuse;
4254 quad[] =
4256 {{ -1.0f, 1.0f, 0.0f}, 0xff00ff00},
4257 {{ 1.0f, 1.0f, 1.0f}, 0xff00ff00},
4258 {{ -1.0f, -1.0f, 0.0f}, 0xff00ff00},
4259 {{ 1.0f, -1.0f, 1.0f}, 0xff00ff00},
4261 static const struct
4263 DWORD vertexmode, tablemode;
4264 D3DCOLOR color_left, color_right;
4266 tests[] =
4268 {D3DFOG_LINEAR, D3DFOG_NONE, 0x00ff0000, 0x00ff0000},
4269 {D3DFOG_NONE, D3DFOG_LINEAR, 0x0000ff00, 0x00ff0000},
4271 union
4273 float f;
4274 DWORD d;
4275 } conv;
4276 D3DCOLOR color;
4277 HRESULT hr;
4278 unsigned int i;
4279 HWND window;
4280 IDirect3DDevice7 *device;
4281 IDirectDrawSurface7 *rt;
4283 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4284 0, 0, 640, 480, 0, 0, 0, 0);
4286 if (!(device = create_device(window, DDSCL_NORMAL)))
4288 skip("Failed to create a 3D device, skipping test.\n");
4289 DestroyWindow(window);
4290 return;
4293 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
4294 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4296 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
4297 ok(SUCCEEDED(hr), "Failed to enable fog, hr %#x.\n", hr);
4298 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0xffff0000);
4299 ok(SUCCEEDED(hr), "Failed to set fog color, hr %#x.\n", hr);
4300 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
4301 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
4302 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
4303 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
4305 conv.f = 0.5f;
4306 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGSTART, conv.d);
4307 ok(SUCCEEDED(hr), "Failed to set fog start, hr %#x.\n", hr);
4308 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGEND, conv.d);
4309 ok(SUCCEEDED(hr), "Failed to set fog end, hr %#x.\n", hr);
4311 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
4313 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x000000ff, 1.0f, 0);
4314 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4316 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, tests[i].vertexmode);
4317 ok(SUCCEEDED(hr), "Failed to set fogvertexmode, hr %#x.\n", hr);
4318 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, tests[i].tablemode);
4319 ok(SUCCEEDED(hr), "Failed to set fogtablemode, hr %#x.\n", hr);
4321 hr = IDirect3DDevice7_BeginScene(device);
4322 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4323 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, 4, 0);
4324 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4325 hr = IDirect3DDevice7_EndScene(device);
4326 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4328 color = get_surface_color(rt, 310, 240);
4329 ok(compare_color(color, tests[i].color_left, 1),
4330 "Expected left color 0x%08x, got 0x%08x, case %u.\n", tests[i].color_left, color, i);
4331 color = get_surface_color(rt, 330, 240);
4332 ok(compare_color(color, tests[i].color_right, 1),
4333 "Expected right color 0x%08x, got 0x%08x, case %u.\n", tests[i].color_right, color, i);
4336 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
4337 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
4339 IDirectDrawSurface7_Release(rt);
4340 IDirect3DDevice7_Release(device);
4341 DestroyWindow(window);
4344 static void test_lighting_interface_versions(void)
4346 IDirect3DDevice7 *device;
4347 IDirectDrawSurface7 *rt;
4348 D3DCOLOR color;
4349 HWND window;
4350 HRESULT hr;
4351 DWORD rs;
4352 unsigned int i;
4353 ULONG ref;
4354 D3DMATERIAL7 material;
4355 static D3DVERTEX quad[] =
4357 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4358 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4359 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4360 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4363 #define FVF_COLORVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_SPECULAR)
4364 static struct
4366 struct vec3 position;
4367 struct vec3 normal;
4368 DWORD diffuse, specular;
4370 quad2[] =
4372 {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4373 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4374 {{-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4375 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4378 static D3DLVERTEX lquad[] =
4380 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4381 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4382 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4383 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4386 #define FVF_LVERTEX2 (D3DFVF_LVERTEX & ~D3DFVF_RESERVED1)
4387 static struct
4389 struct vec3 position;
4390 DWORD diffuse, specular;
4391 struct vec2 texcoord;
4393 lquad2[] =
4395 {{-1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
4396 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
4397 {{-1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
4398 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
4401 static D3DTLVERTEX tlquad[] =
4403 {{ 0.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4404 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4405 {{ 640.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4406 {{ 640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4409 static const struct
4411 DWORD vertextype;
4412 void *data;
4413 DWORD d3drs_lighting, d3drs_specular;
4414 DWORD draw_flags;
4415 D3DCOLOR color;
4417 tests[] =
4419 /* Lighting is enabled when D3DFVF_XYZ is used and D3DRENDERSTATE_LIGHTING is
4420 * enabled. D3DDP_DONOTLIGHT is ignored. Lighting is also enabled when normals
4421 * are not available
4423 * Note that the specular result is 0x00000000 when lighting is on even if the
4424 * input vertex has specular color because D3DRENDERSTATE_COLORVERTEX is not
4425 * enabled */
4427 /* 0 */
4428 { D3DFVF_VERTEX, quad, FALSE, FALSE, 0, 0x00ffffff},
4429 { D3DFVF_VERTEX, quad, TRUE, FALSE, 0, 0x0000ff00},
4430 { D3DFVF_VERTEX, quad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
4431 { D3DFVF_VERTEX, quad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
4432 { D3DFVF_VERTEX, quad, FALSE, TRUE, 0, 0x00ffffff},
4433 { D3DFVF_VERTEX, quad, TRUE, TRUE, 0, 0x0000ff00},
4434 { D3DFVF_VERTEX, quad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
4435 { D3DFVF_VERTEX, quad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
4437 /* 8 */
4438 { FVF_COLORVERTEX, quad2, FALSE, FALSE, 0, 0x00ff0000},
4439 { FVF_COLORVERTEX, quad2, TRUE, FALSE, 0, 0x0000ff00},
4440 { FVF_COLORVERTEX, quad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4441 { FVF_COLORVERTEX, quad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
4442 { FVF_COLORVERTEX, quad2, FALSE, TRUE, 0, 0x00ff8080},
4443 { FVF_COLORVERTEX, quad2, TRUE, TRUE, 0, 0x0000ff00},
4444 { FVF_COLORVERTEX, quad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4445 { FVF_COLORVERTEX, quad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
4447 /* 16 */
4448 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, 0, 0x00ff0000},
4449 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, 0, 0x0000ff00},
4450 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4451 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
4452 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, 0, 0x00ff8080},
4453 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, 0, 0x0000ff00},
4454 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4455 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
4457 /* 24 */
4458 { FVF_LVERTEX2, lquad2, FALSE, FALSE, 0, 0x00ff0000},
4459 { FVF_LVERTEX2, lquad2, TRUE, FALSE, 0, 0x0000ff00},
4460 { FVF_LVERTEX2, lquad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4461 { FVF_LVERTEX2, lquad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
4462 { FVF_LVERTEX2, lquad2, FALSE, TRUE, 0, 0x00ff8080},
4463 { FVF_LVERTEX2, lquad2, TRUE, TRUE, 0, 0x0000ff00},
4464 { FVF_LVERTEX2, lquad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4465 { FVF_LVERTEX2, lquad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
4467 /* 32 */
4468 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, 0, 0x000000ff},
4469 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, 0, 0x000000ff},
4470 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
4471 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
4472 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, 0, 0x008080ff},
4473 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, 0, 0x008080ff},
4474 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
4475 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
4478 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4479 0, 0, 640, 480, 0, 0, 0, 0);
4481 if (!(device = create_device(window, DDSCL_NORMAL)))
4483 skip("Failed to create a 3D device, skipping test.\n");
4484 DestroyWindow(window);
4485 return;
4488 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
4489 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4491 memset(&material, 0, sizeof(material));
4492 U2(U3(material).emissive).g = 1.0f;
4493 hr = IDirect3DDevice7_SetMaterial(device, &material);
4494 ok(SUCCEEDED(hr), "Failed set material, hr %#x.\n", hr);
4495 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
4496 ok(SUCCEEDED(hr), "Failed to disable z test, hr %#x.\n", hr);
4498 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &rs);
4499 ok(SUCCEEDED(hr), "Failed to get lighting render state, hr %#x.\n", hr);
4500 ok(rs == TRUE, "Initial D3DRENDERSTATE_LIGHTING is %#x, expected TRUE.\n", rs);
4501 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, &rs);
4502 ok(SUCCEEDED(hr), "Failed to get specularenable render state, hr %#x.\n", hr);
4503 ok(rs == FALSE, "Initial D3DRENDERSTATE_SPECULARENABLE is %#x, expected FALSE.\n", rs);
4505 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
4507 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff202020, 0.0f, 0);
4508 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
4510 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, tests[i].d3drs_lighting);
4511 ok(SUCCEEDED(hr), "Failed to set lighting render state, hr %#x.\n", hr);
4512 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE,
4513 tests[i].d3drs_specular);
4514 ok(SUCCEEDED(hr), "Failed to set specularenable render state, hr %#x.\n", hr);
4516 hr = IDirect3DDevice7_BeginScene(device);
4517 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4518 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
4519 tests[i].vertextype, tests[i].data, 4, tests[i].draw_flags | D3DDP_WAIT);
4520 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4521 hr = IDirect3DDevice7_EndScene(device);
4522 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4524 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &rs);
4525 ok(SUCCEEDED(hr), "Failed to get lighting render state, hr %#x.\n", hr);
4526 ok(rs == tests[i].d3drs_lighting, "D3DRENDERSTATE_LIGHTING is %#x, expected %#x.\n",
4527 rs, tests[i].d3drs_lighting);
4529 color = get_surface_color(rt, 320, 240);
4530 ok(compare_color(color, tests[i].color, 1),
4531 "Got unexpected color 0x%08x, expected 0x%08x, test %u.\n",
4532 color, tests[i].color, i);
4535 IDirectDrawSurface7_Release(rt);
4536 ref = IDirect3DDevice7_Release(device);
4537 ok(ref == 0, "Device not properly released, refcount %u.\n", ref);
4538 DestroyWindow(window);
4541 static struct
4543 BOOL received;
4544 IDirectDraw7 *ddraw;
4545 HWND window;
4546 DWORD coop_level;
4547 } activateapp_testdata;
4549 static LRESULT CALLBACK activateapp_test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
4551 if (message == WM_ACTIVATEAPP)
4553 if (activateapp_testdata.ddraw)
4555 HRESULT hr;
4556 activateapp_testdata.received = FALSE;
4557 hr = IDirectDraw7_SetCooperativeLevel(activateapp_testdata.ddraw,
4558 activateapp_testdata.window, activateapp_testdata.coop_level);
4559 ok(SUCCEEDED(hr), "Recursive SetCooperativeLevel call failed, hr %#x.\n", hr);
4560 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP during recursive SetCooperativeLevel call.\n");
4562 activateapp_testdata.received = TRUE;
4565 return DefWindowProcA(hwnd, message, wparam, lparam);
4568 static void test_coop_level_activateapp(void)
4570 IDirectDraw7 *ddraw;
4571 HRESULT hr;
4572 HWND window;
4573 WNDCLASSA wc = {0};
4574 DDSURFACEDESC2 ddsd;
4575 IDirectDrawSurface7 *surface;
4577 ddraw = create_ddraw();
4578 ok(!!ddraw, "Failed to create a ddraw object.\n");
4580 wc.lpfnWndProc = activateapp_test_proc;
4581 wc.lpszClassName = "ddraw_test_wndproc_wc";
4582 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4584 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
4585 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
4587 /* Exclusive with window already active. */
4588 SetForegroundWindow(window);
4589 activateapp_testdata.received = FALSE;
4590 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4591 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4592 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP although window was already active.\n");
4593 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4594 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4596 /* Exclusive with window not active. */
4597 SetForegroundWindow(GetDesktopWindow());
4598 activateapp_testdata.received = FALSE;
4599 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4600 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4601 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4602 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4603 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4605 /* Normal with window not active, then exclusive with the same window. */
4606 SetForegroundWindow(GetDesktopWindow());
4607 activateapp_testdata.received = FALSE;
4608 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4609 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4610 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP when setting DDSCL_NORMAL.\n");
4611 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4612 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4613 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4614 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4615 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4617 /* Recursive set of DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. */
4618 SetForegroundWindow(GetDesktopWindow());
4619 activateapp_testdata.received = FALSE;
4620 activateapp_testdata.ddraw = ddraw;
4621 activateapp_testdata.window = window;
4622 activateapp_testdata.coop_level = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
4623 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4624 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4625 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4626 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4627 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4629 /* The recursive call seems to have some bad effect on native ddraw, despite (apparently)
4630 * succeeding. Another switch to exclusive and back to normal is needed to release the
4631 * window properly. Without doing this, SetCooperativeLevel(EXCLUSIVE) will not send
4632 * WM_ACTIVATEAPP messages. */
4633 activateapp_testdata.ddraw = NULL;
4634 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4635 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4636 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4637 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4639 /* Setting DDSCL_NORMAL with recursive invocation. */
4640 SetForegroundWindow(GetDesktopWindow());
4641 activateapp_testdata.received = FALSE;
4642 activateapp_testdata.ddraw = ddraw;
4643 activateapp_testdata.window = window;
4644 activateapp_testdata.coop_level = DDSCL_NORMAL;
4645 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4646 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4647 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4649 /* DDraw is in exclusive mode now. */
4650 memset(&ddsd, 0, sizeof(ddsd));
4651 ddsd.dwSize = sizeof(ddsd);
4652 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
4653 U5(ddsd).dwBackBufferCount = 1;
4654 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
4655 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
4656 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4657 IDirectDrawSurface7_Release(surface);
4659 /* Recover again, just to be sure. */
4660 activateapp_testdata.ddraw = NULL;
4661 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4662 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4663 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4664 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4666 DestroyWindow(window);
4667 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
4668 IDirectDraw7_Release(ddraw);
4671 static void test_texturemanage(void)
4673 IDirectDraw7 *ddraw;
4674 HRESULT hr;
4675 DDSURFACEDESC2 ddsd;
4676 IDirectDrawSurface7 *surface;
4677 unsigned int i;
4678 DDCAPS hal_caps, hel_caps;
4679 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
4680 static const struct
4682 DWORD caps_in, caps2_in;
4683 HRESULT hr;
4684 DWORD caps_out, caps2_out;
4686 tests[] =
4688 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4689 ~0U, ~0U},
4690 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4691 ~0U, ~0U},
4692 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4693 ~0U, ~0U},
4694 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4695 ~0U, ~0U},
4696 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DD_OK,
4697 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE},
4698 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DD_OK,
4699 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE},
4700 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
4701 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_LOCALVIDMEM, 0},
4702 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
4703 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0},
4705 {0, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4706 ~0U, ~0U},
4707 {0, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4708 ~0U, ~0U},
4709 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4710 ~0U, ~0U},
4711 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4712 ~0U, ~0U},
4713 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4714 ~0U, ~0U},
4715 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4716 ~0U, ~0U},
4717 {DDSCAPS_VIDEOMEMORY, 0, DD_OK,
4718 DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY, 0},
4719 {DDSCAPS_SYSTEMMEMORY, 0, DD_OK,
4720 DDSCAPS_SYSTEMMEMORY, 0},
4723 ddraw = create_ddraw();
4724 ok(!!ddraw, "Failed to create a ddraw object.\n");
4725 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4726 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4728 memset(&hal_caps, 0, sizeof(hal_caps));
4729 hal_caps.dwSize = sizeof(hal_caps);
4730 memset(&hel_caps, 0, sizeof(hel_caps));
4731 hel_caps.dwSize = sizeof(hel_caps);
4732 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, &hel_caps);
4733 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
4734 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps)
4736 skip("Managed textures not supported, skipping managed texture test.\n");
4737 IDirectDraw7_Release(ddraw);
4738 return;
4741 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
4743 memset(&ddsd, 0, sizeof(ddsd));
4744 ddsd.dwSize = sizeof(ddsd);
4745 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
4746 ddsd.ddsCaps.dwCaps = tests[i].caps_in;
4747 ddsd.ddsCaps.dwCaps2 = tests[i].caps2_in;
4748 ddsd.dwWidth = 4;
4749 ddsd.dwHeight = 4;
4751 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
4752 if (tests[i].hr == DD_OK && is_ddraw64 && (tests[i].caps_in & DDSCAPS_TEXTURE))
4753 todo_wine ok(hr == E_NOINTERFACE, "Test %u: Got unexpected hr %#x.\n", i, hr);
4754 else
4755 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, tests[i].hr);
4756 if (FAILED(hr))
4757 continue;
4759 memset(&ddsd, 0, sizeof(ddsd));
4760 ddsd.dwSize = sizeof(ddsd);
4761 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
4762 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4764 ok(ddsd.ddsCaps.dwCaps == tests[i].caps_out,
4765 "Input caps %#x, %#x, expected output caps %#x, got %#x, case %u.\n",
4766 tests[i].caps_in, tests[i].caps2_in, tests[i].caps_out, ddsd.ddsCaps.dwCaps, i);
4767 ok(ddsd.ddsCaps.dwCaps2 == tests[i].caps2_out,
4768 "Input caps %#x, %#x, expected output caps %#x, got %#x, case %u.\n",
4769 tests[i].caps_in, tests[i].caps2_in, tests[i].caps2_out, ddsd.ddsCaps.dwCaps2, i);
4771 IDirectDrawSurface7_Release(surface);
4774 IDirectDraw7_Release(ddraw);
4777 #define SUPPORT_DXT1 0x01
4778 #define SUPPORT_DXT2 0x02
4779 #define SUPPORT_DXT3 0x04
4780 #define SUPPORT_DXT4 0x08
4781 #define SUPPORT_DXT5 0x10
4782 #define SUPPORT_YUY2 0x20
4783 #define SUPPORT_UYVY 0x40
4785 static HRESULT WINAPI test_block_formats_creation_cb(DDPIXELFORMAT *fmt, void *ctx)
4787 DWORD *supported_fmts = ctx;
4789 if (!(fmt->dwFlags & DDPF_FOURCC))
4790 return DDENUMRET_OK;
4792 switch (fmt->dwFourCC)
4794 case MAKEFOURCC('D','X','T','1'):
4795 *supported_fmts |= SUPPORT_DXT1;
4796 break;
4797 case MAKEFOURCC('D','X','T','2'):
4798 *supported_fmts |= SUPPORT_DXT2;
4799 break;
4800 case MAKEFOURCC('D','X','T','3'):
4801 *supported_fmts |= SUPPORT_DXT3;
4802 break;
4803 case MAKEFOURCC('D','X','T','4'):
4804 *supported_fmts |= SUPPORT_DXT4;
4805 break;
4806 case MAKEFOURCC('D','X','T','5'):
4807 *supported_fmts |= SUPPORT_DXT5;
4808 break;
4809 case MAKEFOURCC('Y','U','Y','2'):
4810 *supported_fmts |= SUPPORT_YUY2;
4811 break;
4812 case MAKEFOURCC('U','Y','V','Y'):
4813 *supported_fmts |= SUPPORT_UYVY;
4814 break;
4815 default:
4816 break;
4819 return DDENUMRET_OK;
4822 static void test_block_formats_creation(void)
4824 HRESULT hr, expect_hr;
4825 unsigned int i, j, w, h;
4826 HWND window;
4827 IDirectDraw7 *ddraw;
4828 IDirect3D7 *d3d;
4829 IDirect3DDevice7 *device;
4830 IDirectDrawSurface7 *surface;
4831 DWORD supported_fmts = 0, supported_overlay_fmts = 0;
4832 DWORD num_fourcc_codes = 0, *fourcc_codes;
4833 DDSURFACEDESC2 ddsd;
4834 DDCAPS hal_caps;
4835 void *mem;
4837 static const struct
4839 DWORD fourcc;
4840 const char *name;
4841 DWORD support_flag;
4842 unsigned int block_width;
4843 unsigned int block_height;
4844 unsigned int block_size;
4845 BOOL create_size_checked, overlay;
4847 formats[] =
4849 {MAKEFOURCC('D','X','T','1'), "D3DFMT_DXT1", SUPPORT_DXT1, 4, 4, 8, TRUE, FALSE},
4850 {MAKEFOURCC('D','X','T','2'), "D3DFMT_DXT2", SUPPORT_DXT2, 4, 4, 16, TRUE, FALSE},
4851 {MAKEFOURCC('D','X','T','3'), "D3DFMT_DXT3", SUPPORT_DXT3, 4, 4, 16, TRUE, FALSE},
4852 {MAKEFOURCC('D','X','T','4'), "D3DFMT_DXT4", SUPPORT_DXT4, 4, 4, 16, TRUE, FALSE},
4853 {MAKEFOURCC('D','X','T','5'), "D3DFMT_DXT5", SUPPORT_DXT5, 4, 4, 16, TRUE, FALSE},
4854 {MAKEFOURCC('Y','U','Y','2'), "D3DFMT_YUY2", SUPPORT_YUY2, 2, 1, 4, FALSE, TRUE },
4855 {MAKEFOURCC('U','Y','V','Y'), "D3DFMT_UYVY", SUPPORT_UYVY, 2, 1, 4, FALSE, TRUE },
4857 static const struct
4859 DWORD caps, caps2;
4860 const char *name;
4861 BOOL overlay;
4863 types[] =
4865 /* DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY fails to create any fourcc
4866 * surface with DDERR_INVALIDPIXELFORMAT. Don't care about it for now.
4868 * Nvidia returns E_FAIL on DXTN DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY.
4869 * Other hw / drivers successfully create those surfaces. Ignore them, this
4870 * suggests that no game uses this, otherwise Nvidia would support it. */
4872 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0,
4873 "videomemory texture", FALSE
4876 DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY, 0,
4877 "videomemory overlay", TRUE
4880 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0,
4881 "systemmemory texture", FALSE
4884 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
4885 "managed texture", FALSE
4888 enum size_type
4890 SIZE_TYPE_ZERO,
4891 SIZE_TYPE_PITCH,
4892 SIZE_TYPE_SIZE,
4894 static const struct
4896 DWORD flags;
4897 enum size_type size_type;
4898 int rel_size;
4899 HRESULT hr;
4901 user_mem_tests[] =
4903 {DDSD_LINEARSIZE, SIZE_TYPE_ZERO, 0, DD_OK},
4904 {DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
4905 {DDSD_PITCH, SIZE_TYPE_ZERO, 0, DD_OK},
4906 {DDSD_PITCH, SIZE_TYPE_PITCH, 0, DD_OK},
4907 {DDSD_LPSURFACE, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
4908 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
4909 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_PITCH, 0, DDERR_INVALIDPARAMS},
4910 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
4911 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 1, DD_OK},
4912 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, -1, DDERR_INVALIDPARAMS},
4913 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
4914 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_PITCH, 0, DDERR_INVALIDPARAMS},
4915 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_SIZE, 0, DDERR_INVALIDPARAMS},
4916 {DDSD_LPSURFACE | DDSD_PITCH | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DDERR_INVALIDPARAMS},
4919 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
4920 0, 0, 640, 480, 0, 0, 0, 0);
4922 if (!(device = create_device(window, DDSCL_NORMAL)))
4924 skip("Failed to create a 3D device, skipping test.\n");
4925 DestroyWindow(window);
4926 return;
4929 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
4930 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
4931 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **) &ddraw);
4932 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
4933 IDirect3D7_Release(d3d);
4935 hr = IDirect3DDevice7_EnumTextureFormats(device, test_block_formats_creation_cb,
4936 &supported_fmts);
4937 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
4939 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
4940 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
4941 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
4942 num_fourcc_codes * sizeof(*fourcc_codes));
4943 if (!fourcc_codes)
4944 goto cleanup;
4945 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
4946 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
4947 for (i = 0; i < num_fourcc_codes; i++)
4949 for (j = 0; j < sizeof(formats) / sizeof(*formats); j++)
4951 if (fourcc_codes[i] == formats[j].fourcc)
4952 supported_overlay_fmts |= formats[j].support_flag;
4955 HeapFree(GetProcessHeap(), 0, fourcc_codes);
4957 memset(&hal_caps, 0, sizeof(hal_caps));
4958 hal_caps.dwSize = sizeof(hal_caps);
4959 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
4960 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
4962 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 2 * 2 * 16 + 1);
4964 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
4966 for (j = 0; j < sizeof(types) / sizeof(*types); j++)
4968 BOOL support;
4970 if (formats[i].overlay != types[j].overlay
4971 || (types[j].overlay && !(hal_caps.dwCaps & DDCAPS_OVERLAY)))
4972 continue;
4974 if (formats[i].overlay)
4975 support = supported_overlay_fmts & formats[i].support_flag;
4976 else
4977 support = supported_fmts & formats[i].support_flag;
4979 for (w = 1; w <= 8; w++)
4981 for (h = 1; h <= 8; h++)
4983 BOOL block_aligned = TRUE;
4984 BOOL todo = FALSE;
4986 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
4987 block_aligned = FALSE;
4989 memset(&ddsd, 0, sizeof(ddsd));
4990 ddsd.dwSize = sizeof(ddsd);
4991 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
4992 ddsd.ddsCaps.dwCaps = types[j].caps;
4993 ddsd.ddsCaps.dwCaps2 = types[j].caps2;
4994 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
4995 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
4996 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
4997 ddsd.dwWidth = w;
4998 ddsd.dwHeight = h;
5000 /* TODO: Handle power of two limitations. I cannot test the pow2
5001 * behavior on windows because I have no hardware that doesn't at
5002 * least support np2_conditional. There's probably no HW that
5003 * supports DXTN textures but no conditional np2 textures. */
5004 if (!support && !(types[j].caps & DDSCAPS_SYSTEMMEMORY))
5005 expect_hr = DDERR_INVALIDPARAMS;
5006 else if (formats[i].create_size_checked && !block_aligned)
5008 expect_hr = DDERR_INVALIDPARAMS;
5009 if (!(types[j].caps & DDSCAPS_TEXTURE))
5010 todo = TRUE;
5012 else
5013 expect_hr = D3D_OK;
5015 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5016 todo_wine_if (todo)
5017 ok(hr == expect_hr,
5018 "Got unexpected hr %#x for format %s, resource type %s, size %ux%u, expected %#x.\n",
5019 hr, formats[i].name, types[j].name, w, h, expect_hr);
5021 if (SUCCEEDED(hr))
5022 IDirectDrawSurface7_Release(surface);
5027 if (formats[i].overlay)
5028 continue;
5030 for (j = 0; j < sizeof(user_mem_tests) / sizeof(*user_mem_tests); ++j)
5032 memset(&ddsd, 0, sizeof(ddsd));
5033 ddsd.dwSize = sizeof(ddsd);
5034 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | user_mem_tests[j].flags;
5035 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE;
5037 switch (user_mem_tests[j].size_type)
5039 case SIZE_TYPE_ZERO:
5040 U1(ddsd).dwLinearSize = 0;
5041 break;
5043 case SIZE_TYPE_PITCH:
5044 U1(ddsd).dwLinearSize = 2 * formats[i].block_size;
5045 break;
5047 case SIZE_TYPE_SIZE:
5048 U1(ddsd).dwLinearSize = 2 * 2 * formats[i].block_size;
5049 break;
5051 U1(ddsd).dwLinearSize += user_mem_tests[j].rel_size;
5053 ddsd.lpSurface = mem;
5054 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
5055 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
5056 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
5057 ddsd.dwWidth = 8;
5058 ddsd.dwHeight = 8;
5060 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5061 ok(hr == user_mem_tests[j].hr, "Test %u: Got unexpected hr %#x, format %s.\n", j, hr, formats[i].name);
5063 if (FAILED(hr))
5064 continue;
5066 memset(&ddsd, 0, sizeof(ddsd));
5067 ddsd.dwSize = sizeof(ddsd);
5068 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
5069 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", j, hr);
5070 ok(ddsd.dwFlags == (DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_LINEARSIZE),
5071 "Test %u: Got unexpected flags %#x.\n", j, ddsd.dwFlags);
5072 if (user_mem_tests[j].flags & DDSD_LPSURFACE)
5073 ok(U1(ddsd).dwLinearSize == ~0u, "Test %u: Got unexpected linear size %#x.\n",
5074 j, U1(ddsd).dwLinearSize);
5075 else
5076 ok(U1(ddsd).dwLinearSize == 2 * 2 * formats[i].block_size,
5077 "Test %u: Got unexpected linear size %#x, expected %#x.\n",
5078 j, U1(ddsd).dwLinearSize, 2 * 2 * formats[i].block_size);
5079 IDirectDrawSurface7_Release(surface);
5083 HeapFree(GetProcessHeap(), 0, mem);
5084 cleanup:
5085 IDirectDraw7_Release(ddraw);
5086 IDirect3DDevice7_Release(device);
5087 DestroyWindow(window);
5090 struct format_support_check
5092 const DDPIXELFORMAT *format;
5093 BOOL supported;
5096 static HRESULT WINAPI test_unsupported_formats_cb(DDPIXELFORMAT *fmt, void *ctx)
5098 struct format_support_check *format = ctx;
5100 if (!memcmp(format->format, fmt, sizeof(*fmt)))
5102 format->supported = TRUE;
5103 return DDENUMRET_CANCEL;
5106 return DDENUMRET_OK;
5109 static void test_unsupported_formats(void)
5111 HRESULT hr;
5112 BOOL expect_success;
5113 HWND window;
5114 IDirectDraw7 *ddraw;
5115 IDirect3D7 *d3d;
5116 IDirect3DDevice7 *device;
5117 IDirectDrawSurface7 *surface;
5118 DDSURFACEDESC2 ddsd;
5119 unsigned int i, j;
5120 DWORD expected_caps;
5121 static const struct
5123 const char *name;
5124 DDPIXELFORMAT fmt;
5126 formats[] =
5129 "D3DFMT_A8R8G8B8",
5131 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
5132 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
5136 "D3DFMT_P8",
5138 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
5139 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
5143 static const DWORD caps[] = {0, DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY};
5145 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5146 0, 0, 640, 480, 0, 0, 0, 0);
5148 if (!(device = create_device(window, DDSCL_NORMAL)))
5150 skip("Failed to create a 3D device, skipping test.\n");
5151 DestroyWindow(window);
5152 return;
5155 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
5156 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
5157 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **) &ddraw);
5158 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
5159 IDirect3D7_Release(d3d);
5161 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
5163 struct format_support_check check = {&formats[i].fmt, FALSE};
5164 hr = IDirect3DDevice7_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
5165 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
5167 for (j = 0; j < sizeof(caps) / sizeof(*caps); j++)
5169 memset(&ddsd, 0, sizeof(ddsd));
5170 ddsd.dwSize = sizeof(ddsd);
5171 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
5172 U4(ddsd).ddpfPixelFormat = formats[i].fmt;
5173 ddsd.dwWidth = 4;
5174 ddsd.dwHeight = 4;
5175 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | caps[j];
5177 if (caps[j] & DDSCAPS_VIDEOMEMORY && !check.supported)
5178 expect_success = FALSE;
5179 else
5180 expect_success = TRUE;
5182 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5183 ok(SUCCEEDED(hr) == expect_success,
5184 "Got unexpected hr %#x for format %s, caps %#x, expected %s.\n",
5185 hr, formats[i].name, caps[j], expect_success ? "success" : "failure");
5186 if (FAILED(hr))
5187 continue;
5189 memset(&ddsd, 0, sizeof(ddsd));
5190 ddsd.dwSize = sizeof(ddsd);
5191 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
5192 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5194 if (caps[j] & DDSCAPS_VIDEOMEMORY)
5195 expected_caps = DDSCAPS_VIDEOMEMORY;
5196 else if (caps[j] & DDSCAPS_SYSTEMMEMORY)
5197 expected_caps = DDSCAPS_SYSTEMMEMORY;
5198 else if (check.supported)
5199 expected_caps = DDSCAPS_VIDEOMEMORY;
5200 else
5201 expected_caps = DDSCAPS_SYSTEMMEMORY;
5203 ok(ddsd.ddsCaps.dwCaps & expected_caps,
5204 "Expected capability %#x, format %s, input cap %#x.\n",
5205 expected_caps, formats[i].name, caps[j]);
5207 IDirectDrawSurface7_Release(surface);
5211 IDirectDraw7_Release(ddraw);
5212 IDirect3DDevice7_Release(device);
5213 DestroyWindow(window);
5216 static void test_rt_caps(void)
5218 const GUID *devtype = &IID_IDirect3DHALDevice;
5219 PALETTEENTRY palette_entries[256];
5220 IDirectDrawPalette *palette;
5221 IDirectDraw7 *ddraw;
5222 BOOL hal_ok = FALSE;
5223 DDPIXELFORMAT z_fmt;
5224 IDirect3D7 *d3d;
5225 unsigned int i;
5226 ULONG refcount;
5227 HWND window;
5228 HRESULT hr;
5230 static const DDPIXELFORMAT p8_fmt =
5232 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
5233 {8}, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000},
5236 const struct
5238 const DDPIXELFORMAT *pf;
5239 DWORD caps_in;
5240 DWORD caps_out;
5241 HRESULT create_device_hr;
5242 HRESULT set_rt_hr, alternative_set_rt_hr;
5244 test_data[] =
5247 NULL,
5248 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
5249 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5250 D3D_OK,
5251 D3D_OK,
5252 D3D_OK,
5255 NULL,
5256 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5257 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5258 D3D_OK,
5259 D3D_OK,
5260 D3D_OK,
5263 NULL,
5264 DDSCAPS_OFFSCREENPLAIN,
5265 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5266 DDERR_INVALIDCAPS,
5267 DDERR_INVALIDCAPS,
5268 DDERR_INVALIDCAPS,
5271 NULL,
5272 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5273 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5274 D3DERR_SURFACENOTINVIDMEM,
5275 DDERR_INVALIDPARAMS,
5276 D3D_OK,
5279 NULL,
5280 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5281 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5282 DDERR_INVALIDCAPS,
5283 DDERR_INVALIDCAPS,
5284 DDERR_INVALIDCAPS,
5287 NULL,
5288 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
5289 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5290 D3D_OK,
5291 D3D_OK,
5292 D3D_OK,
5295 NULL,
5296 DDSCAPS_3DDEVICE,
5297 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5298 D3D_OK,
5299 D3D_OK,
5300 D3D_OK,
5303 NULL,
5305 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5306 DDERR_INVALIDCAPS,
5307 DDERR_INVALIDCAPS,
5308 DDERR_INVALIDCAPS,
5311 NULL,
5312 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5313 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5314 D3DERR_SURFACENOTINVIDMEM,
5315 DDERR_INVALIDPARAMS,
5316 D3D_OK,
5319 NULL,
5320 DDSCAPS_SYSTEMMEMORY,
5321 DDSCAPS_SYSTEMMEMORY,
5322 DDERR_INVALIDCAPS,
5323 DDERR_INVALIDCAPS,
5324 DDERR_INVALIDCAPS,
5327 &p8_fmt,
5329 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5330 DDERR_INVALIDCAPS,
5331 DDERR_INVALIDCAPS,
5332 DDERR_INVALIDCAPS,
5335 &p8_fmt,
5336 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5337 ~0U /* AMD r200 */,
5338 DDERR_NOPALETTEATTACHED,
5339 DDERR_INVALIDCAPS,
5340 DDERR_INVALIDCAPS,
5343 &p8_fmt,
5344 DDSCAPS_OFFSCREENPLAIN,
5345 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5346 DDERR_INVALIDCAPS,
5347 DDERR_INVALIDCAPS,
5348 DDERR_INVALIDCAPS,
5351 &p8_fmt,
5352 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5353 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5354 DDERR_NOPALETTEATTACHED,
5355 DDERR_INVALIDCAPS,
5356 DDERR_INVALIDCAPS,
5359 &p8_fmt,
5360 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5361 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5362 DDERR_INVALIDCAPS,
5363 DDERR_INVALIDCAPS,
5364 DDERR_INVALIDCAPS,
5367 &z_fmt,
5368 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
5369 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5370 DDERR_INVALIDCAPS,
5371 DDERR_INVALIDPIXELFORMAT,
5372 DDERR_INVALIDPIXELFORMAT,
5375 &z_fmt,
5376 DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5377 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5378 DDERR_INVALIDCAPS,
5379 DDERR_INVALIDPIXELFORMAT,
5380 DDERR_INVALIDPIXELFORMAT,
5383 &z_fmt,
5384 DDSCAPS_ZBUFFER,
5385 DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5386 DDERR_INVALIDCAPS,
5387 DDERR_INVALIDCAPS,
5388 DDERR_INVALIDCAPS,
5391 &z_fmt,
5392 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5393 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5394 DDERR_INVALIDCAPS,
5395 DDERR_INVALIDPARAMS,
5396 DDERR_INVALIDPIXELFORMAT,
5399 &z_fmt,
5400 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
5401 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
5402 DDERR_INVALIDCAPS,
5403 DDERR_INVALIDCAPS,
5404 DDERR_INVALIDCAPS,
5408 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5409 0, 0, 640, 480, 0, 0, 0, 0);
5410 ddraw = create_ddraw();
5411 ok(!!ddraw, "Failed to create a ddraw object.\n");
5412 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5413 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5415 if (FAILED(IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d)))
5417 skip("D3D interface is not available, skipping test.\n");
5418 goto done;
5421 hr = IDirect3D7_EnumDevices(d3d, enum_devtype_cb, &hal_ok);
5422 ok(SUCCEEDED(hr), "Failed to enumerate devices, hr %#x.\n", hr);
5423 if (hal_ok)
5424 devtype = &IID_IDirect3DTnLHalDevice;
5426 memset(&z_fmt, 0, sizeof(z_fmt));
5427 hr = IDirect3D7_EnumZBufferFormats(d3d, devtype, enum_z_fmt, &z_fmt);
5428 if (FAILED(hr) || !z_fmt.dwSize)
5430 skip("No depth buffer formats available, skipping test.\n");
5431 IDirect3D7_Release(d3d);
5432 goto done;
5435 memset(palette_entries, 0, sizeof(palette_entries));
5436 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
5437 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
5439 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
5441 IDirectDrawSurface7 *surface, *rt, *expected_rt, *tmp;
5442 DDSURFACEDESC2 surface_desc;
5443 IDirect3DDevice7 *device;
5445 memset(&surface_desc, 0, sizeof(surface_desc));
5446 surface_desc.dwSize = sizeof(surface_desc);
5447 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5448 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5449 if (test_data[i].pf)
5451 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
5452 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
5454 surface_desc.dwWidth = 640;
5455 surface_desc.dwHeight = 480;
5456 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5457 ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
5458 i, test_data[i].caps_in, hr);
5460 memset(&surface_desc, 0, sizeof(surface_desc));
5461 surface_desc.dwSize = sizeof(surface_desc);
5462 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
5463 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
5464 ok(test_data[i].caps_out == ~0U || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out,
5465 "Test %u: Got unexpected caps %#x, expected %#x.\n",
5466 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
5468 hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
5469 ok(hr == test_data[i].create_device_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n",
5470 i, hr, test_data[i].create_device_hr);
5471 if (FAILED(hr))
5473 if (hr == DDERR_NOPALETTEATTACHED)
5475 hr = IDirectDrawSurface7_SetPalette(surface, palette);
5476 ok(SUCCEEDED(hr), "Test %u: Failed to set palette, hr %#x.\n", i, hr);
5477 hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
5478 if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
5479 ok(hr == DDERR_INVALIDPIXELFORMAT, "Test %u: Got unexpected hr %#x.\n", i, hr);
5480 else
5481 ok(hr == D3DERR_SURFACENOTINVIDMEM, "Test %u: Got unexpected hr %#x.\n", i, hr);
5483 IDirectDrawSurface7_Release(surface);
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 = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
5489 surface_desc.dwWidth = 640;
5490 surface_desc.dwHeight = 480;
5491 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5492 ok(SUCCEEDED(hr), "Test %u: Failed to create surface, hr %#x.\n", i, hr);
5494 hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
5495 ok(SUCCEEDED(hr), "Test %u: Failed to create device, hr %#x.\n", i, hr);
5498 memset(&surface_desc, 0, sizeof(surface_desc));
5499 surface_desc.dwSize = sizeof(surface_desc);
5500 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5501 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5502 if (test_data[i].pf)
5504 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
5505 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
5507 surface_desc.dwWidth = 640;
5508 surface_desc.dwHeight = 480;
5509 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &rt, NULL);
5510 ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
5511 i, test_data[i].caps_in, hr);
5513 hr = IDirect3DDevice7_SetRenderTarget(device, rt, 0);
5514 ok(hr == test_data[i].set_rt_hr || broken(hr == test_data[i].alternative_set_rt_hr),
5515 "Test %u: Got unexpected hr %#x, expected %#x.\n",
5516 i, hr, test_data[i].set_rt_hr);
5517 if (SUCCEEDED(hr) || hr == DDERR_INVALIDPIXELFORMAT)
5518 expected_rt = rt;
5519 else
5520 expected_rt = surface;
5522 hr = IDirect3DDevice7_GetRenderTarget(device, &tmp);
5523 ok(SUCCEEDED(hr), "Test %u: Failed to get render target, hr %#x.\n", i, hr);
5524 ok(tmp == expected_rt, "Test %u: Got unexpected rt %p.\n", i, tmp);
5526 IDirectDrawSurface7_Release(tmp);
5527 IDirectDrawSurface7_Release(rt);
5528 refcount = IDirect3DDevice7_Release(device);
5529 ok(refcount == 0, "Test %u: The device was not properly freed, refcount %u.\n", i, refcount);
5530 refcount = IDirectDrawSurface7_Release(surface);
5531 ok(refcount == 0, "Test %u: The surface was not properly freed, refcount %u.\n", i, refcount);
5534 IDirectDrawPalette_Release(palette);
5535 IDirect3D7_Release(d3d);
5537 done:
5538 refcount = IDirectDraw7_Release(ddraw);
5539 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5540 DestroyWindow(window);
5543 static void test_primary_caps(void)
5545 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
5546 IDirectDrawSurface7 *surface;
5547 DDSURFACEDESC2 surface_desc;
5548 IDirectDraw7 *ddraw;
5549 unsigned int i;
5550 ULONG refcount;
5551 HWND window;
5552 HRESULT hr;
5554 static const struct
5556 DWORD coop_level;
5557 DWORD caps_in;
5558 DWORD back_buffer_count;
5559 HRESULT hr;
5560 DWORD caps_out;
5562 test_data[] =
5565 DDSCL_NORMAL,
5566 DDSCAPS_PRIMARYSURFACE,
5567 ~0u,
5568 DD_OK,
5569 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE,
5572 DDSCL_NORMAL,
5573 DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE,
5574 ~0u,
5575 DDERR_INVALIDCAPS,
5576 ~0u,
5579 DDSCL_NORMAL,
5580 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
5581 ~0u,
5582 DDERR_INVALIDCAPS,
5583 ~0u,
5586 DDSCL_NORMAL,
5587 DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER,
5588 ~0u,
5589 DDERR_INVALIDCAPS,
5590 ~0u,
5593 DDSCL_NORMAL,
5594 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP,
5595 ~0u,
5596 DDERR_INVALIDCAPS,
5597 ~0u,
5600 DDSCL_NORMAL,
5601 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX,
5602 ~0u,
5603 DDERR_INVALIDCAPS,
5604 ~0u,
5607 DDSCL_NORMAL,
5608 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5609 ~0u,
5610 DDERR_INVALIDCAPS,
5611 ~0u,
5614 DDSCL_NORMAL,
5615 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5617 DDERR_INVALIDCAPS,
5618 ~0u,
5621 DDSCL_NORMAL,
5622 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5624 DDERR_NOEXCLUSIVEMODE,
5625 ~0u,
5628 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5629 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5631 DDERR_INVALIDCAPS,
5632 ~0u,
5635 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5636 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5638 DD_OK,
5639 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX,
5642 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5643 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER,
5645 DDERR_INVALIDCAPS,
5646 ~0u,
5649 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5650 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_BACKBUFFER,
5652 DDERR_INVALIDCAPS,
5653 ~0u,
5657 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5658 0, 0, 640, 480, 0, 0, 0, 0);
5659 ddraw = create_ddraw();
5660 ok(!!ddraw, "Failed to create a ddraw object.\n");
5662 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
5664 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, test_data[i].coop_level);
5665 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5667 memset(&surface_desc, 0, sizeof(surface_desc));
5668 surface_desc.dwSize = sizeof(surface_desc);
5669 surface_desc.dwFlags = DDSD_CAPS;
5670 if (test_data[i].back_buffer_count != ~0u)
5671 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
5672 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5673 U5(surface_desc).dwBackBufferCount = test_data[i].back_buffer_count;
5674 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5675 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
5676 if (FAILED(hr))
5677 continue;
5679 memset(&surface_desc, 0, sizeof(surface_desc));
5680 surface_desc.dwSize = sizeof(surface_desc);
5681 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
5682 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
5683 ok((surface_desc.ddsCaps.dwCaps & ~placement) == test_data[i].caps_out,
5684 "Test %u: Got unexpected caps %#x, expected %#x.\n",
5685 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
5687 IDirectDrawSurface7_Release(surface);
5690 refcount = IDirectDraw7_Release(ddraw);
5691 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5692 DestroyWindow(window);
5695 static void test_surface_lock(void)
5697 IDirectDraw7 *ddraw;
5698 IDirect3D7 *d3d = NULL;
5699 IDirectDrawSurface7 *surface;
5700 IDirect3DDevice7 *device;
5701 HRESULT hr, expected_hr;
5702 HWND window;
5703 unsigned int i;
5704 DDSURFACEDESC2 ddsd;
5705 ULONG refcount;
5706 DDPIXELFORMAT z_fmt;
5707 BOOL hal_ok = FALSE;
5708 const GUID *devtype = &IID_IDirect3DHALDevice;
5709 D3DDEVICEDESC7 device_desc;
5710 BOOL cubemap_supported;
5711 static const struct
5713 DWORD caps;
5714 DWORD caps2;
5715 const char *name;
5717 tests[] =
5720 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
5722 "videomemory offscreenplain"
5725 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5727 "systemmemory offscreenplain"
5730 DDSCAPS_PRIMARYSURFACE,
5732 "primary"
5735 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
5737 "videomemory texture"
5740 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
5741 DDSCAPS2_OPAQUE,
5742 "opaque videomemory texture"
5745 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
5747 "systemmemory texture"
5750 DDSCAPS_TEXTURE,
5751 DDSCAPS2_TEXTUREMANAGE,
5752 "managed texture"
5755 DDSCAPS_TEXTURE,
5756 DDSCAPS2_D3DTEXTUREMANAGE,
5757 "managed texture"
5760 DDSCAPS_TEXTURE,
5761 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_OPAQUE,
5762 "opaque managed texture"
5765 DDSCAPS_TEXTURE,
5766 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_OPAQUE,
5767 "opaque managed texture"
5770 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5772 "render target"
5775 DDSCAPS_ZBUFFER,
5777 "Z buffer"
5780 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY,
5781 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
5782 "videomemory cube"
5785 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY,
5786 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_OPAQUE,
5787 "opaque videomemory cube"
5790 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_SYSTEMMEMORY,
5791 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
5792 "systemmemory cube"
5795 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
5796 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
5797 "managed cube"
5800 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
5801 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
5802 "managed cube"
5805 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
5806 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_OPAQUE,
5807 "opaque managed cube"
5810 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
5811 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_OPAQUE,
5812 "opaque managed cube"
5816 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5817 0, 0, 640, 480, 0, 0, 0, 0);
5818 ddraw = create_ddraw();
5819 ok(!!ddraw, "Failed to create a ddraw object.\n");
5820 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5821 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5823 if (FAILED(IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d)))
5825 skip("D3D interface is not available, skipping test.\n");
5826 goto done;
5829 hr = IDirect3D7_EnumDevices(d3d, enum_devtype_cb, &hal_ok);
5830 ok(SUCCEEDED(hr), "Failed to enumerate devices, hr %#x.\n", hr);
5831 if (hal_ok)
5832 devtype = &IID_IDirect3DTnLHalDevice;
5834 memset(&z_fmt, 0, sizeof(z_fmt));
5835 hr = IDirect3D7_EnumZBufferFormats(d3d, devtype, enum_z_fmt, &z_fmt);
5836 if (FAILED(hr) || !z_fmt.dwSize)
5838 skip("No depth buffer formats available, skipping test.\n");
5839 goto done;
5842 memset(&ddsd, 0, sizeof(ddsd));
5843 ddsd.dwSize = sizeof(ddsd);
5844 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5845 ddsd.dwWidth = 64;
5846 ddsd.dwHeight = 64;
5847 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
5848 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5849 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5851 hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
5852 ok(SUCCEEDED(hr), "Failed to create device, hr %#x.\n", hr);
5853 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
5854 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5855 cubemap_supported = !!(device_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP);
5856 IDirect3DDevice7_Release(device);
5858 IDirectDrawSurface7_Release(surface);
5860 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
5862 if (!cubemap_supported && tests[i].caps2 & DDSCAPS2_CUBEMAP)
5863 continue;
5865 memset(&ddsd, 0, sizeof(ddsd));
5866 ddsd.dwSize = sizeof(ddsd);
5867 ddsd.dwFlags = DDSD_CAPS;
5868 if (!(tests[i].caps & DDSCAPS_PRIMARYSURFACE))
5870 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
5871 ddsd.dwWidth = 64;
5872 ddsd.dwHeight = 64;
5874 if (tests[i].caps & DDSCAPS_ZBUFFER)
5876 ddsd.dwFlags |= DDSD_PIXELFORMAT;
5877 U4(ddsd).ddpfPixelFormat = z_fmt;
5879 ddsd.ddsCaps.dwCaps = tests[i].caps;
5880 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
5882 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5883 ok(SUCCEEDED(hr), "Failed to create surface, type %s, hr %#x.\n", tests[i].name, hr);
5885 memset(&ddsd, 0, sizeof(ddsd));
5886 ddsd.dwSize = sizeof(ddsd);
5887 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
5888 ok(SUCCEEDED(hr), "Failed to lock surface, type %s, hr %#x.\n", tests[i].name, hr);
5889 if (SUCCEEDED(hr))
5891 ok(ddsd.dwSize == sizeof(ddsd), "Got unexpected dwSize %u, type %s.\n", ddsd.dwSize, tests[i].name);
5892 hr = IDirectDrawSurface7_Unlock(surface, NULL);
5893 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
5896 memset(&ddsd, 0, sizeof(ddsd));
5897 expected_hr = tests[i].caps & DDSCAPS_TEXTURE && !(tests[i].caps & DDSCAPS_VIDEOMEMORY)
5898 ? DD_OK : DDERR_INVALIDPARAMS;
5899 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
5900 ok(hr == expected_hr, "Got hr %#x, expected %#x, type %s.\n", hr, expected_hr, tests[i].name);
5901 if (SUCCEEDED(hr))
5903 ok(!ddsd.dwSize, "Got unexpected dwSize %u, type %s.\n", ddsd.dwSize, tests[i].name);
5904 ok(!!ddsd.lpSurface, "Got NULL lpSurface, type %s.\n", tests[i].name);
5905 hr = IDirectDrawSurface7_Unlock(surface, NULL);
5906 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
5909 IDirectDrawSurface7_Release(surface);
5912 done:
5913 if (d3d)
5914 IDirect3D7_Release(d3d);
5915 refcount = IDirectDraw7_Release(ddraw);
5916 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5917 DestroyWindow(window);
5920 static void test_surface_discard(void)
5922 IDirect3DDevice7 *device;
5923 IDirect3D7 *d3d;
5924 IDirectDraw7 *ddraw;
5925 HRESULT hr;
5926 HWND window;
5927 DDSURFACEDESC2 ddsd;
5928 IDirectDrawSurface7 *surface, *target;
5929 void *addr;
5930 static const struct
5932 DWORD caps, caps2;
5933 BOOL discard;
5935 tests[] =
5937 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, TRUE},
5938 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
5939 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, TRUE},
5940 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
5941 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE},
5942 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
5943 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE},
5944 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
5946 unsigned int i;
5948 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
5949 0, 0, 640, 480, 0, 0, 0, 0);
5951 if (!(device = create_device(window, DDSCL_NORMAL)))
5953 skip("Failed to create a 3D device, skipping test.\n");
5954 DestroyWindow(window);
5955 return;
5957 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
5958 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
5959 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
5960 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
5961 hr = IDirect3DDevice7_GetRenderTarget(device, &target);
5962 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
5964 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
5966 BOOL discarded;
5968 memset(&ddsd, 0, sizeof(ddsd));
5969 ddsd.dwSize = sizeof(ddsd);
5970 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5971 ddsd.ddsCaps.dwCaps = tests[i].caps;
5972 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
5973 ddsd.dwWidth = 64;
5974 ddsd.dwHeight = 64;
5975 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5976 ok(SUCCEEDED(hr), "Failed to create offscreen surface, hr %#x, case %u.\n", hr, i);
5978 memset(&ddsd, 0, sizeof(ddsd));
5979 ddsd.dwSize = sizeof(ddsd);
5980 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, 0, NULL);
5981 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5982 addr = ddsd.lpSurface;
5983 hr = IDirectDrawSurface7_Unlock(surface, NULL);
5984 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5986 memset(&ddsd, 0, sizeof(ddsd));
5987 ddsd.dwSize = sizeof(ddsd);
5988 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
5989 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5990 discarded = ddsd.lpSurface != addr;
5991 hr = IDirectDrawSurface7_Unlock(surface, NULL);
5992 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5994 hr = IDirectDrawSurface7_Blt(target, NULL, surface, NULL, DDBLT_WAIT, NULL);
5995 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
5997 memset(&ddsd, 0, sizeof(ddsd));
5998 ddsd.dwSize = sizeof(ddsd);
5999 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
6000 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6001 discarded |= ddsd.lpSurface != addr;
6002 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6003 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6005 IDirectDrawSurface7_Release(surface);
6007 /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler,
6008 * AMD r500, evergreen). Windows XP, at least on AMD r200, does not. */
6009 ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i);
6012 IDirectDrawSurface7_Release(target);
6013 IDirectDraw7_Release(ddraw);
6014 IDirect3D7_Release(d3d);
6015 IDirect3DDevice7_Release(device);
6016 DestroyWindow(window);
6019 static void test_flip(void)
6021 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
6022 IDirectDrawSurface7 *frontbuffer, *backbuffer1, *backbuffer2, *backbuffer3, *surface;
6023 DDSCAPS2 caps = {DDSCAPS_FLIP, 0, 0, {0}};
6024 DDSURFACEDESC2 surface_desc;
6025 D3DDEVICEDESC7 device_desc;
6026 IDirect3DDevice7 *device;
6027 BOOL sysmem_primary;
6028 IDirectDraw7 *ddraw;
6029 DWORD expected_caps;
6030 unsigned int i;
6031 D3DCOLOR color;
6032 ULONG refcount;
6033 HWND window;
6034 DDBLTFX fx;
6035 HRESULT hr;
6037 static const struct
6039 const char *name;
6040 DWORD caps;
6042 test_data[] =
6044 {"PRIMARYSURFACE", DDSCAPS_PRIMARYSURFACE},
6045 {"OFFSCREENPLAIN", DDSCAPS_OFFSCREENPLAIN},
6046 {"TEXTURE", DDSCAPS_TEXTURE},
6049 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6050 0, 0, 640, 480, 0, 0, 0, 0);
6051 ddraw = create_ddraw();
6052 ok(!!ddraw, "Failed to create a ddraw object.\n");
6054 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6055 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6057 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
6059 /* Creating a flippable texture induces a BSoD on some versions of the
6060 * Intel graphics driver. At least Intel GMA 950 with driver version
6061 * 6.14.10.4926 on Windows XP SP3 is affected. */
6062 if ((test_data[i].caps & DDSCAPS_TEXTURE) && ddraw_is_intel(ddraw))
6064 win_skip("Skipping flippable texture test.\n");
6065 continue;
6068 memset(&surface_desc, 0, sizeof(surface_desc));
6069 surface_desc.dwSize = sizeof(surface_desc);
6070 surface_desc.dwFlags = DDSD_CAPS;
6071 if (!(test_data[i].caps & DDSCAPS_PRIMARYSURFACE))
6072 surface_desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
6073 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
6074 surface_desc.dwWidth = 512;
6075 surface_desc.dwHeight = 512;
6076 U5(surface_desc).dwBackBufferCount = 3;
6077 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6078 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6080 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_FLIP;
6081 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
6082 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6083 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6085 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_COMPLEX;
6086 surface_desc.ddsCaps.dwCaps |= DDSCAPS_FLIP;
6087 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6088 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6090 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
6091 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6092 if (is_ddraw64 && test_data[i].caps & DDSCAPS_TEXTURE)
6093 todo_wine ok(hr == E_NOINTERFACE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6094 else todo_wine_if(test_data[i].caps & DDSCAPS_TEXTURE)
6095 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
6096 if (FAILED(hr))
6097 continue;
6099 memset(&surface_desc, 0, sizeof(surface_desc));
6100 surface_desc.dwSize = sizeof(surface_desc);
6101 hr = IDirectDrawSurface7_GetSurfaceDesc(frontbuffer, &surface_desc);
6102 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6103 expected_caps = DDSCAPS_FRONTBUFFER | DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
6104 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
6105 expected_caps |= DDSCAPS_VISIBLE;
6106 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6107 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6108 sysmem_primary = surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
6110 hr = IDirectDrawSurface7_GetAttachedSurface(frontbuffer, &caps, &backbuffer1);
6111 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6112 memset(&surface_desc, 0, sizeof(surface_desc));
6113 surface_desc.dwSize = sizeof(surface_desc);
6114 hr = IDirectDrawSurface7_GetSurfaceDesc(backbuffer1, &surface_desc);
6115 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6116 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
6117 test_data[i].name, U5(surface_desc).dwBackBufferCount);
6118 expected_caps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER);
6119 expected_caps |= DDSCAPS_BACKBUFFER;
6120 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6121 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6123 hr = IDirectDrawSurface7_GetAttachedSurface(backbuffer1, &caps, &backbuffer2);
6124 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6125 memset(&surface_desc, 0, sizeof(surface_desc));
6126 surface_desc.dwSize = sizeof(surface_desc);
6127 hr = IDirectDrawSurface7_GetSurfaceDesc(backbuffer2, &surface_desc);
6128 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6129 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
6130 test_data[i].name, U5(surface_desc).dwBackBufferCount);
6131 expected_caps &= ~DDSCAPS_BACKBUFFER;
6132 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6133 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6135 hr = IDirectDrawSurface7_GetAttachedSurface(backbuffer2, &caps, &backbuffer3);
6136 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6137 memset(&surface_desc, 0, sizeof(surface_desc));
6138 surface_desc.dwSize = sizeof(surface_desc);
6139 hr = IDirectDrawSurface7_GetSurfaceDesc(backbuffer3, &surface_desc);
6140 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6141 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
6142 test_data[i].name, U5(surface_desc).dwBackBufferCount);
6143 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6144 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6146 hr = IDirectDrawSurface7_GetAttachedSurface(backbuffer3, &caps, &surface);
6147 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6148 ok(surface == frontbuffer, "%s: Got unexpected surface %p, expected %p.\n",
6149 test_data[i].name, surface, frontbuffer);
6150 IDirectDrawSurface7_Release(surface);
6152 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
6153 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
6154 hr = IDirectDrawSurface7_IsLost(frontbuffer);
6155 ok(hr == DD_OK, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6156 hr = IDirectDrawSurface7_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6157 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
6158 ok(hr == DDERR_NOEXCLUSIVEMODE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6159 else
6160 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6161 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6162 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
6163 hr = IDirectDrawSurface7_IsLost(frontbuffer);
6164 todo_wine ok(hr == DDERR_SURFACELOST, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6165 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
6166 ok(SUCCEEDED(hr), "%s: Failed to restore surfaces, hr %#x.\n", test_data[i].name, hr);
6168 memset(&surface_desc, 0, sizeof(surface_desc));
6169 surface_desc.dwSize = sizeof(surface_desc);
6170 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6171 surface_desc.ddsCaps.dwCaps = 0;
6172 surface_desc.dwWidth = 640;
6173 surface_desc.dwHeight = 480;
6174 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6175 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
6176 hr = IDirectDrawSurface7_Flip(frontbuffer, surface, DDFLIP_WAIT);
6177 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6178 IDirectDrawSurface7_Release(surface);
6180 hr = IDirectDrawSurface7_Flip(frontbuffer, frontbuffer, DDFLIP_WAIT);
6181 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6182 hr = IDirectDrawSurface7_Flip(backbuffer1, NULL, DDFLIP_WAIT);
6183 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6184 hr = IDirectDrawSurface7_Flip(backbuffer2, NULL, DDFLIP_WAIT);
6185 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6186 hr = IDirectDrawSurface7_Flip(backbuffer3, NULL, DDFLIP_WAIT);
6187 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6189 memset(&fx, 0, sizeof(fx));
6190 fx.dwSize = sizeof(fx);
6191 U5(fx).dwFillColor = 0xffff0000;
6192 hr = IDirectDrawSurface7_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6193 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
6194 U5(fx).dwFillColor = 0xff00ff00;
6195 hr = IDirectDrawSurface7_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6196 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
6197 U5(fx).dwFillColor = 0xff0000ff;
6198 hr = IDirectDrawSurface7_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6199 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
6201 hr = IDirectDrawSurface7_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6202 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6203 color = get_surface_color(backbuffer1, 320, 240);
6204 /* The testbot seems to just copy the contents of one surface to all the
6205 * others, instead of properly flipping. */
6206 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
6207 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6208 color = get_surface_color(backbuffer2, 320, 240);
6209 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6210 U5(fx).dwFillColor = 0xffff0000;
6211 hr = IDirectDrawSurface7_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6212 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
6214 hr = IDirectDrawSurface7_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6215 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6216 color = get_surface_color(backbuffer1, 320, 240);
6217 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
6218 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6219 color = get_surface_color(backbuffer2, 320, 240);
6220 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6221 U5(fx).dwFillColor = 0xff00ff00;
6222 hr = IDirectDrawSurface7_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6223 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
6225 hr = IDirectDrawSurface7_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6226 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6227 color = get_surface_color(backbuffer1, 320, 240);
6228 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
6229 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6230 color = get_surface_color(backbuffer2, 320, 240);
6231 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6232 U5(fx).dwFillColor = 0xff0000ff;
6233 hr = IDirectDrawSurface7_Blt(backbuffer3, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6234 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
6236 hr = IDirectDrawSurface7_Flip(frontbuffer, backbuffer1, DDFLIP_WAIT);
6237 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6238 color = get_surface_color(backbuffer2, 320, 240);
6239 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
6240 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6241 color = get_surface_color(backbuffer3, 320, 240);
6242 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6243 U5(fx).dwFillColor = 0xffff0000;
6244 hr = IDirectDrawSurface7_Blt(backbuffer1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6245 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
6247 hr = IDirectDrawSurface7_Flip(frontbuffer, backbuffer2, DDFLIP_WAIT);
6248 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6249 color = get_surface_color(backbuffer1, 320, 240);
6250 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6251 color = get_surface_color(backbuffer3, 320, 240);
6252 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
6253 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6254 U5(fx).dwFillColor = 0xff00ff00;
6255 hr = IDirectDrawSurface7_Blt(backbuffer2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
6256 ok(SUCCEEDED(hr), "%s: Failed to fill surface, hr %#x.\n", test_data[i].name, hr);
6258 hr = IDirectDrawSurface7_Flip(frontbuffer, backbuffer3, DDFLIP_WAIT);
6259 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6260 color = get_surface_color(backbuffer1, 320, 240);
6261 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
6262 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6263 color = get_surface_color(backbuffer2, 320, 240);
6264 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6266 IDirectDrawSurface7_Release(backbuffer3);
6267 IDirectDrawSurface7_Release(backbuffer2);
6268 IDirectDrawSurface7_Release(backbuffer1);
6269 IDirectDrawSurface7_Release(frontbuffer);
6272 if (!(device = create_device(window, DDSCL_NORMAL)))
6274 skip("Failed to create 3D device.\n");
6275 goto done;
6277 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
6278 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6279 IDirect3DDevice7_Release(device);
6280 if (!(device_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP))
6282 skip("Cubemaps are not supported.\n");
6283 goto done;
6286 memset(&surface_desc, 0, sizeof(surface_desc));
6287 surface_desc.dwSize = sizeof(surface_desc);
6288 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6289 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_TEXTURE;
6290 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
6291 surface_desc.dwWidth = 128;
6292 surface_desc.dwHeight = 128;
6293 U5(surface_desc).dwBackBufferCount = 3;
6294 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6295 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x.\n", hr);
6297 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_FLIP;
6298 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
6299 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6300 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6302 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_COMPLEX;
6303 surface_desc.ddsCaps.dwCaps |= DDSCAPS_FLIP;
6304 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6305 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x.\n", hr);
6307 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
6308 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6309 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6311 U5(surface_desc).dwBackBufferCount = 1;
6312 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6313 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6315 U5(surface_desc).dwBackBufferCount = 0;
6316 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6317 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x.\n", hr);
6319 done:
6320 refcount = IDirectDraw7_Release(ddraw);
6321 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
6322 DestroyWindow(window);
6325 static void reset_ddsd(DDSURFACEDESC2 *ddsd)
6327 memset(ddsd, 0, sizeof(*ddsd));
6328 ddsd->dwSize = sizeof(*ddsd);
6331 static void test_set_surface_desc(void)
6333 IDirectDraw7 *ddraw;
6334 HWND window;
6335 HRESULT hr;
6336 DDSURFACEDESC2 ddsd;
6337 IDirectDrawSurface7 *surface;
6338 BYTE data[16*16*4];
6339 ULONG ref;
6340 unsigned int i;
6341 static const struct
6343 DWORD caps, caps2;
6344 BOOL supported;
6345 const char *name;
6347 invalid_caps_tests[] =
6349 {DDSCAPS_VIDEOMEMORY, 0, FALSE, "videomemory plain"},
6350 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, TRUE, "systemmemory texture"},
6351 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE, "managed texture"},
6352 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE, "managed texture"},
6353 {DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY, 0, FALSE, "systemmemory primary"},
6356 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6357 0, 0, 640, 480, 0, 0, 0, 0);
6358 ddraw = create_ddraw();
6359 ok(!!ddraw, "Failed to create a ddraw object.\n");
6360 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6361 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6363 reset_ddsd(&ddsd);
6364 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
6365 ddsd.dwWidth = 8;
6366 ddsd.dwHeight = 8;
6367 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6368 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6369 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6370 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6371 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6372 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6373 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6375 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6376 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6378 reset_ddsd(&ddsd);
6379 ddsd.dwFlags = DDSD_LPSURFACE;
6380 ddsd.lpSurface = data;
6381 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6382 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6384 /* Redundantly setting the same lpSurface is not an error. */
6385 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6386 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6388 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6389 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6390 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
6391 ok(ddsd.lpSurface == NULL, "lpSurface is %p, expected NULL.\n", ddsd.lpSurface);
6393 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, 0, NULL);
6394 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6395 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
6396 ok(ddsd.lpSurface == data, "lpSurface is %p, expected %p.\n", data, data);
6397 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6398 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6400 reset_ddsd(&ddsd);
6401 ddsd.dwFlags = DDSD_LPSURFACE;
6402 ddsd.lpSurface = data;
6403 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 1);
6404 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with flags=1 returned %#x.\n", hr);
6406 ddsd.lpSurface = NULL;
6407 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6408 ok(hr == DDERR_INVALIDPARAMS, "Setting lpSurface=NULL returned %#x.\n", hr);
6410 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, NULL, 0);
6411 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with NULL desc returned %#x.\n", hr);
6413 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6414 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6415 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
6416 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
6417 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#x.\n", 0);
6419 /* Setting the caps is an error. This also means the original description cannot be reapplied. */
6420 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6421 ok(hr == DDERR_INVALIDPARAMS, "Setting the original desc returned %#x.\n", hr);
6423 ddsd.dwFlags = DDSD_CAPS;
6424 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6425 ok(hr == DDERR_INVALIDPARAMS, "Setting DDSD_CAPS returned %#x.\n", hr);
6427 /* dwCaps = 0 is allowed, but ignored. Caps2 can be anything and is ignored too. */
6428 ddsd.dwFlags = DDSD_CAPS | DDSD_LPSURFACE;
6429 ddsd.lpSurface = data;
6430 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6431 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
6432 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6433 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6434 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
6435 ddsd.ddsCaps.dwCaps = 0;
6436 ddsd.ddsCaps.dwCaps2 = 0xdeadbeef;
6437 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6438 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6440 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6441 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6442 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
6443 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
6444 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#x.\n", 0);
6446 /* Setting the height is allowed, but it cannot be set to 0, and only if LPSURFACE is set too. */
6447 reset_ddsd(&ddsd);
6448 ddsd.dwFlags = DDSD_HEIGHT;
6449 ddsd.dwHeight = 16;
6450 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6451 ok(hr == DDERR_INVALIDPARAMS, "Setting height without lpSurface returned %#x.\n", hr);
6453 ddsd.lpSurface = data;
6454 ddsd.dwFlags = DDSD_HEIGHT | DDSD_LPSURFACE;
6455 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6456 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6458 ddsd.dwHeight = 0;
6459 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6460 ok(hr == DDERR_INVALIDPARAMS, "Setting height=0 returned %#x.\n", hr);
6462 reset_ddsd(&ddsd);
6463 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6464 ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr);
6465 ok(ddsd.dwWidth == 8, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
6466 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
6468 /* Pitch and width can be set, but only together, and only with LPSURFACE. They must not be 0. */
6469 reset_ddsd(&ddsd);
6470 ddsd.dwFlags = DDSD_PITCH;
6471 U1(ddsd).lPitch = 8 * 4;
6472 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6473 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch without lpSurface or width returned %#x.\n", hr);
6475 ddsd.dwFlags = DDSD_WIDTH;
6476 ddsd.dwWidth = 16;
6477 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6478 ok(hr == DDERR_INVALIDPARAMS, "Setting width without lpSurface or pitch returned %#x.\n", hr);
6480 ddsd.dwFlags = DDSD_PITCH | DDSD_LPSURFACE;
6481 ddsd.lpSurface = data;
6482 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6483 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch and lpSurface without width returned %#x.\n", hr);
6485 ddsd.dwFlags = DDSD_WIDTH | DDSD_LPSURFACE;
6486 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6487 ok(hr == DDERR_INVALIDPARAMS, "Setting width and lpSurface without pitch returned %#x.\n", hr);
6489 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6490 U1(ddsd).lPitch = 16 * 4;
6491 ddsd.dwWidth = 16;
6492 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6493 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6495 reset_ddsd(&ddsd);
6496 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6497 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6498 ok(ddsd.dwWidth == 16, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
6499 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
6500 ok(U1(ddsd).lPitch == 16 * 4, "SetSurfaceDesc: Expected pitch 64, got %u.\n", U1(ddsd).lPitch);
6502 /* The pitch must be 32 bit aligned and > 0, but is not verified for sanity otherwise.
6504 * VMware rejects those calls, but all real drivers accept it. Mark the VMware behavior broken. */
6505 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6506 U1(ddsd).lPitch = 4 * 4;
6507 ddsd.lpSurface = data;
6508 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6509 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
6511 U1(ddsd).lPitch = 4;
6512 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6513 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
6515 U1(ddsd).lPitch = 16 * 4 + 1;
6516 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6517 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
6519 U1(ddsd).lPitch = 16 * 4 + 3;
6520 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6521 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
6523 U1(ddsd).lPitch = -4;
6524 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6525 ok(hr == DDERR_INVALIDPARAMS, "Setting negative pitch returned %#x.\n", hr);
6527 U1(ddsd).lPitch = 16 * 4;
6528 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6529 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6531 reset_ddsd(&ddsd);
6532 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6533 U1(ddsd).lPitch = 0;
6534 ddsd.dwWidth = 16;
6535 ddsd.lpSurface = data;
6536 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6537 ok(hr == DDERR_INVALIDPARAMS, "Setting zero pitch returned %#x.\n", hr);
6539 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6540 U1(ddsd).lPitch = 16 * 4;
6541 ddsd.dwWidth = 0;
6542 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6543 ok(hr == DDERR_INVALIDPARAMS, "Setting zero width returned %#x.\n", hr);
6545 /* Setting the pixelformat without LPSURFACE is an error, but with LPSURFACE it works. */
6546 ddsd.dwFlags = DDSD_PIXELFORMAT;
6547 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6548 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6549 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6550 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6551 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6552 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6553 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6554 ok(hr == DDERR_INVALIDPARAMS, "Setting the pixel format returned %#x.\n", hr);
6556 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_LPSURFACE;
6557 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6558 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6560 /* Can't set color keys. */
6561 reset_ddsd(&ddsd);
6562 ddsd.dwFlags = DDSD_CKSRCBLT;
6563 ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff0000;
6564 ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff0000;
6565 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6566 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
6568 ddsd.dwFlags = DDSD_CKSRCBLT | DDSD_LPSURFACE;
6569 ddsd.lpSurface = data;
6570 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6571 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
6573 IDirectDrawSurface7_Release(surface);
6575 /* SetSurfaceDesc needs systemmemory surfaces.
6577 * As a sidenote, fourcc surfaces aren't allowed in sysmem, thus testing DDSD_LINEARSIZE is moot. */
6578 for (i = 0; i < sizeof(invalid_caps_tests) / sizeof(*invalid_caps_tests); i++)
6580 reset_ddsd(&ddsd);
6581 ddsd.dwFlags = DDSD_CAPS;
6582 ddsd.ddsCaps.dwCaps = invalid_caps_tests[i].caps;
6583 ddsd.ddsCaps.dwCaps2 = invalid_caps_tests[i].caps2;
6584 if (!(invalid_caps_tests[i].caps & DDSCAPS_PRIMARYSURFACE))
6586 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6587 ddsd.dwWidth = 8;
6588 ddsd.dwHeight = 8;
6589 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6590 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6591 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6592 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6593 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6594 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6597 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6598 if (is_ddraw64 && (invalid_caps_tests[i].caps & DDSCAPS_TEXTURE))
6599 todo_wine ok(hr == E_NOINTERFACE, "Test %u: Got unexpected hr %#x.\n", i, hr);
6600 else
6601 ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWHW, "Test %u: Got unexpected hr %#x.\n", i, hr);
6602 if (FAILED(hr))
6603 continue;
6605 reset_ddsd(&ddsd);
6606 ddsd.dwFlags = DDSD_LPSURFACE;
6607 ddsd.lpSurface = data;
6608 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6609 if (invalid_caps_tests[i].supported)
6611 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6613 else
6615 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
6616 invalid_caps_tests[i].name, hr);
6618 /* Check priority of error conditions. */
6619 ddsd.dwFlags = DDSD_WIDTH;
6620 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6621 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
6622 invalid_caps_tests[i].name, hr);
6625 IDirectDrawSurface7_Release(surface);
6628 ref = IDirectDraw7_Release(ddraw);
6629 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
6630 DestroyWindow(window);
6633 static void test_user_memory_getdc(void)
6635 IDirectDraw7 *ddraw;
6636 HWND window;
6637 HRESULT hr;
6638 DDSURFACEDESC2 ddsd;
6639 IDirectDrawSurface7 *surface;
6640 DWORD data[16][16];
6641 HGDIOBJ *bitmap;
6642 DIBSECTION dib;
6643 ULONG ref;
6644 int size;
6645 HDC dc;
6646 unsigned int x, y;
6648 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6649 0, 0, 640, 480, 0, 0, 0, 0);
6650 ddraw = create_ddraw();
6651 ok(!!ddraw, "Failed to create a ddraw object.\n");
6652 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6653 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6655 reset_ddsd(&ddsd);
6656 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
6657 ddsd.dwWidth = 16;
6658 ddsd.dwHeight = 16;
6659 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6660 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6661 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6662 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6663 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6664 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6665 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6666 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6667 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6669 memset(data, 0xaa, sizeof(data));
6670 reset_ddsd(&ddsd);
6671 ddsd.dwFlags = DDSD_LPSURFACE;
6672 ddsd.lpSurface = data;
6673 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6674 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6676 hr = IDirectDrawSurface7_GetDC(surface, &dc);
6677 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
6678 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
6679 ok(!!bitmap, "Failed to get bitmap.\n");
6680 size = GetObjectA(bitmap, sizeof(dib), &dib);
6681 ok(size == sizeof(dib), "Got unexpected size %d.\n", size);
6682 ok(dib.dsBm.bmBits == data, "Got unexpected bits %p, expected %p.\n", dib.dsBm.bmBits, data);
6683 BitBlt(dc, 0, 0, 16, 8, NULL, 0, 0, WHITENESS);
6684 BitBlt(dc, 0, 8, 16, 8, NULL, 0, 0, BLACKNESS);
6685 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
6686 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
6688 ok(data[0][0] == 0xffffffff, "Expected color 0xffffffff, got %#x.\n", data[0][0]);
6689 ok(data[15][15] == 0x00000000, "Expected color 0x00000000, got %#x.\n", data[15][15]);
6691 ddsd.dwFlags = DDSD_LPSURFACE | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH;
6692 ddsd.lpSurface = data;
6693 ddsd.dwWidth = 4;
6694 ddsd.dwHeight = 8;
6695 U1(ddsd).lPitch = sizeof(*data);
6696 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6697 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6699 memset(data, 0xaa, sizeof(data));
6700 hr = IDirectDrawSurface7_GetDC(surface, &dc);
6701 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
6702 BitBlt(dc, 0, 0, 4, 8, NULL, 0, 0, BLACKNESS);
6703 BitBlt(dc, 1, 1, 2, 2, NULL, 0, 0, WHITENESS);
6704 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
6705 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
6707 for (y = 0; y < 4; y++)
6709 for (x = 0; x < 4; x++)
6711 if ((x == 1 || x == 2) && (y == 1 || y == 2))
6712 ok(data[y][x] == 0xffffffff, "Expected color 0xffffffff on position %ux%u, got %#x.\n",
6713 x, y, data[y][x]);
6714 else
6715 ok(data[y][x] == 0x00000000, "Expected color 0x00000000 on position %ux%u, got %#x.\n",
6716 x, y, data[y][x]);
6719 ok(data[0][5] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 5x0, got %#x.\n",
6720 data[0][5]);
6721 ok(data[7][3] == 0x00000000, "Expected color 0x00000000 on position 3x7, got %#x.\n",
6722 data[7][3]);
6723 ok(data[7][4] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 4x7, got %#x.\n",
6724 data[7][4]);
6725 ok(data[8][0] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 0x8, got %#x.\n",
6726 data[8][0]);
6728 IDirectDrawSurface7_Release(surface);
6729 ref = IDirectDraw7_Release(ddraw);
6730 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
6731 DestroyWindow(window);
6734 static void test_sysmem_overlay(void)
6736 IDirectDraw7 *ddraw;
6737 HWND window;
6738 HRESULT hr;
6739 DDSURFACEDESC2 ddsd;
6740 IDirectDrawSurface7 *surface;
6741 ULONG ref;
6743 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6744 0, 0, 640, 480, 0, 0, 0, 0);
6745 ddraw = create_ddraw();
6746 ok(!!ddraw, "Failed to create a ddraw object.\n");
6747 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6748 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6750 reset_ddsd(&ddsd);
6751 ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
6752 ddsd.dwWidth = 16;
6753 ddsd.dwHeight = 16;
6754 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OVERLAY;
6755 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6756 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6757 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6758 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6759 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6760 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6761 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6762 ok(hr == DDERR_NOOVERLAYHW, "Got unexpected hr %#x.\n", hr);
6764 ref = IDirectDraw7_Release(ddraw);
6765 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
6766 DestroyWindow(window);
6769 static void test_primary_palette(void)
6771 DDSCAPS2 surface_caps = {DDSCAPS_FLIP, 0, 0, {0}};
6772 IDirectDrawSurface7 *primary, *backbuffer;
6773 PALETTEENTRY palette_entries[256];
6774 IDirectDrawPalette *palette, *tmp;
6775 DDSURFACEDESC2 surface_desc;
6776 IDirectDraw7 *ddraw;
6777 DWORD palette_caps;
6778 ULONG refcount;
6779 HWND window;
6780 HRESULT hr;
6782 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6783 0, 0, 640, 480, 0, 0, 0, 0);
6784 ddraw = create_ddraw();
6785 ok(!!ddraw, "Failed to create a ddraw object.\n");
6786 if (FAILED(IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
6788 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
6789 IDirectDraw7_Release(ddraw);
6790 DestroyWindow(window);
6791 return;
6793 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6794 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6796 memset(&surface_desc, 0, sizeof(surface_desc));
6797 surface_desc.dwSize = sizeof(surface_desc);
6798 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
6799 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
6800 U5(surface_desc).dwBackBufferCount = 1;
6801 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
6802 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6803 hr = IDirectDrawSurface7_GetAttachedSurface(primary, &surface_caps, &backbuffer);
6804 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
6806 memset(palette_entries, 0, sizeof(palette_entries));
6807 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_entries, &palette, NULL);
6808 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
6809 refcount = get_refcount((IUnknown *)palette);
6810 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6812 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
6813 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
6814 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
6816 hr = IDirectDrawSurface7_SetPalette(primary, palette);
6817 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6819 /* The Windows 8 testbot attaches the palette to the backbuffer as well,
6820 * and is generally somewhat broken with respect to 8 bpp / palette
6821 * handling. */
6822 if (SUCCEEDED(IDirectDrawSurface7_GetPalette(backbuffer, &tmp)))
6824 win_skip("Broken palette handling detected, skipping tests.\n");
6825 IDirectDrawPalette_Release(tmp);
6826 IDirectDrawPalette_Release(palette);
6827 /* The Windows 8 testbot keeps extra references to the primary and
6828 * backbuffer while in 8 bpp mode. */
6829 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
6830 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
6831 goto done;
6834 refcount = get_refcount((IUnknown *)palette);
6835 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
6837 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
6838 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
6839 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE | DDPCAPS_ALLOW256),
6840 "Got unexpected palette caps %#x.\n", palette_caps);
6842 hr = IDirectDrawSurface7_SetPalette(primary, NULL);
6843 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6844 refcount = get_refcount((IUnknown *)palette);
6845 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6847 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
6848 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
6849 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
6851 hr = IDirectDrawSurface7_SetPalette(primary, palette);
6852 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6853 refcount = get_refcount((IUnknown *)palette);
6854 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
6856 hr = IDirectDrawSurface7_GetPalette(primary, &tmp);
6857 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
6858 ok(tmp == palette, "Got unexpected palette %p, expected %p.\n", tmp, palette);
6859 IDirectDrawPalette_Release(tmp);
6860 hr = IDirectDrawSurface7_GetPalette(backbuffer, &tmp);
6861 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
6863 refcount = IDirectDrawPalette_Release(palette);
6864 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6865 refcount = IDirectDrawPalette_Release(palette);
6866 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6868 /* Note that this only seems to work when the palette is attached to the
6869 * primary surface. When attached to a regular surface, attempting to get
6870 * the palette here will cause an access violation. */
6871 hr = IDirectDrawSurface7_GetPalette(primary, &tmp);
6872 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
6874 hr = IDirectDrawSurface7_IsLost(primary);
6875 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6877 memset(&surface_desc, 0, sizeof(surface_desc));
6878 surface_desc.dwSize = sizeof(surface_desc);
6879 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &surface_desc);
6880 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6881 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
6882 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
6883 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 8, "Got unexpected bit count %u.\n",
6884 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
6886 hr = set_display_mode(ddraw, 640, 480);
6887 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
6889 memset(&surface_desc, 0, sizeof(surface_desc));
6890 surface_desc.dwSize = sizeof(surface_desc);
6891 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &surface_desc);
6892 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6893 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
6894 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
6895 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 32
6896 || U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 24,
6897 "Got unexpected bit count %u.\n", U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
6899 hr = IDirectDrawSurface7_IsLost(primary);
6900 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
6901 hr = IDirectDrawSurface7_Restore(primary);
6902 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
6903 hr = IDirectDrawSurface7_IsLost(primary);
6904 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
6906 memset(&surface_desc, 0, sizeof(surface_desc));
6907 surface_desc.dwSize = sizeof(surface_desc);
6908 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &surface_desc);
6909 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6910 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
6911 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
6912 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 32
6913 || U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 24,
6914 "Got unexpected bit count %u.\n", U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
6916 done:
6917 refcount = IDirectDrawSurface7_Release(backbuffer);
6918 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6919 refcount = IDirectDrawSurface7_Release(primary);
6920 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6921 refcount = IDirectDraw7_Release(ddraw);
6922 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6923 DestroyWindow(window);
6926 static HRESULT WINAPI surface_counter(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
6928 UINT *surface_count = context;
6930 ++(*surface_count);
6931 IDirectDrawSurface_Release(surface);
6933 return DDENUMRET_OK;
6936 static void test_surface_attachment(void)
6938 IDirectDrawSurface7 *surface1, *surface2, *surface3, *surface4;
6939 IDirectDrawSurface *surface1v1, *surface2v1;
6940 DDSCAPS2 caps = {DDSCAPS_TEXTURE, 0, 0, {0}};
6941 DDSURFACEDESC2 surface_desc;
6942 IDirectDraw7 *ddraw;
6943 UINT surface_count;
6944 ULONG refcount;
6945 HWND window;
6946 HRESULT hr;
6948 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
6949 0, 0, 640, 480, 0, 0, 0, 0);
6950 ddraw = create_ddraw();
6951 ok(!!ddraw, "Failed to create a ddraw object.\n");
6952 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6953 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6955 memset(&surface_desc, 0, sizeof(surface_desc));
6956 surface_desc.dwSize = sizeof(surface_desc);
6957 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
6958 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
6959 U2(surface_desc).dwMipMapCount = 3;
6960 surface_desc.dwWidth = 128;
6961 surface_desc.dwHeight = 128;
6962 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL)))
6964 skip("Failed to create a texture, skipping tests.\n");
6965 IDirectDraw7_Release(ddraw);
6966 DestroyWindow(window);
6967 return;
6970 hr = IDirectDrawSurface7_GetAttachedSurface(surface1, &caps, &surface2);
6971 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
6972 hr = IDirectDrawSurface7_GetAttachedSurface(surface2, &caps, &surface3);
6973 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
6974 hr = IDirectDrawSurface7_GetAttachedSurface(surface3, &caps, &surface4);
6975 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
6977 surface_count = 0;
6978 IDirectDrawSurface7_EnumAttachedSurfaces(surface1, &surface_count, surface_counter);
6979 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
6980 surface_count = 0;
6981 IDirectDrawSurface7_EnumAttachedSurfaces(surface2, &surface_count, surface_counter);
6982 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
6983 surface_count = 0;
6984 IDirectDrawSurface7_EnumAttachedSurfaces(surface3, &surface_count, surface_counter);
6985 ok(!surface_count, "Got unexpected surface_count %u.\n", surface_count);
6987 memset(&surface_desc, 0, sizeof(surface_desc));
6988 surface_desc.dwSize = sizeof(surface_desc);
6989 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6990 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6991 surface_desc.dwWidth = 16;
6992 surface_desc.dwHeight = 16;
6993 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
6994 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6996 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
6997 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
6998 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
6999 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7000 hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface4);
7001 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7002 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface3);
7003 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7004 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface4);
7005 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7006 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface2);
7007 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7009 IDirectDrawSurface7_Release(surface4);
7011 memset(&surface_desc, 0, sizeof(surface_desc));
7012 surface_desc.dwSize = sizeof(surface_desc);
7013 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7014 surface_desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
7015 surface_desc.dwWidth = 16;
7016 surface_desc.dwHeight = 16;
7017 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
7018 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7020 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
7021 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7022 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
7023 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7024 hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface4);
7025 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7026 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface3);
7027 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7028 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface4);
7029 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7030 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface2);
7031 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7033 IDirectDrawSurface7_Release(surface4);
7034 IDirectDrawSurface7_Release(surface3);
7035 IDirectDrawSurface7_Release(surface2);
7036 IDirectDrawSurface7_Release(surface1);
7038 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7039 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7041 /* Try a single primary and two offscreen plain surfaces. */
7042 memset(&surface_desc, 0, sizeof(surface_desc));
7043 surface_desc.dwSize = sizeof(surface_desc);
7044 surface_desc.dwFlags = DDSD_CAPS;
7045 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7046 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7047 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7049 memset(&surface_desc, 0, sizeof(surface_desc));
7050 surface_desc.dwSize = sizeof(surface_desc);
7051 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7052 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7053 surface_desc.dwWidth = registry_mode.dmPelsWidth;
7054 surface_desc.dwHeight = registry_mode.dmPelsHeight;
7055 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
7056 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7058 memset(&surface_desc, 0, sizeof(surface_desc));
7059 surface_desc.dwSize = sizeof(surface_desc);
7060 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7061 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7062 surface_desc.dwWidth = registry_mode.dmPelsWidth;
7063 surface_desc.dwHeight = registry_mode.dmPelsHeight;
7064 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
7065 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7067 /* This one has a different size. */
7068 memset(&surface_desc, 0, sizeof(surface_desc));
7069 surface_desc.dwSize = sizeof(surface_desc);
7070 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7071 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7072 surface_desc.dwWidth = 128;
7073 surface_desc.dwHeight = 128;
7074 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
7075 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7077 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
7078 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7079 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface1);
7080 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7081 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface3);
7082 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7083 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
7084 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7085 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
7086 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7088 IDirectDrawSurface7_Release(surface4);
7089 IDirectDrawSurface7_Release(surface3);
7090 IDirectDrawSurface7_Release(surface2);
7091 IDirectDrawSurface7_Release(surface1);
7093 /* Test DeleteAttachedSurface() and automatic detachment of attached surfaces on release. */
7094 memset(&surface_desc, 0, sizeof(surface_desc));
7095 surface_desc.dwSize = sizeof(surface_desc);
7096 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7097 surface_desc.dwWidth = 64;
7098 surface_desc.dwHeight = 64;
7099 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
7100 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7101 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
7102 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
7103 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
7104 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
7105 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
7106 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7107 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7108 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
7109 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7111 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
7112 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
7113 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = 16;
7114 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = 0x0000ffff;
7115 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
7116 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7118 hr = IDirectDrawSurface7_QueryInterface(surface1, &IID_IDirectDrawSurface, (void **)&surface1v1);
7119 ok(SUCCEEDED(hr), "Failed to get interface, hr %#x.\n", hr);
7120 hr = IDirectDrawSurface7_QueryInterface(surface2, &IID_IDirectDrawSurface, (void **)&surface2v1);
7121 ok(SUCCEEDED(hr), "Failed to get interface, hr %#x.\n", hr);
7123 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
7124 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7125 refcount = get_refcount((IUnknown *)surface2);
7126 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
7127 refcount = get_refcount((IUnknown *)surface2v1);
7128 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7129 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
7130 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
7131 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
7132 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7133 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
7134 ok(hr == DDERR_SURFACENOTATTACHED, "Got unexpected hr %#x.\n", hr);
7136 /* Attaching while already attached to other surface. */
7137 hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface2);
7138 todo_wine ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7139 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface3, 0, surface2);
7140 todo_wine ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7141 IDirectDrawSurface7_Release(surface3);
7143 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface2);
7144 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7145 refcount = get_refcount((IUnknown *)surface2);
7146 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7147 refcount = get_refcount((IUnknown *)surface2v1);
7148 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7150 /* DeleteAttachedSurface() when attaching via IDirectDrawSurface. */
7151 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
7152 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7153 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface2);
7154 ok(hr == DDERR_SURFACENOTATTACHED, "Got unexpected hr %#x.\n", hr);
7155 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
7156 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7157 refcount = IDirectDrawSurface7_Release(surface2);
7158 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7159 refcount = IDirectDrawSurface7_Release(surface1);
7160 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7162 /* Automatic detachment on release. */
7163 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
7164 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7165 refcount = get_refcount((IUnknown *)surface2v1);
7166 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
7167 refcount = IDirectDrawSurface_Release(surface1v1);
7168 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7169 refcount = IDirectDrawSurface_Release(surface2v1);
7170 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7171 refcount = IDirectDraw7_Release(ddraw);
7172 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7173 DestroyWindow(window);
7176 static void test_private_data(void)
7178 IDirectDraw7 *ddraw;
7179 IDirectDrawSurface7 *surface, *surface2;
7180 DDSURFACEDESC2 surface_desc;
7181 ULONG refcount, refcount2, refcount3;
7182 IUnknown *ptr;
7183 DWORD size = sizeof(ptr);
7184 HRESULT hr;
7185 HWND window;
7186 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
7187 DWORD data[] = {1, 2, 3, 4};
7188 DDCAPS hal_caps;
7189 static const GUID ddraw_private_data_test_guid =
7191 0xfdb37466,
7192 0x428f,
7193 0x4edf,
7194 {0xa3,0x7f,0x9b,0x1d,0xf4,0x88,0xc5,0xfc}
7196 static const GUID ddraw_private_data_test_guid2 =
7198 0x2e5afac2,
7199 0x87b5,
7200 0x4c10,
7201 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
7204 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7205 0, 0, 640, 480, 0, 0, 0, 0);
7206 ddraw = create_ddraw();
7207 ok(!!ddraw, "Failed to create a ddraw object.\n");
7208 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7209 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7211 reset_ddsd(&surface_desc);
7212 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
7213 surface_desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
7214 surface_desc.dwHeight = 4;
7215 surface_desc.dwWidth = 4;
7216 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7217 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7219 /* NULL pointers are not valid, but don't cause a crash. */
7220 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL,
7221 sizeof(IUnknown *), DDSPD_IUNKNOWNPOINTER);
7222 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7223 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL, 0, 0);
7224 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7225 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL, 1, 0);
7226 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7228 /* DDSPD_IUNKNOWNPOINTER needs sizeof(IUnknown *) bytes of data. */
7229 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7230 0, DDSPD_IUNKNOWNPOINTER);
7231 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7232 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7233 5, DDSPD_IUNKNOWNPOINTER);
7234 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7235 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7236 sizeof(ddraw) * 2, DDSPD_IUNKNOWNPOINTER);
7237 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7239 /* Note that with a size != 0 and size != sizeof(IUnknown *) and
7240 * DDSPD_IUNKNOWNPOINTER set SetPrivateData in ddraw4 and ddraw7
7241 * erases the old content and returns an error. This behavior has
7242 * been fixed in d3d8 and d3d9. Unless an application is found
7243 * that depends on this we don't care about this behavior. */
7244 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7245 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7246 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7247 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7248 0, DDSPD_IUNKNOWNPOINTER);
7249 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7250 size = sizeof(ptr);
7251 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
7252 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7253 hr = IDirectDrawSurface7_FreePrivateData(surface, &ddraw_private_data_test_guid);
7254 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7256 refcount = get_refcount((IUnknown *)ddraw);
7257 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7258 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7259 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7260 refcount2 = get_refcount((IUnknown *)ddraw);
7261 ok(refcount2 == refcount + 1, "Got unexpected refcount %u.\n", refcount2);
7263 hr = IDirectDrawSurface7_FreePrivateData(surface, &ddraw_private_data_test_guid);
7264 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7265 refcount2 = get_refcount((IUnknown *)ddraw);
7266 ok(refcount2 == refcount, "Got unexpected refcount %u.\n", refcount2);
7268 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7269 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7270 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7271 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, surface,
7272 sizeof(surface), DDSPD_IUNKNOWNPOINTER);
7273 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7274 refcount2 = get_refcount((IUnknown *)ddraw);
7275 ok(refcount2 == refcount, "Got unexpected refcount %u.\n", refcount2);
7277 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7278 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7279 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7280 size = 2 * sizeof(ptr);
7281 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
7282 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7283 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
7284 refcount2 = get_refcount(ptr);
7285 /* Object is NOT addref'ed by the getter. */
7286 ok(ptr == (IUnknown *)ddraw, "Returned interface pointer is %p, expected %p.\n", ptr, ddraw);
7287 ok(refcount2 == refcount + 1, "Got unexpected refcount %u.\n", refcount2);
7289 ptr = (IUnknown *)0xdeadbeef;
7290 size = 1;
7291 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, &size);
7292 ok(hr == DDERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
7293 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
7294 size = 2 * sizeof(ptr);
7295 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, &size);
7296 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7297 ok(size == 2 * sizeof(ptr), "Got unexpected size %u.\n", size);
7298 size = 1;
7299 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
7300 ok(hr == DDERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
7301 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
7302 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7303 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid2, NULL, NULL);
7304 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7305 size = 0xdeadbabe;
7306 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid2, &ptr, &size);
7307 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7308 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7309 ok(size == 0xdeadbabe, "Got unexpected size %u.\n", size);
7310 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, NULL);
7311 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7313 refcount3 = IDirectDrawSurface7_Release(surface);
7314 ok(!refcount3, "Got unexpected refcount %u.\n", refcount3);
7316 /* Destroying the surface frees the reference held on the private data. It also frees
7317 * the reference the surface is holding on its creating object. */
7318 refcount2 = get_refcount((IUnknown *)ddraw);
7319 ok(refcount2 == refcount - 1, "Got unexpected refcount %u.\n", refcount2);
7321 memset(&hal_caps, 0, sizeof(hal_caps));
7322 hal_caps.dwSize = sizeof(hal_caps);
7323 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
7324 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7325 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) == (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)
7326 && !is_ddraw64)
7328 reset_ddsd(&surface_desc);
7329 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_MIPMAPCOUNT;
7330 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7331 surface_desc.dwHeight = 4;
7332 surface_desc.dwWidth = 4;
7333 U2(surface_desc).dwMipMapCount = 2;
7334 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7335 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7336 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &surface2);
7337 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
7339 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, data, sizeof(data), 0);
7340 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7341 hr = IDirectDrawSurface7_GetPrivateData(surface2, &ddraw_private_data_test_guid, NULL, NULL);
7342 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7344 IDirectDrawSurface7_Release(surface2);
7345 IDirectDrawSurface7_Release(surface);
7347 else
7348 skip("Mipmapped textures not supported, skipping mipmap private data test.\n");
7350 refcount = IDirectDraw7_Release(ddraw);
7351 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7352 DestroyWindow(window);
7355 static void test_pixel_format(void)
7357 HWND window, window2 = NULL;
7358 HDC hdc, hdc2 = NULL;
7359 HMODULE gl = NULL;
7360 int format, test_format;
7361 PIXELFORMATDESCRIPTOR pfd;
7362 IDirectDraw7 *ddraw = NULL;
7363 IDirectDrawClipper *clipper = NULL;
7364 DDSURFACEDESC2 ddsd;
7365 IDirectDrawSurface7 *primary = NULL;
7366 DDBLTFX fx;
7367 HRESULT hr;
7369 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
7370 100, 100, 160, 160, NULL, NULL, NULL, NULL);
7371 if (!window)
7373 skip("Failed to create window\n");
7374 return;
7377 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
7378 100, 100, 160, 160, NULL, NULL, NULL, NULL);
7380 hdc = GetDC(window);
7381 if (!hdc)
7383 skip("Failed to get DC\n");
7384 goto cleanup;
7387 if (window2)
7388 hdc2 = GetDC(window2);
7390 gl = LoadLibraryA("opengl32.dll");
7391 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
7393 format = GetPixelFormat(hdc);
7394 ok(format == 0, "new window has pixel format %d\n", format);
7396 ZeroMemory(&pfd, sizeof(pfd));
7397 pfd.nSize = sizeof(pfd);
7398 pfd.nVersion = 1;
7399 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
7400 pfd.iPixelType = PFD_TYPE_RGBA;
7401 pfd.iLayerType = PFD_MAIN_PLANE;
7402 format = ChoosePixelFormat(hdc, &pfd);
7403 if (format <= 0)
7405 skip("no pixel format available\n");
7406 goto cleanup;
7409 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
7411 skip("failed to set pixel format\n");
7412 goto cleanup;
7415 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
7417 skip("failed to set pixel format on second window\n");
7418 if (hdc2)
7420 ReleaseDC(window2, hdc2);
7421 hdc2 = NULL;
7425 ddraw = create_ddraw();
7426 ok(!!ddraw, "Failed to create a ddraw object.\n");
7428 test_format = GetPixelFormat(hdc);
7429 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7431 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7432 if (FAILED(hr))
7434 skip("Failed to set cooperative level, hr %#x.\n", hr);
7435 goto cleanup;
7438 test_format = GetPixelFormat(hdc);
7439 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7441 if (hdc2)
7443 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
7444 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
7445 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window2);
7446 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
7448 test_format = GetPixelFormat(hdc);
7449 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7451 test_format = GetPixelFormat(hdc2);
7452 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7455 memset(&ddsd, 0, sizeof(ddsd));
7456 ddsd.dwSize = sizeof(ddsd);
7457 ddsd.dwFlags = DDSD_CAPS;
7458 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7460 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
7461 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
7463 test_format = GetPixelFormat(hdc);
7464 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7466 if (hdc2)
7468 test_format = GetPixelFormat(hdc2);
7469 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7472 if (clipper)
7474 hr = IDirectDrawSurface7_SetClipper(primary, clipper);
7475 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
7477 test_format = GetPixelFormat(hdc);
7478 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7480 test_format = GetPixelFormat(hdc2);
7481 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7484 memset(&fx, 0, sizeof(fx));
7485 fx.dwSize = sizeof(fx);
7486 hr = IDirectDrawSurface7_Blt(primary, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7487 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
7489 test_format = GetPixelFormat(hdc);
7490 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7492 if (hdc2)
7494 test_format = GetPixelFormat(hdc2);
7495 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7498 cleanup:
7499 if (primary) IDirectDrawSurface7_Release(primary);
7500 if (clipper) IDirectDrawClipper_Release(clipper);
7501 if (ddraw) IDirectDraw7_Release(ddraw);
7502 if (gl) FreeLibrary(gl);
7503 if (hdc) ReleaseDC(window, hdc);
7504 if (hdc2) ReleaseDC(window2, hdc2);
7505 if (window) DestroyWindow(window);
7506 if (window2) DestroyWindow(window2);
7509 static void test_create_surface_pitch(void)
7511 IDirectDrawSurface7 *surface;
7512 DDSURFACEDESC2 surface_desc;
7513 IDirectDraw7 *ddraw;
7514 unsigned int i;
7515 ULONG refcount;
7516 HWND window;
7517 HRESULT hr;
7518 void *mem;
7520 static const struct
7522 DWORD caps;
7523 DWORD flags_in;
7524 DWORD pitch_in;
7525 HRESULT hr;
7526 DWORD flags_out;
7527 DWORD pitch_out32;
7528 DWORD pitch_out64;
7530 test_data[] =
7532 /* 0 */
7533 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7534 0, 0, DD_OK,
7535 DDSD_PITCH, 0x100, 0x100},
7536 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7537 DDSD_PITCH, 0x104, DD_OK,
7538 DDSD_PITCH, 0x100, 0x100},
7539 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7540 DDSD_PITCH, 0x0f8, DD_OK,
7541 DDSD_PITCH, 0x100, 0x100},
7542 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7543 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
7544 0, 0, 0 },
7545 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7546 0, 0, DD_OK,
7547 DDSD_PITCH, 0x100, 0x0fc},
7548 /* 5 */
7549 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7550 DDSD_PITCH, 0x104, DD_OK,
7551 DDSD_PITCH, 0x100, 0x0fc},
7552 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7553 DDSD_PITCH, 0x0f8, DD_OK,
7554 DDSD_PITCH, 0x100, 0x0fc},
7555 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7556 DDSD_PITCH | DDSD_LINEARSIZE, 0, DD_OK,
7557 DDSD_PITCH, 0x100, 0x0fc},
7558 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7559 DDSD_LPSURFACE, 0, DDERR_INVALIDPARAMS,
7560 0, 0, 0 },
7561 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7562 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DD_OK,
7563 DDSD_PITCH, 0x100, 0x100},
7564 /* 10 */
7565 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7566 DDSD_LPSURFACE | DDSD_PITCH, 0x0fe, DDERR_INVALIDPARAMS,
7567 0, 0, 0 },
7568 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7569 DDSD_LPSURFACE | DDSD_PITCH, 0x0fc, DD_OK,
7570 DDSD_PITCH, 0x0fc, 0x0fc},
7571 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7572 DDSD_LPSURFACE | DDSD_PITCH, 0x0f8, DDERR_INVALIDPARAMS,
7573 0, 0, 0 },
7574 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7575 DDSD_LPSURFACE | DDSD_LINEARSIZE, 0x100, DDERR_INVALIDPARAMS,
7576 0, 0, 0 },
7577 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7578 DDSD_LPSURFACE | DDSD_LINEARSIZE, 0x3f00, DDERR_INVALIDPARAMS,
7579 0, 0, 0 },
7580 /* 15 */
7581 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7582 DDSD_LPSURFACE | DDSD_PITCH | DDSD_LINEARSIZE, 0x100, DD_OK,
7583 DDSD_PITCH, 0x100, 0x100},
7584 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
7585 0, 0, DDERR_INVALIDCAPS,
7586 0, 0, 0 },
7587 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7588 0, 0, DD_OK,
7589 DDSD_PITCH, 0x100, 0 },
7590 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7591 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
7592 0, 0, 0 },
7593 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
7594 0, 0, DDERR_INVALIDCAPS,
7595 0, 0, 0 },
7596 /* 20 */
7597 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7598 0, 0, DD_OK,
7599 DDSD_PITCH, 0x100, 0 },
7600 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7601 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DD_OK,
7602 DDSD_PITCH, 0x100, 0 },
7604 DWORD flags_mask = DDSD_PITCH | DDSD_LPSURFACE | DDSD_LINEARSIZE;
7606 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7607 0, 0, 640, 480, 0, 0, 0, 0);
7608 ddraw = create_ddraw();
7609 ok(!!ddraw, "Failed to create a ddraw object.\n");
7610 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7611 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7613 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((63 * 4) + 8) * 63);
7615 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
7617 memset(&surface_desc, 0, sizeof(surface_desc));
7618 surface_desc.dwSize = sizeof(surface_desc);
7619 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | test_data[i].flags_in;
7620 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
7621 surface_desc.dwWidth = 63;
7622 surface_desc.dwHeight = 63;
7623 U1(surface_desc).lPitch = test_data[i].pitch_in;
7624 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7625 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
7626 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
7627 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7628 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7629 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7630 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7631 if (test_data[i].flags_in & DDSD_LPSURFACE)
7633 HRESULT expected_hr = SUCCEEDED(test_data[i].hr) ? DDERR_INVALIDPARAMS : test_data[i].hr;
7634 ok(hr == expected_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, expected_hr);
7635 surface_desc.lpSurface = mem;
7636 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7638 if ((test_data[i].caps & DDSCAPS_VIDEOMEMORY) && hr == DDERR_NODIRECTDRAWHW)
7639 continue;
7640 if (is_ddraw64 && (test_data[i].caps & DDSCAPS_TEXTURE) && SUCCEEDED(test_data[i].hr))
7641 todo_wine ok(hr == E_NOINTERFACE, "Test %u: Got unexpected hr %#x.\n", i, hr);
7642 else
7643 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
7644 if (FAILED(hr))
7645 continue;
7647 memset(&surface_desc, 0, sizeof(surface_desc));
7648 surface_desc.dwSize = sizeof(surface_desc);
7649 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
7650 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
7651 ok((surface_desc.dwFlags & flags_mask) == test_data[i].flags_out,
7652 "Test %u: Got unexpected flags %#x, expected %#x.\n",
7653 i, surface_desc.dwFlags & flags_mask, test_data[i].flags_out);
7654 /* The pitch for textures seems to be implementation specific. */
7655 if (!(test_data[i].caps & DDSCAPS_TEXTURE))
7657 if (is_ddraw64 && test_data[i].pitch_out32 != test_data[i].pitch_out64)
7658 todo_wine ok(U1(surface_desc).lPitch == test_data[i].pitch_out64,
7659 "Test %u: Got unexpected pitch %u, expected %u.\n",
7660 i, U1(surface_desc).lPitch, test_data[i].pitch_out64);
7661 else
7662 ok(U1(surface_desc).lPitch == test_data[i].pitch_out32,
7663 "Test %u: Got unexpected pitch %u, expected %u.\n",
7664 i, U1(surface_desc).lPitch, test_data[i].pitch_out32);
7666 ok(!surface_desc.lpSurface, "Test %u: Got unexpected lpSurface %p.\n", i, surface_desc.lpSurface);
7668 IDirectDrawSurface7_Release(surface);
7671 HeapFree(GetProcessHeap(), 0, mem);
7672 refcount = IDirectDraw7_Release(ddraw);
7673 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7674 DestroyWindow(window);
7677 static void test_mipmap(void)
7679 IDirectDrawSurface7 *surface, *surface2;
7680 DDSURFACEDESC2 surface_desc;
7681 IDirectDraw7 *ddraw;
7682 unsigned int i;
7683 ULONG refcount;
7684 HWND window;
7685 HRESULT hr;
7686 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
7687 DDCAPS hal_caps;
7689 static const struct
7691 DWORD flags;
7692 DWORD caps;
7693 DWORD width;
7694 DWORD height;
7695 DWORD mipmap_count_in;
7696 HRESULT hr;
7697 DWORD mipmap_count_out;
7699 tests[] =
7701 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 3, DD_OK, 3},
7702 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDPARAMS, 0},
7703 {0, DDSCAPS_TEXTURE | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 1},
7704 {0, DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDCAPS, 0},
7705 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 8},
7706 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 32, 64, 0, DD_OK, 7},
7709 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7710 0, 0, 640, 480, 0, 0, 0, 0);
7711 ddraw = create_ddraw();
7712 ok(!!ddraw, "Failed to create a ddraw object.\n");
7713 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7714 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7716 memset(&hal_caps, 0, sizeof(hal_caps));
7717 hal_caps.dwSize = sizeof(hal_caps);
7718 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
7719 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7720 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)
7721 || is_ddraw64)
7723 skip("Mipmapped textures not supported, skipping tests.\n");
7724 IDirectDraw7_Release(ddraw);
7725 DestroyWindow(window);
7726 return;
7729 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
7731 memset(&surface_desc, 0, sizeof(surface_desc));
7732 surface_desc.dwSize = sizeof(surface_desc);
7733 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | tests[i].flags;
7734 surface_desc.ddsCaps.dwCaps = tests[i].caps;
7735 surface_desc.dwWidth = tests[i].width;
7736 surface_desc.dwHeight = tests[i].height;
7737 if (tests[i].flags & DDSD_MIPMAPCOUNT)
7738 U2(surface_desc).dwMipMapCount = tests[i].mipmap_count_in;
7739 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7740 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x.\n", i, hr);
7741 if (FAILED(hr))
7742 continue;
7744 memset(&surface_desc, 0, sizeof(surface_desc));
7745 surface_desc.dwSize = sizeof(surface_desc);
7746 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
7747 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
7748 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
7749 "Test %u: Got unexpected flags %#x.\n", i, surface_desc.dwFlags);
7750 ok(U2(surface_desc).dwMipMapCount == tests[i].mipmap_count_out,
7751 "Test %u: Got unexpected mipmap count %u.\n", i, U2(surface_desc).dwMipMapCount);
7753 if (U2(surface_desc).dwMipMapCount > 1)
7755 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &surface2);
7756 ok(SUCCEEDED(hr), "Test %u: Failed to get attached surface, hr %#x.\n", i, hr);
7758 memset(&surface_desc, 0, sizeof(surface_desc));
7759 surface_desc.dwSize = sizeof(surface_desc);
7760 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, 0, NULL);
7761 ok(SUCCEEDED(hr), "Test %u: Failed to lock surface, hr %#x.\n", i, hr);
7762 memset(&surface_desc, 0, sizeof(surface_desc));
7763 surface_desc.dwSize = sizeof(surface_desc);
7764 hr = IDirectDrawSurface7_Lock(surface2, NULL, &surface_desc, 0, NULL);
7765 ok(SUCCEEDED(hr), "Test %u: Failed to lock surface, hr %#x.\n", i, hr);
7766 IDirectDrawSurface7_Unlock(surface2, NULL);
7767 IDirectDrawSurface7_Unlock(surface, NULL);
7769 IDirectDrawSurface7_Release(surface2);
7772 IDirectDrawSurface7_Release(surface);
7775 refcount = IDirectDraw7_Release(ddraw);
7776 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7777 DestroyWindow(window);
7780 static void test_palette_complex(void)
7782 IDirectDrawSurface7 *surface, *mipmap, *tmp;
7783 DDSURFACEDESC2 surface_desc;
7784 IDirectDraw7 *ddraw;
7785 IDirectDrawPalette *palette, *palette2;
7786 ULONG refcount;
7787 HWND window;
7788 HRESULT hr;
7789 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
7790 DDCAPS hal_caps;
7791 PALETTEENTRY palette_entries[256];
7792 unsigned int i;
7794 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7795 0, 0, 640, 480, 0, 0, 0, 0);
7796 ddraw = create_ddraw();
7797 ok(!!ddraw, "Failed to create a ddraw object.\n");
7798 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7799 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7801 memset(&hal_caps, 0, sizeof(hal_caps));
7802 hal_caps.dwSize = sizeof(hal_caps);
7803 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
7804 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7805 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)
7806 || is_ddraw64)
7808 skip("Mipmapped textures not supported, skipping mipmap palette test.\n");
7809 IDirectDraw7_Release(ddraw);
7810 DestroyWindow(window);
7811 return;
7814 memset(&surface_desc, 0, sizeof(surface_desc));
7815 surface_desc.dwSize = sizeof(surface_desc);
7816 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7817 surface_desc.dwWidth = 128;
7818 surface_desc.dwHeight = 128;
7819 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7820 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7821 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
7822 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
7823 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7824 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7826 memset(palette_entries, 0, sizeof(palette_entries));
7827 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7828 palette_entries, &palette, NULL);
7829 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7831 palette2 = (void *)0xdeadbeef;
7832 hr = IDirectDrawSurface7_GetPalette(surface, &palette2);
7833 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
7834 ok(!palette2, "Got unexpected palette %p.\n", palette2);
7835 hr = IDirectDrawSurface7_SetPalette(surface, palette);
7836 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7837 hr = IDirectDrawSurface7_GetPalette(surface, &palette2);
7838 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
7839 ok(palette == palette2, "Got unexpected palette %p.\n", palette2);
7840 IDirectDrawPalette_Release(palette2);
7842 mipmap = surface;
7843 IDirectDrawSurface7_AddRef(mipmap);
7844 for (i = 0; i < 7; ++i)
7846 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
7847 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
7848 palette2 = (void *)0xdeadbeef;
7849 hr = IDirectDrawSurface7_GetPalette(tmp, &palette2);
7850 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x, i %u.\n", hr, i);
7851 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
7853 hr = IDirectDrawSurface7_SetPalette(tmp, palette);
7854 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x, i %u.\n", hr, i);
7856 hr = IDirectDrawSurface7_GetPalette(tmp, &palette2);
7857 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x, i %u.\n", hr, i);
7858 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
7860 /* Ddraw7 uses the palette of the mipmap for GetDC, just like previous
7861 * ddraw versions. Combined with the test results above this means no
7862 * palette is available. So depending on the driver either GetDC fails
7863 * or the DIB color table contains random data. */
7865 IDirectDrawSurface7_Release(mipmap);
7866 mipmap = tmp;
7869 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
7870 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7871 IDirectDrawSurface7_Release(mipmap);
7872 refcount = IDirectDrawSurface7_Release(surface);
7873 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7875 /* Test DDERR_INVALIDPIXELFORMAT vs DDERR_NOTONMIPMAPSUBLEVEL. */
7876 memset(&surface_desc, 0, sizeof(surface_desc));
7877 surface_desc.dwSize = sizeof(surface_desc);
7878 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7879 surface_desc.dwWidth = 128;
7880 surface_desc.dwHeight = 128;
7881 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7882 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7883 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
7884 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
7885 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7886 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7887 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7888 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7889 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7891 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
7892 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
7893 hr = IDirectDrawSurface7_SetPalette(mipmap, palette);
7894 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x.\n", hr);
7896 IDirectDrawSurface7_Release(mipmap);
7897 refcount = IDirectDrawSurface7_Release(surface);
7898 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7899 refcount = IDirectDrawPalette_Release(palette);
7900 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7902 refcount = IDirectDraw7_Release(ddraw);
7903 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7904 DestroyWindow(window);
7907 static void test_p8_blit(void)
7909 IDirectDrawSurface7 *src, *dst, *dst_p8;
7910 DDSURFACEDESC2 surface_desc;
7911 IDirectDraw7 *ddraw;
7912 IDirectDrawPalette *palette, *palette2;
7913 ULONG refcount;
7914 HWND window;
7915 HRESULT hr;
7916 PALETTEENTRY palette_entries[256];
7917 unsigned int x;
7918 DDBLTFX fx;
7919 BOOL is_warp;
7920 static const BYTE src_data[] = {0x10, 0x1, 0x2, 0x3, 0x4, 0x5, 0xff, 0x80};
7921 static const BYTE src_data2[] = {0x10, 0x5, 0x4, 0x3, 0x2, 0x1, 0xff, 0x80};
7922 static const BYTE expected_p8[] = {0x10, 0x1, 0x4, 0x3, 0x4, 0x5, 0xff, 0x80};
7923 static const D3DCOLOR expected[] =
7925 0x00101010, 0x00010101, 0x00020202, 0x00030303,
7926 0x00040404, 0x00050505, 0x00ffffff, 0x00808080,
7928 D3DCOLOR color;
7930 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
7931 0, 0, 640, 480, 0, 0, 0, 0);
7932 ddraw = create_ddraw();
7933 ok(!!ddraw, "Failed to create a ddraw object.\n");
7934 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7935 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7936 is_warp = ddraw_is_warp(ddraw);
7938 memset(palette_entries, 0, sizeof(palette_entries));
7939 palette_entries[1].peGreen = 0xff;
7940 palette_entries[2].peBlue = 0xff;
7941 palette_entries[3].peFlags = 0xff;
7942 palette_entries[4].peRed = 0xff;
7943 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7944 palette_entries, &palette, NULL);
7945 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7946 palette_entries[1].peBlue = 0xff;
7947 palette_entries[2].peGreen = 0xff;
7948 palette_entries[3].peRed = 0xff;
7949 palette_entries[4].peFlags = 0x0;
7950 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7951 palette_entries, &palette2, NULL);
7952 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7954 memset(&surface_desc, 0, sizeof(surface_desc));
7955 surface_desc.dwSize = sizeof(surface_desc);
7956 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7957 surface_desc.dwWidth = 8;
7958 surface_desc.dwHeight = 1;
7959 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7960 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7961 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
7962 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
7963 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
7964 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7965 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_p8, NULL);
7966 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7967 hr = IDirectDrawSurface7_SetPalette(dst_p8, palette2);
7968 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7970 memset(&surface_desc, 0, sizeof(surface_desc));
7971 surface_desc.dwSize = sizeof(surface_desc);
7972 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7973 surface_desc.dwWidth = 8;
7974 surface_desc.dwHeight = 1;
7975 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7976 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7977 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
7978 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
7979 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7980 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7981 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7982 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
7983 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
7984 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7986 memset(&surface_desc, 0, sizeof(surface_desc));
7987 surface_desc.dwSize = sizeof(surface_desc);
7988 hr = IDirectDrawSurface7_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
7989 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
7990 memcpy(surface_desc.lpSurface, src_data, sizeof(src_data));
7991 hr = IDirectDrawSurface7_Unlock(src, NULL);
7992 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
7994 hr = IDirectDrawSurface7_Lock(dst_p8, NULL, &surface_desc, DDLOCK_WAIT, NULL);
7995 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#x.\n", hr);
7996 memcpy(surface_desc.lpSurface, src_data2, sizeof(src_data2));
7997 hr = IDirectDrawSurface7_Unlock(dst_p8, NULL);
7998 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#x.\n", hr);
8000 hr = IDirectDrawSurface7_SetPalette(src, palette);
8001 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8002 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_WAIT, NULL);
8003 /* The r500 Windows 7 driver returns E_NOTIMPL. r200 on Windows XP works.
8004 * The Geforce 7 driver on Windows Vista returns E_FAIL. Newer Nvidia GPUs work. */
8005 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL) || broken(hr == E_FAIL),
8006 "Failed to blit, hr %#x.\n", hr);
8008 if (SUCCEEDED(hr))
8010 for (x = 0; x < sizeof(expected) / sizeof(*expected); x++)
8012 color = get_surface_color(dst, x, 0);
8013 todo_wine ok(compare_color(color, expected[x], 0),
8014 "Pixel %u: Got color %#x, expected %#x.\n",
8015 x, color, expected[x]);
8019 memset(&fx, 0, sizeof(fx));
8020 fx.dwSize = sizeof(fx);
8021 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x2;
8022 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x2;
8023 hr = IDirectDrawSurface7_Blt(dst_p8, NULL, src, NULL, DDBLT_WAIT | DDBLT_KEYSRCOVERRIDE, &fx);
8024 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
8026 hr = IDirectDrawSurface7_Lock(dst_p8, NULL, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
8027 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#x.\n", hr);
8028 /* A color keyed P8 blit doesn't do anything on WARP - it just leaves the data in the destination
8029 * surface untouched. P8 blits without color keys work. Error checking (DDBLT_KEYSRC without a key
8030 * for example) also works as expected.
8032 * Using DDBLT_KEYSRC instead of DDBLT_KEYSRCOVERRIDE doesn't change this. Doing this blit with
8033 * the display mode set to P8 doesn't help either. */
8034 ok(!memcmp(surface_desc.lpSurface, expected_p8, sizeof(expected_p8))
8035 || broken(is_warp && !memcmp(surface_desc.lpSurface, src_data2, sizeof(src_data2))),
8036 "Got unexpected P8 color key blit result.\n");
8037 hr = IDirectDrawSurface7_Unlock(dst_p8, NULL);
8038 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#x.\n", hr);
8040 IDirectDrawSurface7_Release(src);
8041 IDirectDrawSurface7_Release(dst);
8042 IDirectDrawSurface7_Release(dst_p8);
8043 IDirectDrawPalette_Release(palette);
8044 IDirectDrawPalette_Release(palette2);
8046 refcount = IDirectDraw7_Release(ddraw);
8047 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8048 DestroyWindow(window);
8051 static void test_material(void)
8053 static const D3DCOLORVALUE null_color;
8054 IDirect3DDevice7 *device;
8055 D3DMATERIAL7 material;
8056 ULONG refcount;
8057 HWND window;
8058 HRESULT hr;
8060 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8061 0, 0, 640, 480, 0, 0, 0, 0);
8062 if (!(device = create_device(window, DDSCL_NORMAL)))
8064 skip("Failed to create a 3D device, skipping test.\n");
8065 DestroyWindow(window);
8066 return;
8069 hr = IDirect3DDevice7_GetMaterial(device, &material);
8070 ok(SUCCEEDED(hr), "Failed to get material, hr %#x.\n", hr);
8071 ok(!memcmp(&U(material).diffuse, &null_color, sizeof(null_color)),
8072 "Got unexpected diffuse color {%.8e, %.8e, %.8e, %.8e}.\n",
8073 U1(U(material).diffuse).r, U2(U(material).diffuse).g,
8074 U3(U(material).diffuse).b, U4(U(material).diffuse).a);
8075 ok(!memcmp(&U1(material).ambient, &null_color, sizeof(null_color)),
8076 "Got unexpected ambient color {%.8e, %.8e, %.8e, %.8e}.\n",
8077 U1(U1(material).ambient).r, U2(U1(material).ambient).g,
8078 U3(U1(material).ambient).b, U4(U1(material).ambient).a);
8079 ok(!memcmp(&U2(material).specular, &null_color, sizeof(null_color)),
8080 "Got unexpected specular color {%.8e, %.8e, %.8e, %.8e}.\n",
8081 U1(U2(material).specular).r, U2(U2(material).specular).g,
8082 U3(U2(material).specular).b, U4(U2(material).specular).a);
8083 ok(!memcmp(&U3(material).emissive, &null_color, sizeof(null_color)),
8084 "Got unexpected emissive color {%.8e, %.8e, %.8e, %.8e}.\n",
8085 U1(U3(material).emissive).r, U2(U3(material).emissive).g,
8086 U3(U3(material).emissive).b, U4(U3(material).emissive).a);
8087 ok(U4(material).power == 0.0f, "Got unexpected power %.8e.\n", U4(material).power);
8089 refcount = IDirect3DDevice7_Release(device);
8090 ok(!refcount, "Device has %u references left.\n", refcount);
8091 DestroyWindow(window);
8094 static void test_palette_gdi(void)
8096 IDirectDrawSurface7 *surface, *primary;
8097 DDSURFACEDESC2 surface_desc;
8098 IDirectDraw7 *ddraw;
8099 IDirectDrawPalette *palette, *palette2;
8100 ULONG refcount;
8101 HWND window;
8102 HRESULT hr;
8103 PALETTEENTRY palette_entries[256];
8104 UINT i;
8105 HDC dc;
8106 DDBLTFX fx;
8107 RECT r;
8108 COLORREF color;
8109 /* On the Windows 8 testbot palette index 0 of the onscreen palette is forced to
8110 * r = 0, g = 0, b = 0. Do not attempt to set it to something else as this is
8111 * not the point of this test. */
8112 static const RGBQUAD expected1[] =
8114 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
8115 {0x03, 0x00, 0x00, 0x00}, {0x15, 0x14, 0x13, 0x00},
8117 static const RGBQUAD expected2[] =
8119 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
8120 {0x03, 0x00, 0x00, 0x00}, {0x25, 0x24, 0x23, 0x00},
8122 static const RGBQUAD expected3[] =
8124 {0x00, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x40, 0x00},
8125 {0x00, 0x40, 0x00, 0x00}, {0x56, 0x34, 0x12, 0x00},
8127 HPALETTE ddraw_palette_handle;
8128 /* Similar to index 0, index 255 is r = 0xff, g = 0xff, b = 0xff on the Win8 VMs. */
8129 RGBQUAD rgbquad[255];
8130 static const RGBQUAD rgb_zero = {0, 0, 0, 0};
8132 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8133 0, 0, 640, 480, 0, 0, 0, 0);
8134 ddraw = create_ddraw();
8135 ok(!!ddraw, "Failed to create a ddraw object.\n");
8136 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8137 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8139 memset(&surface_desc, 0, sizeof(surface_desc));
8140 surface_desc.dwSize = sizeof(surface_desc);
8141 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8142 surface_desc.dwWidth = 16;
8143 surface_desc.dwHeight = 16;
8144 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8145 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8146 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
8147 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
8148 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8149 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8151 /* Avoid colors from the Windows default palette. */
8152 memset(palette_entries, 0, sizeof(palette_entries));
8153 palette_entries[1].peRed = 0x01;
8154 palette_entries[2].peGreen = 0x02;
8155 palette_entries[3].peBlue = 0x03;
8156 palette_entries[4].peRed = 0x13;
8157 palette_entries[4].peGreen = 0x14;
8158 palette_entries[4].peBlue = 0x15;
8159 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8160 palette_entries, &palette, NULL);
8161 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8163 /* If there is no palette assigned and the display mode is not 8 bpp, some
8164 * drivers refuse to create a DC while others allow it. If a DC is created,
8165 * the DIB color table is uninitialized and contains random colors. No error
8166 * is generated when trying to read pixels and random garbage is returned.
8168 * The most likely explanation is that if the driver creates a DC, it (or
8169 * the higher-level runtime) uses GetSystemPaletteEntries to find the
8170 * palette, but GetSystemPaletteEntries fails when bpp > 8 and the palette
8171 * contains uninitialized garbage. See comments below for the P8 case. */
8173 hr = IDirectDrawSurface7_SetPalette(surface, palette);
8174 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8175 hr = IDirectDrawSurface7_GetDC(surface, &dc);
8176 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8177 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
8178 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
8179 "Got unexpected palette %p, expected %p.\n",
8180 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
8182 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
8183 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
8184 for (i = 0; i < sizeof(expected1) / sizeof(*expected1); i++)
8186 ok(!memcmp(&rgbquad[i], &expected1[i], sizeof(rgbquad[i])),
8187 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8188 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8189 expected1[i].rgbRed, expected1[i].rgbGreen, expected1[i].rgbBlue);
8191 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
8193 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8194 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8195 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8198 /* Update the palette while the DC is in use. This does not modify the DC. */
8199 palette_entries[4].peRed = 0x23;
8200 palette_entries[4].peGreen = 0x24;
8201 palette_entries[4].peBlue = 0x25;
8202 hr = IDirectDrawPalette_SetEntries(palette, 0, 4, 1, &palette_entries[4]);
8203 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
8205 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
8206 ok(i == 1, "Expected count 1, got %u.\n", i);
8207 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
8208 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8209 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
8210 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
8212 /* Neither does re-setting the palette. */
8213 hr = IDirectDrawSurface7_SetPalette(surface, NULL);
8214 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8215 hr = IDirectDrawSurface7_SetPalette(surface, palette);
8216 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8218 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
8219 ok(i == 1, "Expected count 1, got %u.\n", i);
8220 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
8221 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8222 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
8223 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
8225 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
8226 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8228 /* Refresh the DC. This updates the palette. */
8229 hr = IDirectDrawSurface7_GetDC(surface, &dc);
8230 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8231 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
8232 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
8233 for (i = 0; i < sizeof(expected2) / sizeof(*expected2); i++)
8235 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8236 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8237 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8238 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8240 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
8242 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8243 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8244 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8246 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
8247 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8249 refcount = IDirectDrawSurface7_Release(surface);
8250 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8252 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
8253 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8254 if (FAILED(IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
8256 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
8257 IDirectDrawPalette_Release(palette);
8258 IDirectDraw7_Release(ddraw);
8259 DestroyWindow(window);
8260 return;
8262 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
8264 memset(&surface_desc, 0, sizeof(surface_desc));
8265 surface_desc.dwSize = sizeof(surface_desc);
8266 surface_desc.dwFlags = DDSD_CAPS;
8267 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8268 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
8269 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8271 memset(&fx, 0, sizeof(fx));
8272 fx.dwSize = sizeof(fx);
8273 U5(fx).dwFillColor = 3;
8274 SetRect(&r, 0, 0, 319, 479);
8275 hr = IDirectDrawSurface7_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8276 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#x.\n", hr);
8277 SetRect(&r, 320, 0, 639, 479);
8278 U5(fx).dwFillColor = 4;
8279 hr = IDirectDrawSurface7_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8280 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#x.\n", hr);
8282 hr = IDirectDrawSurface7_SetPalette(primary, palette);
8283 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8284 hr = IDirectDrawSurface7_GetDC(primary, &dc);
8285 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8287 color = GetPixel(dc, 160, 240);
8288 ok(color == 0x00030000, "Clear index 3: Got unexpected color 0x%08x.\n", color);
8289 color = GetPixel(dc, 480, 240);
8290 ok(color == 0x00252423, "Clear index 4: Got unexpected color 0x%08x.\n", color);
8292 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
8293 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
8294 "Got unexpected palette %p, expected %p.\n",
8295 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
8296 SelectPalette(dc, ddraw_palette_handle, FALSE);
8298 /* The primary uses the system palette. In exclusive mode, the system palette matches
8299 * the ddraw palette attached to the primary, so the result is what you would expect
8300 * from a regular surface. Tests for the interaction between the ddraw palette and
8301 * the system palette are not included pending an application that depends on this.
8302 * The relation between those causes problems on Windows Vista and newer for games
8303 * like Age of Empires or StarcCaft. Don't emulate it without a real need. */
8304 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
8305 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
8306 for (i = 0; i < sizeof(expected2) / sizeof(*expected2); i++)
8308 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8309 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8310 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8311 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8313 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
8315 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8316 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8317 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8319 hr = IDirectDrawSurface7_ReleaseDC(primary, dc);
8320 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8322 memset(&surface_desc, 0, sizeof(surface_desc));
8323 surface_desc.dwSize = sizeof(surface_desc);
8324 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8325 surface_desc.dwWidth = 16;
8326 surface_desc.dwHeight = 16;
8327 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8328 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8329 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8331 /* Here the offscreen surface appears to use the primary's palette,
8332 * but in all likelihood it is actually the system palette. */
8333 hr = IDirectDrawSurface7_GetDC(surface, &dc);
8334 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8335 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
8336 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
8337 for (i = 0; i < sizeof(expected2) / sizeof(*expected2); i++)
8339 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8340 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8341 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8342 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8344 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
8346 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8347 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8348 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8350 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
8351 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8353 /* On real hardware a change to the primary surface's palette applies immediately,
8354 * even on device contexts from offscreen surfaces that do not have their own
8355 * palette. On the testbot VMs this is not the case. Don't test this until we
8356 * know of an application that depends on this. */
8358 memset(palette_entries, 0, sizeof(palette_entries));
8359 palette_entries[1].peBlue = 0x40;
8360 palette_entries[2].peRed = 0x40;
8361 palette_entries[3].peGreen = 0x40;
8362 palette_entries[4].peRed = 0x12;
8363 palette_entries[4].peGreen = 0x34;
8364 palette_entries[4].peBlue = 0x56;
8365 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8366 palette_entries, &palette2, NULL);
8367 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8368 hr = IDirectDrawSurface7_SetPalette(surface, palette2);
8369 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8371 /* A palette assigned to the offscreen surface overrides the primary / system
8372 * palette. */
8373 hr = IDirectDrawSurface7_GetDC(surface, &dc);
8374 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8375 i = GetDIBColorTable(dc, 0, sizeof(rgbquad) / sizeof(*rgbquad), rgbquad);
8376 ok(i == sizeof(rgbquad) / sizeof(*rgbquad), "Expected count 255, got %u.\n", i);
8377 for (i = 0; i < sizeof(expected3) / sizeof(*expected3); i++)
8379 ok(!memcmp(&rgbquad[i], &expected3[i], sizeof(rgbquad[i])),
8380 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8381 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8382 expected3[i].rgbRed, expected3[i].rgbGreen, expected3[i].rgbBlue);
8384 for (; i < sizeof(rgbquad) / sizeof(*rgbquad); i++)
8386 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8387 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8388 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8390 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
8391 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8393 refcount = IDirectDrawSurface7_Release(surface);
8394 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8396 /* The Windows 8 testbot keeps extra references to the primary and
8397 * backbuffer while in 8 bpp mode. */
8398 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
8399 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
8401 refcount = IDirectDrawSurface7_Release(primary);
8402 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8403 refcount = IDirectDrawPalette_Release(palette2);
8404 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8405 refcount = IDirectDrawPalette_Release(palette);
8406 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8407 refcount = IDirectDraw7_Release(ddraw);
8408 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8409 DestroyWindow(window);
8412 static void test_palette_alpha(void)
8414 IDirectDrawSurface7 *surface;
8415 DDSURFACEDESC2 surface_desc;
8416 IDirectDraw7 *ddraw;
8417 IDirectDrawPalette *palette;
8418 ULONG refcount;
8419 HWND window;
8420 HRESULT hr;
8421 PALETTEENTRY palette_entries[256];
8422 unsigned int i;
8423 static const struct
8425 DWORD caps, flags;
8426 BOOL attach_allowed;
8427 const char *name;
8429 test_data[] =
8431 {DDSCAPS_OFFSCREENPLAIN, DDSD_WIDTH | DDSD_HEIGHT, FALSE, "offscreenplain"},
8432 {DDSCAPS_TEXTURE, DDSD_WIDTH | DDSD_HEIGHT, TRUE, "texture"},
8433 {DDSCAPS_PRIMARYSURFACE, 0, FALSE, "primary"}
8436 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8437 0, 0, 640, 480, 0, 0, 0, 0);
8438 ddraw = create_ddraw();
8439 ok(!!ddraw, "Failed to create a ddraw object.\n");
8440 if (FAILED(IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
8442 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
8443 IDirectDraw7_Release(ddraw);
8444 DestroyWindow(window);
8445 return;
8447 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8448 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8450 memset(palette_entries, 0, sizeof(palette_entries));
8451 palette_entries[1].peFlags = 0x42;
8452 palette_entries[2].peFlags = 0xff;
8453 palette_entries[3].peFlags = 0x80;
8454 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
8455 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8457 memset(palette_entries, 0x66, sizeof(palette_entries));
8458 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
8459 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
8460 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8461 palette_entries[0].peFlags);
8462 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8463 palette_entries[1].peFlags);
8464 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
8465 palette_entries[2].peFlags);
8466 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
8467 palette_entries[3].peFlags);
8469 IDirectDrawPalette_Release(palette);
8471 memset(palette_entries, 0, sizeof(palette_entries));
8472 palette_entries[1].peFlags = 0x42;
8473 palette_entries[1].peRed = 0xff;
8474 palette_entries[2].peFlags = 0xff;
8475 palette_entries[3].peFlags = 0x80;
8476 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT | DDPCAPS_ALPHA,
8477 palette_entries, &palette, NULL);
8478 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8480 memset(palette_entries, 0x66, sizeof(palette_entries));
8481 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
8482 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
8483 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8484 palette_entries[0].peFlags);
8485 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8486 palette_entries[1].peFlags);
8487 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
8488 palette_entries[2].peFlags);
8489 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
8490 palette_entries[3].peFlags);
8492 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); i++)
8494 memset(&surface_desc, 0, sizeof(surface_desc));
8495 surface_desc.dwSize = sizeof(surface_desc);
8496 surface_desc.dwFlags = DDSD_CAPS | test_data[i].flags;
8497 surface_desc.dwWidth = 128;
8498 surface_desc.dwHeight = 128;
8499 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
8500 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8501 ok(SUCCEEDED(hr), "Failed to create %s surface, hr %#x.\n", test_data[i].name, hr);
8503 hr = IDirectDrawSurface7_SetPalette(surface, palette);
8504 if (test_data[i].attach_allowed)
8505 ok(SUCCEEDED(hr), "Failed to attach palette to %s surface, hr %#x.\n", test_data[i].name, hr);
8506 else
8507 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x, %s surface.\n", hr, test_data[i].name);
8509 if (SUCCEEDED(hr))
8511 HDC dc;
8512 RGBQUAD rgbquad;
8513 UINT retval;
8515 hr = IDirectDrawSurface7_GetDC(surface, &dc);
8516 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x, %s surface.\n", hr, test_data[i].name);
8517 retval = GetDIBColorTable(dc, 1, 1, &rgbquad);
8518 ok(retval == 1, "GetDIBColorTable returned unexpected result %u.\n", retval);
8519 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x, %s surface.\n",
8520 rgbquad.rgbRed, test_data[i].name);
8521 ok(rgbquad.rgbGreen == 0, "Expected rgbGreen = 0, got %#x, %s surface.\n",
8522 rgbquad.rgbGreen, test_data[i].name);
8523 ok(rgbquad.rgbBlue == 0, "Expected rgbBlue = 0, got %#x, %s surface.\n",
8524 rgbquad.rgbBlue, test_data[i].name);
8525 ok(rgbquad.rgbReserved == 0, "Expected rgbReserved = 0, got %u, %s surface.\n",
8526 rgbquad.rgbReserved, test_data[i].name);
8527 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
8528 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8530 IDirectDrawSurface7_Release(surface);
8533 /* Test INVALIDSURFACETYPE vs INVALIDPIXELFORMAT. */
8534 memset(&surface_desc, 0, sizeof(surface_desc));
8535 surface_desc.dwSize = sizeof(surface_desc);
8536 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8537 surface_desc.dwWidth = 128;
8538 surface_desc.dwHeight = 128;
8539 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8540 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8541 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
8542 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
8543 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8544 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8545 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
8546 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8547 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8548 hr = IDirectDrawSurface7_SetPalette(surface, palette);
8549 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x.\n", hr);
8550 IDirectDrawSurface7_Release(surface);
8552 /* The Windows 8 testbot keeps extra references to the primary
8553 * while in 8 bpp mode. */
8554 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
8555 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
8557 refcount = IDirectDrawPalette_Release(palette);
8558 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8559 refcount = IDirectDraw7_Release(ddraw);
8560 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8561 DestroyWindow(window);
8564 static void test_vb_writeonly(void)
8566 IDirect3DDevice7 *device;
8567 IDirect3D7 *d3d;
8568 IDirect3DVertexBuffer7 *buffer;
8569 HWND window;
8570 HRESULT hr;
8571 D3DVERTEXBUFFERDESC desc;
8572 void *ptr;
8573 static const struct vec4 quad[] =
8575 { 0.0f, 480.0f, 0.0f, 1.0f},
8576 { 0.0f, 0.0f, 0.0f, 1.0f},
8577 {640.0f, 480.0f, 0.0f, 1.0f},
8578 {640.0f, 0.0f, 0.0f, 1.0f},
8581 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8582 0, 0, 640, 480, 0, 0, 0, 0);
8584 if (!(device = create_device(window, DDSCL_NORMAL)))
8586 skip("Failed to create a 3D device, skipping test.\n");
8587 DestroyWindow(window);
8588 return;
8591 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
8592 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
8594 memset(&desc, 0, sizeof(desc));
8595 desc.dwSize = sizeof(desc);
8596 desc.dwCaps = D3DVBCAPS_WRITEONLY;
8597 desc.dwFVF = D3DFVF_XYZRHW;
8598 desc.dwNumVertices = sizeof(quad) / sizeof(*quad);
8599 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &buffer, 0);
8600 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
8602 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, &ptr, NULL);
8603 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
8604 memcpy(ptr, quad, sizeof(quad));
8605 hr = IDirect3DVertexBuffer7_Unlock(buffer);
8606 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
8608 hr = IDirect3DDevice7_BeginScene(device);
8609 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8610 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
8611 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8612 hr = IDirect3DDevice7_EndScene(device);
8613 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8615 hr = IDirect3DVertexBuffer7_Lock(buffer, 0, &ptr, NULL);
8616 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
8617 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
8618 hr = IDirect3DVertexBuffer7_Unlock(buffer);
8619 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
8621 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_READONLY, &ptr, NULL);
8622 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
8623 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
8624 hr = IDirect3DVertexBuffer7_Unlock(buffer);
8625 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
8627 IDirect3DVertexBuffer7_Release(buffer);
8628 IDirect3D7_Release(d3d);
8629 IDirect3DDevice7_Release(device);
8630 DestroyWindow(window);
8633 static void test_lost_device(void)
8635 IDirectDrawSurface7 *surface;
8636 DDSURFACEDESC2 surface_desc;
8637 HWND window1, window2;
8638 IDirectDraw7 *ddraw;
8639 ULONG refcount;
8640 HRESULT hr;
8641 BOOL ret;
8643 window1 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8644 0, 0, 640, 480, 0, 0, 0, 0);
8645 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8646 0, 0, 640, 480, 0, 0, 0, 0);
8647 ddraw = create_ddraw();
8648 ok(!!ddraw, "Failed to create a ddraw object.\n");
8649 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8650 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8652 memset(&surface_desc, 0, sizeof(surface_desc));
8653 surface_desc.dwSize = sizeof(surface_desc);
8654 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
8655 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
8656 U5(surface_desc).dwBackBufferCount = 1;
8657 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8658 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8660 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8661 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8662 hr = IDirectDrawSurface7_IsLost(surface);
8663 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8664 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8665 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8667 ret = SetForegroundWindow(GetDesktopWindow());
8668 ok(ret, "Failed to set foreground window.\n");
8669 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8670 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8671 hr = IDirectDrawSurface7_IsLost(surface);
8672 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8673 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8674 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8676 ret = SetForegroundWindow(window1);
8677 ok(ret, "Failed to set foreground window.\n");
8678 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8679 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8680 hr = IDirectDrawSurface7_IsLost(surface);
8681 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8682 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8683 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8685 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
8686 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8687 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8688 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8689 hr = IDirectDrawSurface7_IsLost(surface);
8690 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8691 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8692 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8694 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
8695 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8696 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8697 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8698 hr = IDirectDrawSurface7_IsLost(surface);
8699 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8700 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8701 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8703 /* Trying to restore the primary will crash, probably because flippable
8704 * surfaces can't exist in DDSCL_NORMAL. */
8705 IDirectDrawSurface7_Release(surface);
8706 memset(&surface_desc, 0, sizeof(surface_desc));
8707 surface_desc.dwSize = sizeof(surface_desc);
8708 surface_desc.dwFlags = DDSD_CAPS;
8709 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8710 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8711 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8713 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8714 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8715 hr = IDirectDrawSurface7_IsLost(surface);
8716 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8718 ret = SetForegroundWindow(GetDesktopWindow());
8719 ok(ret, "Failed to set foreground window.\n");
8720 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8721 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8722 hr = IDirectDrawSurface7_IsLost(surface);
8723 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8725 ret = SetForegroundWindow(window1);
8726 ok(ret, "Failed to set foreground window.\n");
8727 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8728 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8729 hr = IDirectDrawSurface7_IsLost(surface);
8730 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8732 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8733 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8734 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8735 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8736 hr = IDirectDrawSurface7_IsLost(surface);
8737 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8739 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
8740 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8741 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8742 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8743 hr = IDirectDrawSurface7_IsLost(surface);
8744 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8746 IDirectDrawSurface7_Release(surface);
8747 memset(&surface_desc, 0, sizeof(surface_desc));
8748 surface_desc.dwSize = sizeof(surface_desc);
8749 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
8750 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
8751 U5(surface_desc).dwBackBufferCount = 1;
8752 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8753 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8755 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8756 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8757 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8758 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8759 hr = IDirectDrawSurface7_IsLost(surface);
8760 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8761 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8762 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8764 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL | DDSCL_FULLSCREEN);
8765 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8766 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8767 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8768 hr = IDirectDrawSurface7_IsLost(surface);
8769 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8770 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8771 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8773 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
8774 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8775 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8776 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8777 hr = IDirectDrawSurface7_IsLost(surface);
8778 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8779 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8780 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8782 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
8783 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8784 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8785 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8786 hr = IDirectDrawSurface7_IsLost(surface);
8787 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8788 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8789 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8791 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL | DDSCL_FULLSCREEN);
8792 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8793 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8794 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8795 hr = IDirectDrawSurface7_IsLost(surface);
8796 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8797 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8798 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8800 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8801 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8802 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8803 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8804 hr = IDirectDrawSurface7_IsLost(surface);
8805 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8806 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8807 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8809 IDirectDrawSurface7_Release(surface);
8810 refcount = IDirectDraw7_Release(ddraw);
8811 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8812 DestroyWindow(window2);
8813 DestroyWindow(window1);
8816 static void test_resource_priority(void)
8818 IDirectDrawSurface7 *surface, *mipmap;
8819 DDSURFACEDESC2 surface_desc;
8820 IDirectDraw7 *ddraw;
8821 ULONG refcount;
8822 HWND window;
8823 HRESULT hr;
8824 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
8825 DDCAPS hal_caps;
8826 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_MIPMAP;
8827 unsigned int i;
8828 DWORD priority;
8829 static const struct
8831 DWORD caps, caps2;
8832 const char *name;
8833 HRESULT hr;
8834 /* SetPriority on offscreenplain surfaces crashes on AMD GPUs on Win7. */
8835 BOOL crash;
8837 test_data[] =
8839 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, "vidmem texture", DDERR_INVALIDPARAMS, FALSE},
8840 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, "sysmem texture", DDERR_INVALIDPARAMS, FALSE},
8841 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, "managed texture", DD_OK, FALSE},
8842 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, "managed texture", DD_OK, FALSE},
8843 {DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP,
8844 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_TEXTUREMANAGE,
8845 "cubemap", DD_OK, FALSE},
8846 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, "vidmem offscreenplain", DDERR_INVALIDOBJECT, TRUE},
8847 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, "sysmem offscreenplain", DDERR_INVALIDOBJECT, TRUE},
8850 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8851 0, 0, 640, 480, 0, 0, 0, 0);
8852 ddraw = create_ddraw();
8853 ok(!!ddraw, "Failed to create a ddraw object.\n");
8854 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8855 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8857 memset(&hal_caps, 0, sizeof(hal_caps));
8858 hal_caps.dwSize = sizeof(hal_caps);
8859 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
8860 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8861 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps
8862 || !(hal_caps.ddsCaps.dwCaps & DDSCAPS2_TEXTUREMANAGE))
8864 skip("Required surface types not supported, skipping test.\n");
8865 goto done;
8868 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); i++)
8870 memset(&surface_desc, 0, sizeof(surface_desc));
8871 surface_desc.dwSize = sizeof(surface_desc);
8872 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
8873 surface_desc.dwWidth = 32;
8874 surface_desc.dwHeight = 32;
8875 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
8876 surface_desc.ddsCaps.dwCaps2 = test_data[i].caps2;
8877 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8878 if (is_ddraw64 && (test_data[i].caps & DDSCAPS_TEXTURE))
8880 todo_wine ok(hr == E_NOINTERFACE, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
8881 if (SUCCEEDED(hr))
8882 IDirectDrawSurface7_Release(surface);
8883 continue;
8885 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n", hr, test_data[i].name);
8887 /* Priority == NULL segfaults. */
8888 priority = 0xdeadbeef;
8889 hr = IDirectDrawSurface7_GetPriority(surface, &priority);
8890 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
8891 if (SUCCEEDED(test_data[i].hr))
8892 ok(priority == 0, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
8893 else
8894 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
8896 if (!test_data[i].crash)
8898 hr = IDirectDrawSurface7_SetPriority(surface, 1);
8899 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
8900 hr = IDirectDrawSurface7_GetPriority(surface, &priority);
8901 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
8902 if (SUCCEEDED(test_data[i].hr))
8904 ok(priority == 1, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
8905 hr = IDirectDrawSurface7_SetPriority(surface, 2);
8906 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
8908 else
8909 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
8912 if (test_data[i].caps2 & DDSCAPS2_CUBEMAP)
8914 caps.dwCaps2 = DDSCAPS2_CUBEMAP_NEGATIVEZ;
8915 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
8916 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
8917 /* IDirectDrawSurface7_SetPriority crashes when called on non-positive X surfaces on Windows */
8918 priority = 0xdeadbeef;
8919 hr = IDirectDrawSurface7_GetPriority(mipmap, &priority);
8920 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
8921 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
8923 IDirectDrawSurface7_Release(mipmap);
8926 IDirectDrawSurface7_Release(surface);
8929 if (is_ddraw64)
8930 goto done;
8932 memset(&surface_desc, 0, sizeof(surface_desc));
8933 surface_desc.dwSize = sizeof(surface_desc);
8934 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_MIPMAPCOUNT;
8935 surface_desc.dwWidth = 32;
8936 surface_desc.dwHeight = 32;
8937 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
8938 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
8939 U2(surface_desc).dwMipMapCount = 2;
8940 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8941 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8942 caps.dwCaps2 = 0;
8943 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
8944 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
8946 priority = 0xdeadbeef;
8947 hr = IDirectDrawSurface7_GetPriority(mipmap, &priority);
8948 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type managed mipmap.\n", hr);
8949 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type managed mipmap.\n", priority);
8950 /* SetPriority on the mipmap surface crashes. */
8951 hr = IDirectDrawSurface7_GetPriority(surface, &priority);
8952 ok(SUCCEEDED(hr), "Failed to get priority, hr %#x.\n", hr);
8953 ok(priority == 0, "Got unexpected priority %u, type managed mipmap.\n", priority);
8955 IDirectDrawSurface7_Release(mipmap);
8956 refcount = IDirectDrawSurface7_Release(surface);
8957 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8959 done:
8960 refcount = IDirectDraw7_Release(ddraw);
8961 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8962 DestroyWindow(window);
8965 static void test_surface_desc_lock(void)
8967 IDirectDrawSurface7 *surface;
8968 DDSURFACEDESC2 surface_desc;
8969 IDirectDraw7 *ddraw;
8970 ULONG refcount;
8971 HWND window;
8972 HRESULT hr;
8974 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8975 0, 0, 640, 480, 0, 0, 0, 0);
8976 ddraw = create_ddraw();
8977 ok(!!ddraw, "Failed to create a ddraw object.\n");
8978 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8979 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8981 memset(&surface_desc, 0, sizeof(surface_desc));
8982 surface_desc.dwSize = sizeof(surface_desc);
8983 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8984 surface_desc.dwWidth = 16;
8985 surface_desc.dwHeight = 16;
8986 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8987 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8988 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8990 memset(&surface_desc, 0xaa, sizeof(surface_desc));
8991 surface_desc.dwSize = sizeof(surface_desc);
8992 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
8993 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8994 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
8996 memset(&surface_desc, 0xaa, sizeof(surface_desc));
8997 surface_desc.dwSize = sizeof(surface_desc);
8998 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, 0, NULL);
8999 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
9000 ok(surface_desc.lpSurface != NULL, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9001 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9002 surface_desc.dwSize = sizeof(surface_desc);
9003 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
9004 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
9005 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9006 hr = IDirectDrawSurface7_Unlock(surface, NULL);
9007 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9009 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9010 surface_desc.dwSize = sizeof(surface_desc);
9011 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
9012 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
9013 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9015 IDirectDrawSurface7_Release(surface);
9016 refcount = IDirectDraw7_Release(ddraw);
9017 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9018 DestroyWindow(window);
9021 static void test_fog_interpolation(void)
9023 HRESULT hr;
9024 IDirect3DDevice7 *device;
9025 IDirectDrawSurface7 *rt;
9026 ULONG refcount;
9027 HWND window;
9028 D3DCOLOR color;
9029 static struct
9031 struct vec3 position;
9032 D3DCOLOR diffuse;
9033 D3DCOLOR specular;
9035 quad[] =
9037 {{-1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff000000},
9038 {{-1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff000000},
9039 {{ 1.0f, -1.0f, 1.0f}, 0xffff0000, 0x00000000},
9040 {{ 1.0f, 1.0f, 1.0f}, 0xffff0000, 0x00000000},
9042 union
9044 DWORD d;
9045 float f;
9046 } conv;
9047 unsigned int i;
9048 static const struct
9050 D3DFOGMODE vfog, tfog;
9051 D3DSHADEMODE shade;
9052 D3DCOLOR middle_color;
9053 BOOL todo;
9055 tests[] =
9057 {D3DFOG_NONE, D3DFOG_NONE, D3DSHADE_FLAT, 0x00007f80, FALSE},
9058 {D3DFOG_NONE, D3DFOG_NONE, D3DSHADE_GOURAUD, 0x00007f80, FALSE},
9059 {D3DFOG_EXP, D3DFOG_NONE, D3DSHADE_FLAT, 0x00007f80, TRUE},
9060 {D3DFOG_EXP, D3DFOG_NONE, D3DSHADE_GOURAUD, 0x00007f80, TRUE},
9061 {D3DFOG_NONE, D3DFOG_EXP, D3DSHADE_FLAT, 0x0000ea15, FALSE},
9062 {D3DFOG_NONE, D3DFOG_EXP, D3DSHADE_GOURAUD, 0x0000ea15, FALSE},
9063 {D3DFOG_EXP, D3DFOG_EXP, D3DSHADE_FLAT, 0x0000ea15, FALSE},
9064 {D3DFOG_EXP, D3DFOG_EXP, D3DSHADE_GOURAUD, 0x0000ea15, FALSE},
9066 D3DDEVICEDESC7 caps;
9068 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9069 0, 0, 640, 480, 0, 0, 0, 0);
9071 if (!(device = create_device(window, DDSCL_NORMAL)))
9073 skip("Failed to create a 3D device, skipping test.\n");
9074 DestroyWindow(window);
9075 return;
9078 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
9079 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9080 hr = IDirect3DDevice7_GetCaps(device, &caps);
9081 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
9082 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE))
9083 skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping some fog tests\n");
9085 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
9086 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9087 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
9088 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9089 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
9090 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9091 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x0000ff00);
9092 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9093 conv.f = 5.0;
9094 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGDENSITY, conv.d);
9095 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9097 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
9098 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
9099 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
9100 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
9101 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x000000ff);
9102 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9104 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
9106 if(!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE) && tests[i].tfog)
9107 continue;
9109 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00808080, 0.0f, 0);
9110 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
9112 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SHADEMODE, tests[i].shade);
9113 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9114 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, tests[i].vfog);
9115 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9116 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, tests[i].tfog);
9117 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9118 hr = IDirect3DDevice7_BeginScene(device);
9119 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9120 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9121 D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR, quad, 4, 0);
9122 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9123 hr = IDirect3DDevice7_EndScene(device);
9124 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9126 color = get_surface_color(rt, 0, 240);
9127 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x, case %u.\n", color, i);
9128 color = get_surface_color(rt, 320, 240);
9129 todo_wine_if (tests[i].todo)
9130 ok(compare_color(color, tests[i].middle_color, 2),
9131 "Got unexpected color 0x%08x, case %u.\n", color, i);
9132 color = get_surface_color(rt, 639, 240);
9133 ok(compare_color(color, 0x0000fd02, 2), "Got unexpected color 0x%08x, case %u.\n", color, i);
9136 IDirectDrawSurface7_Release(rt);
9137 refcount = IDirect3DDevice7_Release(device);
9138 ok(!refcount, "Device has %u references left.\n", refcount);
9139 DestroyWindow(window);
9142 static void test_negative_fixedfunction_fog(void)
9144 HRESULT hr;
9145 IDirect3DDevice7 *device;
9146 IDirectDrawSurface7 *rt;
9147 ULONG refcount;
9148 HWND window;
9149 D3DCOLOR color;
9150 static struct
9152 struct vec3 position;
9153 D3DCOLOR diffuse;
9155 quad[] =
9157 {{-1.0f, -1.0f, -0.5f}, 0xffff0000},
9158 {{-1.0f, 1.0f, -0.5f}, 0xffff0000},
9159 {{ 1.0f, -1.0f, -0.5f}, 0xffff0000},
9160 {{ 1.0f, 1.0f, -0.5f}, 0xffff0000},
9162 static struct
9164 struct vec4 position;
9165 D3DCOLOR diffuse;
9167 tquad[] =
9169 {{ 0.0f, 0.0f, -0.5f, 1.0f}, 0xffff0000},
9170 {{640.0f, 0.0f, -0.5f, 1.0f}, 0xffff0000},
9171 {{ 0.0f, 480.0f, -0.5f, 1.0f}, 0xffff0000},
9172 {{640.0f, 480.0f, -0.5f, 1.0f}, 0xffff0000},
9174 unsigned int i;
9175 static D3DMATRIX zero =
9177 1.0f, 0.0f, 0.0f, 0.0f,
9178 0.0f, 1.0f, 0.0f, 0.0f,
9179 0.0f, 0.0f, 0.0f, 0.0f,
9180 0.0f, 0.0f, 0.0f, 1.0f
9182 static D3DMATRIX identity =
9184 1.0f, 0.0f, 0.0f, 0.0f,
9185 0.0f, 1.0f, 0.0f, 0.0f,
9186 0.0f, 0.0f, 1.0f, 0.0f,
9187 0.0f, 0.0f, 0.0f, 1.0f
9189 static const struct
9191 DWORD pos_type;
9192 void *quad;
9193 D3DMATRIX *matrix;
9194 union
9196 float f;
9197 DWORD d;
9198 } start, end;
9199 D3DFOGMODE vfog, tfog;
9200 DWORD color, color_broken, color_broken2;
9202 tests[] =
9204 /* Run the XYZRHW tests first. Depth clamping is broken after RHW draws on the testbot.
9206 * Geforce8+ GPUs on Windows abs() table fog, everything else does not. */
9207 {D3DFVF_XYZRHW, tquad, &identity, { 0.0f}, {1.0f}, D3DFOG_NONE, D3DFOG_LINEAR,
9208 0x00ff0000, 0x00808000, 0x00808000},
9209 /* r200 GPUs and presumably all d3d8 and older HW clamp the fog
9210 * parameters to 0.0 and 1.0 in the table fog case. */
9211 {D3DFVF_XYZRHW, tquad, &identity, {-1.0f}, {0.0f}, D3DFOG_NONE, D3DFOG_LINEAR,
9212 0x00808000, 0x00ff0000, 0x0000ff00},
9213 /* test_fog_interpolation shows that vertex fog evaluates the fog
9214 * equation in the vertex pipeline. Start = -1.0 && end = 0.0 shows
9215 * that the abs happens before the fog equation is evaluated.
9217 * Vertex fog abs() behavior is the same on all GPUs. */
9218 {D3DFVF_XYZ, quad, &zero, { 0.0f}, {1.0f}, D3DFOG_LINEAR, D3DFOG_NONE,
9219 0x00808000, 0x00808000, 0x00808000},
9220 {D3DFVF_XYZ, quad, &zero, {-1.0f}, {0.0f}, D3DFOG_LINEAR, D3DFOG_NONE,
9221 0x0000ff00, 0x0000ff00, 0x0000ff00},
9222 {D3DFVF_XYZ, quad, &zero, { 0.0f}, {1.0f}, D3DFOG_EXP, D3DFOG_NONE,
9223 0x009b6400, 0x009b6400, 0x009b6400},
9225 D3DDEVICEDESC7 caps;
9227 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9228 0, 0, 640, 480, 0, 0, 0, 0);
9230 if (!(device = create_device(window, DDSCL_NORMAL)))
9232 skip("Failed to create a 3D device, skipping test.\n");
9233 DestroyWindow(window);
9234 return;
9237 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
9238 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9239 hr = IDirect3DDevice7_GetCaps(device, &caps);
9240 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
9241 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE))
9242 skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping some fog tests.\n");
9244 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
9245 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9246 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
9247 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9248 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
9249 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9250 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x0000ff00);
9251 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9252 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
9253 ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
9255 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
9257 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE) && tests[i].tfog)
9258 continue;
9260 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0);
9261 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
9263 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, tests[i].matrix);
9264 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
9265 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGSTART, tests[i].start.d);
9266 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9267 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGEND, tests[i].end.d);
9268 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9269 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, tests[i].vfog);
9270 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9271 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, tests[i].tfog);
9272 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9274 hr = IDirect3DDevice7_BeginScene(device);
9275 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9276 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9277 tests[i].pos_type | D3DFVF_DIFFUSE, tests[i].quad, 4, 0);
9278 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9279 hr = IDirect3DDevice7_EndScene(device);
9280 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9282 color = get_surface_color(rt, 0, 240);
9283 ok(compare_color(color, tests[i].color, 2) || broken(compare_color(color, tests[i].color_broken, 2))
9284 || broken(compare_color(color, tests[i].color_broken2, 2)),
9285 "Got unexpected color 0x%08x, case %u.\n", color, i);
9288 IDirectDrawSurface7_Release(rt);
9289 refcount = IDirect3DDevice7_Release(device);
9290 ok(!refcount, "Device has %u references left.\n", refcount);
9291 DestroyWindow(window);
9294 static void test_table_fog_zw(void)
9296 HRESULT hr;
9297 IDirect3DDevice7 *device;
9298 IDirectDrawSurface7 *rt;
9299 ULONG refcount;
9300 HWND window;
9301 D3DCOLOR color;
9302 static struct
9304 struct vec4 position;
9305 D3DCOLOR diffuse;
9307 quad[] =
9309 {{ 0.0f, 0.0f, 0.0f, 0.0f}, 0xffff0000},
9310 {{640.0f, 0.0f, 0.0f, 0.0f}, 0xffff0000},
9311 {{ 0.0f, 480.0f, 0.0f, 0.0f}, 0xffff0000},
9312 {{640.0f, 480.0f, 0.0f, 0.0f}, 0xffff0000},
9314 static D3DMATRIX identity =
9316 1.0f, 0.0f, 0.0f, 0.0f,
9317 0.0f, 1.0f, 0.0f, 0.0f,
9318 0.0f, 0.0f, 1.0f, 0.0f,
9319 0.0f, 0.0f, 0.0f, 1.0f
9321 D3DDEVICEDESC7 caps;
9322 static const struct
9324 float z, w;
9325 D3DZBUFFERTYPE z_test;
9326 D3DCOLOR color;
9328 tests[] =
9330 {0.7f, 0.0f, D3DZB_TRUE, 0x004cb200},
9331 {0.7f, 0.0f, D3DZB_FALSE, 0x004cb200},
9332 {0.7f, 0.3f, D3DZB_TRUE, 0x004cb200},
9333 {0.7f, 0.3f, D3DZB_FALSE, 0x004cb200},
9334 {0.7f, 3.0f, D3DZB_TRUE, 0x004cb200},
9335 {0.7f, 3.0f, D3DZB_FALSE, 0x004cb200},
9336 {0.3f, 0.0f, D3DZB_TRUE, 0x00b24c00},
9337 {0.3f, 0.0f, D3DZB_FALSE, 0x00b24c00},
9339 unsigned int i;
9341 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9342 0, 0, 640, 480, 0, 0, 0, 0);
9344 if (!(device = create_device(window, DDSCL_NORMAL)))
9346 skip("Failed to create a 3D device, skipping test.\n");
9347 DestroyWindow(window);
9348 return;
9351 hr = IDirect3DDevice7_GetCaps(device, &caps);
9352 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
9353 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE))
9355 skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping POSITIONT table fog test.\n");
9356 goto done;
9358 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
9359 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9361 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
9362 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9363 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
9364 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9365 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x0000ff00);
9366 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9367 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
9368 ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
9369 /* Work around an AMD Windows driver bug. Needs a proj matrix applied redundantly. */
9370 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &identity);
9371 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
9372 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_LINEAR);
9373 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9375 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
9377 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x000000ff, 1.0f, 0);
9378 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
9380 quad[0].position.z = tests[i].z;
9381 quad[1].position.z = tests[i].z;
9382 quad[2].position.z = tests[i].z;
9383 quad[3].position.z = tests[i].z;
9384 quad[0].position.w = tests[i].w;
9385 quad[1].position.w = tests[i].w;
9386 quad[2].position.w = tests[i].w;
9387 quad[3].position.w = tests[i].w;
9388 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, tests[i].z_test);
9389 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9391 hr = IDirect3DDevice7_BeginScene(device);
9392 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9393 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9394 D3DFVF_XYZRHW | D3DFVF_DIFFUSE, quad, 4, 0);
9395 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9396 hr = IDirect3DDevice7_EndScene(device);
9397 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9399 color = get_surface_color(rt, 0, 240);
9400 ok(compare_color(color, tests[i].color, 2),
9401 "Got unexpected color 0x%08x, expected 0x%8x, case %u.\n", color, tests[i].color, i);
9404 IDirectDrawSurface7_Release(rt);
9405 done:
9406 refcount = IDirect3DDevice7_Release(device);
9407 ok(!refcount, "Device has %u references left.\n", refcount);
9408 DestroyWindow(window);
9411 static void test_signed_formats(void)
9413 HRESULT hr;
9414 IDirect3DDevice7 *device;
9415 IDirect3D7 *d3d;
9416 IDirectDraw7 *ddraw;
9417 IDirectDrawSurface7 *surface, *rt;
9418 DDSURFACEDESC2 surface_desc;
9419 ULONG refcount;
9420 HWND window;
9421 D3DCOLOR color, expected_color;
9422 static struct
9424 struct vec3 position;
9425 struct vec2 texcoord;
9427 quad[] =
9429 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
9430 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
9431 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
9432 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
9434 /* See test_signed_formats() in dlls/d3d9/tests/visual.c for an explanation
9435 * of these values. */
9436 static const USHORT content_v8u8[4][4] =
9438 {0x0000, 0x7f7f, 0x8880, 0x0000},
9439 {0x0080, 0x8000, 0x7f00, 0x007f},
9440 {0x193b, 0xe8c8, 0x0808, 0xf8f8},
9441 {0x4444, 0xc0c0, 0xa066, 0x22e0},
9443 static const DWORD content_x8l8v8u8[4][4] =
9445 {0x00000000, 0x00ff7f7f, 0x00008880, 0x00ff0000},
9446 {0x00000080, 0x00008000, 0x00007f00, 0x0000007f},
9447 {0x0041193b, 0x0051e8c8, 0x00040808, 0x00fff8f8},
9448 {0x00824444, 0x0000c0c0, 0x00c2a066, 0x009222e0},
9450 static const USHORT content_l6v5u5[4][4] =
9452 {0x0000, 0xfdef, 0x0230, 0xfc00},
9453 {0x0010, 0x0200, 0x01e0, 0x000f},
9454 {0x4067, 0x53b9, 0x0421, 0xffff},
9455 {0x8108, 0x0318, 0xc28c, 0x909c},
9457 static const struct
9459 const char *name;
9460 const void *content;
9461 SIZE_T pixel_size;
9462 BOOL blue;
9463 unsigned int slop, slop_broken;
9464 DDPIXELFORMAT format;
9466 formats[] =
9469 "D3DFMT_V8U8", content_v8u8, sizeof(WORD), FALSE, 1, 0,
9471 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV, 0,
9472 {16}, {0x000000ff}, {0x0000ff00}, {0x00000000}, {0x00000000}
9476 "D3DFMT_X8L8V8U8", content_x8l8v8u8, sizeof(DWORD), TRUE, 1, 0,
9478 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE, 0,
9479 {32}, {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}
9483 "D3DFMT_L6V5U5", content_l6v5u5, sizeof(WORD), TRUE, 4, 7,
9485 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE, 0,
9486 {16}, {0x0000001f}, {0x000003e0}, {0x0000fc00}, {0x00000000}
9490 /* No V16U16 or Q8W8V8U8 support in ddraw. */
9492 static const D3DCOLOR expected_colors[4][4] =
9494 {0x00808080, 0x00fefeff, 0x00010780, 0x008080ff},
9495 {0x00018080, 0x00800180, 0x0080fe80, 0x00fe8080},
9496 {0x00ba98a0, 0x004767a8, 0x00888881, 0x007878ff},
9497 {0x00c3c3c0, 0x003f3f80, 0x00e51fe1, 0x005fa2c8},
9499 unsigned int i, width, x, y;
9500 D3DDEVICEDESC7 device_desc;
9502 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9503 0, 0, 640, 480, 0, 0, 0, 0);
9505 if (!(device = create_device(window, DDSCL_NORMAL)))
9507 skip("Failed to create a 3D device, skipping test.\n");
9508 DestroyWindow(window);
9509 return;
9512 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
9513 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
9514 if (!(device_desc.dwTextureOpCaps & D3DTEXOPCAPS_BLENDFACTORALPHA))
9516 skip("D3DTOP_BLENDFACTORALPHA not supported, skipping bumpmap format tests.\n");
9517 goto done;
9520 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
9521 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
9522 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
9523 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
9524 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
9525 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9527 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
9528 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9530 /* dst = tex * 0.5 + 1.0 * (1.0 - 0.5) = tex * 0.5 + 0.5 */
9531 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x80ffffff);
9532 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9533 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_BLENDFACTORALPHA);
9534 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
9535 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
9536 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
9537 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
9538 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
9540 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
9542 for (width = 1; width < 5; width += 3)
9544 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
9545 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
9547 memset(&surface_desc, 0, sizeof(surface_desc));
9548 surface_desc.dwSize = sizeof(surface_desc);
9549 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
9550 surface_desc.dwWidth = width;
9551 surface_desc.dwHeight = 4;
9552 U4(surface_desc).ddpfPixelFormat = formats[i].format;
9553 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
9554 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9555 if (FAILED(hr))
9557 skip("%s textures not supported, skipping.\n", formats[i].name);
9558 continue;
9560 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, format %s.\n", hr, formats[i].name);
9561 hr = IDirect3DDevice7_SetTexture(device, 0, surface);
9562 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x, format %s.\n", hr, formats[i].name);
9564 memset(&surface_desc, 0, sizeof(surface_desc));
9565 surface_desc.dwSize = sizeof(surface_desc);
9566 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, 0, NULL);
9567 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, format %s.\n", hr, formats[i].name);
9568 for (y = 0; y < 4; y++)
9570 memcpy((char *)surface_desc.lpSurface + y * U1(surface_desc).lPitch,
9571 (char *)formats[i].content + y * 4 * formats[i].pixel_size,
9572 width * formats[i].pixel_size);
9574 hr = IDirectDrawSurface7_Unlock(surface, NULL);
9575 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, format %s.\n", hr, formats[i].name);
9577 hr = IDirect3DDevice7_BeginScene(device);
9578 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9579 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9580 D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
9581 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9582 hr = IDirect3DDevice7_EndScene(device);
9583 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9585 for (y = 0; y < 4; y++)
9587 for (x = 0; x < width; x++)
9589 expected_color = expected_colors[y][x];
9590 if (!formats[i].blue)
9591 expected_color |= 0x000000ff;
9593 color = get_surface_color(rt, 80 + 160 * x, 60 + 120 * y);
9594 ok(compare_color(color, expected_color, formats[i].slop)
9595 || broken(compare_color(color, expected_color, formats[i].slop_broken)),
9596 "Expected color 0x%08x, got 0x%08x, format %s, location %ux%u.\n",
9597 expected_color, color, formats[i].name, x, y);
9601 IDirectDrawSurface7_Release(surface);
9606 IDirectDrawSurface7_Release(rt);
9607 IDirectDraw7_Release(ddraw);
9608 IDirect3D7_Release(d3d);
9610 done:
9611 refcount = IDirect3DDevice7_Release(device);
9612 ok(!refcount, "Device has %u references left.\n", refcount);
9613 DestroyWindow(window);
9616 static void test_color_fill(void)
9618 HRESULT hr;
9619 IDirect3DDevice7 *device;
9620 IDirect3D7 *d3d;
9621 IDirectDraw7 *ddraw;
9622 IDirectDrawSurface7 *surface, *surface2;
9623 DDSURFACEDESC2 surface_desc;
9624 DDPIXELFORMAT z_fmt;
9625 ULONG refcount;
9626 HWND window;
9627 unsigned int i;
9628 DDBLTFX fx;
9629 RECT rect = {5, 5, 7, 7};
9630 DWORD *color;
9631 DWORD supported_fmts = 0, num_fourcc_codes, *fourcc_codes;
9632 DDCAPS hal_caps;
9633 static const struct
9635 DWORD caps, caps2;
9636 HRESULT colorfill_hr, depthfill_hr;
9637 BOOL rop_success;
9638 const char *name;
9639 DWORD result;
9640 BOOL check_result;
9641 DDPIXELFORMAT format;
9643 tests[] =
9646 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
9647 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain RGB", 0xdeadbeef, TRUE,
9649 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9650 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9654 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0,
9655 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain RGB", 0xdeadbeef, TRUE,
9657 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9658 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9662 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0,
9663 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem texture RGB", 0xdeadbeef, TRUE,
9665 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9666 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9670 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0,
9671 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem texture RGB", 0xdeadbeef, TRUE,
9673 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9674 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9678 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
9679 DD_OK, DDERR_INVALIDPARAMS, TRUE, "managed texture RGB", 0xdeadbeef, TRUE,
9681 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9682 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9686 DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY, 0,
9687 DDERR_INVALIDPARAMS, DD_OK, TRUE, "vidmem zbuffer", 0xdeadbeef, TRUE,
9688 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
9691 DDSCAPS_ZBUFFER | DDSCAPS_SYSTEMMEMORY, 0,
9692 DDERR_INVALIDPARAMS, DD_OK, TRUE, "sysmem zbuffer", 0xdeadbeef, TRUE,
9693 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
9696 /* Colorfill on YUV surfaces always returns DD_OK, but the content is
9697 * different afterwards. DX9+ GPUs set one of the two luminance values
9698 * in each block, but AMD and Nvidia GPUs disagree on which luminance
9699 * value they set. r200 (dx8) just sets the entire block to the clear
9700 * value. */
9701 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
9702 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain YUY2", 0, FALSE,
9704 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
9705 {0}, {0}, {0}, {0}, {0}
9709 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
9710 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain UYVY", 0, FALSE,
9712 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
9713 {0}, {0}, {0}, {0}, {0}
9717 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY, 0,
9718 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay YUY2", 0, FALSE,
9720 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
9721 {0}, {0}, {0}, {0}, {0}
9725 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY, 0,
9726 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay UYVY", 0, FALSE,
9728 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
9729 {0}, {0}, {0}, {0}, {0}
9733 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0,
9734 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "vidmem texture DXT1", 0, FALSE,
9736 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
9737 {0}, {0}, {0}, {0}, {0}
9741 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0,
9742 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "sysmem texture DXT1", 0, FALSE,
9744 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
9745 {0}, {0}, {0}, {0}, {0}
9749 /* The testbot fills this with 0x00 instead of the blue channel. The sysmem
9750 * surface works, presumably because it is handled by the runtime instead of
9751 * the driver. */
9752 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
9753 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain P8", 0xefefefef, FALSE,
9755 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
9756 {8}, {0}, {0}, {0}, {0}
9760 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0,
9761 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain P8", 0xefefefef, TRUE,
9763 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
9764 {8}, {0}, {0}, {0}, {0}
9768 static const struct
9770 DWORD rop;
9771 const char *name;
9772 HRESULT hr;
9774 rops[] =
9776 {SRCCOPY, "SRCCOPY", DD_OK},
9777 {SRCPAINT, "SRCPAINT", DDERR_NORASTEROPHW},
9778 {SRCAND, "SRCAND", DDERR_NORASTEROPHW},
9779 {SRCINVERT, "SRCINVERT", DDERR_NORASTEROPHW},
9780 {SRCERASE, "SRCERASE", DDERR_NORASTEROPHW},
9781 {NOTSRCCOPY, "NOTSRCCOPY", DDERR_NORASTEROPHW},
9782 {NOTSRCERASE, "NOTSRCERASE", DDERR_NORASTEROPHW},
9783 {MERGECOPY, "MERGECOPY", DDERR_NORASTEROPHW},
9784 {MERGEPAINT, "MERGEPAINT", DDERR_NORASTEROPHW},
9785 {PATCOPY, "PATCOPY", DDERR_NORASTEROPHW},
9786 {PATPAINT, "PATPAINT", DDERR_NORASTEROPHW},
9787 {PATINVERT, "PATINVERT", DDERR_NORASTEROPHW},
9788 {DSTINVERT, "DSTINVERT", DDERR_NORASTEROPHW},
9789 {BLACKNESS, "BLACKNESS", DD_OK},
9790 {WHITENESS, "WHITENESS", DD_OK},
9791 {0xaa0029, "0xaa0029", DDERR_NORASTEROPHW} /* noop */
9794 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9795 0, 0, 640, 480, 0, 0, 0, 0);
9797 if (!(device = create_device(window, DDSCL_NORMAL)))
9799 skip("Failed to create a 3D device, skipping test.\n");
9800 DestroyWindow(window);
9801 return;
9804 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
9805 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
9806 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
9807 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
9809 memset(&z_fmt, 0, sizeof(z_fmt));
9810 IDirect3D7_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
9811 if (!z_fmt.dwSize)
9812 skip("No Z buffer formats supported, skipping Z buffer colorfill test.\n");
9814 IDirect3DDevice7_EnumTextureFormats(device, test_block_formats_creation_cb, &supported_fmts);
9815 if (!(supported_fmts & SUPPORT_DXT1))
9816 skip("DXT1 textures not supported, skipping DXT1 colorfill test.\n");
9818 IDirect3D7_Release(d3d);
9820 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
9821 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
9822 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
9823 num_fourcc_codes * sizeof(*fourcc_codes));
9824 if (!fourcc_codes)
9825 goto done;
9826 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
9827 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
9828 for (i = 0; i < num_fourcc_codes; i++)
9830 if (fourcc_codes[i] == MAKEFOURCC('Y', 'U', 'Y', '2'))
9831 supported_fmts |= SUPPORT_YUY2;
9832 else if (fourcc_codes[i] == MAKEFOURCC('U', 'Y', 'V', 'Y'))
9833 supported_fmts |= SUPPORT_UYVY;
9835 HeapFree(GetProcessHeap(), 0, fourcc_codes);
9837 memset(&hal_caps, 0, sizeof(hal_caps));
9838 hal_caps.dwSize = sizeof(hal_caps);
9839 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
9840 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9842 if (!(supported_fmts & (SUPPORT_YUY2 | SUPPORT_UYVY)) || !(hal_caps.dwCaps & DDCAPS_OVERLAY))
9843 skip("Overlays or some YUV formats not supported, skipping YUV colorfill tests.\n");
9845 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
9847 DWORD expected_broken = tests[i].result;
9849 /* Some Windows drivers modify dwFillColor when it is used on P8 or FourCC formats. */
9850 memset(&fx, 0, sizeof(fx));
9851 fx.dwSize = sizeof(fx);
9852 U5(fx).dwFillColor = 0xdeadbeef;
9854 memset(&surface_desc, 0, sizeof(surface_desc));
9855 surface_desc.dwSize = sizeof(surface_desc);
9856 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9857 surface_desc.dwWidth = 64;
9858 surface_desc.dwHeight = 64;
9859 U4(surface_desc).ddpfPixelFormat = tests[i].format;
9860 surface_desc.ddsCaps.dwCaps = tests[i].caps;
9861 surface_desc.ddsCaps.dwCaps2 = tests[i].caps2;
9863 if (tests[i].format.dwFourCC == MAKEFOURCC('D','X','T','1') && !(supported_fmts & SUPPORT_DXT1))
9864 continue;
9865 if (tests[i].format.dwFourCC == MAKEFOURCC('Y','U','Y','2') && !(supported_fmts & SUPPORT_YUY2))
9866 continue;
9867 if (tests[i].format.dwFourCC == MAKEFOURCC('U','Y','V','Y') && !(supported_fmts & SUPPORT_UYVY))
9868 continue;
9869 if (tests[i].caps & DDSCAPS_OVERLAY && !(hal_caps.dwCaps & DDCAPS_OVERLAY))
9870 continue;
9872 if (tests[i].caps & DDSCAPS_ZBUFFER)
9874 if (!z_fmt.dwSize)
9875 continue;
9877 U4(surface_desc).ddpfPixelFormat = z_fmt;
9878 /* Some drivers seem to convert depth values incorrectly or not at
9879 * all. Affects at least AMD PALM, 8.17.10.1247. */
9880 if (tests[i].caps & DDSCAPS_VIDEOMEMORY)
9882 DWORD expected;
9883 float f, g;
9885 expected = tests[i].result & U3(z_fmt).dwZBitMask;
9886 f = ceilf(log2f(expected + 1.0f));
9887 g = (f + 1.0f) / 2.0f;
9888 g -= (int)g;
9889 expected_broken = (expected / exp2f(f) - g) * 256;
9890 expected_broken *= 0x01010101;
9894 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9895 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, surface %s.\n", hr, tests[i].name);
9897 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9898 todo_wine_if (tests[i].format.dwFourCC)
9899 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9900 hr, tests[i].colorfill_hr, tests[i].name);
9902 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9903 todo_wine_if (tests[i].format.dwFourCC)
9904 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9905 hr, tests[i].colorfill_hr, tests[i].name);
9907 if (SUCCEEDED(hr) && tests[i].check_result)
9909 memset(&surface_desc, 0, sizeof(surface_desc));
9910 surface_desc.dwSize = sizeof(surface_desc);
9911 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9912 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9913 color = surface_desc.lpSurface;
9914 ok(*color == tests[i].result, "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
9915 *color, tests[i].result, tests[i].name);
9916 hr = IDirectDrawSurface7_Unlock(surface, NULL);
9917 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9920 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9921 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9922 hr, tests[i].depthfill_hr, tests[i].name);
9923 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9924 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9925 hr, tests[i].depthfill_hr, tests[i].name);
9927 if (SUCCEEDED(hr) && tests[i].check_result)
9929 memset(&surface_desc, 0, sizeof(surface_desc));
9930 surface_desc.dwSize = sizeof(surface_desc);
9931 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9932 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9933 color = surface_desc.lpSurface;
9934 todo_wine_if(tests[i].caps & DDSCAPS_VIDEOMEMORY && U3(z_fmt).dwZBitMask != 0xffff)
9935 ok((*color & U3(z_fmt).dwZBitMask) == (tests[i].result & U3(z_fmt).dwZBitMask)
9936 || broken((*color & U3(z_fmt).dwZBitMask) == (expected_broken & U3(z_fmt).dwZBitMask)),
9937 "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
9938 *color & U3(z_fmt).dwZBitMask, tests[i].result & U3(z_fmt).dwZBitMask, tests[i].name);
9939 hr = IDirectDrawSurface7_Unlock(surface, NULL);
9940 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9943 U5(fx).dwFillColor = 0xdeadbeef;
9944 fx.dwROP = BLACKNESS;
9945 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
9946 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
9947 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
9948 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
9949 U5(fx).dwFillColor, tests[i].name);
9951 if (SUCCEEDED(hr) && tests[i].check_result)
9953 memset(&surface_desc, 0, sizeof(surface_desc));
9954 surface_desc.dwSize = sizeof(surface_desc);
9955 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9956 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9957 color = surface_desc.lpSurface;
9958 ok(*color == 0, "Got clear result 0x%08x, expected 0x00000000, surface %s.\n",
9959 *color, tests[i].name);
9960 hr = IDirectDrawSurface7_Unlock(surface, NULL);
9961 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9964 fx.dwROP = WHITENESS;
9965 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
9966 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
9967 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
9968 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
9969 U5(fx).dwFillColor, tests[i].name);
9971 if (SUCCEEDED(hr) && tests[i].check_result)
9973 memset(&surface_desc, 0, sizeof(surface_desc));
9974 surface_desc.dwSize = sizeof(surface_desc);
9975 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9976 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9977 color = surface_desc.lpSurface;
9978 /* WHITENESS sets the alpha channel to 0x00. Ignore this for now. */
9979 ok((*color & 0x00ffffff) == 0x00ffffff, "Got clear result 0x%08x, expected 0xffffffff, surface %s.\n",
9980 *color, tests[i].name);
9981 hr = IDirectDrawSurface7_Unlock(surface, NULL);
9982 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9985 IDirectDrawSurface7_Release(surface);
9988 memset(&fx, 0, sizeof(fx));
9989 fx.dwSize = sizeof(fx);
9990 U5(fx).dwFillColor = 0xdeadbeef;
9991 fx.dwROP = WHITENESS;
9993 memset(&surface_desc, 0, sizeof(surface_desc));
9994 surface_desc.dwSize = sizeof(surface_desc);
9995 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9996 surface_desc.dwWidth = 64;
9997 surface_desc.dwHeight = 64;
9998 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9999 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
10000 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
10001 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
10002 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
10003 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
10004 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
10005 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10006 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10007 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
10008 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10010 /* No DDBLTFX. */
10011 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, NULL);
10012 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10013 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, NULL);
10014 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10016 /* Unused source rectangle. */
10017 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10018 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10019 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10020 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10022 /* Unused source surface. */
10023 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10024 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10025 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
10026 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10027 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10028 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10029 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10030 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10032 /* Inverted destination or source rectangle. */
10033 SetRect(&rect, 5, 7, 7, 5);
10034 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10035 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10036 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10037 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10038 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10039 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10040 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10041 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10042 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10043 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10045 /* Negative rectangle. */
10046 SetRect(&rect, -1, -1, 5, 5);
10047 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10048 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10049 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10050 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10051 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10052 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10053 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10054 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10055 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10056 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10058 /* Out of bounds rectangle. */
10059 SetRect(&rect, 0, 0, 65, 65);
10060 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10061 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10062 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10063 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10065 /* Combine multiple flags. */
10066 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10067 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10068 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
10069 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10070 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
10071 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10073 for (i = 0; i < sizeof(rops) / sizeof(*rops); i++)
10075 fx.dwROP = rops[i].rop;
10076 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
10077 ok(hr == rops[i].hr, "Got unexpected hr %#x for rop %s.\n", hr, rops[i].name);
10080 IDirectDrawSurface7_Release(surface2);
10081 IDirectDrawSurface7_Release(surface);
10083 if (!z_fmt.dwSize)
10084 goto done;
10086 memset(&surface_desc, 0, sizeof(surface_desc));
10087 surface_desc.dwSize = sizeof(surface_desc);
10088 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10089 surface_desc.dwWidth = 64;
10090 surface_desc.dwHeight = 64;
10091 U4(surface_desc).ddpfPixelFormat = z_fmt;
10092 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
10093 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10094 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10095 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
10096 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10098 /* No DDBLTFX. */
10099 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, NULL);
10100 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10102 /* Unused source rectangle. */
10103 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10104 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10106 /* Unused source surface. */
10107 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10108 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10109 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10110 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10112 /* Inverted destination or source rectangle. */
10113 SetRect(&rect, 5, 7, 7, 5);
10114 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10115 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10116 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10117 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10118 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10119 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10120 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10121 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10123 /* Negative rectangle. */
10124 SetRect(&rect, -1, -1, 5, 5);
10125 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10126 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10127 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10128 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10129 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10130 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10131 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10132 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10134 /* Out of bounds rectangle. */
10135 SetRect(&rect, 0, 0, 65, 65);
10136 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10137 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10139 /* Combine multiple flags. */
10140 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10141 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10143 IDirectDrawSurface7_Release(surface2);
10144 IDirectDrawSurface7_Release(surface);
10146 done:
10147 IDirectDraw7_Release(ddraw);
10148 refcount = IDirect3DDevice7_Release(device);
10149 ok(!refcount, "Device has %u references left.\n", refcount);
10150 DestroyWindow(window);
10153 static void test_texcoordindex(void)
10155 static D3DMATRIX mat =
10157 1.0f, 0.0f, 0.0f, 0.0f,
10158 0.0f, 0.0f, 0.0f, 0.0f,
10159 0.0f, 0.0f, 0.0f, 0.0f,
10160 0.0f, 0.0f, 0.0f, 0.0f,
10162 static struct
10164 struct vec3 pos;
10165 struct vec2 texcoord1;
10166 struct vec2 texcoord2;
10167 struct vec2 texcoord3;
10169 quad[] =
10171 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f}},
10172 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 0.0f}},
10173 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}},
10174 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}},
10176 static const DWORD fvf = D3DFVF_XYZ | D3DFVF_TEX3;
10177 IDirect3DDevice7 *device;
10178 IDirect3D7 *d3d;
10179 IDirectDraw7 *ddraw;
10180 IDirectDrawSurface7 *rt;
10181 HWND window;
10182 HRESULT hr;
10183 IDirectDrawSurface7 *texture1, *texture2;
10184 DDSURFACEDESC2 surface_desc;
10185 ULONG refcount;
10186 D3DCOLOR color;
10187 DWORD *ptr;
10189 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
10190 0, 0, 640, 480, 0, 0, 0, 0);
10191 if (!(device = create_device(window, DDSCL_NORMAL)))
10193 skip("Failed to create a 3D device, skipping test.\n");
10194 DestroyWindow(window);
10195 return;
10198 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
10199 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
10200 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
10201 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
10202 IDirect3D7_Release(d3d);
10204 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
10205 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10207 memset(&surface_desc, 0, sizeof(surface_desc));
10208 surface_desc.dwSize = sizeof(surface_desc);
10209 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10210 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
10211 surface_desc.dwWidth = 2;
10212 surface_desc.dwHeight = 2;
10213 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
10214 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
10215 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
10216 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
10217 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
10218 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
10219 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
10220 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture1, NULL);
10221 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10222 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture2, NULL);
10223 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10225 memset(&surface_desc, 0, sizeof(surface_desc));
10226 surface_desc.dwSize = sizeof(surface_desc);
10227 hr = IDirectDrawSurface7_Lock(texture1, 0, &surface_desc, 0, NULL);
10228 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10229 ptr = surface_desc.lpSurface;
10230 ptr[0] = 0xff000000;
10231 ptr[1] = 0xff00ff00;
10232 ptr += U1(surface_desc).lPitch / sizeof(*ptr);
10233 ptr[0] = 0xff0000ff;
10234 ptr[1] = 0xff00ffff;
10235 hr = IDirectDrawSurface7_Unlock(texture1, NULL);
10236 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10238 memset(&surface_desc, 0, sizeof(surface_desc));
10239 surface_desc.dwSize = sizeof(surface_desc);
10240 hr = IDirectDrawSurface7_Lock(texture2, 0, &surface_desc, 0, NULL);
10241 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10242 ptr = surface_desc.lpSurface;
10243 ptr[0] = 0xff000000;
10244 ptr[1] = 0xff0000ff;
10245 ptr += U1(surface_desc).lPitch / sizeof(*ptr);
10246 ptr[0] = 0xffff0000;
10247 ptr[1] = 0xffff00ff;
10248 hr = IDirectDrawSurface7_Unlock(texture2, 0);
10249 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10251 hr = IDirect3DDevice7_SetTexture(device, 0, texture1);
10252 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
10253 hr = IDirect3DDevice7_SetTexture(device, 1, texture2);
10254 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
10255 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
10256 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
10257 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
10258 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
10259 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
10260 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10261 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_ADD);
10262 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
10263 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
10264 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10265 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
10266 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10267 hr = IDirect3DDevice7_SetTextureStageState(device, 2, D3DTSS_COLOROP, D3DTOP_DISABLE);
10268 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
10270 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_TEXCOORDINDEX, 1);
10271 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
10272 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXCOORDINDEX, 0);
10273 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
10275 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
10276 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
10278 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
10279 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10281 hr = IDirect3DDevice7_BeginScene(device);
10282 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10283 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
10284 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10285 hr = IDirect3DDevice7_EndScene(device);
10286 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10288 color = get_surface_color(rt, 160, 120);
10289 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
10290 color = get_surface_color(rt, 480, 120);
10291 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
10292 color = get_surface_color(rt, 160, 360);
10293 ok(compare_color(color, 0x00ff0000, 2), "Got unexpected color 0x%08x.\n", color);
10294 color = get_surface_color(rt, 480, 360);
10295 ok(compare_color(color, 0x00ffffff, 2), "Got unexpected color 0x%08x.\n", color);
10297 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
10298 ok(SUCCEEDED(hr), "Failed to set texture transform flags, hr %#x.\n", hr);
10299 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_TEXTURE1, &mat);
10300 ok(SUCCEEDED(hr), "Failed to set transformation matrix, hr %#x.\n", hr);
10302 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
10303 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10305 hr = IDirect3DDevice7_BeginScene(device);
10306 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10307 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
10308 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10309 hr = IDirect3DDevice7_EndScene(device);
10310 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10312 color = get_surface_color(rt, 160, 120);
10313 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
10314 color = get_surface_color(rt, 480, 120);
10315 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
10316 color = get_surface_color(rt, 160, 360);
10317 ok(compare_color(color, 0x00000000, 2), "Got unexpected color 0x%08x.\n", color);
10318 color = get_surface_color(rt, 480, 360);
10319 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
10321 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
10322 ok(SUCCEEDED(hr), "Failed to set texture transform flags, hr %#x.\n", hr);
10323 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXCOORDINDEX, 2);
10324 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
10326 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
10327 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10329 hr = IDirect3DDevice7_BeginScene(device);
10330 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10331 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
10332 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10333 hr = IDirect3DDevice7_EndScene(device);
10334 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10336 color = get_surface_color(rt, 160, 120);
10337 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
10338 color = get_surface_color(rt, 480, 120);
10339 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
10340 color = get_surface_color(rt, 160, 360);
10341 ok(compare_color(color, 0x00ff00ff, 2), "Got unexpected color 0x%08x.\n", color);
10342 color = get_surface_color(rt, 480, 360);
10343 ok(compare_color(color, 0x00ffff00, 2), "Got unexpected color 0x%08x.\n", color);
10345 IDirectDrawSurface7_Release(texture1);
10346 IDirectDrawSurface7_Release(texture2);
10348 IDirectDrawSurface7_Release(rt);
10349 IDirectDraw_Release(ddraw);
10350 refcount = IDirect3DDevice7_Release(device);
10351 ok(!refcount, "Device has %u references left.\n", refcount);
10352 DestroyWindow(window);
10355 static void test_colorkey_precision(void)
10357 static struct
10359 struct vec3 pos;
10360 struct vec2 texcoord;
10362 quad[] =
10364 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
10365 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
10366 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
10367 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
10369 IDirect3DDevice7 *device;
10370 IDirect3D7 *d3d;
10371 IDirectDraw7 *ddraw;
10372 IDirectDrawSurface7 *rt;
10373 HWND window;
10374 HRESULT hr;
10375 IDirectDrawSurface7 *src, *dst, *texture;
10376 DDSURFACEDESC2 surface_desc, lock_desc;
10377 ULONG refcount;
10378 D3DCOLOR color;
10379 unsigned int t, c;
10380 DDCOLORKEY ckey;
10381 DDBLTFX fx;
10382 DWORD data[4] = {0}, color_mask;
10383 BOOL is_nvidia, is_warp;
10384 static const struct
10386 unsigned int max, shift, bpp, clear;
10387 const char *name;
10388 BOOL skip_nv;
10389 DDPIXELFORMAT fmt;
10391 tests[] =
10394 255, 0, 4, 0x00345678, "D3DFMT_X8R8G8B8", FALSE,
10396 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
10397 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
10402 63, 5, 2, 0x5678, "D3DFMT_R5G6B5, G channel", FALSE,
10404 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
10405 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
10410 31, 0, 2, 0x5678, "D3DFMT_R5G6B5, B channel", FALSE,
10412 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
10413 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
10418 15, 0, 2, 0x0678, "D3DFMT_A4R4G4B4", TRUE,
10420 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
10421 {16}, {0x0f00}, {0x00f0}, {0x000f}, {0xf000}
10426 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
10427 0, 0, 640, 480, 0, 0, 0, 0);
10428 if (!(device = create_device(window, DDSCL_NORMAL)))
10430 skip("Failed to create a 3D device, skipping test.\n");
10431 DestroyWindow(window);
10432 return;
10435 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
10436 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
10437 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
10438 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
10439 IDirect3D7_Release(d3d);
10440 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
10441 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10443 is_nvidia = ddraw_is_nvidia(ddraw);
10444 /* The Windows 8 WARP driver has plenty of false negatives in X8R8G8B8
10445 * (color key doesn't match although the values are equal), and a false
10446 * positive when the color key is 0 and the texture contains the value 1.
10447 * I don't want to mark this broken unconditionally since this would
10448 * essentially disable the test on Windows. Also on random occasions
10449 * 254 == 255 and 255 != 255.*/
10450 is_warp = ddraw_is_warp(ddraw);
10452 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
10453 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
10454 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
10455 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
10456 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
10457 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
10458 /* Multiply the texture read result with 0, that way the result color if the key doesn't
10459 * match is constant. In theory color keying works without reading the texture result
10460 * (meaning we could just op=arg1, arg1=tfactor), but the Geforce7 Windows driver begs
10461 * to differ. */
10462 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
10463 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
10464 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
10465 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10466 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
10467 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10468 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x00000000);
10469 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10471 memset(&fx, 0, sizeof(fx));
10472 fx.dwSize = sizeof(fx);
10473 memset(&lock_desc, 0, sizeof(lock_desc));
10474 lock_desc.dwSize = sizeof(lock_desc);
10476 for (t = 0; t < sizeof(tests) / sizeof(*tests); ++t)
10478 if (is_nvidia && tests[t].skip_nv)
10480 win_skip("Skipping test %s on Nvidia Windows drivers.\n", tests[t].name);
10481 continue;
10484 memset(&surface_desc, 0, sizeof(surface_desc));
10485 surface_desc.dwSize = sizeof(surface_desc);
10486 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10487 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10488 surface_desc.dwWidth = 4;
10489 surface_desc.dwHeight = 1;
10490 U4(surface_desc).ddpfPixelFormat = tests[t].fmt;
10491 /* Windows XP (at least with the r200 driver, other drivers untested) produces
10492 * garbage when doing color keyed texture->texture blits. */
10493 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
10494 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10495 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
10496 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10498 U5(fx).dwFillColor = tests[t].clear;
10499 /* On the w8 testbot (WARP driver) the blit result has different values in the
10500 * X channel. */
10501 color_mask = U2(tests[t].fmt).dwRBitMask
10502 | U3(tests[t].fmt).dwGBitMask
10503 | U4(tests[t].fmt).dwBBitMask;
10505 for (c = 0; c <= tests[t].max; ++c)
10507 /* The idiotic Nvidia Windows driver can't change the color key on a d3d
10508 * texture after it has been set once... */
10509 surface_desc.dwFlags |= DDSD_CKSRCBLT;
10510 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
10511 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = c << tests[t].shift;
10512 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = c << tests[t].shift;
10513 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
10514 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10515 hr = IDirect3DDevice7_SetTexture(device, 0, texture);
10516 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
10518 hr = IDirectDrawSurface7_Blt(dst, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10519 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
10521 hr = IDirectDrawSurface7_Lock(src, NULL, &lock_desc, DDLOCK_WAIT, NULL);
10522 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10523 switch (tests[t].bpp)
10525 case 4:
10526 ((DWORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
10527 ((DWORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
10528 ((DWORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
10529 ((DWORD *)lock_desc.lpSurface)[3] = 0xffffffff;
10530 break;
10532 case 2:
10533 ((WORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
10534 ((WORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
10535 ((WORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
10536 ((WORD *)lock_desc.lpSurface)[3] = 0xffff;
10537 break;
10539 hr = IDirectDrawSurface7_Unlock(src, 0);
10540 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10541 hr = IDirectDrawSurface7_Blt(texture, NULL, src, NULL, DDBLT_WAIT, NULL);
10542 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
10544 ckey.dwColorSpaceLowValue = c << tests[t].shift;
10545 ckey.dwColorSpaceHighValue = c << tests[t].shift;
10546 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
10547 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10549 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_WAIT, NULL);
10550 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
10552 /* Don't make this read only, it somehow breaks the detection of the Nvidia bug below. */
10553 hr = IDirectDrawSurface7_Lock(dst, NULL, &lock_desc, DDLOCK_WAIT, NULL);
10554 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10555 switch (tests[t].bpp)
10557 case 4:
10558 data[0] = ((DWORD *)lock_desc.lpSurface)[0] & color_mask;
10559 data[1] = ((DWORD *)lock_desc.lpSurface)[1] & color_mask;
10560 data[2] = ((DWORD *)lock_desc.lpSurface)[2] & color_mask;
10561 data[3] = ((DWORD *)lock_desc.lpSurface)[3] & color_mask;
10562 break;
10564 case 2:
10565 data[0] = ((WORD *)lock_desc.lpSurface)[0] & color_mask;
10566 data[1] = ((WORD *)lock_desc.lpSurface)[1] & color_mask;
10567 data[2] = ((WORD *)lock_desc.lpSurface)[2] & color_mask;
10568 data[3] = ((WORD *)lock_desc.lpSurface)[3] & color_mask;
10569 break;
10571 hr = IDirectDrawSurface7_Unlock(dst, 0);
10572 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10574 if (!c)
10576 ok(data[0] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10577 tests[t].clear, data[0], tests[t].name, c);
10579 if (data[3] == tests[t].clear)
10581 /* My Geforce GTX 460 on Windows 7 misbehaves when A4R4G4B4 is blitted with color
10582 * keying: The blit takes ~0.5 seconds, and subsequent color keying draws are broken,
10583 * even when a different surface is used. The blit itself doesn't draw anything,
10584 * so we can detect the bug by looking at the otherwise unused 4th texel. It should
10585 * never be masked out by the key.
10587 * On Windows 10 the problem is worse, Blt just hangs. For this reason the ARGB4444
10588 * test is disabled on Nvidia.
10590 * Also appears to affect the testbot in some way with R5G6B5. Color keying is
10591 * terrible on WARP. */
10592 skip("Nvidia A4R4G4B4 color keying blit bug detected, skipping.\n");
10593 IDirectDrawSurface7_Release(texture);
10594 IDirectDrawSurface7_Release(src);
10595 IDirectDrawSurface7_Release(dst);
10596 goto done;
10599 else
10600 ok(data[0] == (c - 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10601 (c - 1) << tests[t].shift, data[0], tests[t].name, c);
10603 ok(data[1] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10604 tests[t].clear, data[1], tests[t].name, c);
10606 if (c == tests[t].max)
10607 ok(data[2] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10608 tests[t].clear, data[2], tests[t].name, c);
10609 else
10610 ok(data[2] == (c + 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10611 (c + 1) << tests[t].shift, data[2], tests[t].name, c);
10613 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x0000ff00, 1.0f, 0);
10614 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10616 hr = IDirect3DDevice7_BeginScene(device);
10617 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10618 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
10619 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10620 hr = IDirect3DDevice7_EndScene(device);
10621 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10623 color = get_surface_color(rt, 80, 240);
10624 if (!c)
10625 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
10626 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10627 color, tests[t].name, c);
10628 else
10629 ok(compare_color(color, 0x00000000, 1) || broken(is_warp && compare_color(color, 0x0000ff00, 1)),
10630 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10631 color, tests[t].name, c);
10633 color = get_surface_color(rt, 240, 240);
10634 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
10635 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10636 color, tests[t].name, c);
10638 color = get_surface_color(rt, 400, 240);
10639 if (c == tests[t].max)
10640 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
10641 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10642 color, tests[t].name, c);
10643 else
10644 ok(compare_color(color, 0x00000000, 1) || broken(is_warp && compare_color(color, 0x0000ff00, 1)),
10645 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10646 color, tests[t].name, c);
10648 IDirectDrawSurface7_Release(texture);
10650 IDirectDrawSurface7_Release(src);
10651 IDirectDrawSurface7_Release(dst);
10653 done:
10655 IDirectDrawSurface7_Release(rt);
10656 IDirectDraw7_Release(ddraw);
10657 refcount = IDirect3DDevice7_Release(device);
10658 ok(!refcount, "Device has %u references left.\n", refcount);
10659 DestroyWindow(window);
10662 static void test_range_colorkey(void)
10664 IDirectDraw7 *ddraw;
10665 HWND window;
10666 HRESULT hr;
10667 IDirectDrawSurface7 *surface;
10668 DDSURFACEDESC2 surface_desc;
10669 ULONG refcount;
10670 DDCOLORKEY ckey;
10672 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
10673 0, 0, 640, 480, 0, 0, 0, 0);
10674 ddraw = create_ddraw();
10675 ok(!!ddraw, "Failed to create a ddraw object.\n");
10676 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10677 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
10679 memset(&surface_desc, 0, sizeof(surface_desc));
10680 surface_desc.dwSize = sizeof(surface_desc);
10681 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
10682 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
10683 surface_desc.dwWidth = 1;
10684 surface_desc.dwHeight = 1;
10685 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
10686 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
10687 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
10688 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
10689 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
10690 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0x00000000;
10692 /* Creating a surface with a range color key fails with DDERR_NOCOLORKEY. */
10693 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
10694 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
10695 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10696 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10698 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
10699 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
10700 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10701 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10703 /* Same for DDSCAPS_OFFSCREENPLAIN. */
10704 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10705 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
10706 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
10707 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10708 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10710 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
10711 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
10712 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10713 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10715 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
10716 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
10717 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10718 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10720 /* Setting a range color key without DDCKEY_COLORSPACE collapses the key. */
10721 ckey.dwColorSpaceLowValue = 0x00000000;
10722 ckey.dwColorSpaceHighValue = 0x00000001;
10723 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10724 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10726 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10727 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
10728 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
10729 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
10731 ckey.dwColorSpaceLowValue = 0x00000001;
10732 ckey.dwColorSpaceHighValue = 0x00000000;
10733 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10734 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10736 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10737 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
10738 ok(ckey.dwColorSpaceLowValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
10739 ok(ckey.dwColorSpaceHighValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
10741 /* DDCKEY_COLORSPACE is ignored if the key is a single value. */
10742 ckey.dwColorSpaceLowValue = 0x00000000;
10743 ckey.dwColorSpaceHighValue = 0x00000000;
10744 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10745 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10747 /* Using it with a range key results in DDERR_NOCOLORKEYHW. */
10748 ckey.dwColorSpaceLowValue = 0x00000001;
10749 ckey.dwColorSpaceHighValue = 0x00000000;
10750 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10751 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10752 ckey.dwColorSpaceLowValue = 0x00000000;
10753 ckey.dwColorSpaceHighValue = 0x00000001;
10754 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10755 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10756 /* Range destination keys don't work either. */
10757 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_DESTBLT | DDCKEY_COLORSPACE, &ckey);
10758 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10760 /* Just to show it's not because of A, R, and G having equal values. */
10761 ckey.dwColorSpaceLowValue = 0x00000000;
10762 ckey.dwColorSpaceHighValue = 0x01010101;
10763 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10764 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10766 /* None of these operations modified the key. */
10767 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10768 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
10769 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
10770 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
10772 IDirectDrawSurface7_Release(surface),
10773 refcount = IDirectDraw7_Release(ddraw);
10774 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
10775 DestroyWindow(window);
10778 static void test_shademode(void)
10780 IDirect3DVertexBuffer7 *vb_strip, *vb_list, *buffer;
10781 IDirect3DDevice7 *device;
10782 D3DVERTEXBUFFERDESC desc;
10783 IDirectDrawSurface7 *rt;
10784 DWORD color0, color1;
10785 void *data = NULL;
10786 IDirect3D7 *d3d;
10787 ULONG refcount;
10788 UINT i, count;
10789 HWND window;
10790 HRESULT hr;
10791 static const struct
10793 struct vec3 position;
10794 DWORD diffuse;
10796 quad_strip[] =
10798 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
10799 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
10800 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
10801 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
10803 quad_list[] =
10805 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
10806 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
10807 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
10809 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
10810 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
10811 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
10813 static const struct
10815 DWORD primtype;
10816 DWORD shademode;
10817 DWORD color0, color1;
10819 tests[] =
10821 {D3DPT_TRIANGLESTRIP, D3DSHADE_FLAT, 0x00ff0000, 0x0000ff00},
10822 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
10823 {D3DPT_TRIANGLESTRIP, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
10824 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
10825 {D3DPT_TRIANGLELIST, D3DSHADE_FLAT, 0x00ff0000, 0x000000ff},
10826 {D3DPT_TRIANGLELIST, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
10829 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
10830 0, 0, 640, 480, 0, 0, 0, 0);
10832 if (!(device = create_device(window, DDSCL_NORMAL)))
10834 skip("Failed to create a 3D device, skipping test.\n");
10835 DestroyWindow(window);
10836 return;
10839 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
10840 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
10841 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
10842 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10844 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
10845 ok(hr == D3D_OK, "Failed to disable lighting, hr %#x.\n", hr);
10846 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
10847 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
10849 memset(&desc, 0, sizeof(desc));
10850 desc.dwSize = sizeof(desc);
10851 desc.dwCaps = D3DVBCAPS_WRITEONLY;
10852 desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
10853 desc.dwNumVertices = sizeof(quad_strip) / sizeof(*quad_strip);
10854 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &vb_strip, 0);
10855 ok(hr == D3D_OK, "Failed to create vertex buffer, hr %#x.\n", hr);
10856 hr = IDirect3DVertexBuffer7_Lock(vb_strip, 0, &data, NULL);
10857 ok(hr == D3D_OK, "Failed to lock vertex buffer, hr %#x.\n", hr);
10858 memcpy(data, quad_strip, sizeof(quad_strip));
10859 hr = IDirect3DVertexBuffer7_Unlock(vb_strip);
10860 ok(hr == D3D_OK, "Failed to unlock vertex buffer, hr %#x.\n", hr);
10862 desc.dwNumVertices = sizeof(quad_list) / sizeof(*quad_list);
10863 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &vb_list, 0);
10864 ok(hr == D3D_OK, "Failed to create vertex buffer, hr %#x.\n", hr);
10865 hr = IDirect3DVertexBuffer7_Lock(vb_list, 0, &data, NULL);
10866 ok(hr == D3D_OK, "Failed to lock vertex buffer, hr %#x.\n", hr);
10867 memcpy(data, quad_list, sizeof(quad_list));
10868 hr = IDirect3DVertexBuffer7_Unlock(vb_list);
10869 ok(hr == D3D_OK, "Failed to unlock vertex buffer, hr %#x.\n", hr);
10871 /* Try it first with a TRIANGLESTRIP. Do it with different geometry because
10872 * the color fixups we have to do for FLAT shading will be dependent on that. */
10874 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
10876 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
10877 ok(hr == D3D_OK, "Failed to clear, hr %#x.\n", hr);
10879 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SHADEMODE, tests[i].shademode);
10880 ok(hr == D3D_OK, "Failed to set shade mode, hr %#x.\n", hr);
10882 hr = IDirect3DDevice7_BeginScene(device);
10883 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10884 buffer = tests[i].primtype == D3DPT_TRIANGLESTRIP ? vb_strip : vb_list;
10885 count = tests[i].primtype == D3DPT_TRIANGLESTRIP ? 4 : 6;
10886 hr = IDirect3DDevice7_DrawPrimitiveVB(device, tests[i].primtype, buffer, 0, count, 0);
10887 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10888 hr = IDirect3DDevice7_EndScene(device);
10889 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10891 color0 = get_surface_color(rt, 100, 100); /* Inside first triangle */
10892 color1 = get_surface_color(rt, 500, 350); /* Inside second triangle */
10894 /* For D3DSHADE_FLAT it should take the color of the first vertex of
10895 * each triangle. This requires EXT_provoking_vertex or similar
10896 * functionality being available. */
10897 /* PHONG should be the same as GOURAUD, since no hardware implements
10898 * this. */
10899 ok(compare_color(color0, tests[i].color0, 1), "Test %u shading has color0 %08x, expected %08x.\n",
10900 i, color0, tests[i].color0);
10901 ok(compare_color(color1, tests[i].color1, 1), "Test %u shading has color1 %08x, expected %08x.\n",
10902 i, color1, tests[i].color1);
10905 IDirect3DVertexBuffer7_Release(vb_strip);
10906 IDirect3DVertexBuffer7_Release(vb_list);
10907 IDirectDrawSurface7_Release(rt);
10908 IDirect3D7_Release(d3d);
10909 refcount = IDirect3DDevice7_Release(device);
10910 ok(!refcount, "Device has %u references left.\n", refcount);
10911 DestroyWindow(window);
10914 static void test_lockrect_invalid(void)
10916 unsigned int i, r;
10917 IDirectDraw7 *ddraw;
10918 IDirectDrawSurface7 *surface;
10919 HWND window;
10920 HRESULT hr;
10921 DDSURFACEDESC2 surface_desc;
10922 DDSURFACEDESC2 locked_desc;
10923 DDCAPS hal_caps;
10924 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
10925 static RECT valid[] =
10927 {60, 60, 68, 68},
10928 {60, 60, 60, 68},
10929 {60, 60, 68, 60},
10930 {120, 60, 128, 68},
10931 {60, 120, 68, 128},
10933 static RECT invalid[] =
10935 {68, 60, 60, 68}, /* left > right */
10936 {60, 68, 68, 60}, /* top > bottom */
10937 {-8, 60, 0, 68}, /* left < surface */
10938 {60, -8, 68, 0}, /* top < surface */
10939 {-16, 60, -8, 68}, /* right < surface */
10940 {60, -16, 68, -8}, /* bottom < surface */
10941 {60, 60, 136, 68}, /* right > surface */
10942 {60, 60, 68, 136}, /* bottom > surface */
10943 {136, 60, 144, 68}, /* left > surface */
10944 {60, 136, 68, 144}, /* top > surface */
10946 static const struct
10948 DWORD caps, caps2;
10949 const char *name;
10950 HRESULT hr;
10952 resources[] =
10954 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, "sysmem offscreenplain", DDERR_INVALIDPARAMS},
10955 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, "vidmem offscreenplain", DDERR_INVALIDPARAMS},
10956 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, "sysmem texture", DD_OK},
10957 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, "vidmem texture", DDERR_INVALIDPARAMS},
10958 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, "managed texture", DD_OK},
10961 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
10962 0, 0, 640, 480, 0, 0, 0, 0);
10963 ddraw = create_ddraw();
10964 ok(!!ddraw, "Failed to create a ddraw object.\n");
10965 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10966 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
10968 memset(&hal_caps, 0, sizeof(hal_caps));
10969 hal_caps.dwSize = sizeof(hal_caps);
10970 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
10971 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
10972 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps
10973 || !(hal_caps.ddsCaps.dwCaps & DDSCAPS2_TEXTUREMANAGE))
10975 skip("Required surface types not supported, skipping test.\n");
10976 goto done;
10979 for (r = 0; r < sizeof(resources) / sizeof(*resources); ++r)
10981 memset(&surface_desc, 0, sizeof(surface_desc));
10982 surface_desc.dwSize = sizeof(surface_desc);
10983 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10984 surface_desc.ddsCaps.dwCaps = resources[r].caps;
10985 surface_desc.ddsCaps.dwCaps2 = resources[r].caps2;
10986 surface_desc.dwWidth = 128;
10987 surface_desc.dwHeight = 128;
10988 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
10989 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
10990 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
10991 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xff0000;
10992 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x00ff00;
10993 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x0000ff;
10995 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10996 if (is_ddraw64 && (resources[r].caps & DDSCAPS_TEXTURE))
10998 todo_wine ok(hr == E_NOINTERFACE, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
10999 if (SUCCEEDED(hr))
11000 IDirectDrawSurface7_Release(surface);
11001 continue;
11003 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n", hr, resources[r].name);
11005 /* Crashes in ddraw7
11006 hr = IDirectDrawSurface7_Lock(surface, NULL, NULL, DDLOCK_WAIT, NULL);
11007 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
11010 for (i = 0; i < sizeof(valid) / sizeof(*valid); ++i)
11012 RECT *rect = &valid[i];
11014 memset(&locked_desc, 0, sizeof(locked_desc));
11015 locked_desc.dwSize = sizeof(locked_desc);
11017 hr = IDirectDrawSurface7_Lock(surface, rect, &locked_desc, DDLOCK_WAIT, NULL);
11018 ok(SUCCEEDED(hr), "Lock failed (%#x) for rect %s, type %s.\n",
11019 hr, wine_dbgstr_rect(rect), resources[r].name);
11021 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11022 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11025 for (i = 0; i < sizeof(invalid) / sizeof(*invalid); ++i)
11027 RECT *rect = &invalid[i];
11029 memset(&locked_desc, 1, sizeof(locked_desc));
11030 locked_desc.dwSize = sizeof(locked_desc);
11032 hr = IDirectDrawSurface7_Lock(surface, rect, &locked_desc, DDLOCK_WAIT, NULL);
11033 todo_wine_if (SUCCEEDED(resources[r].hr))
11034 ok(hr == resources[r].hr, "Lock returned %#x for rect %s, type %s.\n",
11035 hr, wine_dbgstr_rect(rect), resources[r].name);
11036 if (SUCCEEDED(hr))
11038 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11039 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11041 else
11042 ok(!locked_desc.lpSurface, "Got unexpected lpSurface %p.\n", locked_desc.lpSurface);
11045 hr = IDirectDrawSurface7_Lock(surface, NULL, &locked_desc, DDLOCK_WAIT, NULL);
11046 ok(SUCCEEDED(hr), "Lock(rect = NULL) failed, hr %#x, type %s.\n",
11047 hr, resources[r].name);
11048 hr = IDirectDrawSurface7_Lock(surface, NULL, &locked_desc, DDLOCK_WAIT, NULL);
11049 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = NULL) returned %#x, type %s.\n",
11050 hr, resources[r].name);
11051 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11052 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11054 hr = IDirectDrawSurface7_Lock(surface, &valid[0], &locked_desc, DDLOCK_WAIT, NULL);
11055 ok(SUCCEEDED(hr), "Lock(rect = %s) failed (%#x).\n", wine_dbgstr_rect(&valid[0]), hr);
11056 hr = IDirectDrawSurface7_Lock(surface, &valid[0], &locked_desc, DDLOCK_WAIT, NULL);
11057 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = %s) failed (%#x).\n",
11058 wine_dbgstr_rect(&valid[0]), hr);
11060 /* Locking a different rectangle returns DD_OK, but it seems to break the surface.
11061 * Afterwards unlocking the surface fails(NULL rectangle or both locked rectangles) */
11063 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11064 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11066 IDirectDrawSurface7_Release(surface);
11069 done:
11070 IDirectDraw7_Release(ddraw);
11071 DestroyWindow(window);
11074 static void test_yv12_overlay(void)
11076 IDirectDrawSurface7 *src_surface, *dst_surface;
11077 RECT rect = {13, 17, 14, 18};
11078 unsigned int offset, y;
11079 DDSURFACEDESC2 desc;
11080 unsigned char *base;
11081 IDirectDraw7 *ddraw;
11082 HWND window;
11083 HRESULT hr;
11085 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
11086 0, 0, 640, 480, 0, 0, 0, 0);
11087 ddraw = create_ddraw();
11088 ok(!!ddraw, "Failed to create a ddraw object.\n");
11089 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11090 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11092 if (!(src_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
11094 skip("Failed to create a YV12 overlay, skipping test.\n");
11095 goto done;
11098 memset(&desc, 0, sizeof(desc));
11099 desc.dwSize = sizeof(desc);
11100 hr = IDirectDrawSurface7_Lock(src_surface, NULL, &desc, DDLOCK_WAIT, NULL);
11101 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11103 ok(desc.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH),
11104 "Got unexpected flags %#x.\n", desc.dwFlags);
11105 ok(desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_HWCODEC)
11106 || desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
11107 "Got unexpected caps %#x.\n", desc.ddsCaps.dwCaps);
11108 ok(desc.dwWidth == 256, "Got unexpected width %u.\n", desc.dwWidth);
11109 ok(desc.dwHeight == 256, "Got unexpected height %u.\n", desc.dwHeight);
11110 /* The overlay pitch seems to have 256 byte alignment. */
11111 ok(!(U1(desc).lPitch & 0xff), "Got unexpected pitch %u.\n", U1(desc).lPitch);
11113 /* Fill the surface with some data for the blit test. */
11114 base = desc.lpSurface;
11115 /* Luminance */
11116 for (y = 0; y < desc.dwHeight; ++y)
11118 memset(base + U1(desc).lPitch * y, 0x10, desc.dwWidth);
11120 /* V */
11121 for (; y < desc.dwHeight + desc.dwHeight / 4; ++y)
11123 memset(base + U1(desc).lPitch * y, 0x20, desc.dwWidth);
11125 /* U */
11126 for (; y < desc.dwHeight + desc.dwHeight / 2; ++y)
11128 memset(base + U1(desc).lPitch * y, 0x30, desc.dwWidth);
11131 hr = IDirectDrawSurface7_Unlock(src_surface, NULL);
11132 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11134 /* YV12 uses 2x2 blocks with 6 bytes per block (4*Y, 1*U, 1*V). Unlike
11135 * other block-based formats like DXT the entire Y channel is stored in
11136 * one big chunk of memory, followed by the chroma channels. So partial
11137 * locks do not really make sense. Show that they are allowed nevertheless
11138 * and the offset points into the luminance data. */
11139 hr = IDirectDrawSurface7_Lock(src_surface, &rect, &desc, DDLOCK_WAIT, NULL);
11140 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11141 offset = ((const unsigned char *)desc.lpSurface - base);
11142 ok(offset == rect.top * U1(desc).lPitch + rect.left, "Got unexpected offset %u, expected %u.\n",
11143 offset, rect.top * U1(desc).lPitch + rect.left);
11144 hr = IDirectDrawSurface7_Unlock(src_surface, NULL);
11145 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11147 if (!(dst_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
11149 /* Windows XP with a Radeon X1600 GPU refuses to create a second
11150 * overlay surface, DDERR_NOOVERLAYHW, making the blit tests moot. */
11151 skip("Failed to create a second YV12 surface, skipping blit test.\n");
11152 IDirectDrawSurface7_Release(src_surface);
11153 goto done;
11156 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, src_surface, NULL, DDBLT_WAIT, NULL);
11157 /* VMware rejects YV12 blits. This behavior has not been seen on real
11158 * hardware yet, so mark it broken. */
11159 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL), "Failed to blit, hr %#x.\n", hr);
11161 if (SUCCEEDED(hr))
11163 memset(&desc, 0, sizeof(desc));
11164 desc.dwSize = sizeof(desc);
11165 hr = IDirectDrawSurface7_Lock(dst_surface, NULL, &desc, DDLOCK_WAIT, NULL);
11166 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11168 base = desc.lpSurface;
11169 ok(base[0] == 0x10, "Got unexpected Y data 0x%02x.\n", base[0]);
11170 base += desc.dwHeight * U1(desc).lPitch;
11171 todo_wine ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]);
11172 base += desc.dwHeight / 4 * U1(desc).lPitch;
11173 todo_wine ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]);
11175 hr = IDirectDrawSurface7_Unlock(dst_surface, NULL);
11176 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11179 IDirectDrawSurface7_Release(dst_surface);
11180 IDirectDrawSurface7_Release(src_surface);
11181 done:
11182 IDirectDraw7_Release(ddraw);
11183 DestroyWindow(window);
11186 static BOOL dwm_enabled(void)
11188 BOOL ret = FALSE;
11190 if (!strcmp(winetest_platform, "wine"))
11191 return FALSE;
11192 if (!pDwmIsCompositionEnabled)
11193 return FALSE;
11194 if (FAILED(pDwmIsCompositionEnabled(&ret)))
11195 return FALSE;
11196 return ret;
11199 static void test_offscreen_overlay(void)
11201 IDirectDrawSurface7 *overlay, *offscreen, *primary;
11202 DDSURFACEDESC2 surface_desc;
11203 IDirectDraw7 *ddraw;
11204 HWND window;
11205 HRESULT hr;
11206 HDC dc;
11208 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
11209 0, 0, 640, 480, 0, 0, 0, 0);
11210 ddraw = create_ddraw();
11211 ok(!!ddraw, "Failed to create a ddraw object.\n");
11212 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11213 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11215 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
11217 skip("Failed to create a UYVY overlay, skipping test.\n");
11218 goto done;
11221 memset(&surface_desc, 0, sizeof(surface_desc));
11222 surface_desc.dwSize = sizeof(surface_desc);
11223 surface_desc.dwFlags = DDSD_CAPS;
11224 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
11225 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
11226 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
11228 /* On Windows 7, and probably Vista, UpdateOverlay() will return
11229 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
11230 * surface prevents this by disabling the dwm. */
11231 hr = IDirectDrawSurface7_GetDC(primary, &dc);
11232 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
11233 hr = IDirectDrawSurface7_ReleaseDC(primary, dc);
11234 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
11236 /* Try to overlay a NULL surface. */
11237 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_SHOW, NULL);
11238 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11239 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_HIDE, NULL);
11240 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11242 /* Try to overlay an offscreen surface. */
11243 memset(&surface_desc, 0, sizeof(surface_desc));
11244 surface_desc.dwSize = sizeof(surface_desc);
11245 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
11246 surface_desc.dwWidth = 64;
11247 surface_desc.dwHeight = 64;
11248 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11249 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
11250 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
11251 U4(surface_desc).ddpfPixelFormat.dwFourCC = 0;
11252 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
11253 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
11254 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
11255 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
11256 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
11257 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
11259 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, offscreen, NULL, DDOVER_SHOW, NULL);
11260 ok(SUCCEEDED(hr) || broken(hr == DDERR_OUTOFCAPS && dwm_enabled()),
11261 "Failed to update overlay, hr %#x.\n", hr);
11263 /* Try to overlay the primary with a non-overlay surface. */
11264 hr = IDirectDrawSurface7_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_SHOW, NULL);
11265 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
11266 hr = IDirectDrawSurface7_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_HIDE, NULL);
11267 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
11269 IDirectDrawSurface7_Release(offscreen);
11270 IDirectDrawSurface7_Release(primary);
11271 IDirectDrawSurface7_Release(overlay);
11272 done:
11273 IDirectDraw7_Release(ddraw);
11274 DestroyWindow(window);
11277 static void test_overlay_rect(void)
11279 IDirectDrawSurface7 *overlay, *primary = NULL;
11280 DDSURFACEDESC2 surface_desc;
11281 RECT rect = {0, 0, 64, 64};
11282 IDirectDraw7 *ddraw;
11283 LONG pos_x, pos_y;
11284 HRESULT hr, hr2;
11285 HWND window;
11286 HDC dc;
11288 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
11289 0, 0, 640, 480, 0, 0, 0, 0);
11290 ddraw = create_ddraw();
11291 ok(!!ddraw, "Failed to create a ddraw object.\n");
11292 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11293 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11295 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
11297 skip("Failed to create a UYVY overlay, skipping test.\n");
11298 goto done;
11301 memset(&surface_desc, 0, sizeof(surface_desc));
11302 surface_desc.dwSize = sizeof(surface_desc);
11303 surface_desc.dwFlags = DDSD_CAPS;
11304 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
11305 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
11306 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
11308 /* On Windows 7, and probably Vista, UpdateOverlay() will return
11309 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
11310 * surface prevents this by disabling the dwm. */
11311 hr = IDirectDrawSurface7_GetDC(primary, &dc);
11312 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
11313 hr = IDirectDrawSurface7_ReleaseDC(primary, dc);
11314 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
11316 /* On Windows 8 and newer DWM can't be turned off, making overlays unusable. */
11317 if (dwm_enabled())
11319 win_skip("Cannot disable DWM, skipping overlay test.\n");
11320 goto done;
11323 /* The dx sdk sort of implies that rect must be set when DDOVER_SHOW is
11324 * used. This is not true in Windows Vista and earlier, but changed in
11325 * Windows 7. */
11326 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
11327 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
11328 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_HIDE, NULL);
11329 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
11330 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_SHOW, NULL);
11331 ok(hr == DD_OK || hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11333 /* Show that the overlay position is the (top, left) coordinate of the
11334 * destination rectangle. */
11335 OffsetRect(&rect, 32, 16);
11336 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
11337 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
11338 pos_x = -1; pos_y = -1;
11339 hr = IDirectDrawSurface7_GetOverlayPosition(overlay, &pos_x, &pos_y);
11340 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
11341 ok(pos_x == rect.left, "Got unexpected pos_x %d, expected %d.\n", pos_x, rect.left);
11342 ok(pos_y == rect.top, "Got unexpected pos_y %d, expected %d.\n", pos_y, rect.top);
11344 /* Passing a NULL dest rect sets the position to 0/0. Visually it can be
11345 * seen that the overlay overlays the whole primary(==screen). */
11346 hr2 = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, NULL, 0, NULL);
11347 ok(hr2 == DD_OK || hr2 == DDERR_INVALIDPARAMS || hr2 == DDERR_OUTOFCAPS, "Got unexpected hr %#x.\n", hr2);
11348 hr = IDirectDrawSurface7_GetOverlayPosition(overlay, &pos_x, &pos_y);
11349 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
11350 if (SUCCEEDED(hr2))
11352 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
11353 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
11355 else
11357 ok(pos_x == 32, "Got unexpected pos_x %d.\n", pos_x);
11358 ok(pos_y == 16, "Got unexpected pos_y %d.\n", pos_y);
11361 /* The position cannot be retrieved when the overlay is not shown. */
11362 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_HIDE, NULL);
11363 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
11364 pos_x = -1; pos_y = -1;
11365 hr = IDirectDrawSurface7_GetOverlayPosition(overlay, &pos_x, &pos_y);
11366 ok(hr == DDERR_OVERLAYNOTVISIBLE, "Got unexpected hr %#x.\n", hr);
11367 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
11368 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
11370 IDirectDrawSurface7_Release(overlay);
11371 done:
11372 if (primary)
11373 IDirectDrawSurface7_Release(primary);
11374 IDirectDraw7_Release(ddraw);
11375 DestroyWindow(window);
11378 static void test_blt(void)
11380 IDirectDrawSurface7 *surface, *rt;
11381 DDSURFACEDESC2 surface_desc;
11382 IDirect3DDevice7 *device;
11383 IDirectDraw7 *ddraw;
11384 IDirect3D7 *d3d;
11385 unsigned int i;
11386 ULONG refcount;
11387 HWND window;
11388 HRESULT hr;
11390 static struct
11392 RECT src_rect;
11393 RECT dst_rect;
11394 HRESULT hr;
11396 test_data[] =
11398 {{160, 0, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit. */
11399 {{160, 480, 640, 0}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, flipped source. */
11400 {{640, 0, 160, 480}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, mirrored source. */
11401 {{160, 0, 480, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched x. */
11402 {{160, 160, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched y. */
11403 {{ 0, 0, 640, 480}, { 0, 0, 640, 480}, DD_OK}, /* Full surface blit. */
11404 {{ 0, 0, 640, 480}, { 0, 480, 640, 0}, DDERR_INVALIDRECT}, /* Full surface, flipped destination. */
11405 {{ 0, 0, 640, 480}, {640, 0, 0, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored destination. */
11406 {{ 0, 480, 640, 0}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, flipped source. */
11407 {{640, 0, 0, 480}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored source. */
11410 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
11411 0, 0, 640, 480, 0, 0, 0, 0);
11412 if (!(device = create_device(window, DDSCL_NORMAL)))
11414 skip("Failed to create a 3D device, skipping test.\n");
11415 DestroyWindow(window);
11416 return;
11419 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
11420 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
11421 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
11422 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
11423 IDirect3D7_Release(d3d);
11424 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
11425 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11427 memset(&surface_desc, 0, sizeof(surface_desc));
11428 surface_desc.dwSize = sizeof(surface_desc);
11429 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
11430 surface_desc.dwWidth = 640;
11431 surface_desc.dwHeight = 480;
11432 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11433 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11434 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11436 hr = IDirectDrawSurface_Blt(surface, NULL, surface, NULL, 0, NULL);
11437 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
11439 hr = IDirectDrawSurface_Blt(surface, NULL, rt, NULL, 0, NULL);
11440 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
11442 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
11444 hr = IDirectDrawSurface_Blt(surface, &test_data[i].dst_rect,
11445 surface, &test_data[i].src_rect, DDBLT_WAIT, NULL);
11446 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
11448 hr = IDirectDrawSurface_Blt(surface, &test_data[i].dst_rect,
11449 rt, &test_data[i].src_rect, DDBLT_WAIT, NULL);
11450 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
11453 IDirectDrawSurface7_Release(surface);
11454 IDirectDrawSurface7_Release(rt);
11455 IDirectDraw7_Release(ddraw);
11456 refcount = IDirect3DDevice7_Release(device);
11457 ok(!refcount, "Device has %u references left.\n", refcount);
11458 DestroyWindow(window);
11461 static void test_color_clamping(void)
11463 static D3DMATRIX mat =
11465 1.0f, 0.0f, 0.0f, 0.0f,
11466 0.0f, 1.0f, 0.0f, 0.0f,
11467 0.0f, 0.0f, 1.0f, 0.0f,
11468 0.0f, 0.0f, 0.0f, 1.0f,
11470 static struct vec3 quad[] =
11472 {-1.0f, -1.0f, 0.1f},
11473 {-1.0f, 1.0f, 0.1f},
11474 { 1.0f, -1.0f, 0.1f},
11475 { 1.0f, 1.0f, 0.1f},
11477 IDirect3DDevice7 *device;
11478 IDirectDrawSurface7 *rt;
11479 ULONG refcount;
11480 D3DCOLOR color;
11481 HWND window;
11482 HRESULT hr;
11484 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
11485 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11487 if (!(device = create_device(window, DDSCL_NORMAL)))
11489 skip("Failed to create a 3D device, skipping test.\n");
11490 DestroyWindow(window);
11491 return;
11494 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
11495 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11497 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
11498 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
11499 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
11500 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
11501 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
11502 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
11503 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
11504 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
11505 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
11506 ok(SUCCEEDED(hr), "Failed to disable Z test, hr %#x.\n", hr);
11507 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
11508 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
11509 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
11510 ok(SUCCEEDED(hr), "Failed to disable stencil test, hr %#x.\n", hr);
11511 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
11512 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
11513 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
11514 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
11516 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0xff404040);
11517 ok(SUCCEEDED(hr), "Failed to set texture factor, hr %#x.\n", hr);
11518 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_ADD);
11519 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
11520 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
11521 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11522 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_SPECULAR);
11523 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11524 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_MODULATE);
11525 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
11526 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TFACTOR);
11527 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11528 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
11529 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11531 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
11532 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
11534 hr = IDirect3DDevice7_BeginScene(device);
11535 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11537 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
11538 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11540 hr = IDirect3DDevice7_EndScene(device);
11541 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11543 color = get_surface_color(rt, 320, 240);
11544 ok(compare_color(color, 0x00404040, 1), "Got unexpected color 0x%08x.\n", color);
11546 IDirectDrawSurface7_Release(rt);
11547 refcount = IDirect3DDevice7_Release(device);
11548 ok(!refcount, "Device has %u references left.\n", refcount);
11549 DestroyWindow(window);
11552 static void test_getdc(void)
11554 DDSCAPS2 caps = {DDSCAPS_COMPLEX, DDSCAPS2_CUBEMAP_NEGATIVEZ, 0, {0}};
11555 IDirectDrawSurface7 *surface, *surface2, *tmp;
11556 DDSURFACEDESC2 surface_desc, map_desc;
11557 IDirectDraw7 *ddraw;
11558 unsigned int i;
11559 HWND window;
11560 HDC dc, dc2;
11561 HRESULT hr;
11563 static const struct
11565 const char *name;
11566 DDPIXELFORMAT format;
11567 BOOL getdc_supported;
11568 HRESULT alt_result;
11570 test_data[] =
11572 {"D3DFMT_A8R8G8B8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
11573 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}}, TRUE},
11574 {"D3DFMT_X8R8G8B8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
11575 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}}, TRUE},
11576 {"D3DFMT_R5G6B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
11577 {0x0000f800}, {0x000007e0}, {0x0000001f}, {0x00000000}}, TRUE},
11578 {"D3DFMT_X1R5G5B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
11579 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00000000}}, TRUE},
11580 {"D3DFMT_A1R5G5B5", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
11581 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00008000}}, TRUE},
11582 {"D3DFMT_A4R4G4B4", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
11583 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x0000f000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
11584 {"D3DFMT_X4R4G4B4", {sizeof(test_data->format), DDPF_RGB, 0, {16},
11585 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
11586 {"D3DFMT_A2R10G10B10", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
11587 {0xc0000000}, {0x3ff00000}, {0x000ffc00}, {0x000003ff}}, TRUE},
11588 {"D3DFMT_A8B8G8R8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
11589 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0xff000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
11590 {"D3DFMT_X8B8G8R8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
11591 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
11592 {"D3DFMT_R3G3B2", {sizeof(test_data->format), DDPF_RGB, 0, {8},
11593 {0x000000e0}, {0x0000001c}, {0x00000003}, {0x00000000}}, FALSE},
11594 /* GetDC() on a P8 surface fails unless the display mode is 8 bpp.
11595 * This is not implemented in wine yet, so disable the test for now.
11596 * Succeeding P8 GetDC() calls are tested in the ddraw:visual test.
11597 {"D3DFMT_P8", {sizeof(test_data->format), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0, {8 },
11598 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11600 {"D3DFMT_L8", {sizeof(test_data->format), DDPF_LUMINANCE, 0, {8},
11601 {0x000000ff}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11602 {"D3DFMT_A8L8", {sizeof(test_data->format), DDPF_ALPHAPIXELS | DDPF_LUMINANCE, 0, {16},
11603 {0x000000ff}, {0x00000000}, {0x00000000}, {0x0000ff00}}, FALSE},
11604 {"D3DFMT_DXT1", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','1'), {0},
11605 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11606 {"D3DFMT_DXT2", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','2'), {0},
11607 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11608 {"D3DFMT_DXT3", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','3'), {0},
11609 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11610 {"D3DFMT_DXT4", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','4'), {0},
11611 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11612 {"D3DFMT_DXT5", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','5'), {0},
11613 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11616 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
11617 0, 0, 640, 480, 0, 0, 0, 0);
11618 ddraw = create_ddraw();
11619 ok(!!ddraw, "Failed to create a ddraw object.\n");
11620 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11621 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11623 for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
11625 memset(&surface_desc, 0, sizeof(surface_desc));
11626 surface_desc.dwSize = sizeof(surface_desc);
11627 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
11628 surface_desc.dwWidth = 64;
11629 surface_desc.dwHeight = 64;
11630 U4(surface_desc).ddpfPixelFormat = test_data[i].format;
11631 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11633 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
11635 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
11636 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
11637 if (FAILED(hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
11639 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", test_data[i].name, hr);
11640 continue;
11644 dc = (void *)0x1234;
11645 hr = IDirectDrawSurface7_GetDC(surface, &dc);
11646 if (test_data[i].getdc_supported)
11647 ok(SUCCEEDED(hr) || (test_data[i].alt_result && hr == test_data[i].alt_result),
11648 "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11649 else
11650 ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11652 if (SUCCEEDED(hr))
11654 unsigned int width_bytes;
11655 DIBSECTION dib;
11656 HBITMAP bitmap;
11657 DWORD type;
11658 int size;
11660 type = GetObjectType(dc);
11661 ok(type == OBJ_MEMDC, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
11662 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
11663 type = GetObjectType(bitmap);
11664 ok(type == OBJ_BITMAP, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
11666 size = GetObjectA(bitmap, sizeof(dib), &dib);
11667 ok(size == sizeof(dib), "Got unexpected size %d for format %s.\n", size, test_data[i].name);
11668 ok(!dib.dsBm.bmType, "Got unexpected type %#x for format %s.\n",
11669 dib.dsBm.bmType, test_data[i].name);
11670 ok(dib.dsBm.bmWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
11671 dib.dsBm.bmWidth, test_data[i].name);
11672 ok(dib.dsBm.bmHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
11673 dib.dsBm.bmHeight, test_data[i].name);
11674 width_bytes = ((dib.dsBm.bmWidth * U1(test_data[i].format).dwRGBBitCount + 31) >> 3) & ~3;
11675 ok(dib.dsBm.bmWidthBytes == width_bytes, "Got unexpected width bytes %d for format %s.\n",
11676 dib.dsBm.bmWidthBytes, test_data[i].name);
11677 ok(dib.dsBm.bmPlanes == 1, "Got unexpected plane count %d for format %s.\n",
11678 dib.dsBm.bmPlanes, test_data[i].name);
11679 ok(dib.dsBm.bmBitsPixel == U1(test_data[i].format).dwRGBBitCount,
11680 "Got unexpected bit count %d for format %s.\n",
11681 dib.dsBm.bmBitsPixel, test_data[i].name);
11682 ok(!!dib.dsBm.bmBits, "Got unexpected bits %p for format %s.\n",
11683 dib.dsBm.bmBits, test_data[i].name);
11685 ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "Got unexpected size %u for format %s.\n",
11686 dib.dsBmih.biSize, test_data[i].name);
11687 ok(dib.dsBmih.biWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
11688 dib.dsBmih.biHeight, test_data[i].name);
11689 ok(dib.dsBmih.biHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
11690 dib.dsBmih.biHeight, test_data[i].name);
11691 ok(dib.dsBmih.biPlanes == 1, "Got unexpected plane count %u for format %s.\n",
11692 dib.dsBmih.biPlanes, test_data[i].name);
11693 ok(dib.dsBmih.biBitCount == U1(test_data[i].format).dwRGBBitCount,
11694 "Got unexpected bit count %u for format %s.\n",
11695 dib.dsBmih.biBitCount, test_data[i].name);
11696 ok(dib.dsBmih.biCompression == (U1(test_data[i].format).dwRGBBitCount == 16 ? BI_BITFIELDS : BI_RGB)
11697 || broken(U1(test_data[i].format).dwRGBBitCount == 32 && dib.dsBmih.biCompression == BI_BITFIELDS),
11698 "Got unexpected compression %#x for format %s.\n",
11699 dib.dsBmih.biCompression, test_data[i].name);
11700 ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
11701 dib.dsBmih.biSizeImage, test_data[i].name);
11702 ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n",
11703 dib.dsBmih.biXPelsPerMeter, test_data[i].name);
11704 ok(!dib.dsBmih.biYPelsPerMeter, "Got unexpected vertical resolution %d for format %s.\n",
11705 dib.dsBmih.biYPelsPerMeter, test_data[i].name);
11706 ok(!dib.dsBmih.biClrUsed, "Got unexpected used colour count %u for format %s.\n",
11707 dib.dsBmih.biClrUsed, test_data[i].name);
11708 ok(!dib.dsBmih.biClrImportant, "Got unexpected important colour count %u for format %s.\n",
11709 dib.dsBmih.biClrImportant, test_data[i].name);
11711 if (dib.dsBmih.biCompression == BI_BITFIELDS)
11713 ok((dib.dsBitfields[0] == U2(test_data[i].format).dwRBitMask
11714 && dib.dsBitfields[1] == U3(test_data[i].format).dwGBitMask
11715 && dib.dsBitfields[2] == U4(test_data[i].format).dwBBitMask)
11716 || broken(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2]),
11717 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
11718 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
11720 else
11722 ok(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2],
11723 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
11724 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
11726 ok(!dib.dshSection, "Got unexpected section %p for format %s.\n", dib.dshSection, test_data[i].name);
11727 ok(!dib.dsOffset, "Got unexpected offset %u for format %s.\n", dib.dsOffset, test_data[i].name);
11729 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
11730 ok(hr == DD_OK, "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11732 else
11734 ok(!dc, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
11737 IDirectDrawSurface7_Release(surface);
11739 if (FAILED(hr))
11740 continue;
11742 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
11743 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_TEXTUREMANAGE;
11744 if (FAILED(hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
11746 skip("Failed to create cube texture for format %s (hr %#x), skipping tests.\n", test_data[i].name, hr);
11747 continue;
11750 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &surface2);
11751 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
11752 hr = IDirectDrawSurface7_GetAttachedSurface(surface2, &caps, &tmp);
11753 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
11754 IDirectDrawSurface7_Release(surface2);
11755 hr = IDirectDrawSurface7_GetAttachedSurface(tmp, &caps, &surface2);
11756 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
11757 IDirectDrawSurface7_Release(tmp);
11759 hr = IDirectDrawSurface7_GetDC(surface, &dc);
11760 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11761 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
11762 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11763 hr = IDirectDrawSurface7_GetDC(surface2, &dc);
11764 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11765 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc);
11766 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11768 hr = IDirectDrawSurface7_GetDC(surface, &dc);
11769 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11770 dc2 = (void *)0x1234;
11771 hr = IDirectDrawSurface7_GetDC(surface, &dc2);
11772 ok(hr == DDERR_DCALREADYCREATED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11773 ok(dc2 == (void *)0x1234, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
11774 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
11775 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11776 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
11777 ok(hr == DDERR_NODC, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11779 map_desc.dwSize = sizeof(map_desc);
11780 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11781 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11782 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11783 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11784 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11785 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11786 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11787 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11789 hr = IDirectDrawSurface7_GetDC(surface, &dc);
11790 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11791 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11792 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11793 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
11794 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11796 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11797 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11798 hr = IDirectDrawSurface7_GetDC(surface, &dc);
11799 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11800 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
11801 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11802 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11803 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11805 hr = IDirectDrawSurface7_GetDC(surface, &dc);
11806 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11807 hr = IDirectDrawSurface7_GetDC(surface2, &dc2);
11808 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11809 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc2);
11810 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11811 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
11812 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11814 hr = IDirectDrawSurface7_GetDC(surface2, &dc);
11815 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11816 hr = IDirectDrawSurface7_GetDC(surface, &dc2);
11817 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11818 hr = IDirectDrawSurface7_ReleaseDC(surface, dc2);
11819 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11820 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc);
11821 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11823 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11824 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11825 hr = IDirectDrawSurface7_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11826 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11827 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
11828 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11829 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11830 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11832 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11833 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11834 hr = IDirectDrawSurface7_GetDC(surface, &dc);
11835 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11836 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
11837 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11838 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11839 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11841 hr = IDirectDrawSurface7_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11842 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11843 hr = IDirectDrawSurface7_GetDC(surface, &dc);
11844 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11845 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
11846 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11847 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
11848 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11850 hr = IDirectDrawSurface7_GetDC(surface, &dc);
11851 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11852 hr = IDirectDrawSurface7_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11853 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11854 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
11855 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11856 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
11857 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11859 hr = IDirectDrawSurface7_GetDC(surface2, &dc);
11860 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11861 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11862 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11863 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11864 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11865 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc);
11866 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11868 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11869 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11870 hr = IDirectDrawSurface7_GetDC(surface2, &dc);
11871 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11872 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11873 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11874 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc);
11875 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11876 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11877 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11879 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
11880 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11881 hr = IDirectDrawSurface7_GetDC(surface, &dc);
11882 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11883 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
11884 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11885 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
11886 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11887 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
11888 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11890 IDirectDrawSurface7_Release(surface2);
11891 IDirectDrawSurface7_Release(surface);
11894 IDirectDraw7_Release(ddraw);
11895 DestroyWindow(window);
11898 static void test_draw_primitive(void)
11900 static WORD indices[] = {0, 1, 2, 3};
11901 static struct vec3 quad[] =
11903 {-1.0f, -1.0f, 0.0f},
11904 {-1.0f, 1.0f, 0.0f},
11905 { 1.0f, -1.0f, 0.0f},
11906 { 1.0f, 1.0f, 0.0f},
11908 D3DDRAWPRIMITIVESTRIDEDDATA strided;
11909 D3DVERTEXBUFFERDESC vb_desc;
11910 IDirect3DVertexBuffer7 *vb;
11911 IDirect3DDevice7 *device;
11912 IDirect3D7 *d3d;
11913 ULONG refcount;
11914 HWND window;
11915 HRESULT hr;
11916 void *data;
11918 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
11919 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11921 if (!(device = create_device(window, DDSCL_NORMAL)))
11923 skip("Failed to create a 3D device, skipping test.\n");
11924 DestroyWindow(window);
11925 return;
11928 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
11929 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
11931 memset(&vb_desc, 0, sizeof(vb_desc));
11932 vb_desc.dwSize = sizeof(vb_desc);
11933 vb_desc.dwFVF = D3DFVF_XYZ;
11934 vb_desc.dwNumVertices = 4;
11935 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &vb, 0);
11936 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
11938 IDirect3D7_Release(d3d);
11940 memset(&strided, 0, sizeof(strided));
11942 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, NULL, 0, 0);
11943 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11944 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device,
11945 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, NULL, 0, 0);
11946 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11947 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, NULL, 0, 0);
11948 todo_wine ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
11949 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, NULL, 0, 0);
11950 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11951 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, 0);
11952 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11953 hr = IDirect3DDevice7_DrawPrimitiveStrided(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, 0);
11954 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11955 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, 0);
11956 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11958 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, indices, 4, 0);
11959 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11960 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device,
11961 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, indices, 4, 0);
11962 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11963 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, indices, 4, 0);
11964 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11966 strided.position.lpvData = quad;
11967 strided.position.dwStride = sizeof(*quad);
11968 hr = IDirect3DVertexBuffer7_Lock(vb, 0, &data, NULL);
11969 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
11970 memcpy(data, quad, sizeof(quad));
11971 hr = IDirect3DVertexBuffer7_Unlock(vb);
11972 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
11974 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, NULL, 0, 0);
11975 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11976 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device,
11977 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, NULL, 0, 0);
11978 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11979 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, NULL, 0, 0);
11980 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11981 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
11982 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11983 hr = IDirect3DDevice7_DrawPrimitiveStrided(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, 0);
11984 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11985 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, 0);
11986 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11988 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, indices, 4, 0);
11989 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11990 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device,
11991 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, indices, 4, 0);
11992 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11993 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, indices, 4, 0);
11994 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11996 IDirect3DVertexBuffer7_Release(vb);
11997 refcount = IDirect3DDevice7_Release(device);
11998 ok(!refcount, "Device has %u references left.\n", refcount);
11999 DestroyWindow(window);
12002 static void test_edge_antialiasing_blending(void)
12004 IDirectDrawSurface7 *offscreen;
12005 DDSURFACEDESC2 surface_desc;
12006 D3DDEVICEDESC7 device_desc;
12007 IDirect3DDevice7 *device;
12008 IDirectDraw7 *ddraw;
12009 IDirect3D7 *d3d;
12010 ULONG refcount;
12011 D3DCOLOR color;
12012 HWND window;
12013 HRESULT hr;
12015 static D3DMATRIX mat =
12017 1.0f, 0.0f, 0.0f, 0.0f,
12018 0.0f, 1.0f, 0.0f, 0.0f,
12019 0.0f, 0.0f, 1.0f, 0.0f,
12020 0.0f, 0.0f, 0.0f, 1.0f,
12022 static struct
12024 struct vec3 position;
12025 DWORD diffuse;
12027 green_quad[] =
12029 {{-1.0f, -1.0f, 0.1f}, 0x7f00ff00},
12030 {{-1.0f, 1.0f, 0.1f}, 0x7f00ff00},
12031 {{ 1.0f, -1.0f, 0.1f}, 0x7f00ff00},
12032 {{ 1.0f, 1.0f, 0.1f}, 0x7f00ff00},
12034 static struct
12036 struct vec3 position;
12037 DWORD diffuse;
12039 red_quad[] =
12041 {{-1.0f, -1.0f, 0.1f}, 0xccff0000},
12042 {{-1.0f, 1.0f, 0.1f}, 0xccff0000},
12043 {{ 1.0f, -1.0f, 0.1f}, 0xccff0000},
12044 {{ 1.0f, 1.0f, 0.1f}, 0xccff0000},
12047 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
12048 0, 0, 640, 480, NULL, NULL, NULL, NULL);
12049 if (!(device = create_device(window, DDSCL_NORMAL)))
12051 skip("Failed to create a 3D device.\n");
12052 DestroyWindow(window);
12053 return;
12056 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
12057 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
12058 trace("Line edge antialiasing support: %#x.\n",
12059 device_desc.dpcLineCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
12060 trace("Triangle edge antialiasing support: %#x.\n",
12061 device_desc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
12063 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
12064 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
12065 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
12066 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
12067 IDirect3D7_Release(d3d);
12069 memset(&surface_desc, 0, sizeof(surface_desc));
12070 surface_desc.dwSize = sizeof(surface_desc);
12071 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
12072 surface_desc.dwWidth = 640;
12073 surface_desc.dwHeight = 480;
12074 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
12075 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
12076 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
12077 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
12078 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
12079 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
12080 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
12081 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
12082 ok(hr == D3D_OK, "Creating the offscreen render target failed, hr %#x.\n", hr);
12084 hr = IDirect3DDevice7_SetRenderTarget(device, offscreen, 0);
12085 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
12087 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
12088 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
12089 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
12090 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
12091 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
12092 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
12093 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
12094 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
12095 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
12096 ok(SUCCEEDED(hr), "Failed to disable Z test, hr %#x.\n", hr);
12097 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
12098 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
12099 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
12100 ok(SUCCEEDED(hr), "Failed to disable stencil test, hr %#x.\n", hr);
12101 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
12102 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
12103 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
12104 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
12106 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
12107 ok(SUCCEEDED(hr), "Failed to enable blending, hr %#x.\n", hr);
12108 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
12109 ok(SUCCEEDED(hr), "Failed to set src blend, hr %#x.\n", hr);
12110 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_DESTALPHA);
12111 ok(SUCCEEDED(hr), "Failed to set dest blend, hr %#x.\n", hr);
12113 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
12114 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
12115 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
12116 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
12117 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
12118 ok(SUCCEEDED(hr), "Failed to set alpha op, hr %#x.\n", hr);
12119 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
12120 ok(SUCCEEDED(hr), "Failed to set alpha arg, hr %#x.\n", hr);
12122 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
12123 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12124 hr = IDirect3DDevice7_BeginScene(device);
12125 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12126 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12127 green_quad, 4, 0);
12128 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12129 hr = IDirect3DDevice7_EndScene(device);
12130 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12131 color = get_surface_color(offscreen, 320, 240);
12132 ok(compare_color(color, 0x00cc7f00, 1), "Got unexpected color 0x%08x.\n", color);
12134 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
12135 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12136 hr = IDirect3DDevice7_BeginScene(device);
12137 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12138 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12139 red_quad, 4, 0);
12140 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12141 hr = IDirect3DDevice7_EndScene(device);
12142 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12143 color = get_surface_color(offscreen, 320, 240);
12144 ok(compare_color(color, 0x00cc7f00, 1), "Got unexpected color 0x%08x.\n", color);
12146 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
12147 ok(SUCCEEDED(hr), "Failed to disable blending, hr %#x.\n", hr);
12149 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
12150 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12151 hr = IDirect3DDevice7_BeginScene(device);
12152 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12153 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12154 green_quad, 4, 0);
12155 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12156 hr = IDirect3DDevice7_EndScene(device);
12157 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12158 color = get_surface_color(offscreen, 320, 240);
12159 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12161 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
12162 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12163 hr = IDirect3DDevice7_BeginScene(device);
12164 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12165 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12166 red_quad, 4, 0);
12167 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12168 hr = IDirect3DDevice7_EndScene(device);
12169 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12170 color = get_surface_color(offscreen, 320, 240);
12171 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
12173 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_EDGEANTIALIAS, TRUE);
12174 ok(SUCCEEDED(hr), "Failed to enable edge antialiasing, hr %#x.\n", hr);
12176 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
12177 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12178 hr = IDirect3DDevice7_BeginScene(device);
12179 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12180 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12181 green_quad, 4, 0);
12182 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12183 hr = IDirect3DDevice7_EndScene(device);
12184 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12185 color = get_surface_color(offscreen, 320, 240);
12186 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12188 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
12189 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12190 hr = IDirect3DDevice7_BeginScene(device);
12191 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12192 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12193 red_quad, 4, 0);
12194 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12195 hr = IDirect3DDevice7_EndScene(device);
12196 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12197 color = get_surface_color(offscreen, 320, 240);
12198 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
12200 IDirectDrawSurface7_Release(offscreen);
12201 IDirectDraw7_Release(ddraw);
12202 refcount = IDirect3DDevice7_Release(device);
12203 ok(!refcount, "Device has %u references left.\n", refcount);
12204 DestroyWindow(window);
12207 static void test_display_mode_surface_pixel_format(void)
12209 unsigned int width, height, bpp;
12210 IDirectDrawSurface7 *surface;
12211 DDSURFACEDESC2 surface_desc;
12212 IDirectDraw7 *ddraw;
12213 ULONG refcount;
12214 HWND window;
12215 HRESULT hr;
12217 if (!(ddraw = create_ddraw()))
12219 skip("Failed to create ddraw.\n");
12220 return;
12223 surface_desc.dwSize = sizeof(surface_desc);
12224 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
12225 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr);
12226 width = surface_desc.dwWidth;
12227 height = surface_desc.dwHeight;
12229 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
12230 0, 0, width, height, NULL, NULL, NULL, NULL);
12231 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
12232 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12234 bpp = 0;
12235 if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 16, 0, 0)))
12236 bpp = 16;
12237 if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 24, 0, 0)))
12238 bpp = 24;
12239 if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
12240 bpp = 32;
12241 ok(bpp, "Set display mode failed.\n");
12243 surface_desc.dwSize = sizeof(surface_desc);
12244 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
12245 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr);
12246 ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width);
12247 ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height);
12248 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
12249 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
12251 memset(&surface_desc, 0, sizeof(surface_desc));
12252 surface_desc.dwSize = sizeof(surface_desc);
12253 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
12254 U5(surface_desc).dwBackBufferCount = 1;
12255 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE;
12256 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12257 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
12258 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
12259 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
12260 ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width);
12261 ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height);
12262 ok(U4(surface_desc).ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n",
12263 U4(surface_desc).ddpfPixelFormat.dwFlags);
12264 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
12265 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
12266 IDirectDrawSurface7_Release(surface);
12268 memset(&surface_desc, 0, sizeof(surface_desc));
12269 surface_desc.dwSize = sizeof(surface_desc);
12270 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
12271 surface_desc.dwWidth = width;
12272 surface_desc.dwHeight = height;
12273 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12274 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12275 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
12276 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
12277 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
12278 ok(U4(surface_desc).ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n",
12279 U4(surface_desc).ddpfPixelFormat.dwFlags);
12280 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
12281 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
12282 IDirectDrawSurface7_Release(surface);
12284 refcount = IDirectDraw7_Release(ddraw);
12285 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
12286 DestroyWindow(window);
12289 static void test_surface_desc_size(void)
12291 union
12293 DWORD dwSize;
12294 DDSURFACEDESC desc1;
12295 DDSURFACEDESC2 desc2;
12296 BYTE blob[1024];
12297 } desc;
12298 IDirectDrawSurface7 *surface7;
12299 IDirectDrawSurface3 *surface3;
12300 IDirectDrawSurface *surface;
12301 DDSURFACEDESC2 surface_desc;
12302 HRESULT expected_hr, hr;
12303 IDirectDraw7 *ddraw;
12304 unsigned int i, j;
12305 ULONG refcount;
12307 static const struct
12309 unsigned int caps;
12310 const char *name;
12312 surface_caps[] =
12314 {DDSCAPS_OFFSCREENPLAIN, "offscreenplain"},
12315 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, "systemmemory texture"},
12316 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, "videomemory texture"},
12318 static const unsigned int desc_sizes[] =
12320 sizeof(DDSURFACEDESC),
12321 sizeof(DDSURFACEDESC2),
12322 sizeof(DDSURFACEDESC) + 1,
12323 sizeof(DDSURFACEDESC2) + 1,
12324 2 * sizeof(DDSURFACEDESC),
12325 2 * sizeof(DDSURFACEDESC2),
12326 sizeof(DDSURFACEDESC) - 1,
12327 sizeof(DDSURFACEDESC2) - 1,
12328 sizeof(DDSURFACEDESC) / 2,
12329 sizeof(DDSURFACEDESC2) / 2,
12333 sizeof(desc) / 2,
12334 sizeof(desc) - 100,
12337 if (!(ddraw = create_ddraw()))
12339 skip("Failed to create ddraw.\n");
12340 return;
12342 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
12343 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12345 for (i = 0; i < sizeof(surface_caps) / sizeof(*surface_caps); ++i)
12347 memset(&surface_desc, 0, sizeof(surface_desc));
12348 surface_desc.dwSize = sizeof(surface_desc);
12349 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
12350 surface_desc.ddsCaps.dwCaps = surface_caps[i].caps;
12351 surface_desc.dwHeight = 128;
12352 surface_desc.dwWidth = 128;
12353 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface7, NULL)))
12355 skip("Failed to create surface, type %s.\n", surface_caps[i].name);
12356 continue;
12358 hr = IDirectDrawSurface_QueryInterface(surface7, &IID_IDirectDrawSurface, (void **)&surface);
12359 ok(hr == DD_OK, "Failed to query IDirectDrawSurface, hr %#x, type %s.\n", hr, surface_caps[i].name);
12360 hr = IDirectDrawSurface_QueryInterface(surface7, &IID_IDirectDrawSurface3, (void **)&surface3);
12361 ok(hr == DD_OK, "Failed to query IDirectDrawSurface3, hr %#x, type %s.\n", hr, surface_caps[i].name);
12363 /* GetSurfaceDesc() */
12364 for (j = 0; j < sizeof(desc_sizes) / sizeof(*desc_sizes); ++j)
12366 memset(&desc, 0, sizeof(desc));
12367 desc.dwSize = desc_sizes[j];
12368 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC) ? DD_OK : DDERR_INVALIDPARAMS;
12369 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &desc.desc1);
12370 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
12371 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
12373 memset(&desc, 0, sizeof(desc));
12374 desc.dwSize = desc_sizes[j];
12375 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC) ? DD_OK : DDERR_INVALIDPARAMS;
12376 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &desc.desc1);
12377 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
12378 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
12380 memset(&desc, 0, sizeof(desc));
12381 desc.dwSize = desc_sizes[j];
12382 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC2) ? DD_OK : DDERR_INVALIDPARAMS;
12383 hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &desc.desc2);
12384 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
12385 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
12388 /* Lock() */
12389 for (j = 0; j < sizeof(desc_sizes) / sizeof(*desc_sizes); ++j)
12391 const BOOL ignore_size = surface_caps[i].caps & DDSCAPS_TEXTURE
12392 && !(surface_caps[i].caps & DDSCAPS_VIDEOMEMORY);
12393 const BOOL valid_size = desc_sizes[j] == sizeof(DDSURFACEDESC)
12394 || desc_sizes[j] == sizeof(DDSURFACEDESC2);
12395 DWORD expected_texture_stage;
12397 memset(&desc, 0, sizeof(desc));
12398 desc.dwSize = desc_sizes[j];
12399 desc.desc2.dwTextureStage = 0xdeadbeef;
12400 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
12401 hr = IDirectDrawSurface_Lock(surface, NULL, &desc.desc1, 0, 0);
12402 expected_hr = ignore_size || valid_size ? DD_OK : DDERR_INVALIDPARAMS;
12403 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
12404 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
12405 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
12406 desc_sizes[j], desc.dwSize, surface_caps[i].name);
12407 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
12408 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
12409 if (SUCCEEDED(hr))
12411 ok(desc.desc1.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
12412 desc.desc1.dwWidth, desc_sizes[j], surface_caps[i].name);
12413 ok(desc.desc1.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
12414 desc.desc1.dwHeight, desc_sizes[j], surface_caps[i].name);
12415 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
12416 todo_wine_if(!expected_texture_stage)
12417 ok(desc.desc2.dwTextureStage == expected_texture_stage,
12418 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
12419 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
12420 IDirectDrawSurface_Unlock(surface, NULL);
12423 memset(&desc, 0, sizeof(desc));
12424 desc.dwSize = desc_sizes[j];
12425 desc.desc2.dwTextureStage = 0xdeadbeef;
12426 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
12427 hr = IDirectDrawSurface3_Lock(surface3, NULL, &desc.desc1, 0, 0);
12428 expected_hr = ignore_size || valid_size ? DD_OK : DDERR_INVALIDPARAMS;
12429 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
12430 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
12431 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
12432 desc_sizes[j], desc.dwSize, surface_caps[i].name);
12433 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
12434 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
12435 if (SUCCEEDED(hr))
12437 ok(desc.desc1.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
12438 desc.desc1.dwWidth, desc_sizes[j], surface_caps[i].name);
12439 ok(desc.desc1.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
12440 desc.desc1.dwHeight, desc_sizes[j], surface_caps[i].name);
12441 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
12442 todo_wine_if(!expected_texture_stage)
12443 ok(desc.desc2.dwTextureStage == expected_texture_stage,
12444 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
12445 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
12446 IDirectDrawSurface3_Unlock(surface3, NULL);
12449 memset(&desc, 0, sizeof(desc));
12450 desc.dwSize = desc_sizes[j];
12451 desc.desc2.dwTextureStage = 0xdeadbeef;
12452 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
12453 hr = IDirectDrawSurface7_Lock(surface7, NULL, &desc.desc2, 0, 0);
12454 expected_hr = ignore_size || valid_size ? DD_OK : DDERR_INVALIDPARAMS;
12455 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
12456 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
12457 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
12458 desc_sizes[j], desc.dwSize, surface_caps[i].name);
12459 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
12460 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
12461 if (SUCCEEDED(hr))
12463 ok(desc.desc2.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
12464 desc.desc2.dwWidth, desc_sizes[j], surface_caps[i].name);
12465 ok(desc.desc2.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
12466 desc.desc2.dwHeight, desc_sizes[j], surface_caps[i].name);
12467 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
12468 ok(desc.desc2.dwTextureStage == expected_texture_stage,
12469 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
12470 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
12471 IDirectDrawSurface7_Unlock(surface7, NULL);
12475 IDirectDrawSurface7_Release(surface7);
12476 IDirectDrawSurface3_Release(surface3);
12477 IDirectDrawSurface_Release(surface);
12480 refcount = IDirectDraw7_Release(ddraw);
12481 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
12484 static void test_get_surface_from_dc(void)
12486 IDirectDrawSurface *surface1, *tmp1;
12487 IDirectDrawSurface7 *surface, *tmp;
12488 DDSURFACEDESC2 surface_desc;
12489 IDirectDraw7 *ddraw;
12490 HDC dc, device_dc;
12491 ULONG refcount;
12492 HWND window;
12493 HRESULT hr;
12494 DWORD ret;
12496 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
12497 0, 0, 640, 480, 0, 0, 0, 0);
12498 ddraw = create_ddraw();
12499 ok(!!ddraw, "Failed to create a ddraw object.\n");
12500 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12501 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12503 memset(&surface_desc, 0, sizeof(surface_desc));
12504 surface_desc.dwSize = sizeof(surface_desc);
12505 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
12506 surface_desc.dwWidth = 64;
12507 surface_desc.dwHeight = 64;
12508 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12510 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12511 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12512 hr = IDirectDrawSurface7_QueryInterface(surface, &IID_IDirectDrawSurface, (void **)&surface1);
12513 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
12515 refcount = get_refcount((IUnknown *)surface1);
12516 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
12517 refcount = get_refcount((IUnknown *)surface);
12518 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
12520 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12521 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
12523 tmp1 = (void *)0xdeadbeef;
12524 device_dc = (void *)0xdeadbeef;
12525 hr = GetSurfaceFromDC(NULL, &tmp1, &device_dc);
12526 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
12527 ok(!tmp1, "Got unexpected surface %p.\n", tmp1);
12528 ok(!device_dc, "Got unexpected device_dc %p.\n", device_dc);
12530 device_dc = (void *)0xdeadbeef;
12531 hr = GetSurfaceFromDC(dc, NULL, &device_dc);
12532 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
12533 ok(device_dc == (void *)0xdeadbeef, "Got unexpected device_dc %p.\n", device_dc);
12535 tmp1 = (void *)0xdeadbeef;
12536 hr = GetSurfaceFromDC(dc, &tmp1, NULL);
12537 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
12538 ok(!tmp1, "Got unexpected surface %p.\n", tmp1);
12540 hr = GetSurfaceFromDC(dc, &tmp1, &device_dc);
12541 ok(SUCCEEDED(hr), "GetSurfaceFromDC failed, hr %#x.\n", hr);
12542 ok(tmp1 == surface1, "Got unexpected surface %p, expected %p.\n", tmp1, surface1);
12543 IDirectDrawSurface_Release(tmp1);
12545 ret = GetObjectType(device_dc);
12546 todo_wine ok(ret == OBJ_DC, "Got unexpected object type %#x.\n", ret);
12547 ret = GetDeviceCaps(device_dc, TECHNOLOGY);
12548 todo_wine ok(ret == DT_RASDISPLAY, "Got unexpected technology %#x.\n", ret);
12550 hr = IDirectDraw7_GetSurfaceFromDC(ddraw, dc, NULL);
12551 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
12553 hr = IDirectDraw7_GetSurfaceFromDC(ddraw, dc, &tmp);
12554 ok(SUCCEEDED(hr), "GetSurfaceFromDC failed, hr %#x.\n", hr);
12555 ok(tmp == surface, "Got unexpected surface %p, expected %p.\n", tmp, surface);
12557 refcount = get_refcount((IUnknown *)surface1);
12558 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
12559 refcount = get_refcount((IUnknown *)surface);
12560 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
12562 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12563 ok(SUCCEEDED(hr), "ReleaseDC failed, hr %#x.\n", hr);
12565 IDirectDrawSurface_Release(tmp);
12567 dc = CreateCompatibleDC(NULL);
12568 ok(!!dc, "CreateCompatibleDC failed.\n");
12570 tmp1 = (void *)0xdeadbeef;
12571 device_dc = (void *)0xdeadbeef;
12572 hr = GetSurfaceFromDC(dc, &tmp1, &device_dc);
12573 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
12574 ok(!tmp1, "Got unexpected surface %p.\n", tmp1);
12575 ok(!device_dc, "Got unexpected device_dc %p.\n", device_dc);
12577 tmp = (void *)0xdeadbeef;
12578 hr = IDirectDraw7_GetSurfaceFromDC(ddraw, dc, &tmp);
12579 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
12580 ok(!tmp, "Got unexpected surface %p.\n", tmp);
12582 ok(DeleteDC(dc), "DeleteDC failed.\n");
12584 tmp = (void *)0xdeadbeef;
12585 hr = IDirectDraw7_GetSurfaceFromDC(ddraw, NULL, &tmp);
12586 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
12587 ok(!tmp, "Got unexpected surface %p.\n", tmp);
12589 IDirectDrawSurface7_Release(surface);
12590 IDirectDrawSurface_Release(surface1);
12591 IDirectDraw7_Release(ddraw);
12592 DestroyWindow(window);
12595 static void test_ck_operation(void)
12597 IDirectDrawSurface7 *src, *dst;
12598 IDirectDrawSurface *src1, *dst1;
12599 DDSURFACEDESC2 surface_desc;
12600 IDirectDraw7 *ddraw;
12601 ULONG refcount;
12602 HWND window;
12603 HRESULT hr;
12604 D3DCOLOR *color;
12605 unsigned int i;
12606 DDCOLORKEY ckey;
12607 DDBLTFX fx;
12609 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
12610 0, 0, 640, 480, 0, 0, 0, 0);
12611 ddraw = create_ddraw();
12612 ok(!!ddraw, "Failed to create a ddraw object.\n");
12613 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12614 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12616 memset(&surface_desc, 0, sizeof(surface_desc));
12617 surface_desc.dwSize = sizeof(surface_desc);
12618 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
12619 surface_desc.dwWidth = 4;
12620 surface_desc.dwHeight = 1;
12621 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12622 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
12623 U1(U4(surface_desc.ddpfPixelFormat)).dwRGBBitCount = 32;
12624 U2(U4(surface_desc.ddpfPixelFormat)).dwRBitMask = 0x00ff0000;
12625 U3(U4(surface_desc.ddpfPixelFormat)).dwGBitMask = 0x0000ff00;
12626 U4(U4(surface_desc.ddpfPixelFormat)).dwBBitMask = 0x000000ff;
12627 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
12628 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12630 surface_desc.dwFlags |= DDSD_CKSRCBLT;
12631 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff00ff;
12632 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff00ff;
12633 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
12634 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12636 hr = IDirectDrawSurface7_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12637 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12638 ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n");
12639 color = surface_desc.lpSurface;
12640 color[0] = 0x77010203;
12641 color[1] = 0x00010203;
12642 color[2] = 0x77ff00ff;
12643 color[3] = 0x00ff00ff;
12644 hr = IDirectDrawSurface7_Unlock(src, NULL);
12645 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12647 for (i = 0; i < 2; ++i)
12649 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12650 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12651 color = surface_desc.lpSurface;
12652 color[0] = 0xcccccccc;
12653 color[1] = 0xcccccccc;
12654 color[2] = 0xcccccccc;
12655 color[3] = 0xcccccccc;
12656 hr = IDirectDrawSurface7_Unlock(dst, NULL);
12657 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12659 if (i)
12661 hr = IDirectDrawSurface7_BltFast(dst, 0, 0, src, NULL, DDBLTFAST_SRCCOLORKEY);
12662 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12664 else
12666 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, NULL);
12667 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12670 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT | DDLOCK_READONLY, NULL);
12671 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12672 ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n");
12673 color = surface_desc.lpSurface;
12674 /* Different behavior on some drivers / windows versions. Some versions ignore the X channel when
12675 * color keying, but copy it to the destination surface. Others (sysmem surfaces) apply it for
12676 * color keying, but do not copy it into the destination surface. Nvidia neither uses it for
12677 * color keying nor copies it. */
12678 ok((color[0] == 0x77010203 && color[1] == 0x00010203
12679 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* AMD, Wine */
12680 || broken(color[0] == 0x00010203 && color[1] == 0x00010203
12681 && color[2] == 0x00ff00ff && color[3] == 0xcccccccc) /* Sysmem surfaces? */
12682 || broken(color[0] == 0x00010203 && color[1] == 0x00010203
12683 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Nvidia */
12684 || broken(color[0] == 0xff010203 && color[1] == 0xff010203
12685 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Testbot */,
12686 "Destination data after blitting is %08x %08x %08x %08x, i=%u.\n",
12687 color[0], color[1], color[2], color[3], i);
12688 hr = IDirectDrawSurface7_Unlock(dst, NULL);
12689 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12692 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
12693 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
12694 ok(ckey.dwColorSpaceLowValue == 0x00ff00ff && ckey.dwColorSpaceHighValue == 0x00ff00ff,
12695 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
12697 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
12698 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
12699 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12701 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
12702 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
12703 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
12704 ok(ckey.dwColorSpaceLowValue == 0x0000ff00 && ckey.dwColorSpaceHighValue == 0x0000ff00,
12705 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
12707 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0;
12708 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0;
12709 hr = IDirectDrawSurface7_GetSurfaceDesc(src, &surface_desc);
12710 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
12711 ok(surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue == 0x0000ff00
12712 && surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue == 0x0000ff00,
12713 "Got unexpected color key low=%08x high=%08x.\n", surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue,
12714 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue);
12716 /* Test SetColorKey with dwColorSpaceHighValue < dwColorSpaceLowValue */
12717 ckey.dwColorSpaceLowValue = 0x000000ff;
12718 ckey.dwColorSpaceHighValue = 0x00000000;
12719 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
12720 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12722 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
12723 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
12724 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
12725 ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff,
12726 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
12728 ckey.dwColorSpaceLowValue = 0x000000ff;
12729 ckey.dwColorSpaceHighValue = 0x00000001;
12730 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
12731 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12733 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
12734 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
12735 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
12736 ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff,
12737 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
12739 ckey.dwColorSpaceLowValue = 0x000000fe;
12740 ckey.dwColorSpaceHighValue = 0x000000fd;
12741 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
12742 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12744 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
12745 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
12746 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
12747 ok(ckey.dwColorSpaceLowValue == 0x000000fe && ckey.dwColorSpaceHighValue == 0x000000fe,
12748 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
12750 IDirectDrawSurface7_Release(src);
12751 IDirectDrawSurface7_Release(dst);
12753 /* Test source and destination keys and where they are read from. Use a surface with alpha
12754 * to avoid driver-dependent content in the X channel. */
12755 memset(&surface_desc, 0, sizeof(surface_desc));
12756 surface_desc.dwSize = sizeof(surface_desc);
12757 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
12758 surface_desc.dwWidth = 6;
12759 surface_desc.dwHeight = 1;
12760 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12761 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
12762 U1(U4(surface_desc.ddpfPixelFormat)).dwRGBBitCount = 32;
12763 U2(U4(surface_desc.ddpfPixelFormat)).dwRBitMask = 0x00ff0000;
12764 U3(U4(surface_desc.ddpfPixelFormat)).dwGBitMask = 0x0000ff00;
12765 U4(U4(surface_desc.ddpfPixelFormat)).dwBBitMask = 0x000000ff;
12766 U5(U4(surface_desc.ddpfPixelFormat)).dwRGBAlphaBitMask = 0xff000000;
12767 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
12768 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12769 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
12770 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12772 ckey.dwColorSpaceLowValue = 0x0000ff00;
12773 ckey.dwColorSpaceHighValue = 0x0000ff00;
12774 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
12775 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12776 ckey.dwColorSpaceLowValue = 0x00ff0000;
12777 ckey.dwColorSpaceHighValue = 0x00ff0000;
12778 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_DESTBLT, &ckey);
12779 ok(SUCCEEDED(hr) || hr == DDERR_NOCOLORKEYHW, "Failed to set color key, hr %#x.\n", hr);
12780 if (FAILED(hr))
12782 /* Nvidia reject dest keys, AMD allows them. This applies to vidmem and sysmem surfaces. */
12783 skip("Failed to set destination color key, skipping related tests.\n");
12784 goto done;
12787 ckey.dwColorSpaceLowValue = 0x000000ff;
12788 ckey.dwColorSpaceHighValue = 0x000000ff;
12789 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
12790 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12791 ckey.dwColorSpaceLowValue = 0x000000aa;
12792 ckey.dwColorSpaceHighValue = 0x000000aa;
12793 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_DESTBLT, &ckey);
12794 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12796 memset(&fx, 0, sizeof(fx));
12797 fx.dwSize = sizeof(fx);
12798 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x00110000;
12799 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x00110000;
12800 fx.ddckDestColorkey.dwColorSpaceHighValue = 0x00001100;
12801 fx.ddckDestColorkey.dwColorSpaceLowValue = 0x00001100;
12803 hr = IDirectDrawSurface7_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12804 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12805 color = surface_desc.lpSurface;
12806 color[0] = 0x000000ff; /* Applies to src blt key in src surface. */
12807 color[1] = 0x000000aa; /* Applies to dst blt key in src surface. */
12808 color[2] = 0x00ff0000; /* Dst color key in dst surface. */
12809 color[3] = 0x0000ff00; /* Src color key in dst surface. */
12810 color[4] = 0x00001100; /* Src color key in ddbltfx. */
12811 color[5] = 0x00110000; /* Dst color key in ddbltfx. */
12812 hr = IDirectDrawSurface7_Unlock(src, NULL);
12813 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12815 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12816 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12817 color = surface_desc.lpSurface;
12818 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
12819 hr = IDirectDrawSurface7_Unlock(dst, NULL);
12820 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12822 /* Test a blit without keying. */
12823 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, 0, &fx);
12824 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12826 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12827 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12828 color = surface_desc.lpSurface;
12829 /* Should have copied src data unmodified to dst. */
12830 ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
12831 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
12832 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12833 color[0], color[1], color[2], color[3], color[4], color[5]);
12835 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
12836 hr = IDirectDrawSurface7_Unlock(dst, NULL);
12837 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12839 /* Src key. */
12840 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx);
12841 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12843 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12844 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12845 color = surface_desc.lpSurface;
12846 /* Src key applied to color[0]. It is unmodified, the others are copied. */
12847 ok(color[0] == 0x55555555 && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
12848 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
12849 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12850 color[0], color[1], color[2], color[3], color[4], color[5]);
12852 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
12853 hr = IDirectDrawSurface7_Unlock(dst, NULL);
12854 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12856 /* Src override. */
12857 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, &fx);
12858 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12860 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12861 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12862 color = surface_desc.lpSurface;
12863 /* Override key applied to color[5]. It is unmodified, the others are copied. */
12864 ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
12865 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x55555555,
12866 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12867 color[0], color[1], color[2], color[3], color[4], color[5]);
12869 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
12870 hr = IDirectDrawSurface7_Unlock(dst, NULL);
12871 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12873 /* Src override AND src key. That is not supposed to work. */
12874 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE, &fx);
12875 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
12877 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12878 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12879 color = surface_desc.lpSurface;
12880 /* Ensure the destination was not changed. */
12881 ok(color[0] == 0x55555555 && color[1] == 0x55555555 && color[2] == 0x55555555 &&
12882 color[3] == 0x55555555 && color[4] == 0x55555555 && color[5] == 0x55555555,
12883 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12884 color[0], color[1], color[2], color[3], color[4], color[5]);
12886 /* Use different dst colors for the dst key test. */
12887 color[0] = 0x00ff0000; /* Dest key in dst surface. */
12888 color[1] = 0x00ff0000; /* Dest key in dst surface. */
12889 color[2] = 0x00001100; /* Dest key in override. */
12890 color[3] = 0x00001100; /* Dest key in override. */
12891 color[4] = 0x000000aa; /* Dest key in src surface. */
12892 color[5] = 0x000000aa; /* Dest key in src surface. */
12893 hr = IDirectDrawSurface7_Unlock(dst, NULL);
12894 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12896 /* Dest key blit. The key is taken from the DESTINATION surface in v7! */
12897 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
12898 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12900 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12901 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12902 color = surface_desc.lpSurface;
12903 /* Dst key applied to color[0,1], they are the only changed pixels. */
12904 todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 &&
12905 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
12906 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12907 color[0], color[1], color[2], color[3], color[4], color[5]);
12909 color[0] = 0x00ff0000; /* Dest key in dst surface. */
12910 color[1] = 0x00ff0000; /* Dest key in dst surface. */
12911 color[2] = 0x00001100; /* Dest key in override. */
12912 color[3] = 0x00001100; /* Dest key in override. */
12913 color[4] = 0x000000aa; /* Dest key in src surface. */
12914 color[5] = 0x000000aa; /* Dest key in src surface. */
12915 hr = IDirectDrawSurface7_Unlock(dst, NULL);
12916 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12918 /* What happens with a QI'd older version of the interface? It takes the key
12919 * from the source surface. */
12920 hr = IDirectDrawSurface7_QueryInterface(src, &IID_IDirectDrawSurface, (void **)&src1);
12921 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
12922 hr = IDirectDrawSurface7_QueryInterface(dst, &IID_IDirectDrawSurface, (void **)&dst1);
12923 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
12925 hr = IDirectDrawSurface_Blt(dst1, NULL, src1, NULL, DDBLT_KEYDEST, &fx);
12926 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12928 IDirectDrawSurface_Release(dst1);
12929 IDirectDrawSurface_Release(src1);
12931 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12932 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12933 color = surface_desc.lpSurface;
12934 /* Dst key applied to color[4,5], they are the only changed pixels. */
12935 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
12936 color[3] == 0x00001100 && color[4] == 0x00001100 && color[5] == 0x00110000,
12937 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12938 color[0], color[1], color[2], color[3], color[4], color[5]);
12940 color[0] = 0x00ff0000; /* Dest key in dst surface. */
12941 color[1] = 0x00ff0000; /* Dest key in dst surface. */
12942 color[2] = 0x00001100; /* Dest key in override. */
12943 color[3] = 0x00001100; /* Dest key in override. */
12944 color[4] = 0x000000aa; /* Dest key in src surface. */
12945 color[5] = 0x000000aa; /* Dest key in src surface. */
12946 hr = IDirectDrawSurface7_Unlock(dst, NULL);
12947 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12949 /* Dest override key blit. */
12950 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, &fx);
12951 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12953 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12954 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12955 color = surface_desc.lpSurface;
12956 /* Dst key applied to color[2,3], they are the only changed pixels. */
12957 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00ff0000 &&
12958 color[3] == 0x0000ff00 && color[4] == 0x000000aa && color[5] == 0x000000aa,
12959 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12960 color[0], color[1], color[2], color[3], color[4], color[5]);
12962 color[0] = 0x00ff0000; /* Dest key in dst surface. */
12963 color[1] = 0x00ff0000; /* Dest key in dst surface. */
12964 color[2] = 0x00001100; /* Dest key in override. */
12965 color[3] = 0x00001100; /* Dest key in override. */
12966 color[4] = 0x000000aa; /* Dest key in src surface. */
12967 color[5] = 0x000000aa; /* Dest key in src surface. */
12968 hr = IDirectDrawSurface7_Unlock(dst, NULL);
12969 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12971 /* Dest override together with surface key. Supposed to fail. */
12972 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYDESTOVERRIDE, &fx);
12973 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
12975 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12976 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12977 color = surface_desc.lpSurface;
12978 /* Destination is unchanged. */
12979 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
12980 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
12981 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12982 color[0], color[1], color[2], color[3], color[4], color[5]);
12983 hr = IDirectDrawSurface7_Unlock(dst, NULL);
12984 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12986 /* Source and destination key. This is driver dependent. New HW treats it like
12987 * DDBLT_KEYSRC. Older HW and some software renderers apply both keys. */
12988 if (0)
12990 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYSRC, &fx);
12991 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12993 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12994 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12995 color = surface_desc.lpSurface;
12996 /* Color[0] is filtered by the src key, 2-5 are filtered by the dst key, if
12997 * the driver applies it. */
12998 ok(color[0] == 0x00ff0000 && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
12999 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
13000 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13001 color[0], color[1], color[2], color[3], color[4], color[5]);
13003 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13004 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13005 color[2] = 0x00001100; /* Dest key in override. */
13006 color[3] = 0x00001100; /* Dest key in override. */
13007 color[4] = 0x000000aa; /* Dest key in src surface. */
13008 color[5] = 0x000000aa; /* Dest key in src surface. */
13009 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13010 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13013 /* Override keys without ddbltfx parameter fail */
13014 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, NULL);
13015 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13016 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, NULL);
13017 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13019 /* Try blitting without keys in the source surface. */
13020 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, NULL);
13021 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13022 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_DESTBLT, NULL);
13023 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13025 /* That fails now. Do not bother to check that the data is unmodified. */
13026 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx);
13027 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13029 /* Dest key blit still works, the destination surface key is used in v7. */
13030 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
13031 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13033 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13034 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13035 color = surface_desc.lpSurface;
13036 /* Dst key applied to color[0,1], they are the only changed pixels. */
13037 todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 &&
13038 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
13039 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13040 color[0], color[1], color[2], color[3], color[4], color[5]);
13041 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13042 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13044 /* Try blitting without keys in the destination surface. */
13045 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_SRCBLT, NULL);
13046 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13047 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_DESTBLT, NULL);
13048 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13050 /* This fails, as sanity would dictate. */
13051 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
13052 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13054 done:
13055 IDirectDrawSurface7_Release(src);
13056 IDirectDrawSurface7_Release(dst);
13057 refcount = IDirectDraw7_Release(ddraw);
13058 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
13059 DestroyWindow(window);
13062 static void test_vb_refcount(void)
13064 ULONG prev_d3d_refcount, prev_device_refcount;
13065 ULONG cur_d3d_refcount, cur_device_refcount;
13066 IDirect3DVertexBuffer7 *vb, *vb7;
13067 D3DVERTEXBUFFERDESC vb_desc;
13068 IDirect3DVertexBuffer *vb1;
13069 IDirect3DDevice7 *device;
13070 IDirect3D7 *d3d;
13071 ULONG refcount;
13072 IUnknown *unk;
13073 HWND window;
13074 HRESULT hr;
13076 window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
13077 0, 0, 640, 480, 0, 0, 0, 0);
13078 if (!(device = create_device(window, DDSCL_NORMAL)))
13080 skip("Failed to create a 3D device, skipping test.\n");
13081 DestroyWindow(window);
13082 return;
13085 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
13086 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
13088 prev_d3d_refcount = get_refcount((IUnknown *)d3d);
13089 prev_device_refcount = get_refcount((IUnknown *)device);
13091 memset(&vb_desc, 0, sizeof(vb_desc));
13092 vb_desc.dwSize = sizeof(vb_desc);
13093 vb_desc.dwFVF = D3DFVF_XYZ;
13094 vb_desc.dwNumVertices = 4;
13095 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &vb, 0);
13096 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
13098 cur_d3d_refcount = get_refcount((IUnknown *)d3d);
13099 cur_device_refcount = get_refcount((IUnknown *)device);
13100 ok(cur_d3d_refcount > prev_d3d_refcount, "D3D object refcount didn't change from %u.\n", prev_d3d_refcount);
13101 ok(cur_device_refcount == prev_device_refcount, "Device refcount changed from %u to %u.\n",
13102 prev_device_refcount, cur_device_refcount);
13104 prev_d3d_refcount = cur_d3d_refcount;
13105 hr = IDirect3DVertexBuffer7_QueryInterface(vb, &IID_IDirect3DVertexBuffer7, (void **)&vb7);
13106 ok(hr == DD_OK, "Failed to query IDirect3DVertexBuffer7, hr %#x.\n", hr);
13107 cur_d3d_refcount = get_refcount((IUnknown *)d3d);
13108 ok(cur_d3d_refcount == prev_d3d_refcount, "D3D object refcount changed from %u to %u.\n",
13109 prev_d3d_refcount, cur_d3d_refcount);
13110 IDirect3DVertexBuffer7_Release(vb7);
13112 hr = IDirect3DVertexBuffer7_QueryInterface(vb, &IID_IDirect3DVertexBuffer, (void **)&vb1);
13113 ok(hr == E_NOINTERFACE, "Querying IDirect3DVertexBuffer returned unexpected hr %#x.\n", hr);
13115 hr = IDirect3DVertexBuffer_QueryInterface(vb, &IID_IUnknown, (void **)&unk);
13116 ok(hr == DD_OK, "Failed to query IUnknown, hr %#x.\n", hr);
13117 ok((IUnknown *)vb == unk,
13118 "IDirect3DVertexBuffer7 and IUnknown interface pointers don't match, %p != %p.\n", vb, unk);
13119 IUnknown_Release(unk);
13121 refcount = IDirect3DVertexBuffer7_Release(vb);
13122 ok(!refcount, "Vertex buffer has %u references left.\n", refcount);
13124 IDirect3D7_Release(d3d);
13125 refcount = IDirect3DDevice7_Release(device);
13126 ok(!refcount, "Device has %u references left.\n", refcount);
13127 DestroyWindow(window);
13130 static void test_compute_sphere_visibility(void)
13132 static D3DVALUE clip_plane[4] = {1.0f, 0.0f, 0.0f, 0.5f};
13133 static D3DMATRIX proj_1 =
13135 1.810660f, 0.000000f, 0.000000f, 0.000000f,
13136 0.000000f, 2.414213f, 0.000000f, 0.000000f,
13137 0.000000f, 0.000000f, 1.020408f, 1.000000f,
13138 0.000000f, 0.000000f, -0.102041f, 0.000000f,
13140 static D3DMATRIX proj_2 =
13142 10.0f, 0.0f, 0.0f, 0.0f,
13143 0.0f, 10.0f, 0.0f, 0.0f,
13144 0.0f, 0.0f, 10.0f, 0.0f,
13145 0.0f, 0.0f, 0.0f, 1.0f,
13147 static D3DMATRIX view_1 =
13149 1.000000f, 0.000000f, 0.000000f, 0.000000f,
13150 0.000000f, 0.768221f, -0.640185f, 0.000000f,
13151 -0.000000f, 0.640185f, 0.768221f, 0.000000f,
13152 -14.852037f, 9.857489f, 11.600972f, 1.000000f,
13154 static D3DMATRIX identity =
13156 1.0f, 0.0f, 0.0f, 0.0f,
13157 0.0f, 1.0f, 0.0f, 0.0f,
13158 0.0f, 0.0f, 1.0f, 0.0f,
13159 0.0f, 0.0f, 0.0f, 1.0f,
13161 static struct
13163 D3DMATRIX *view, *proj;
13164 unsigned int sphere_count;
13165 D3DVECTOR center[3];
13166 D3DVALUE radius[3];
13167 DWORD enable_planes;
13168 const DWORD expected[3];
13170 tests[] =
13172 {&view_1, &proj_1, 1, {{{11.461533f}, {-4.761727f}, {-1.171646f}}}, {38.252632f}, 0, {0x3f}},
13173 {&view_1, &proj_1, 3, {{{-3.515620f}, {-1.560661f}, {-12.464638f}},
13174 {{14.290396f}, {-2.981143f}, {-24.311312f}},
13175 {{1.461626f}, {-6.093709f}, {-13.901010f}}},
13176 {4.354097f, 12.500704f, 17.251318f}, 0, {0x103d, 0x3f, 0x3f}},
13177 {&identity, &proj_2, 1, {{{0.0f}, {0.0f}, {0.05f}}}, {0.04f}, 0, {0}},
13178 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.5f}}}, {0.5f}, 0, {0}},
13179 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.0f}}}, {0.0f}, 0, {0}},
13180 {&identity, &identity, 1, {{{-1.0f}, {-1.0f}, {0.5f}}}, {0.25f}, 0, {0x9}}, /* 5 */
13181 {&identity, &identity, 1, {{{-20.0f}, {0.0f}, {0.5f}}}, {3.0f}, 0, {0x103d}},
13182 {&identity, &identity, 1, {{{20.0f}, {0.0f}, {0.5f}}}, {3.0f}, 0, {0x203e}},
13183 {&identity, &identity, 1, {{{0.0f}, {-20.0f}, {0.5f}}}, {3.0f}, 0, {0x803b}},
13184 {&identity, &identity, 1, {{{0.0f}, {20.0f}, {0.5f}}}, {3.0f}, 0, {0x4037}},
13185 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {-20.0f}}}, {3.0f}, 0, {0x1001f}}, /* 10 */
13186 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {20.0f}}}, {3.0f}, 0, {0x2002f}},
13187 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.0f}}}, {5.0f}, 1, {0x7f}},
13188 {&identity, &identity, 1, {{{-0.5f}, {0.0f}, {0.0f}}}, {5.0f}, 1, {0x7f}},
13189 {&identity, &identity, 1, {{{-0.5f}, {0.0f}, {0.0f}}}, {1.0f}, 1, {0x51}},
13190 {&identity, &identity, 1, {{{-2.5f}, {0.0f}, {0.0f}}}, {1.0f}, 1, {0x41051}}, /* 15 */
13192 IDirect3DDevice7 *device;
13193 unsigned int i, j;
13194 DWORD result[3];
13195 ULONG refcount;
13196 HWND window;
13197 HRESULT hr;
13199 window = CreateWindowA("static", "d3d_test", WS_OVERLAPPEDWINDOW,
13200 0, 0, 640, 480, 0, 0, 0, 0);
13201 if (!(device = create_device(window, DDSCL_NORMAL)))
13203 skip("Failed to create a 3D device, skipping test.\n");
13204 DestroyWindow(window);
13205 return;
13208 hr = IDirect3DDevice7_SetClipPlane(device, 0, clip_plane);
13209 ok(SUCCEEDED(hr), "Failed to set user clip plane, hr %#x.\n", hr);
13211 IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &identity);
13213 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
13215 IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, tests[i].view);
13216 IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, tests[i].proj);
13218 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE,
13219 tests[i].enable_planes);
13220 ok(SUCCEEDED(hr), "Failed to enable / disable user clip planes, hr %#x.\n", hr);
13222 hr = IDirect3DDevice7_ComputeSphereVisibility(device, tests[i].center, tests[i].radius,
13223 tests[i].sphere_count, 0, result);
13224 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13226 for (j = 0; j < tests[i].sphere_count; ++j)
13227 ok(result[j] == tests[i].expected[j], "Test %u sphere %u: expected %#x, got %#x.\n",
13228 i, j, tests[i].expected[j], result[j]);
13231 refcount = IDirect3DDevice7_Release(device);
13232 ok(!refcount, "Device has %u references left.\n", refcount);
13233 DestroyWindow(window);
13236 START_TEST(ddraw7)
13238 HMODULE module = GetModuleHandleA("ddraw.dll");
13239 HMODULE dwmapi;
13240 IDirectDraw7 *ddraw;
13241 DEVMODEW current_mode;
13243 if (!(pDirectDrawCreateEx = (void *)GetProcAddress(module, "DirectDrawCreateEx")))
13245 win_skip("DirectDrawCreateEx not available, skipping tests.\n");
13246 return;
13249 if (!(ddraw = create_ddraw()))
13251 skip("Failed to create a ddraw object, skipping tests.\n");
13252 return;
13254 IDirectDraw7_Release(ddraw);
13256 memset(&current_mode, 0, sizeof(current_mode));
13257 current_mode.dmSize = sizeof(current_mode);
13258 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
13259 registry_mode.dmSize = sizeof(registry_mode);
13260 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
13261 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
13262 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
13264 skip("Current mode does not match registry mode, skipping test.\n");
13265 return;
13268 if ((dwmapi = LoadLibraryA("dwmapi.dll")))
13269 pDwmIsCompositionEnabled = (void *)GetProcAddress(dwmapi, "DwmIsCompositionEnabled");
13271 test_process_vertices();
13272 test_coop_level_create_device_window();
13273 test_clipper_blt();
13274 test_coop_level_d3d_state();
13275 test_surface_interface_mismatch();
13276 test_coop_level_threaded();
13277 test_depth_blit();
13278 test_texture_load_ckey();
13279 test_zenable();
13280 test_ck_rgba();
13281 test_ck_default();
13282 test_ck_complex();
13283 test_surface_qi();
13284 test_device_qi();
13285 test_wndproc();
13286 test_window_style();
13287 test_redundant_mode_set();
13288 test_coop_level_mode_set();
13289 test_coop_level_mode_set_multi();
13290 test_initialize();
13291 test_coop_level_surf_create();
13292 test_vb_discard();
13293 test_coop_level_multi_window();
13294 test_draw_strided();
13295 test_lighting();
13296 test_specular_lighting();
13297 test_clear_rect_count();
13298 test_coop_level_versions();
13299 test_fog_special();
13300 test_lighting_interface_versions();
13301 test_coop_level_activateapp();
13302 test_texturemanage();
13303 test_block_formats_creation();
13304 test_unsupported_formats();
13305 test_rt_caps();
13306 test_primary_caps();
13307 test_surface_lock();
13308 test_surface_discard();
13309 test_flip();
13310 test_set_surface_desc();
13311 test_user_memory_getdc();
13312 test_sysmem_overlay();
13313 test_primary_palette();
13314 test_surface_attachment();
13315 test_private_data();
13316 test_pixel_format();
13317 test_create_surface_pitch();
13318 test_mipmap();
13319 test_palette_complex();
13320 test_p8_blit();
13321 test_material();
13322 test_palette_gdi();
13323 test_palette_alpha();
13324 test_vb_writeonly();
13325 test_lost_device();
13326 test_resource_priority();
13327 test_surface_desc_lock();
13328 test_fog_interpolation();
13329 test_negative_fixedfunction_fog();
13330 test_table_fog_zw();
13331 test_signed_formats();
13332 test_color_fill();
13333 test_texcoordindex();
13334 test_colorkey_precision();
13335 test_range_colorkey();
13336 test_shademode();
13337 test_lockrect_invalid();
13338 test_yv12_overlay();
13339 test_offscreen_overlay();
13340 test_overlay_rect();
13341 test_blt();
13342 test_color_clamping();
13343 test_getdc();
13344 test_draw_primitive();
13345 test_edge_antialiasing_blending();
13346 test_display_mode_surface_pixel_format();
13347 test_surface_desc_size();
13348 test_get_surface_from_dc();
13349 test_ck_operation();
13350 test_vb_refcount();
13351 test_compute_sphere_visibility();