ddraw/tests: Rewrite SetRenderState() tests.
[wine.git] / dlls / ddraw / tests / ddraw7.c
blob2e41ff3715ba1b662a3981a1667116f20fab4ad7
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 #ifndef ARRAY_SIZE
36 #define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
37 #endif
39 struct vec2
41 float x, y;
44 struct vec3
46 float x, y, z;
49 struct vec4
51 float x, y, z, w;
54 struct create_window_thread_param
56 HWND window;
57 HANDLE window_created;
58 HANDLE destroy_window;
59 HANDLE thread;
62 static BOOL compare_float(float f, float g, unsigned int ulps)
64 int x = *(int *)&f;
65 int y = *(int *)&g;
67 if (x < 0)
68 x = INT_MIN - x;
69 if (y < 0)
70 y = INT_MIN - y;
72 if (abs(x - y) > ulps)
73 return FALSE;
75 return TRUE;
78 static BOOL compare_vec3(struct vec3 *vec, float x, float y, float z, unsigned int ulps)
80 return compare_float(vec->x, x, ulps)
81 && compare_float(vec->y, y, ulps)
82 && compare_float(vec->z, z, ulps);
85 static BOOL compare_vec4(const struct vec4 *vec, float x, float y, float z, float w, unsigned int ulps)
87 return compare_float(vec->x, x, ulps)
88 && compare_float(vec->y, y, ulps)
89 && compare_float(vec->z, z, ulps)
90 && compare_float(vec->w, w, ulps);
93 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
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 c1 >>= 8; c2 >>= 8;
99 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
100 c1 >>= 8; c2 >>= 8;
101 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
102 return TRUE;
105 static ULONG get_refcount(IUnknown *iface)
107 IUnknown_AddRef(iface);
108 return IUnknown_Release(iface);
111 static BOOL ddraw_get_identifier(IDirectDraw7 *ddraw, DDDEVICEIDENTIFIER2 *identifier)
113 HRESULT hr;
115 hr = IDirectDraw7_GetDeviceIdentifier(ddraw, identifier, 0);
116 ok(SUCCEEDED(hr), "Failed to get device identifier, hr %#x.\n", hr);
118 return SUCCEEDED(hr);
121 static BOOL ddraw_is_warp(IDirectDraw7 *ddraw)
123 DDDEVICEIDENTIFIER2 identifier;
125 return strcmp(winetest_platform, "wine")
126 && ddraw_get_identifier(ddraw, &identifier)
127 && strstr(identifier.szDriver, "warp");
130 static BOOL ddraw_is_vendor(IDirectDraw7 *ddraw, DWORD vendor)
132 DDDEVICEIDENTIFIER2 identifier;
134 return strcmp(winetest_platform, "wine")
135 && ddraw_get_identifier(ddraw, &identifier)
136 && identifier.dwVendorId == vendor;
139 static BOOL ddraw_is_intel(IDirectDraw7 *ddraw)
141 return ddraw_is_vendor(ddraw, 0x8086);
144 static BOOL ddraw_is_nvidia(IDirectDraw7 *ddraw)
146 return ddraw_is_vendor(ddraw, 0x10de);
149 static BOOL ddraw_is_vmware(IDirectDraw7 *ddraw)
151 return ddraw_is_vendor(ddraw, 0x15ad);
154 static IDirectDrawSurface7 *create_overlay(IDirectDraw7 *ddraw,
155 unsigned int width, unsigned int height, DWORD format)
157 IDirectDrawSurface7 *surface;
158 DDSURFACEDESC2 desc;
160 memset(&desc, 0, sizeof(desc));
161 desc.dwSize = sizeof(desc);
162 desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
163 desc.dwWidth = width;
164 desc.dwHeight = height;
165 desc.ddsCaps.dwCaps = DDSCAPS_OVERLAY;
166 U4(desc).ddpfPixelFormat.dwSize = sizeof(U4(desc).ddpfPixelFormat);
167 U4(desc).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
168 U4(desc).ddpfPixelFormat.dwFourCC = format;
170 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &desc, &surface, NULL)))
171 return NULL;
172 return surface;
175 static HWND create_window(void)
177 RECT r = {0, 0, 640, 480};
179 AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
181 return CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
182 CW_USEDEFAULT, CW_USEDEFAULT, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL);
185 static DWORD WINAPI create_window_thread_proc(void *param)
187 struct create_window_thread_param *p = param;
188 DWORD res;
189 BOOL ret;
191 p->window = create_window();
192 ret = SetEvent(p->window_created);
193 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
195 for (;;)
197 MSG msg;
199 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
200 DispatchMessageA(&msg);
201 res = WaitForSingleObject(p->destroy_window, 100);
202 if (res == WAIT_OBJECT_0)
203 break;
204 if (res != WAIT_TIMEOUT)
206 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
207 break;
211 DestroyWindow(p->window);
213 return 0;
216 static void create_window_thread(struct create_window_thread_param *p)
218 DWORD res, tid;
220 p->window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
221 ok(!!p->window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
222 p->destroy_window = CreateEventA(NULL, FALSE, FALSE, NULL);
223 ok(!!p->destroy_window, "CreateEvent failed, last error %#x.\n", GetLastError());
224 p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
225 ok(!!p->thread, "Failed to create thread, last error %#x.\n", GetLastError());
226 res = WaitForSingleObject(p->window_created, INFINITE);
227 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
230 static void destroy_window_thread(struct create_window_thread_param *p)
232 SetEvent(p->destroy_window);
233 WaitForSingleObject(p->thread, INFINITE);
234 CloseHandle(p->destroy_window);
235 CloseHandle(p->window_created);
236 CloseHandle(p->thread);
239 static IDirectDrawSurface7 *get_depth_stencil(IDirect3DDevice7 *device)
241 IDirectDrawSurface7 *rt, *ret;
242 DDSCAPS2 caps = {DDSCAPS_ZBUFFER, 0, 0, {0}};
243 HRESULT hr;
245 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
246 ok(SUCCEEDED(hr), "Failed to get the render target, hr %#x.\n", hr);
247 hr = IDirectDrawSurface7_GetAttachedSurface(rt, &caps, &ret);
248 ok(SUCCEEDED(hr) || hr == DDERR_NOTFOUND, "Failed to get the z buffer, hr %#x.\n", hr);
249 IDirectDrawSurface7_Release(rt);
250 return ret;
253 static HRESULT set_display_mode(IDirectDraw7 *ddraw, DWORD width, DWORD height)
255 if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
256 return DD_OK;
257 return IDirectDraw7_SetDisplayMode(ddraw, width, height, 24, 0, 0);
260 static D3DCOLOR get_surface_color(IDirectDrawSurface7 *surface, UINT x, UINT y)
262 RECT rect = {x, y, x + 1, y + 1};
263 DDSURFACEDESC2 surface_desc;
264 D3DCOLOR color;
265 HRESULT hr;
267 memset(&surface_desc, 0, sizeof(surface_desc));
268 surface_desc.dwSize = sizeof(surface_desc);
270 hr = IDirectDrawSurface7_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY, NULL);
271 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
272 if (FAILED(hr))
273 return 0xdeadbeef;
275 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
277 hr = IDirectDrawSurface7_Unlock(surface, &rect);
278 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
280 return color;
283 static HRESULT CALLBACK enum_z_fmt(DDPIXELFORMAT *format, void *ctx)
285 DDPIXELFORMAT *z_fmt = ctx;
287 if (U1(*format).dwZBufferBitDepth > U1(*z_fmt).dwZBufferBitDepth)
288 *z_fmt = *format;
290 return DDENUMRET_OK;
293 static IDirectDraw7 *create_ddraw(void)
295 IDirectDraw7 *ddraw;
297 if (FAILED(pDirectDrawCreateEx(NULL, (void **)&ddraw, &IID_IDirectDraw7, NULL)))
298 return NULL;
300 return ddraw;
303 static HRESULT WINAPI enum_devtype_cb(char *desc_str, char *name, D3DDEVICEDESC7 *desc, void *ctx)
305 BOOL *hal_ok = ctx;
306 if (IsEqualGUID(&desc->deviceGUID, &IID_IDirect3DTnLHalDevice))
308 *hal_ok = TRUE;
309 return DDENUMRET_CANCEL;
311 return DDENUMRET_OK;
314 static IDirect3DDevice7 *create_device(HWND window, DWORD coop_level)
316 IDirectDrawSurface7 *surface, *ds;
317 IDirect3DDevice7 *device = NULL;
318 DDSURFACEDESC2 surface_desc;
319 DDPIXELFORMAT z_fmt;
320 IDirectDraw7 *ddraw;
321 IDirect3D7 *d3d7;
322 HRESULT hr;
323 BOOL hal_ok = FALSE;
324 const GUID *devtype = &IID_IDirect3DHALDevice;
326 if (!(ddraw = create_ddraw()))
327 return NULL;
329 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, coop_level);
330 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
332 memset(&surface_desc, 0, sizeof(surface_desc));
333 surface_desc.dwSize = sizeof(surface_desc);
334 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
335 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
336 surface_desc.dwWidth = 640;
337 surface_desc.dwHeight = 480;
339 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
340 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
342 if (coop_level & DDSCL_NORMAL)
344 IDirectDrawClipper *clipper;
346 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
347 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
348 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
349 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
350 hr = IDirectDrawSurface7_SetClipper(surface, clipper);
351 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\n", hr);
352 IDirectDrawClipper_Release(clipper);
355 hr = IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d7);
356 IDirectDraw7_Release(ddraw);
357 if (FAILED(hr))
359 IDirectDrawSurface7_Release(surface);
360 return NULL;
363 hr = IDirect3D7_EnumDevices(d3d7, enum_devtype_cb, &hal_ok);
364 ok(SUCCEEDED(hr), "Failed to enumerate devices, hr %#x.\n", hr);
365 if (hal_ok) devtype = &IID_IDirect3DTnLHalDevice;
367 memset(&z_fmt, 0, sizeof(z_fmt));
368 hr = IDirect3D7_EnumZBufferFormats(d3d7, devtype, enum_z_fmt, &z_fmt);
369 if (FAILED(hr) || !z_fmt.dwSize)
371 IDirect3D7_Release(d3d7);
372 IDirectDrawSurface7_Release(surface);
373 return NULL;
376 memset(&surface_desc, 0, sizeof(surface_desc));
377 surface_desc.dwSize = sizeof(surface_desc);
378 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
379 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
380 U4(surface_desc).ddpfPixelFormat = z_fmt;
381 surface_desc.dwWidth = 640;
382 surface_desc.dwHeight = 480;
383 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL);
384 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
385 if (FAILED(hr))
387 IDirect3D7_Release(d3d7);
388 IDirectDrawSurface7_Release(surface);
389 return NULL;
392 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
393 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
394 IDirectDrawSurface7_Release(ds);
395 if (FAILED(hr))
397 IDirect3D7_Release(d3d7);
398 IDirectDrawSurface7_Release(surface);
399 return NULL;
402 hr = IDirect3D7_CreateDevice(d3d7, devtype, surface, &device);
403 IDirect3D7_Release(d3d7);
404 IDirectDrawSurface7_Release(surface);
405 if (FAILED(hr))
406 return NULL;
408 return device;
411 struct message
413 UINT message;
414 BOOL check_wparam;
415 WPARAM expect_wparam;
418 static const struct message *expect_messages;
420 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
422 if (expect_messages && message == expect_messages->message)
424 if (expect_messages->check_wparam)
425 ok (wparam == expect_messages->expect_wparam,
426 "Got unexpected wparam %lx for message %x, expected %lx.\n",
427 wparam, message, expect_messages->expect_wparam);
429 ++expect_messages;
432 return DefWindowProcA(hwnd, message, wparam, lparam);
435 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
436 * interface. This prevents subsequent SetCooperativeLevel() calls on a
437 * different window from failing with DDERR_HWNDALREADYSET. */
438 static void fix_wndproc(HWND window, LONG_PTR proc)
440 IDirectDraw7 *ddraw;
441 HRESULT hr;
443 if (!(ddraw = create_ddraw()))
444 return;
446 SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
447 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
448 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
449 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
450 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
452 IDirectDraw7_Release(ddraw);
455 static void test_process_vertices(void)
457 IDirect3DVertexBuffer7 *src_vb, *dst_vb1, *dst_vb2;
458 D3DVERTEXBUFFERDESC vb_desc;
459 IDirect3DDevice7 *device;
460 struct vec4 *dst_data;
461 struct vec3 *dst_data2;
462 struct vec3 *src_data;
463 IDirect3D7 *d3d7;
464 D3DVIEWPORT7 vp;
465 HWND window;
466 HRESULT hr;
468 static D3DMATRIX world =
470 0.0f, 1.0f, 0.0f, 0.0f,
471 1.0f, 0.0f, 0.0f, 0.0f,
472 0.0f, 0.0f, 0.0f, 1.0f,
473 0.0f, 1.0f, 1.0f, 1.0f,
475 static D3DMATRIX view =
477 2.0f, 0.0f, 0.0f, 0.0f,
478 0.0f, -1.0f, 0.0f, 0.0f,
479 0.0f, 0.0f, 1.0f, 0.0f,
480 0.0f, 0.0f, 0.0f, 3.0f,
482 static D3DMATRIX proj =
484 1.0f, 0.0f, 0.0f, 1.0f,
485 0.0f, 1.0f, 1.0f, 0.0f,
486 0.0f, 1.0f, 1.0f, 0.0f,
487 1.0f, 0.0f, 0.0f, 1.0f,
490 window = create_window();
491 if (!(device = create_device(window, DDSCL_NORMAL)))
493 skip("Failed to create a 3D device, skipping test.\n");
494 DestroyWindow(window);
495 return;
498 hr = IDirect3DDevice7_GetDirect3D(device, &d3d7);
499 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
501 memset(&vb_desc, 0, sizeof(vb_desc));
502 vb_desc.dwSize = sizeof(vb_desc);
503 vb_desc.dwFVF = D3DFVF_XYZ;
504 vb_desc.dwNumVertices = 4;
505 hr = IDirect3D7_CreateVertexBuffer(d3d7, &vb_desc, &src_vb, 0);
506 ok(SUCCEEDED(hr), "Failed to create source vertex buffer, hr %#x.\n", hr);
508 hr = IDirect3DVertexBuffer7_Lock(src_vb, 0, (void **)&src_data, NULL);
509 ok(SUCCEEDED(hr), "Failed to lock source vertex buffer, hr %#x.\n", hr);
510 src_data[0].x = 0.0f;
511 src_data[0].y = 0.0f;
512 src_data[0].z = 0.0f;
513 src_data[1].x = 1.0f;
514 src_data[1].y = 1.0f;
515 src_data[1].z = 1.0f;
516 src_data[2].x = -1.0f;
517 src_data[2].y = -1.0f;
518 src_data[2].z = 0.5f;
519 src_data[3].x = 0.5f;
520 src_data[3].y = -0.5f;
521 src_data[3].z = 0.25f;
522 hr = IDirect3DVertexBuffer7_Unlock(src_vb);
523 ok(SUCCEEDED(hr), "Failed to unlock source vertex buffer, hr %#x.\n", hr);
525 memset(&vb_desc, 0, sizeof(vb_desc));
526 vb_desc.dwSize = sizeof(vb_desc);
527 vb_desc.dwFVF = D3DFVF_XYZRHW;
528 vb_desc.dwNumVertices = 4;
529 /* MSDN says that the last parameter must be 0 - check that. */
530 hr = IDirect3D7_CreateVertexBuffer(d3d7, &vb_desc, &dst_vb1, 4);
531 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
533 memset(&vb_desc, 0, sizeof(vb_desc));
534 vb_desc.dwSize = sizeof(vb_desc);
535 vb_desc.dwFVF = D3DFVF_XYZ;
536 vb_desc.dwNumVertices = 5;
537 /* MSDN says that the last parameter must be 0 - check that. */
538 hr = IDirect3D7_CreateVertexBuffer(d3d7, &vb_desc, &dst_vb2, 12345678);
539 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
541 memset(&vp, 0, sizeof(vp));
542 vp.dwX = 64;
543 vp.dwY = 64;
544 vp.dwWidth = 128;
545 vp.dwHeight = 128;
546 vp.dvMinZ = 0.0f;
547 vp.dvMaxZ = 1.0f;
548 hr = IDirect3DDevice7_SetViewport(device, &vp);
549 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
551 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
552 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
553 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb2, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
554 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
556 hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
557 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
558 ok(compare_vec4(&dst_data[0], +1.280e+2f, +1.280e+2f, +0.000e+0f, +1.000e+0f, 4096),
559 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
560 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
561 ok(compare_vec4(&dst_data[1], +1.920e+2f, +6.400e+1f, +1.000e+0f, +1.000e+0f, 4096),
562 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
563 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
564 ok(compare_vec4(&dst_data[2], +6.400e+1f, +1.920e+2f, +5.000e-1f, +1.000e+0f, 4096),
565 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
566 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
567 ok(compare_vec4(&dst_data[3], +1.600e+2f, +1.600e+2f, +2.500e-1f, +1.000e+0f, 4096),
568 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
569 dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
570 hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
571 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
573 hr = IDirect3DVertexBuffer7_Lock(dst_vb2, 0, (void **)&dst_data2, NULL);
574 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
575 /* Small thing without much practical meaning, but I stumbled upon it,
576 * so let's check for it: If the output vertex buffer has no RHW value,
577 * the RHW value of the last vertex is written into the next vertex. */
578 ok(compare_vec3(&dst_data2[4], +1.000e+0f, +0.000e+0f, +0.000e+0f, 4096),
579 "Got unexpected vertex 4 {%.8e, %.8e, %.8e}.\n",
580 dst_data2[4].x, dst_data2[4].y, dst_data2[4].z);
581 hr = IDirect3DVertexBuffer7_Unlock(dst_vb2);
582 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
584 /* Try a more complicated viewport, same vertices. */
585 memset(&vp, 0, sizeof(vp));
586 vp.dwX = 10;
587 vp.dwY = 5;
588 vp.dwWidth = 246;
589 vp.dwHeight = 130;
590 vp.dvMinZ = -2.0f;
591 vp.dvMaxZ = 4.0f;
592 hr = IDirect3DDevice7_SetViewport(device, &vp);
593 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
595 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
596 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
598 hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
599 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
600 ok(compare_vec4(&dst_data[0], +1.330e+2f, +7.000e+1f, -2.000e+0f, +1.000e+0f, 4096),
601 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
602 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
603 ok(compare_vec4(&dst_data[1], +2.560e+2f, +5.000e+0f, +4.000e+0f, +1.000e+0f, 4096),
604 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
605 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
606 ok(compare_vec4(&dst_data[2], +1.000e+1f, +1.350e+2f, +1.000e+0f, +1.000e+0f, 4096),
607 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
608 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
609 ok(compare_vec4(&dst_data[3], +1.945e+2f, +1.025e+2f, -5.000e-1f, +1.000e+0f, 4096),
610 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
611 dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
612 hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
613 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
615 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &world);
616 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
617 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &view);
618 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
619 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &proj);
620 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
622 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
623 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
625 hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
626 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
627 ok(compare_vec4(&dst_data[0], +2.560e+2f, +7.000e+1f, -2.000e+0f, +3.333e-1f, 4096),
628 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
629 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
630 ok(compare_vec4(&dst_data[1], +2.560e+2f, +7.813e+1f, -2.750e+0f, +1.250e-1f, 4096),
631 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
632 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
633 ok(compare_vec4(&dst_data[2], +2.560e+2f, +4.400e+1f, +4.000e-1f, +4.000e-1f, 4096),
634 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
635 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
636 ok(compare_vec4(&dst_data[3], +2.560e+2f, +8.182e+1f, -3.091e+0f, +3.636e-1f, 4096),
637 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
638 dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
639 hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
640 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
642 IDirect3DVertexBuffer7_Release(dst_vb2);
643 IDirect3DVertexBuffer7_Release(dst_vb1);
644 IDirect3DVertexBuffer7_Release(src_vb);
645 IDirect3D7_Release(d3d7);
646 IDirect3DDevice7_Release(device);
647 DestroyWindow(window);
650 static void test_coop_level_create_device_window(void)
652 HWND focus_window, device_window;
653 IDirectDraw7 *ddraw;
654 HRESULT hr;
656 focus_window = create_window();
657 ddraw = create_ddraw();
658 ok(!!ddraw, "Failed to create a ddraw object.\n");
660 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
661 ok(hr == DD_OK, "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);
665 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
666 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
667 ok(!device_window, "Unexpected device window found.\n");
668 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
669 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
670 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
671 ok(!device_window, "Unexpected device window found.\n");
672 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
673 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
674 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
675 ok(!device_window, "Unexpected device window found.\n");
676 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
677 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
678 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
679 ok(!device_window, "Unexpected device window found.\n");
681 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
682 if (broken(hr == DDERR_INVALIDPARAMS))
684 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
685 IDirectDraw7_Release(ddraw);
686 DestroyWindow(focus_window);
687 return;
690 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
691 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
692 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
693 ok(!device_window, "Unexpected device window found.\n");
694 hr = IDirectDraw7_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
695 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
696 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
697 ok(!device_window, "Unexpected device window found.\n");
699 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
700 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
701 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
702 ok(!device_window, "Unexpected device window found.\n");
703 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
704 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
705 ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
706 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
707 ok(!!device_window, "Device window not found.\n");
709 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
710 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
711 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
712 ok(!device_window, "Unexpected device window found.\n");
713 hr = IDirectDraw7_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
714 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
715 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
716 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
717 ok(!!device_window, "Device window not found.\n");
719 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
720 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
721 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
722 ok(!device_window, "Unexpected device window found.\n");
723 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
724 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
725 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
726 ok(!device_window, "Unexpected device window found.\n");
727 hr = IDirectDraw7_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
728 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
729 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
730 ok(!device_window, "Unexpected device window found.\n");
731 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
732 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
733 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
734 ok(!!device_window, "Device window not found.\n");
736 IDirectDraw7_Release(ddraw);
737 DestroyWindow(focus_window);
740 static void test_clipper_blt(void)
742 IDirectDrawSurface7 *src_surface, *dst_surface;
743 RECT client_rect, src_rect;
744 IDirectDrawClipper *clipper;
745 DDSURFACEDESC2 surface_desc;
746 unsigned int i, j, x, y;
747 IDirectDraw7 *ddraw;
748 RGNDATA *rgn_data;
749 D3DCOLOR color;
750 ULONG refcount;
751 HRGN r1, r2;
752 HWND window;
753 DDBLTFX fx;
754 HRESULT hr;
755 DWORD *ptr;
756 DWORD ret;
758 static const DWORD src_data[] =
760 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
761 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
762 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
764 static const D3DCOLOR expected1[] =
766 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
767 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
768 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
769 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
771 /* Nvidia on Windows seems to have an off-by-one error
772 * when processing source rectangles. Our left = 1 and
773 * right = 5 input reads from x = {1, 2, 3}. x = 4 is
774 * read as well, but only for the edge pixels on the
775 * output image. The bug happens on the y axis as well,
776 * but we only read one row there, and all source rows
777 * contain the same data. This bug is not dependent on
778 * the presence of a clipper. */
779 static const D3DCOLOR expected1_broken[] =
781 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
782 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
783 0x00000000, 0x00000000, 0x00ff0000, 0x00ff0000,
784 0x00000000, 0x00000000, 0x0000ff00, 0x00ff0000,
786 static const D3DCOLOR expected2[] =
788 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
789 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
790 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
791 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
794 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
795 10, 10, 640, 480, 0, 0, 0, 0);
796 ShowWindow(window, SW_SHOW);
797 ddraw = create_ddraw();
798 ok(!!ddraw, "Failed to create a ddraw object.\n");
800 ret = GetClientRect(window, &client_rect);
801 ok(ret, "Failed to get client rect.\n");
802 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
803 ok(ret, "Failed to map client rect.\n");
805 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
806 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
808 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
809 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
810 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
811 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
812 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
813 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
814 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
815 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
816 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
817 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
818 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
819 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
820 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
821 ok(rgn_data->rdh.nCount >= 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
822 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
823 "Got unexpected bounding rect %s, expected %s.\n",
824 wine_dbgstr_rect(&rgn_data->rdh.rcBound), wine_dbgstr_rect(&client_rect));
825 HeapFree(GetProcessHeap(), 0, rgn_data);
827 r1 = CreateRectRgn(0, 0, 320, 240);
828 ok(!!r1, "Failed to create region.\n");
829 r2 = CreateRectRgn(320, 240, 640, 480);
830 ok(!!r2, "Failed to create region.\n");
831 CombineRgn(r1, r1, r2, RGN_OR);
832 ret = GetRegionData(r1, 0, NULL);
833 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
834 ret = GetRegionData(r1, ret, rgn_data);
835 ok(!!ret, "Failed to get region data.\n");
837 DeleteObject(r2);
838 DeleteObject(r1);
840 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
841 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
842 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
843 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
844 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
845 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
847 HeapFree(GetProcessHeap(), 0, rgn_data);
849 memset(&surface_desc, 0, sizeof(surface_desc));
850 surface_desc.dwSize = sizeof(surface_desc);
851 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
852 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
853 surface_desc.dwWidth = 640;
854 surface_desc.dwHeight = 480;
855 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
856 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
857 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
858 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
859 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
860 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
862 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
863 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
864 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
865 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
867 memset(&fx, 0, sizeof(fx));
868 fx.dwSize = sizeof(fx);
869 hr = IDirectDrawSurface7_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
870 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
871 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
872 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
874 hr = IDirectDrawSurface7_Lock(src_surface, NULL, &surface_desc, 0, NULL);
875 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
876 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
877 ptr = surface_desc.lpSurface;
878 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
879 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
880 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
881 hr = IDirectDrawSurface7_Unlock(src_surface, NULL);
882 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
884 hr = IDirectDrawSurface7_SetClipper(dst_surface, clipper);
885 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
887 SetRect(&src_rect, 1, 1, 5, 2);
888 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
889 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
890 for (i = 0; i < 4; ++i)
892 for (j = 0; j < 4; ++j)
894 x = 80 * ((2 * j) + 1);
895 y = 60 * ((2 * i) + 1);
896 color = get_surface_color(dst_surface, x, y);
897 ok(compare_color(color, expected1[i * 4 + j], 1)
898 || broken(compare_color(color, expected1_broken[i * 4 + j], 1)),
899 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
903 U5(fx).dwFillColor = 0xff0000ff;
904 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
905 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
906 for (i = 0; i < 4; ++i)
908 for (j = 0; j < 4; ++j)
910 x = 80 * ((2 * j) + 1);
911 y = 60 * ((2 * i) + 1);
912 color = get_surface_color(dst_surface, x, y);
913 ok(compare_color(color, expected2[i * 4 + j], 1),
914 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
918 hr = IDirectDrawSurface7_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
919 ok(hr == DDERR_BLTFASTCANTCLIP, "Got unexpected hr %#x.\n", hr);
921 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
922 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
923 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
924 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
925 DestroyWindow(window);
926 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
927 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
928 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
929 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
930 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
931 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
932 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
933 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
934 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
935 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
936 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
937 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
939 IDirectDrawSurface7_Release(dst_surface);
940 IDirectDrawSurface7_Release(src_surface);
941 refcount = IDirectDrawClipper_Release(clipper);
942 ok(!refcount, "Clipper has %u references left.\n", refcount);
943 IDirectDraw7_Release(ddraw);
946 static void test_coop_level_d3d_state(void)
948 IDirectDrawSurface7 *rt, *surface;
949 IDirect3DDevice7 *device;
950 IDirectDraw7 *ddraw;
951 IDirect3D7 *d3d;
952 D3DCOLOR color;
953 DWORD value;
954 HWND window;
955 HRESULT hr;
957 window = create_window();
958 if (!(device = create_device(window, DDSCL_NORMAL)))
960 skip("Failed to create a 3D device, skipping test.\n");
961 DestroyWindow(window);
962 return;
965 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
966 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
967 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
968 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
969 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
970 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
971 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
972 ok(!value, "Got unexpected alpha blend enable state %#x.\n", value);
973 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
974 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
975 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
976 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
977 color = get_surface_color(rt, 320, 240);
978 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
980 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
981 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
982 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
983 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
984 IDirect3D7_Release(d3d);
985 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
986 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
987 hr = IDirectDrawSurface7_IsLost(rt);
988 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
989 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
990 ok(SUCCEEDED(hr), "Failed to restore surfaces, hr %#x.\n", hr);
991 IDirectDraw7_Release(ddraw);
993 hr = IDirect3DDevice7_GetRenderTarget(device, &surface);
994 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
995 ok(surface == rt, "Got unexpected surface %p.\n", surface);
996 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
997 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
998 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
999 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
1000 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1001 ok(!!value, "Got unexpected alpha blend enable state %#x.\n", value);
1002 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
1003 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1004 color = get_surface_color(rt, 320, 240);
1005 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1007 IDirectDrawSurface7_Release(surface);
1008 IDirectDrawSurface7_Release(rt);
1009 IDirect3DDevice7_Release(device);
1010 DestroyWindow(window);
1013 static void test_surface_interface_mismatch(void)
1015 IDirectDraw7 *ddraw = NULL;
1016 IDirect3D7 *d3d = NULL;
1017 IDirectDrawSurface7 *surface = NULL, *ds;
1018 IDirectDrawSurface3 *surface3 = NULL;
1019 IDirect3DDevice7 *device = NULL;
1020 DDSURFACEDESC2 surface_desc;
1021 DDPIXELFORMAT z_fmt;
1022 ULONG refcount;
1023 HRESULT hr;
1024 D3DCOLOR color;
1025 HWND window;
1027 window = create_window();
1028 ddraw = create_ddraw();
1029 ok(!!ddraw, "Failed to create a ddraw object.\n");
1030 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1031 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1033 memset(&surface_desc, 0, sizeof(surface_desc));
1034 surface_desc.dwSize = sizeof(surface_desc);
1035 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1036 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
1037 surface_desc.dwWidth = 640;
1038 surface_desc.dwHeight = 480;
1040 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1041 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1043 hr = IDirectDrawSurface7_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
1044 ok(SUCCEEDED(hr), "Failed to QI IDirectDrawSurface3, hr %#x.\n", hr);
1046 if (FAILED(IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d)))
1048 skip("D3D interface is not available, skipping test.\n");
1049 goto cleanup;
1052 memset(&z_fmt, 0, sizeof(z_fmt));
1053 hr = IDirect3D7_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
1054 if (FAILED(hr) || !z_fmt.dwSize)
1056 skip("No depth buffer formats available, skipping test.\n");
1057 goto cleanup;
1060 memset(&surface_desc, 0, sizeof(surface_desc));
1061 surface_desc.dwSize = sizeof(surface_desc);
1062 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
1063 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1064 U4(surface_desc).ddpfPixelFormat = z_fmt;
1065 surface_desc.dwWidth = 640;
1066 surface_desc.dwHeight = 480;
1067 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL);
1068 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
1069 if (FAILED(hr))
1070 goto cleanup;
1072 /* Using a different surface interface version still works */
1073 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
1074 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
1075 refcount = IDirectDrawSurface7_Release(ds);
1076 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
1077 if (FAILED(hr))
1078 goto cleanup;
1080 /* Here too */
1081 hr = IDirect3D7_CreateDevice(d3d, &IID_IDirect3DHALDevice, (IDirectDrawSurface7 *)surface3, &device);
1082 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
1083 if (FAILED(hr))
1084 goto cleanup;
1086 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
1087 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1088 color = get_surface_color(surface, 320, 240);
1089 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1091 cleanup:
1092 if (surface3) IDirectDrawSurface3_Release(surface3);
1093 if (surface) IDirectDrawSurface7_Release(surface);
1094 if (device) IDirect3DDevice7_Release(device);
1095 if (d3d) IDirect3D7_Release(d3d);
1096 if (ddraw) IDirectDraw7_Release(ddraw);
1097 DestroyWindow(window);
1100 static void test_coop_level_threaded(void)
1102 struct create_window_thread_param p;
1103 IDirectDraw7 *ddraw;
1104 HRESULT hr;
1106 ddraw = create_ddraw();
1107 ok(!!ddraw, "Failed to create a ddraw object.\n");
1108 create_window_thread(&p);
1110 hr = IDirectDraw7_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1111 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1113 IDirectDraw7_Release(ddraw);
1114 destroy_window_thread(&p);
1117 static void test_depth_blit(void)
1119 IDirect3DDevice7 *device;
1120 static struct
1122 float x, y, z;
1123 DWORD color;
1125 quad1[] =
1127 { -1.0, 1.0, 0.50f, 0xff00ff00},
1128 { 1.0, 1.0, 0.50f, 0xff00ff00},
1129 { -1.0, -1.0, 0.50f, 0xff00ff00},
1130 { 1.0, -1.0, 0.50f, 0xff00ff00},
1132 static const D3DCOLOR expected_colors[4][4] =
1134 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1135 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1136 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1137 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1139 DDSURFACEDESC2 ddsd_new, ddsd_existing;
1141 IDirectDrawSurface7 *ds1, *ds2, *ds3, *rt;
1142 RECT src_rect, dst_rect;
1143 unsigned int i, j;
1144 D3DCOLOR color;
1145 HRESULT hr;
1146 IDirect3D7 *d3d;
1147 IDirectDraw7 *ddraw;
1148 DDBLTFX fx;
1149 HWND window;
1151 window = create_window();
1152 if (!(device = create_device(window, DDSCL_NORMAL)))
1154 skip("Failed to create a 3D device, skipping test.\n");
1155 DestroyWindow(window);
1156 return;
1159 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1160 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
1161 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1162 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
1163 IDirect3D7_Release(d3d);
1165 ds1 = get_depth_stencil(device);
1167 memset(&ddsd_new, 0, sizeof(ddsd_new));
1168 ddsd_new.dwSize = sizeof(ddsd_new);
1169 memset(&ddsd_existing, 0, sizeof(ddsd_existing));
1170 ddsd_existing.dwSize = sizeof(ddsd_existing);
1171 hr = IDirectDrawSurface7_GetSurfaceDesc(ds1, &ddsd_existing);
1172 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
1173 ddsd_new.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1174 ddsd_new.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1175 ddsd_new.dwWidth = ddsd_existing.dwWidth;
1176 ddsd_new.dwHeight = ddsd_existing.dwHeight;
1177 U4(ddsd_new).ddpfPixelFormat = U4(ddsd_existing).ddpfPixelFormat;
1178 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd_new, &ds2, NULL);
1179 ok(SUCCEEDED(hr), "Failed to create a z buffer, hr %#x.\n", hr);
1180 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd_new, &ds3, NULL);
1181 ok(SUCCEEDED(hr), "Failed to create a z buffer, hr %#x.\n", hr);
1182 IDirectDraw7_Release(ddraw);
1184 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
1185 ok(SUCCEEDED(hr), "Failed to enable z testing, hr %#x.\n", hr);
1186 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
1187 ok(SUCCEEDED(hr), "Failed to set the z function, hr %#x.\n", hr);
1188 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
1189 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
1191 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
1192 ok(SUCCEEDED(hr), "Failed to clear the z buffer, hr %#x.\n", hr);
1194 /* Partial blit. */
1195 SetRect(&src_rect, 0, 0, 320, 240);
1196 SetRect(&dst_rect, 0, 0, 320, 240);
1197 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1198 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1199 /* Different locations. */
1200 SetRect(&src_rect, 0, 0, 320, 240);
1201 SetRect(&dst_rect, 320, 240, 640, 480);
1202 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1203 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1204 /* Stretched. */
1205 SetRect(&src_rect, 0, 0, 320, 240);
1206 SetRect(&dst_rect, 0, 0, 640, 480);
1207 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1208 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1209 /* Flipped. */
1210 SetRect(&src_rect, 0, 480, 640, 0);
1211 SetRect(&dst_rect, 0, 0, 640, 480);
1212 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1213 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1214 SetRect(&src_rect, 0, 0, 640, 480);
1215 SetRect(&dst_rect, 0, 480, 640, 0);
1216 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1217 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1218 /* Full, explicit. */
1219 SetRect(&src_rect, 0, 0, 640, 480);
1220 SetRect(&dst_rect, 0, 0, 640, 480);
1221 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1222 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1223 /* Depth -> color blit: Succeeds on Win7 + Radeon HD 5700, fails on WinXP + Radeon X1600 */
1225 /* Depth blit inside a BeginScene / EndScene pair */
1226 hr = IDirect3DDevice7_BeginScene(device);
1227 ok(SUCCEEDED(hr), "Failed to start scene, hr %#x.\n", hr);
1228 /* From the current depth stencil */
1229 hr = IDirectDrawSurface7_Blt(ds2, NULL, ds1, NULL, DDBLT_WAIT, NULL);
1230 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1231 /* To the current depth stencil */
1232 hr = IDirectDrawSurface7_Blt(ds1, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1233 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1234 /* Between unbound surfaces */
1235 hr = IDirectDrawSurface7_Blt(ds3, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1236 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1237 hr = IDirect3DDevice7_EndScene(device);
1238 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1240 /* Avoid changing the depth stencil, it doesn't work properly on Windows.
1241 * Instead use DDBLT_DEPTHFILL to clear the depth stencil. Unfortunately
1242 * drivers disagree on the meaning of dwFillDepth. Only 0 seems to produce
1243 * a reliable result(z = 0.0) */
1244 memset(&fx, 0, sizeof(fx));
1245 fx.dwSize = sizeof(fx);
1246 hr = IDirectDrawSurface7_Blt(ds2, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
1247 ok(SUCCEEDED(hr), "Failed to clear the source z buffer, hr %#x.\n", hr);
1249 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET, 0xffff0000, 1.0f, 0);
1250 ok(SUCCEEDED(hr), "Failed to clear the color and z buffers, hr %#x.\n", hr);
1251 SetRect(&dst_rect, 0, 0, 320, 240);
1252 hr = IDirectDrawSurface7_Blt(ds1, &dst_rect, ds2, NULL, DDBLT_WAIT, NULL);
1253 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1254 IDirectDrawSurface7_Release(ds3);
1255 IDirectDrawSurface7_Release(ds2);
1256 IDirectDrawSurface7_Release(ds1);
1258 hr = IDirect3DDevice7_BeginScene(device);
1259 ok(SUCCEEDED(hr), "Failed to start scene, hr %#x.\n", hr);
1260 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
1261 quad1, 4, 0);
1262 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1263 hr = IDirect3DDevice7_EndScene(device);
1264 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1266 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1267 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1268 for (i = 0; i < 4; ++i)
1270 for (j = 0; j < 4; ++j)
1272 unsigned int x = 80 * ((2 * j) + 1);
1273 unsigned int y = 60 * ((2 * i) + 1);
1274 color = get_surface_color(rt, x, y);
1275 ok(compare_color(color, expected_colors[i][j], 1),
1276 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
1280 IDirectDrawSurface7_Release(rt);
1281 IDirect3DDevice7_Release(device);
1282 DestroyWindow(window);
1285 static void test_texture_load_ckey(void)
1287 HWND window;
1288 IDirect3DDevice7 *device;
1289 IDirectDraw7 *ddraw;
1290 IDirectDrawSurface7 *src;
1291 IDirectDrawSurface7 *dst;
1292 DDSURFACEDESC2 ddsd;
1293 HRESULT hr;
1294 DDCOLORKEY ckey;
1295 IDirect3D7 *d3d;
1297 window = create_window();
1298 if (!(device = create_device(window, DDSCL_NORMAL)))
1300 skip("Failed to create a 3D device, skipping test.\n");
1301 DestroyWindow(window);
1302 return;
1305 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1306 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
1307 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1308 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
1309 IDirect3D7_Release(d3d);
1311 memset(&ddsd, 0, sizeof(ddsd));
1312 ddsd.dwSize = sizeof(ddsd);
1313 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
1314 ddsd.dwHeight = 128;
1315 ddsd.dwWidth = 128;
1316 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
1317 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &src, NULL);
1318 ok(SUCCEEDED(hr), "Failed to create source texture, hr %#x.\n", hr);
1319 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1320 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &dst, NULL);
1321 ok(SUCCEEDED(hr), "Failed to create destination texture, hr %#x.\n", hr);
1323 /* No surface has a color key */
1324 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1325 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1326 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0xdeadbeef;
1327 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1328 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1329 ok(ckey.dwColorSpaceLowValue == 0xdeadbeef, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1330 ok(ckey.dwColorSpaceHighValue == 0xdeadbeef, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1332 /* Source surface has a color key */
1333 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
1334 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
1335 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1336 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1337 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1338 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1339 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1340 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1341 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1343 /* Both surfaces have a color key: Dest ckey is overwritten */
1344 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x000000ff;
1345 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1346 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1347 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1348 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1349 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1350 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1351 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1352 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1354 /* Only the destination has a color key: It is deleted. This behavior differs from
1355 * IDirect3DTexture(2)::Load */
1356 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, NULL);
1357 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1358 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
1359 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1360 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1361 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1362 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1363 todo_wine ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1365 IDirectDrawSurface7_Release(dst);
1366 IDirectDrawSurface7_Release(src);
1367 IDirectDraw7_Release(ddraw);
1368 IDirect3DDevice7_Release(device);
1369 DestroyWindow(window);
1372 static void test_zenable(void)
1374 static struct
1376 struct vec4 position;
1377 D3DCOLOR diffuse;
1379 tquad[] =
1381 {{ 0.0f, 480.0f, -0.5f, 1.0f}, 0xff00ff00},
1382 {{ 0.0f, 0.0f, -0.5f, 1.0f}, 0xff00ff00},
1383 {{640.0f, 480.0f, 1.5f, 1.0f}, 0xff00ff00},
1384 {{640.0f, 0.0f, 1.5f, 1.0f}, 0xff00ff00},
1386 IDirect3DDevice7 *device;
1387 IDirectDrawSurface7 *rt;
1388 D3DCOLOR color;
1389 HWND window;
1390 HRESULT hr;
1391 UINT x, y;
1392 UINT i, j;
1394 window = create_window();
1395 if (!(device = create_device(window, DDSCL_NORMAL)))
1397 skip("Failed to create a 3D device, skipping test.\n");
1398 DestroyWindow(window);
1399 return;
1402 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1403 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
1405 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 0.0f, 0);
1406 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1407 hr = IDirect3DDevice7_BeginScene(device);
1408 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1409 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_DIFFUSE, tquad, 4, 0);
1410 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1411 hr = IDirect3DDevice7_EndScene(device);
1412 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1414 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1415 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1416 for (i = 0; i < 4; ++i)
1418 for (j = 0; j < 4; ++j)
1420 x = 80 * ((2 * j) + 1);
1421 y = 60 * ((2 * i) + 1);
1422 color = get_surface_color(rt, x, y);
1423 ok(compare_color(color, 0x0000ff00, 1),
1424 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1427 IDirectDrawSurface7_Release(rt);
1429 IDirect3DDevice7_Release(device);
1430 DestroyWindow(window);
1433 static void test_ck_rgba(void)
1435 static struct
1437 struct vec4 position;
1438 struct vec2 texcoord;
1440 tquad[] =
1442 {{ 0.0f, 480.0f, 0.25f, 1.0f}, {0.0f, 0.0f}},
1443 {{ 0.0f, 0.0f, 0.25f, 1.0f}, {0.0f, 1.0f}},
1444 {{640.0f, 480.0f, 0.25f, 1.0f}, {1.0f, 0.0f}},
1445 {{640.0f, 0.0f, 0.25f, 1.0f}, {1.0f, 1.0f}},
1446 {{ 0.0f, 480.0f, 0.75f, 1.0f}, {0.0f, 0.0f}},
1447 {{ 0.0f, 0.0f, 0.75f, 1.0f}, {0.0f, 1.0f}},
1448 {{640.0f, 480.0f, 0.75f, 1.0f}, {1.0f, 0.0f}},
1449 {{640.0f, 0.0f, 0.75f, 1.0f}, {1.0f, 1.0f}},
1451 static const struct
1453 D3DCOLOR fill_color;
1454 BOOL color_key;
1455 BOOL blend;
1456 D3DCOLOR result1, result1_broken;
1457 D3DCOLOR result2, result2_broken;
1459 tests[] =
1461 /* r200 on Windows doesn't check the alpha component when applying the color
1462 * key, so the key matches on every texel. */
1463 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1464 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1465 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1466 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1467 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00ff0000, 0x00807f00, 0x000000ff},
1468 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x00ff0000, 0x0000ff00, 0x000000ff},
1469 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00, 0x00807f00, 0x00807f00},
1470 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1473 IDirectDrawSurface7 *texture;
1474 DDSURFACEDESC2 surface_desc;
1475 IDirect3DDevice7 *device;
1476 IDirectDrawSurface7 *rt;
1477 IDirectDraw7 *ddraw;
1478 IDirect3D7 *d3d;
1479 D3DCOLOR color;
1480 HWND window;
1481 DDBLTFX fx;
1482 HRESULT hr;
1483 UINT i;
1485 window = create_window();
1486 if (!(device = create_device(window, DDSCL_NORMAL)))
1488 skip("Failed to create a 3D device, skipping test.\n");
1489 DestroyWindow(window);
1490 return;
1493 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1494 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1495 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1496 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1497 IDirect3D7_Release(d3d);
1499 memset(&surface_desc, 0, sizeof(surface_desc));
1500 surface_desc.dwSize = sizeof(surface_desc);
1501 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1502 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1503 surface_desc.dwWidth = 256;
1504 surface_desc.dwHeight = 256;
1505 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1506 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1507 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1508 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1509 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1510 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1511 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1512 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1513 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1514 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
1515 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1517 hr = IDirect3DDevice7_SetTexture(device, 0, texture);
1518 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1519 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1520 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1521 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1522 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1524 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1525 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1527 for (i = 0; i < ARRAY_SIZE(tests); ++i)
1529 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1530 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1531 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1532 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1534 memset(&fx, 0, sizeof(fx));
1535 fx.dwSize = sizeof(fx);
1536 U5(fx).dwFillColor = tests[i].fill_color;
1537 hr = IDirectDrawSurface7_Blt(texture, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1538 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1540 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 1.0f, 0);
1541 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1542 hr = IDirect3DDevice7_BeginScene(device);
1543 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1544 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1545 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1546 hr = IDirect3DDevice7_EndScene(device);
1547 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1549 color = get_surface_color(rt, 320, 240);
1550 ok(compare_color(color, tests[i].result1, 1) || compare_color(color, tests[i].result1_broken, 1),
1551 "Expected color 0x%08x for test %u, got 0x%08x.\n",
1552 tests[i].result1, i, color);
1554 U5(fx).dwFillColor = 0xff0000ff;
1555 hr = IDirectDrawSurface7_Blt(texture, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1556 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1558 hr = IDirect3DDevice7_BeginScene(device);
1559 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1560 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[4], 4, 0);
1561 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1562 hr = IDirect3DDevice7_EndScene(device);
1563 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1565 /* This tests that fragments that are masked out by the color key are
1566 * discarded, instead of just fully transparent. */
1567 color = get_surface_color(rt, 320, 240);
1568 ok(compare_color(color, tests[i].result2, 1) || compare_color(color, tests[i].result2_broken, 1),
1569 "Expected color 0x%08x for test %u, got 0x%08x.\n",
1570 tests[i].result2, i, color);
1573 IDirectDrawSurface7_Release(rt);
1574 IDirectDrawSurface7_Release(texture);
1575 IDirectDraw7_Release(ddraw);
1576 IDirect3DDevice7_Release(device);
1577 DestroyWindow(window);
1580 static void test_ck_default(void)
1582 static struct
1584 struct vec4 position;
1585 struct vec2 texcoord;
1587 tquad[] =
1589 {{ 0.0f, 480.0f, 0.0f, 1.0f}, {0.0f, 0.0f}},
1590 {{ 0.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 1.0f}},
1591 {{640.0f, 480.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
1592 {{640.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
1594 IDirectDrawSurface7 *surface, *rt;
1595 DDSURFACEDESC2 surface_desc;
1596 IDirect3DDevice7 *device;
1597 IDirectDraw7 *ddraw;
1598 IDirect3D7 *d3d;
1599 D3DCOLOR color;
1600 DWORD value;
1601 HWND window;
1602 DDBLTFX fx;
1603 HRESULT hr;
1605 window = create_window();
1606 if (!(device = create_device(window, DDSCL_NORMAL)))
1608 skip("Failed to create a 3D device, skipping test.\n");
1609 DestroyWindow(window);
1610 return;
1613 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1614 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1615 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1616 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1617 IDirect3D7_Release(d3d);
1619 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1620 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1622 memset(&surface_desc, 0, sizeof(surface_desc));
1623 surface_desc.dwSize = sizeof(surface_desc);
1624 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1625 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1626 surface_desc.dwWidth = 256;
1627 surface_desc.dwHeight = 256;
1628 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1629 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
1630 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1631 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1632 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1633 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1634 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
1635 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
1636 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1637 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1638 hr = IDirect3DDevice7_SetTexture(device, 0, surface);
1639 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1641 memset(&fx, 0, sizeof(fx));
1642 fx.dwSize = sizeof(fx);
1643 U5(fx).dwFillColor = 0x000000ff;
1644 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1645 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
1647 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
1648 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1649 hr = IDirect3DDevice7_BeginScene(device);
1650 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1651 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1652 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1653 ok(!value, "Got unexpected color keying state %#x.\n", value);
1654 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1655 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1656 hr = IDirect3DDevice7_EndScene(device);
1657 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1658 color = get_surface_color(rt, 320, 240);
1659 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1661 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
1662 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1663 hr = IDirect3DDevice7_BeginScene(device);
1664 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1665 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
1666 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1667 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1668 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1669 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1670 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1671 ok(!!value, "Got unexpected color keying state %#x.\n", value);
1672 hr = IDirect3DDevice7_EndScene(device);
1673 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1674 color = get_surface_color(rt, 320, 240);
1675 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1677 IDirectDrawSurface7_Release(surface);
1678 IDirectDrawSurface7_Release(rt);
1679 IDirect3DDevice7_Release(device);
1680 IDirectDraw7_Release(ddraw);
1681 DestroyWindow(window);
1684 static void test_ck_complex(void)
1686 IDirectDrawSurface7 *surface, *mipmap, *tmp;
1687 D3DDEVICEDESC7 device_desc;
1688 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
1689 DDSURFACEDESC2 surface_desc;
1690 IDirect3DDevice7 *device;
1691 DDCOLORKEY color_key;
1692 IDirectDraw7 *ddraw;
1693 IDirect3D7 *d3d;
1694 unsigned int i;
1695 ULONG refcount;
1696 HWND window;
1697 HRESULT hr;
1699 window = create_window();
1700 if (!(device = create_device(window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
1702 skip("Failed to create a 3D device, skipping test.\n");
1703 DestroyWindow(window);
1704 return;
1706 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
1707 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
1708 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1709 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1710 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1711 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1712 IDirect3D7_Release(d3d);
1714 memset(&surface_desc, 0, sizeof(surface_desc));
1715 surface_desc.dwSize = sizeof(surface_desc);
1716 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1717 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1718 surface_desc.dwWidth = 128;
1719 surface_desc.dwHeight = 128;
1720 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1721 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1723 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1724 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1725 color_key.dwColorSpaceLowValue = 0x0000ff00;
1726 color_key.dwColorSpaceHighValue = 0x0000ff00;
1727 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1728 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1729 memset(&color_key, 0, sizeof(color_key));
1730 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1731 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1732 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1733 color_key.dwColorSpaceLowValue);
1734 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1735 color_key.dwColorSpaceHighValue);
1737 mipmap = surface;
1738 IDirectDrawSurface_AddRef(mipmap);
1739 for (i = 0; i < 7; ++i)
1741 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
1742 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
1743 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1744 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1746 color_key.dwColorSpaceLowValue = 0x000000ff;
1747 color_key.dwColorSpaceHighValue = 0x000000ff;
1748 hr = IDirectDrawSurface7_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1749 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x, i %u.\n", hr, i);
1751 IDirectDrawSurface_Release(mipmap);
1752 mipmap = tmp;
1755 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
1756 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
1757 IDirectDrawSurface_Release(mipmap);
1758 refcount = IDirectDrawSurface7_Release(surface);
1759 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1761 memset(&surface_desc, 0, sizeof(surface_desc));
1762 surface_desc.dwSize = sizeof(surface_desc);
1763 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
1764 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
1765 U5(surface_desc).dwBackBufferCount = 1;
1766 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1767 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1769 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1770 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1771 color_key.dwColorSpaceLowValue = 0x0000ff00;
1772 color_key.dwColorSpaceHighValue = 0x0000ff00;
1773 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1774 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1775 memset(&color_key, 0, sizeof(color_key));
1776 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1777 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1778 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1779 color_key.dwColorSpaceLowValue);
1780 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1781 color_key.dwColorSpaceHighValue);
1783 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &tmp);
1784 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
1786 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1787 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1788 color_key.dwColorSpaceLowValue = 0x0000ff00;
1789 color_key.dwColorSpaceHighValue = 0x0000ff00;
1790 hr = IDirectDrawSurface7_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1791 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1792 memset(&color_key, 0, sizeof(color_key));
1793 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1794 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1795 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1796 color_key.dwColorSpaceLowValue);
1797 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1798 color_key.dwColorSpaceHighValue);
1800 IDirectDrawSurface_Release(tmp);
1802 refcount = IDirectDrawSurface7_Release(surface);
1803 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1805 if (!(device_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP))
1807 skip("Device does not support cubemaps.\n");
1808 goto cleanup;
1810 memset(&surface_desc, 0, sizeof(surface_desc));
1811 surface_desc.dwSize = sizeof(surface_desc);
1812 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1813 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1814 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
1815 surface_desc.dwWidth = 128;
1816 surface_desc.dwHeight = 128;
1817 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1818 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1820 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1821 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1822 color_key.dwColorSpaceLowValue = 0x0000ff00;
1823 color_key.dwColorSpaceHighValue = 0x0000ff00;
1824 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1825 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1827 caps.dwCaps2 = DDSCAPS2_CUBEMAP_NEGATIVEZ;
1828 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
1829 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
1831 hr = IDirectDrawSurface7_GetColorKey(mipmap, DDCKEY_SRCBLT, &color_key);
1832 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1833 color_key.dwColorSpaceLowValue = 0x000000ff;
1834 color_key.dwColorSpaceHighValue = 0x000000ff;
1835 hr = IDirectDrawSurface7_SetColorKey(mipmap, DDCKEY_SRCBLT, &color_key);
1836 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1838 color_key.dwColorSpaceLowValue = 0;
1839 color_key.dwColorSpaceHighValue = 0;
1840 hr = IDirectDrawSurface7_GetColorKey(mipmap, DDCKEY_SRCBLT, &color_key);
1841 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1842 ok(color_key.dwColorSpaceLowValue == 0x000000ff, "Got unexpected value 0x%08x.\n",
1843 color_key.dwColorSpaceLowValue);
1844 ok(color_key.dwColorSpaceHighValue == 0x000000ff, "Got unexpected value 0x%08x.\n",
1845 color_key.dwColorSpaceHighValue);
1847 IDirectDrawSurface_AddRef(mipmap);
1848 for (i = 0; i < 7; ++i)
1850 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
1851 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
1852 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1853 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1855 color_key.dwColorSpaceLowValue = 0x000000ff;
1856 color_key.dwColorSpaceHighValue = 0x000000ff;
1857 hr = IDirectDrawSurface7_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1858 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x, i %u.\n", hr, i);
1860 IDirectDrawSurface_Release(mipmap);
1861 mipmap = tmp;
1864 IDirectDrawSurface7_Release(mipmap);
1866 refcount = IDirectDrawSurface7_Release(surface);
1867 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1869 cleanup:
1870 IDirectDraw7_Release(ddraw);
1871 refcount = IDirect3DDevice7_Release(device);
1872 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1873 DestroyWindow(window);
1876 struct qi_test
1878 REFIID iid;
1879 REFIID refcount_iid;
1880 HRESULT hr;
1883 static void test_qi(const char *test_name, IUnknown *base_iface,
1884 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
1886 ULONG refcount, expected_refcount;
1887 IUnknown *iface1, *iface2;
1888 HRESULT hr;
1889 UINT i, j;
1891 for (i = 0; i < entry_count; ++i)
1893 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
1894 ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
1895 if (SUCCEEDED(hr))
1897 for (j = 0; j < entry_count; ++j)
1899 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
1900 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
1901 if (SUCCEEDED(hr))
1903 expected_refcount = 0;
1904 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
1905 ++expected_refcount;
1906 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
1907 ++expected_refcount;
1908 refcount = IUnknown_Release(iface2);
1909 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
1910 refcount, test_name, i, j, expected_refcount);
1914 expected_refcount = 0;
1915 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
1916 ++expected_refcount;
1917 refcount = IUnknown_Release(iface1);
1918 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
1919 refcount, test_name, i, expected_refcount);
1924 static void test_surface_qi(void)
1926 static const struct qi_test tests[] =
1928 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
1929 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
1930 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
1931 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1932 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
1933 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
1934 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
1935 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
1936 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
1937 {&IID_IDirect3DDevice7, NULL, E_NOINTERFACE},
1938 {&IID_IDirect3DDevice3, NULL, E_NOINTERFACE},
1939 {&IID_IDirect3DDevice2, NULL, E_NOINTERFACE},
1940 {&IID_IDirect3DDevice, NULL, E_NOINTERFACE},
1941 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
1942 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
1943 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
1944 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
1945 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
1946 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
1947 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
1948 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
1949 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
1950 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
1951 {&IID_IDirect3D, NULL, E_NOINTERFACE},
1952 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
1953 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
1954 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
1955 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
1956 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
1957 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
1958 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
1959 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
1960 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
1961 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
1962 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
1963 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
1964 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
1965 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
1966 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
1967 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
1968 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
1969 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
1970 {NULL, NULL, E_INVALIDARG },
1973 IDirectDrawSurface7 *surface;
1974 DDSURFACEDESC2 surface_desc;
1975 IDirect3DDevice7 *device;
1976 IDirectDraw7 *ddraw;
1977 HWND window;
1978 HRESULT hr;
1980 window = create_window();
1981 /* Try to create a D3D device to see if the ddraw implementation supports
1982 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
1983 * doesn't support e.g. the IDirect3DTexture interfaces. */
1984 if (!(device = create_device(window, DDSCL_NORMAL)))
1986 skip("Failed to create a 3D device, skipping test.\n");
1987 DestroyWindow(window);
1988 return;
1990 IDirect3DDevice_Release(device);
1991 ddraw = create_ddraw();
1992 ok(!!ddraw, "Failed to create a ddraw object.\n");
1993 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1994 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1996 memset(&surface_desc, 0, sizeof(surface_desc));
1997 surface_desc.dwSize = sizeof(surface_desc);
1998 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1999 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2000 surface_desc.dwWidth = 512;
2001 surface_desc.dwHeight = 512;
2002 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, (IDirectDrawSurface7 **)0xdeadbeef, NULL);
2003 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
2004 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2005 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
2007 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface7, tests, ARRAY_SIZE(tests));
2009 IDirectDrawSurface7_Release(surface);
2010 IDirectDraw7_Release(ddraw);
2011 DestroyWindow(window);
2014 static void test_device_qi(void)
2016 static const struct qi_test tests[] =
2018 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
2019 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
2020 {&IID_IDirectDrawGammaControl, NULL, E_NOINTERFACE},
2021 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2022 {&IID_IDirectDrawSurface7, NULL, E_NOINTERFACE},
2023 {&IID_IDirectDrawSurface4, NULL, E_NOINTERFACE},
2024 {&IID_IDirectDrawSurface3, NULL, E_NOINTERFACE},
2025 {&IID_IDirectDrawSurface2, NULL, E_NOINTERFACE},
2026 {&IID_IDirectDrawSurface, NULL, E_NOINTERFACE},
2027 {&IID_IDirect3DDevice7, &IID_IDirect3DDevice7, S_OK },
2028 {&IID_IDirect3DDevice3, NULL, E_NOINTERFACE},
2029 {&IID_IDirect3DDevice2, NULL, E_NOINTERFACE},
2030 {&IID_IDirect3DDevice, NULL, E_NOINTERFACE},
2031 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
2032 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
2033 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
2034 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
2035 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
2036 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
2037 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
2038 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
2039 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
2040 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
2041 {&IID_IDirect3D, NULL, E_NOINTERFACE},
2042 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
2043 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
2044 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
2045 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
2046 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
2047 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
2048 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
2049 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
2050 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
2051 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
2052 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
2053 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
2054 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
2055 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
2056 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
2057 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
2058 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
2059 {&IID_IUnknown, &IID_IDirect3DDevice7, S_OK },
2062 IDirect3DDevice7 *device;
2063 HWND window;
2065 window = create_window();
2066 if (!(device = create_device(window, DDSCL_NORMAL)))
2068 skip("Failed to create a 3D device, skipping test.\n");
2069 DestroyWindow(window);
2070 return;
2073 test_qi("device_qi", (IUnknown *)device, &IID_IDirect3DDevice7, tests, ARRAY_SIZE(tests));
2075 IDirect3DDevice7_Release(device);
2076 DestroyWindow(window);
2079 static void test_wndproc(void)
2081 LONG_PTR proc, ddraw_proc;
2082 IDirectDraw7 *ddraw;
2083 WNDCLASSA wc = {0};
2084 HWND window;
2085 HRESULT hr;
2086 ULONG ref;
2088 static struct message messages[] =
2090 {WM_WINDOWPOSCHANGING, FALSE, 0},
2091 {WM_MOVE, FALSE, 0},
2092 {WM_SIZE, FALSE, 0},
2093 {WM_WINDOWPOSCHANGING, FALSE, 0},
2094 {WM_ACTIVATE, FALSE, 0},
2095 {WM_SETFOCUS, FALSE, 0},
2096 {0, FALSE, 0},
2099 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
2100 ddraw = create_ddraw();
2101 ok(!!ddraw, "Failed to create a ddraw object.\n");
2103 wc.lpfnWndProc = test_proc;
2104 wc.lpszClassName = "ddraw_test_wndproc_wc";
2105 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2107 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
2108 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
2110 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2111 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2112 (LONG_PTR)test_proc, proc);
2113 expect_messages = messages;
2114 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2115 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2116 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2117 expect_messages = NULL;
2118 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2119 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2120 (LONG_PTR)test_proc, proc);
2121 ref = IDirectDraw7_Release(ddraw);
2122 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2123 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2124 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2125 (LONG_PTR)test_proc, proc);
2127 /* DDSCL_NORMAL doesn't. */
2128 ddraw = create_ddraw();
2129 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2130 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2131 (LONG_PTR)test_proc, proc);
2132 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2133 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2134 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2135 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2136 (LONG_PTR)test_proc, proc);
2137 ref = IDirectDraw7_Release(ddraw);
2138 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2139 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2140 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2141 (LONG_PTR)test_proc, proc);
2143 /* The original window proc is only restored by ddraw if the current
2144 * window proc matches the one ddraw set. This also affects switching
2145 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
2146 ddraw = create_ddraw();
2147 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2148 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2149 (LONG_PTR)test_proc, proc);
2150 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2151 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2152 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2153 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2154 (LONG_PTR)test_proc, proc);
2155 ddraw_proc = proc;
2156 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2157 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2158 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2159 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2160 (LONG_PTR)test_proc, proc);
2161 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2162 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2163 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2164 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2165 (LONG_PTR)test_proc, proc);
2166 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2167 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2168 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2169 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2170 (LONG_PTR)DefWindowProcA, proc);
2171 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2172 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2173 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)ddraw_proc);
2174 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2175 (LONG_PTR)DefWindowProcA, proc);
2176 ref = IDirectDraw7_Release(ddraw);
2177 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2178 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2179 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2180 (LONG_PTR)test_proc, proc);
2182 ddraw = create_ddraw();
2183 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2184 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2185 (LONG_PTR)test_proc, proc);
2186 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2187 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2188 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2189 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2190 (LONG_PTR)test_proc, proc);
2191 ref = IDirectDraw7_Release(ddraw);
2192 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2193 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2194 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2195 (LONG_PTR)DefWindowProcA, proc);
2197 fix_wndproc(window, (LONG_PTR)test_proc);
2198 expect_messages = NULL;
2199 DestroyWindow(window);
2200 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2203 static void test_window_style(void)
2205 LONG style, exstyle, tmp, expected_style;
2206 RECT fullscreen_rect, r;
2207 IDirectDraw7 *ddraw;
2208 HWND window;
2209 HRESULT hr;
2210 ULONG ref;
2211 BOOL ret;
2213 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2214 0, 0, 100, 100, 0, 0, 0, 0);
2215 ddraw = create_ddraw();
2216 ok(!!ddraw, "Failed to create a ddraw object.\n");
2218 style = GetWindowLongA(window, GWL_STYLE);
2219 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
2220 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2222 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2223 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2225 tmp = GetWindowLongA(window, GWL_STYLE);
2226 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2227 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2228 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2230 GetWindowRect(window, &r);
2231 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
2232 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
2233 GetClientRect(window, &r);
2234 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2236 ret = SetForegroundWindow(GetDesktopWindow());
2237 ok(ret, "Failed to set foreground window.\n");
2239 tmp = GetWindowLongA(window, GWL_STYLE);
2240 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2241 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2242 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2244 ret = SetForegroundWindow(window);
2245 ok(ret, "Failed to set foreground window.\n");
2246 /* Windows 7 (but not Vista and XP) shows the window when it receives focus. Hide it again,
2247 * the next tests expect this. */
2248 ShowWindow(window, SW_HIDE);
2250 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2251 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2253 tmp = GetWindowLongA(window, GWL_STYLE);
2254 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2255 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2256 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2258 ShowWindow(window, SW_SHOW);
2259 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2260 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2262 tmp = GetWindowLongA(window, GWL_STYLE);
2263 expected_style = style | WS_VISIBLE;
2264 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2265 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2266 expected_style = exstyle | WS_EX_TOPMOST;
2267 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2269 ret = SetForegroundWindow(GetDesktopWindow());
2270 ok(ret, "Failed to set foreground window.\n");
2271 tmp = GetWindowLongA(window, GWL_STYLE);
2272 expected_style = style | WS_VISIBLE | WS_MINIMIZE;
2273 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2274 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2275 expected_style = exstyle | WS_EX_TOPMOST;
2276 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2278 ref = IDirectDraw7_Release(ddraw);
2279 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2281 DestroyWindow(window);
2284 static void test_redundant_mode_set(void)
2286 DDSURFACEDESC2 surface_desc = {0};
2287 IDirectDraw7 *ddraw;
2288 RECT q, r, s;
2289 HWND window;
2290 HRESULT hr;
2291 ULONG ref;
2293 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2294 0, 0, 100, 100, 0, 0, 0, 0);
2295 ddraw = create_ddraw();
2296 ok(!!ddraw, "Failed to create a ddraw object.\n");
2297 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2298 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2300 surface_desc.dwSize = sizeof(surface_desc);
2301 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
2302 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
2304 hr = IDirectDraw7_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2305 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
2306 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2308 GetWindowRect(window, &q);
2309 r = q;
2310 r.right /= 2;
2311 r.bottom /= 2;
2312 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
2313 GetWindowRect(window, &s);
2314 ok(EqualRect(&r, &s), "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2316 hr = IDirectDraw7_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2317 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
2318 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2320 GetWindowRect(window, &s);
2321 ok(EqualRect(&r, &s) || broken(EqualRect(&q, &s) /* Windows 10 */),
2322 "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2324 ref = IDirectDraw7_Release(ddraw);
2325 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2327 DestroyWindow(window);
2330 static SIZE screen_size, screen_size2;
2332 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2334 if (message == WM_SIZE)
2336 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2337 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2340 return test_proc(hwnd, message, wparam, lparam);
2343 static LRESULT CALLBACK mode_set_proc2(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2345 if (message == WM_SIZE)
2347 screen_size2.cx = GetSystemMetrics(SM_CXSCREEN);
2348 screen_size2.cy = GetSystemMetrics(SM_CYSCREEN);
2351 return test_proc(hwnd, message, wparam, lparam);
2354 struct test_coop_level_mode_set_enum_param
2356 DWORD ddraw_width, ddraw_height, user32_width, user32_height;
2359 static HRESULT CALLBACK test_coop_level_mode_set_enum_cb(DDSURFACEDESC2 *surface_desc, void *context)
2361 struct test_coop_level_mode_set_enum_param *param = context;
2363 if (U1(U4(*surface_desc).ddpfPixelFormat).dwRGBBitCount != registry_mode.dmBitsPerPel)
2364 return DDENUMRET_OK;
2365 if (surface_desc->dwWidth == registry_mode.dmPelsWidth
2366 && surface_desc->dwHeight == registry_mode.dmPelsHeight)
2367 return DDENUMRET_OK;
2369 if (!param->ddraw_width)
2371 param->ddraw_width = surface_desc->dwWidth;
2372 param->ddraw_height = surface_desc->dwHeight;
2373 return DDENUMRET_OK;
2375 if (surface_desc->dwWidth == param->ddraw_width && surface_desc->dwHeight == param->ddraw_height)
2376 return DDENUMRET_OK;
2378 param->user32_width = surface_desc->dwWidth;
2379 param->user32_height = surface_desc->dwHeight;
2380 return DDENUMRET_CANCEL;
2383 static void test_coop_level_mode_set(void)
2385 IDirectDrawSurface7 *primary;
2386 RECT registry_rect, ddraw_rect, user32_rect, r;
2387 IDirectDraw7 *ddraw;
2388 DDSURFACEDESC2 ddsd;
2389 WNDCLASSA wc = {0};
2390 HWND window, window2;
2391 HRESULT hr;
2392 ULONG ref;
2393 MSG msg;
2394 struct test_coop_level_mode_set_enum_param param;
2395 DEVMODEW devmode;
2396 BOOL ret;
2397 LONG change_ret;
2399 static const struct message exclusive_messages[] =
2401 {WM_WINDOWPOSCHANGING, FALSE, 0},
2402 {WM_WINDOWPOSCHANGED, FALSE, 0},
2403 {WM_SIZE, FALSE, 0},
2404 {WM_DISPLAYCHANGE, FALSE, 0},
2405 {0, FALSE, 0},
2407 static const struct message exclusive_focus_loss_messages[] =
2409 {WM_ACTIVATE, TRUE, WA_INACTIVE},
2410 {WM_DISPLAYCHANGE, FALSE, 0},
2411 {WM_WINDOWPOSCHANGING, FALSE, 0},
2412 /* Like d3d8 and d3d9 ddraw seems to use SW_SHOWMINIMIZED instead of
2413 * SW_MINIMIZED, causing a recursive window activation that does not
2414 * produce the same result in Wine yet. Ignore the difference for now.
2415 * {WM_ACTIVATE, TRUE, 0x200000 | WA_ACTIVE}, */
2416 {WM_WINDOWPOSCHANGED, FALSE, 0},
2417 {WM_MOVE, FALSE, 0},
2418 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2419 {WM_ACTIVATEAPP, TRUE, FALSE},
2420 {0, FALSE, 0},
2422 static const struct message exclusive_focus_restore_messages[] =
2424 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* From the ShowWindow(SW_RESTORE). */
2425 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Generated by ddraw, matches d3d9 behavior. */
2426 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching previous message. */
2427 {WM_SIZE, FALSE, 0}, /* DefWindowProc. */
2428 {WM_DISPLAYCHANGE, FALSE, 0}, /* Ddraw restores mode. */
2429 /* Native redundantly sets the window size here. */
2430 {WM_ACTIVATEAPP, TRUE, TRUE}, /* End of ddraw's hooks. */
2431 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching the one from ShowWindow. */
2432 {WM_MOVE, FALSE, 0}, /* DefWindowProc. */
2433 {WM_SIZE, TRUE, SIZE_RESTORED}, /* DefWindowProc. */
2434 {0, FALSE, 0},
2436 static const struct message sc_restore_messages[] =
2438 {WM_SYSCOMMAND, TRUE, SC_RESTORE},
2439 {WM_WINDOWPOSCHANGING, FALSE, 0},
2440 {WM_WINDOWPOSCHANGED, FALSE, 0},
2441 {WM_SIZE, TRUE, SIZE_RESTORED},
2442 {0, FALSE, 0},
2444 static const struct message sc_minimize_messages[] =
2446 {WM_SYSCOMMAND, TRUE, SC_MINIMIZE},
2447 {WM_WINDOWPOSCHANGING, FALSE, 0},
2448 {WM_WINDOWPOSCHANGED, FALSE, 0},
2449 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2450 {0, FALSE, 0},
2452 static const struct message sc_maximize_messages[] =
2454 {WM_SYSCOMMAND, TRUE, SC_MAXIMIZE},
2455 {WM_WINDOWPOSCHANGING, FALSE, 0},
2456 {WM_WINDOWPOSCHANGED, FALSE, 0},
2457 {WM_SIZE, TRUE, SIZE_MAXIMIZED},
2458 {0, FALSE, 0},
2461 static const struct message normal_messages[] =
2463 {WM_DISPLAYCHANGE, FALSE, 0},
2464 {0, FALSE, 0},
2467 ddraw = create_ddraw();
2468 ok(!!ddraw, "Failed to create a ddraw object.\n");
2470 memset(&param, 0, sizeof(param));
2471 hr = IDirectDraw7_EnumDisplayModes(ddraw, 0, NULL, &param, test_coop_level_mode_set_enum_cb);
2472 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
2473 ref = IDirectDraw7_Release(ddraw);
2474 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2476 if (!param.user32_height)
2478 skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
2479 return;
2482 SetRect(&registry_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2483 SetRect(&ddraw_rect, 0, 0, param.ddraw_width, param.ddraw_height);
2484 SetRect(&user32_rect, 0, 0, param.user32_width, param.user32_height);
2486 memset(&devmode, 0, sizeof(devmode));
2487 devmode.dmSize = sizeof(devmode);
2488 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2489 devmode.dmPelsWidth = param.user32_width;
2490 devmode.dmPelsHeight = param.user32_height;
2491 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2492 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2494 ddraw = create_ddraw();
2495 ok(!!ddraw, "Failed to create a ddraw object.\n");
2497 wc.lpfnWndProc = mode_set_proc;
2498 wc.lpszClassName = "ddraw_test_wndproc_wc";
2499 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2500 wc.lpfnWndProc = mode_set_proc2;
2501 wc.lpszClassName = "ddraw_test_wndproc_wc2";
2502 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2504 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
2505 0, 0, 100, 100, 0, 0, 0, 0);
2506 window2 = CreateWindowA("ddraw_test_wndproc_wc2", "ddraw_test", WS_OVERLAPPEDWINDOW,
2507 0, 0, 100, 100, 0, 0, 0, 0);
2509 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2510 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2512 GetWindowRect(window, &r);
2513 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2514 wine_dbgstr_rect(&r));
2516 memset(&ddsd, 0, sizeof(ddsd));
2517 ddsd.dwSize = sizeof(ddsd);
2518 ddsd.dwFlags = DDSD_CAPS;
2519 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2521 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2522 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2523 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2524 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2525 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2526 param.user32_width, ddsd.dwWidth);
2527 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2528 param.user32_height, ddsd.dwHeight);
2530 GetWindowRect(window, &r);
2531 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2532 wine_dbgstr_rect(&r));
2534 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2535 expect_messages = exclusive_messages;
2536 screen_size.cx = 0;
2537 screen_size.cy = 0;
2539 hr = IDirectDrawSurface7_IsLost(primary);
2540 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2541 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2542 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2543 hr = IDirectDrawSurface7_IsLost(primary);
2544 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2546 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2547 expect_messages = NULL;
2548 ok(screen_size.cx == param.ddraw_width && screen_size.cy == param.ddraw_height,
2549 "Expected screen size %ux%u, got %ux%u.\n",
2550 param.ddraw_width, param.ddraw_height, screen_size.cx, screen_size.cy);
2552 GetWindowRect(window, &r);
2553 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2554 wine_dbgstr_rect(&r));
2556 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2557 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2558 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2559 param.user32_width, ddsd.dwWidth);
2560 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2561 param.user32_height, ddsd.dwHeight);
2562 IDirectDrawSurface7_Release(primary);
2564 memset(&ddsd, 0, sizeof(ddsd));
2565 ddsd.dwSize = sizeof(ddsd);
2566 ddsd.dwFlags = DDSD_CAPS;
2567 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2569 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2570 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2571 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2572 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2573 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2574 param.ddraw_width, ddsd.dwWidth);
2575 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2576 param.ddraw_height, ddsd.dwHeight);
2578 GetWindowRect(window, &r);
2579 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2580 wine_dbgstr_rect(&r));
2582 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2583 expect_messages = exclusive_messages;
2584 screen_size.cx = 0;
2585 screen_size.cy = 0;
2587 hr = IDirectDrawSurface7_IsLost(primary);
2588 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2589 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2590 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2591 hr = IDirectDrawSurface7_IsLost(primary);
2592 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2594 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2595 expect_messages = NULL;
2596 ok(screen_size.cx == param.user32_width && screen_size.cy == param.user32_height,
2597 "Expected screen size %ux%u, got %ux%u.\n",
2598 param.user32_width, param.user32_height, screen_size.cx, screen_size.cy);
2600 GetWindowRect(window, &r);
2601 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2602 wine_dbgstr_rect(&r));
2604 expect_messages = exclusive_focus_loss_messages;
2605 ret = SetForegroundWindow(GetDesktopWindow());
2606 ok(ret, "Failed to set foreground window.\n");
2607 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2608 memset(&devmode, 0, sizeof(devmode));
2609 devmode.dmSize = sizeof(devmode);
2610 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2611 ok(ret, "Failed to get display mode.\n");
2612 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2613 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
2614 devmode.dmPelsWidth, devmode.dmPelsHeight);
2616 expect_messages = exclusive_focus_restore_messages;
2617 ShowWindow(window, SW_RESTORE);
2618 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2620 GetWindowRect(window, &r);
2621 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2622 wine_dbgstr_rect(&r));
2623 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2624 ok(ret, "Failed to get display mode.\n");
2625 ok(devmode.dmPelsWidth == param.ddraw_width
2626 && devmode.dmPelsHeight == param.ddraw_height, "Got unexpect screen size %ux%u.\n",
2627 devmode.dmPelsWidth, devmode.dmPelsHeight);
2629 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2630 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2631 /* Normally the primary should be restored here. Unfortunately this causes the
2632 * GetSurfaceDesc call after the next display mode change to crash on the Windows 8
2633 * testbot. Another Restore call would presumably avoid the crash, but it also moots
2634 * the point of the GetSurfaceDesc call. */
2636 expect_messages = sc_minimize_messages;
2637 SendMessageA(window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
2638 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2639 expect_messages = NULL;
2641 expect_messages = sc_restore_messages;
2642 SendMessageA(window, WM_SYSCOMMAND, SC_RESTORE, 0);
2643 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2644 expect_messages = NULL;
2646 expect_messages = sc_maximize_messages;
2647 SendMessageA(window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
2648 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2649 expect_messages = NULL;
2651 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2652 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2654 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2655 expect_messages = exclusive_messages;
2656 screen_size.cx = 0;
2657 screen_size.cy = 0;
2659 hr = IDirectDrawSurface7_IsLost(primary);
2660 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2661 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
2662 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2663 hr = IDirectDrawSurface7_IsLost(primary);
2664 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2666 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2667 expect_messages = NULL;
2668 ok(screen_size.cx == registry_mode.dmPelsWidth
2669 && screen_size.cy == registry_mode.dmPelsHeight,
2670 "Expected screen size %ux%u, got %ux%u.\n",
2671 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size.cx, screen_size.cy);
2673 GetWindowRect(window, &r);
2674 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2675 wine_dbgstr_rect(&r));
2677 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2678 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2679 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2680 param.ddraw_width, ddsd.dwWidth);
2681 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2682 param.ddraw_height, ddsd.dwHeight);
2683 IDirectDrawSurface7_Release(primary);
2685 /* For Wine. */
2686 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
2687 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2689 memset(&ddsd, 0, sizeof(ddsd));
2690 ddsd.dwSize = sizeof(ddsd);
2691 ddsd.dwFlags = DDSD_CAPS;
2692 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2694 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2695 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2696 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2697 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2698 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2699 registry_mode.dmPelsWidth, ddsd.dwWidth);
2700 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2701 registry_mode.dmPelsHeight, ddsd.dwHeight);
2703 GetWindowRect(window, &r);
2704 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2705 wine_dbgstr_rect(&r));
2707 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2708 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2710 GetWindowRect(window, &r);
2711 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2712 wine_dbgstr_rect(&r));
2714 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2715 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2716 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2717 registry_mode.dmPelsWidth, ddsd.dwWidth);
2718 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2719 registry_mode.dmPelsHeight, ddsd.dwHeight);
2720 IDirectDrawSurface7_Release(primary);
2722 memset(&ddsd, 0, sizeof(ddsd));
2723 ddsd.dwSize = sizeof(ddsd);
2724 ddsd.dwFlags = DDSD_CAPS;
2725 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2727 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2728 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2729 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2730 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2731 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2732 registry_mode.dmPelsWidth, ddsd.dwWidth);
2733 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2734 registry_mode.dmPelsHeight, ddsd.dwHeight);
2736 GetWindowRect(window, &r);
2737 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2738 wine_dbgstr_rect(&r));
2740 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2741 expect_messages = normal_messages;
2742 screen_size.cx = 0;
2743 screen_size.cy = 0;
2745 hr = IDirectDrawSurface7_IsLost(primary);
2746 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2747 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2748 devmode.dmPelsWidth = param.user32_width;
2749 devmode.dmPelsHeight = param.user32_height;
2750 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2751 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2752 hr = IDirectDrawSurface7_IsLost(primary);
2753 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2755 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2756 expect_messages = NULL;
2757 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2759 GetWindowRect(window, &r);
2760 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2761 wine_dbgstr_rect(&r));
2763 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2764 expect_messages = normal_messages;
2765 screen_size.cx = 0;
2766 screen_size.cy = 0;
2768 hr = IDirectDrawSurface7_Restore(primary);
2769 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2770 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2771 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2772 hr = IDirectDrawSurface7_Restore(primary);
2773 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2774 hr = IDirectDrawSurface7_IsLost(primary);
2775 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2777 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2778 expect_messages = NULL;
2779 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2781 GetWindowRect(window, &r);
2782 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2783 wine_dbgstr_rect(&r));
2785 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2786 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2787 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2788 registry_mode.dmPelsWidth, ddsd.dwWidth);
2789 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2790 registry_mode.dmPelsHeight, ddsd.dwHeight);
2791 IDirectDrawSurface7_Release(primary);
2793 memset(&ddsd, 0, sizeof(ddsd));
2794 ddsd.dwSize = sizeof(ddsd);
2795 ddsd.dwFlags = DDSD_CAPS;
2796 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2798 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2799 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2800 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2801 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2802 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2803 param.ddraw_width, ddsd.dwWidth);
2804 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2805 param.ddraw_height, ddsd.dwHeight);
2807 GetWindowRect(window, &r);
2808 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2809 wine_dbgstr_rect(&r));
2811 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2812 expect_messages = normal_messages;
2813 screen_size.cx = 0;
2814 screen_size.cy = 0;
2816 hr = IDirectDrawSurface7_IsLost(primary);
2817 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2818 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
2819 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2820 hr = IDirectDrawSurface7_IsLost(primary);
2821 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2823 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2824 expect_messages = NULL;
2825 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2827 GetWindowRect(window, &r);
2828 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2829 wine_dbgstr_rect(&r));
2831 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2832 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2833 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2834 param.ddraw_width, ddsd.dwWidth);
2835 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2836 param.ddraw_height, ddsd.dwHeight);
2837 IDirectDrawSurface7_Release(primary);
2839 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2840 ok(ret, "Failed to get display mode.\n");
2841 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2842 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
2843 "Expected resolution %ux%u, got %ux%u.\n",
2844 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
2845 devmode.dmPelsWidth, devmode.dmPelsHeight);
2846 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
2847 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2849 memset(&ddsd, 0, sizeof(ddsd));
2850 ddsd.dwSize = sizeof(ddsd);
2851 ddsd.dwFlags = DDSD_CAPS;
2852 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2854 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2855 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2856 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2857 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2858 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2859 registry_mode.dmPelsWidth, ddsd.dwWidth);
2860 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2861 registry_mode.dmPelsHeight, ddsd.dwHeight);
2863 GetWindowRect(window, &r);
2864 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2865 wine_dbgstr_rect(&r));
2867 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
2868 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
2869 * not DDSCL_FULLSCREEN. */
2870 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2871 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2873 GetWindowRect(window, &r);
2874 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2875 wine_dbgstr_rect(&r));
2877 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2878 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2879 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2880 registry_mode.dmPelsWidth, ddsd.dwWidth);
2881 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2882 registry_mode.dmPelsHeight, ddsd.dwHeight);
2883 IDirectDrawSurface7_Release(primary);
2885 memset(&ddsd, 0, sizeof(ddsd));
2886 ddsd.dwSize = sizeof(ddsd);
2887 ddsd.dwFlags = DDSD_CAPS;
2888 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2890 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2891 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2892 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2893 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2894 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2895 registry_mode.dmPelsWidth, ddsd.dwWidth);
2896 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2897 registry_mode.dmPelsHeight, ddsd.dwHeight);
2899 GetWindowRect(window, &r);
2900 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2901 wine_dbgstr_rect(&r));
2903 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2904 expect_messages = normal_messages;
2905 screen_size.cx = 0;
2906 screen_size.cy = 0;
2908 hr = IDirectDrawSurface7_IsLost(primary);
2909 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2910 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2911 devmode.dmPelsWidth = param.user32_width;
2912 devmode.dmPelsHeight = param.user32_height;
2913 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2914 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2915 hr = IDirectDrawSurface7_IsLost(primary);
2916 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2918 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2919 expect_messages = NULL;
2920 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2922 GetWindowRect(window, &r);
2923 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2924 wine_dbgstr_rect(&r));
2926 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2927 expect_messages = normal_messages;
2928 screen_size.cx = 0;
2929 screen_size.cy = 0;
2931 hr = IDirectDrawSurface7_Restore(primary);
2932 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2933 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2934 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2935 hr = IDirectDrawSurface7_Restore(primary);
2936 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2937 hr = IDirectDrawSurface7_IsLost(primary);
2938 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2940 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2941 expect_messages = NULL;
2942 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2944 GetWindowRect(window, &r);
2945 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2946 wine_dbgstr_rect(&r));
2948 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2949 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2950 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2951 registry_mode.dmPelsWidth, ddsd.dwWidth);
2952 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2953 registry_mode.dmPelsHeight, ddsd.dwHeight);
2954 IDirectDrawSurface7_Release(primary);
2956 memset(&ddsd, 0, sizeof(ddsd));
2957 ddsd.dwSize = sizeof(ddsd);
2958 ddsd.dwFlags = DDSD_CAPS;
2959 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2961 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2962 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2963 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2964 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2965 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2966 param.ddraw_width, ddsd.dwWidth);
2967 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2968 param.ddraw_height, ddsd.dwHeight);
2970 GetWindowRect(window, &r);
2971 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2972 wine_dbgstr_rect(&r));
2974 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2975 expect_messages = normal_messages;
2976 screen_size.cx = 0;
2977 screen_size.cy = 0;
2979 hr = IDirectDrawSurface7_IsLost(primary);
2980 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2981 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
2982 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2983 hr = IDirectDrawSurface7_IsLost(primary);
2984 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2986 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2987 expect_messages = NULL;
2988 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2990 GetWindowRect(window, &r);
2991 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2992 wine_dbgstr_rect(&r));
2994 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2995 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2996 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2997 param.ddraw_width, ddsd.dwWidth);
2998 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2999 param.ddraw_height, ddsd.dwHeight);
3000 IDirectDrawSurface7_Release(primary);
3002 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3003 ok(ret, "Failed to get display mode.\n");
3004 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3005 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3006 "Expected resolution %ux%u, got %ux%u.\n",
3007 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3008 devmode.dmPelsWidth, devmode.dmPelsHeight);
3009 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3010 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3012 memset(&ddsd, 0, sizeof(ddsd));
3013 ddsd.dwSize = sizeof(ddsd);
3014 ddsd.dwFlags = DDSD_CAPS;
3015 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3017 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3018 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3019 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3020 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3021 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3022 registry_mode.dmPelsWidth, ddsd.dwWidth);
3023 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3024 registry_mode.dmPelsHeight, ddsd.dwHeight);
3025 IDirectDrawSurface7_Release(primary);
3027 GetWindowRect(window, &r);
3028 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3029 wine_dbgstr_rect(&r));
3031 /* Changing the coop level from EXCLUSIVE to NORMAL restores the screen resolution */
3032 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3033 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3034 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3035 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3037 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3038 expect_messages = exclusive_messages;
3039 screen_size.cx = 0;
3040 screen_size.cy = 0;
3042 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3043 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3045 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3046 expect_messages = NULL;
3047 ok(screen_size.cx == registry_mode.dmPelsWidth
3048 && screen_size.cy == registry_mode.dmPelsHeight,
3049 "Expected screen size %ux%u, got %ux%u.\n",
3050 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3051 screen_size.cx, screen_size.cy);
3053 GetWindowRect(window, &r);
3054 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3055 wine_dbgstr_rect(&r));
3057 memset(&ddsd, 0, sizeof(ddsd));
3058 ddsd.dwSize = sizeof(ddsd);
3059 ddsd.dwFlags = DDSD_CAPS;
3060 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3062 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3063 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3064 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3065 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3066 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3067 registry_mode.dmPelsWidth, ddsd.dwWidth);
3068 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3069 registry_mode.dmPelsHeight, ddsd.dwHeight);
3070 IDirectDrawSurface7_Release(primary);
3072 /* The screen restore is a property of DDSCL_EXCLUSIVE */
3073 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3074 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3075 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3076 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3078 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3079 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3081 memset(&ddsd, 0, sizeof(ddsd));
3082 ddsd.dwSize = sizeof(ddsd);
3083 ddsd.dwFlags = DDSD_CAPS;
3084 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3086 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3087 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3088 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3089 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3090 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3091 param.ddraw_width, ddsd.dwWidth);
3092 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3093 param.ddraw_height, ddsd.dwHeight);
3094 IDirectDrawSurface7_Release(primary);
3096 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
3097 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3099 /* If the window is changed at the same time, messages are sent to the new window. */
3100 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3101 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3102 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3103 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3105 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3106 expect_messages = exclusive_messages;
3107 screen_size.cx = 0;
3108 screen_size.cy = 0;
3109 screen_size2.cx = 0;
3110 screen_size2.cy = 0;
3112 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3113 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3115 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3116 expect_messages = NULL;
3117 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n",
3118 screen_size.cx, screen_size.cy);
3119 ok(screen_size2.cx == registry_mode.dmPelsWidth && screen_size2.cy == registry_mode.dmPelsHeight,
3120 "Expected screen size 2 %ux%u, got %ux%u.\n",
3121 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size2.cx, screen_size2.cy);
3123 GetWindowRect(window, &r);
3124 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3125 wine_dbgstr_rect(&r));
3126 GetWindowRect(window2, &r);
3127 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3128 wine_dbgstr_rect(&r));
3130 memset(&ddsd, 0, sizeof(ddsd));
3131 ddsd.dwSize = sizeof(ddsd);
3132 ddsd.dwFlags = DDSD_CAPS;
3133 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3135 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3136 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3137 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3138 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3139 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3140 registry_mode.dmPelsWidth, ddsd.dwWidth);
3141 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3142 registry_mode.dmPelsHeight, ddsd.dwHeight);
3143 IDirectDrawSurface7_Release(primary);
3145 ref = IDirectDraw7_Release(ddraw);
3146 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3148 GetWindowRect(window, &r);
3149 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3150 wine_dbgstr_rect(&r));
3152 expect_messages = NULL;
3153 DestroyWindow(window);
3154 DestroyWindow(window2);
3155 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
3156 UnregisterClassA("ddraw_test_wndproc_wc2", GetModuleHandleA(NULL));
3159 static void test_coop_level_mode_set_multi(void)
3161 IDirectDraw7 *ddraw1, *ddraw2;
3162 UINT w, h;
3163 HWND window;
3164 HRESULT hr;
3165 ULONG ref;
3167 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3168 0, 0, 100, 100, 0, 0, 0, 0);
3169 ddraw1 = create_ddraw();
3170 ok(!!ddraw1, "Failed to create a ddraw object.\n");
3172 /* With just a single ddraw object, the display mode is restored on
3173 * release. */
3174 hr = set_display_mode(ddraw1, 800, 600);
3175 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3176 w = GetSystemMetrics(SM_CXSCREEN);
3177 ok(w == 800, "Got unexpected screen width %u.\n", w);
3178 h = GetSystemMetrics(SM_CYSCREEN);
3179 ok(h == 600, "Got unexpected screen height %u.\n", h);
3181 ref = IDirectDraw7_Release(ddraw1);
3182 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3183 w = GetSystemMetrics(SM_CXSCREEN);
3184 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3185 h = GetSystemMetrics(SM_CYSCREEN);
3186 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3188 /* When there are multiple ddraw objects, the display mode is restored to
3189 * the initial mode, before the first SetDisplayMode() call. */
3190 ddraw1 = create_ddraw();
3191 hr = set_display_mode(ddraw1, 800, 600);
3192 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3193 w = GetSystemMetrics(SM_CXSCREEN);
3194 ok(w == 800, "Got unexpected screen width %u.\n", w);
3195 h = GetSystemMetrics(SM_CYSCREEN);
3196 ok(h == 600, "Got unexpected screen height %u.\n", h);
3198 ddraw2 = create_ddraw();
3199 hr = set_display_mode(ddraw2, 640, 480);
3200 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3201 w = GetSystemMetrics(SM_CXSCREEN);
3202 ok(w == 640, "Got unexpected screen width %u.\n", w);
3203 h = GetSystemMetrics(SM_CYSCREEN);
3204 ok(h == 480, "Got unexpected screen height %u.\n", h);
3206 ref = IDirectDraw7_Release(ddraw2);
3207 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3208 w = GetSystemMetrics(SM_CXSCREEN);
3209 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3210 h = GetSystemMetrics(SM_CYSCREEN);
3211 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3213 ref = IDirectDraw7_Release(ddraw1);
3214 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3215 w = GetSystemMetrics(SM_CXSCREEN);
3216 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3217 h = GetSystemMetrics(SM_CYSCREEN);
3218 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3220 /* Regardless of release ordering. */
3221 ddraw1 = create_ddraw();
3222 hr = set_display_mode(ddraw1, 800, 600);
3223 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3224 w = GetSystemMetrics(SM_CXSCREEN);
3225 ok(w == 800, "Got unexpected screen width %u.\n", w);
3226 h = GetSystemMetrics(SM_CYSCREEN);
3227 ok(h == 600, "Got unexpected screen height %u.\n", h);
3229 ddraw2 = create_ddraw();
3230 hr = set_display_mode(ddraw2, 640, 480);
3231 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3232 w = GetSystemMetrics(SM_CXSCREEN);
3233 ok(w == 640, "Got unexpected screen width %u.\n", w);
3234 h = GetSystemMetrics(SM_CYSCREEN);
3235 ok(h == 480, "Got unexpected screen height %u.\n", h);
3237 ref = IDirectDraw7_Release(ddraw1);
3238 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3239 w = GetSystemMetrics(SM_CXSCREEN);
3240 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3241 h = GetSystemMetrics(SM_CYSCREEN);
3242 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3244 ref = IDirectDraw7_Release(ddraw2);
3245 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3246 w = GetSystemMetrics(SM_CXSCREEN);
3247 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3248 h = GetSystemMetrics(SM_CYSCREEN);
3249 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3251 /* But only for ddraw objects that called SetDisplayMode(). */
3252 ddraw1 = create_ddraw();
3253 ddraw2 = create_ddraw();
3254 hr = set_display_mode(ddraw2, 640, 480);
3255 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3256 w = GetSystemMetrics(SM_CXSCREEN);
3257 ok(w == 640, "Got unexpected screen width %u.\n", w);
3258 h = GetSystemMetrics(SM_CYSCREEN);
3259 ok(h == 480, "Got unexpected screen height %u.\n", h);
3261 ref = IDirectDraw7_Release(ddraw1);
3262 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3263 w = GetSystemMetrics(SM_CXSCREEN);
3264 ok(w == 640, "Got unexpected screen width %u.\n", w);
3265 h = GetSystemMetrics(SM_CYSCREEN);
3266 ok(h == 480, "Got unexpected screen height %u.\n", h);
3268 ref = IDirectDraw7_Release(ddraw2);
3269 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3270 w = GetSystemMetrics(SM_CXSCREEN);
3271 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3272 h = GetSystemMetrics(SM_CYSCREEN);
3273 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3275 /* If there's a ddraw object that's currently in exclusive mode, it blocks
3276 * restoring the display mode. */
3277 ddraw1 = create_ddraw();
3278 hr = set_display_mode(ddraw1, 800, 600);
3279 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3280 w = GetSystemMetrics(SM_CXSCREEN);
3281 ok(w == 800, "Got unexpected screen width %u.\n", w);
3282 h = GetSystemMetrics(SM_CYSCREEN);
3283 ok(h == 600, "Got unexpected screen height %u.\n", h);
3285 ddraw2 = create_ddraw();
3286 hr = set_display_mode(ddraw2, 640, 480);
3287 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3288 w = GetSystemMetrics(SM_CXSCREEN);
3289 ok(w == 640, "Got unexpected screen width %u.\n", w);
3290 h = GetSystemMetrics(SM_CYSCREEN);
3291 ok(h == 480, "Got unexpected screen height %u.\n", h);
3293 hr = IDirectDraw7_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3294 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3296 ref = IDirectDraw7_Release(ddraw1);
3297 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3298 w = GetSystemMetrics(SM_CXSCREEN);
3299 ok(w == 640, "Got unexpected screen width %u.\n", w);
3300 h = GetSystemMetrics(SM_CYSCREEN);
3301 ok(h == 480, "Got unexpected screen height %u.\n", h);
3303 ref = IDirectDraw7_Release(ddraw2);
3304 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3305 w = GetSystemMetrics(SM_CXSCREEN);
3306 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3307 h = GetSystemMetrics(SM_CYSCREEN);
3308 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3310 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
3311 ddraw1 = create_ddraw();
3312 hr = set_display_mode(ddraw1, 800, 600);
3313 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3314 w = GetSystemMetrics(SM_CXSCREEN);
3315 ok(w == 800, "Got unexpected screen width %u.\n", w);
3316 h = GetSystemMetrics(SM_CYSCREEN);
3317 ok(h == 600, "Got unexpected screen height %u.\n", h);
3319 hr = IDirectDraw7_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3320 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3322 ddraw2 = create_ddraw();
3323 hr = set_display_mode(ddraw2, 640, 480);
3324 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
3326 ref = IDirectDraw7_Release(ddraw1);
3327 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3328 w = GetSystemMetrics(SM_CXSCREEN);
3329 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3330 h = GetSystemMetrics(SM_CYSCREEN);
3331 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3333 ref = IDirectDraw7_Release(ddraw2);
3334 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3335 w = GetSystemMetrics(SM_CXSCREEN);
3336 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3337 h = GetSystemMetrics(SM_CYSCREEN);
3338 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3340 DestroyWindow(window);
3343 static void test_initialize(void)
3345 IDirectDraw7 *ddraw;
3346 HRESULT hr;
3348 ddraw = create_ddraw();
3349 ok(!!ddraw, "Failed to create a ddraw object.\n");
3351 hr = IDirectDraw7_Initialize(ddraw, NULL);
3352 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
3353 IDirectDraw7_Release(ddraw);
3355 CoInitialize(NULL);
3356 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw7, (void **)&ddraw);
3357 ok(SUCCEEDED(hr), "Failed to create IDirectDraw7 instance, hr %#x.\n", hr);
3358 hr = IDirectDraw7_Initialize(ddraw, NULL);
3359 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
3360 hr = IDirectDraw7_Initialize(ddraw, NULL);
3361 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
3362 IDirectDraw7_Release(ddraw);
3363 CoUninitialize();
3366 static void test_coop_level_surf_create(void)
3368 IDirectDrawSurface7 *surface;
3369 IDirectDraw7 *ddraw;
3370 DDSURFACEDESC2 ddsd;
3371 HRESULT hr;
3373 ddraw = create_ddraw();
3374 ok(!!ddraw, "Failed to create a ddraw object.\n");
3376 memset(&ddsd, 0, sizeof(ddsd));
3377 ddsd.dwSize = sizeof(ddsd);
3378 ddsd.dwFlags = DDSD_CAPS;
3379 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3380 surface = (void *)0xdeadbeef;
3381 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
3382 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
3383 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
3385 surface = (void *)0xdeadbeef;
3386 hr = IDirectDraw7_CreateSurface(ddraw, NULL, &surface, NULL);
3387 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
3388 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
3390 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3391 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3393 surface = (void *)0xdeadbeef;
3394 hr = IDirectDraw7_CreateSurface(ddraw, NULL, &surface, NULL);
3395 ok(hr == DDERR_INVALIDPARAMS, "Unexpected hr %#x.\n", hr);
3396 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
3398 IDirectDraw7_Release(ddraw);
3401 static void test_vb_discard(void)
3403 static const struct vec4 quad[] =
3405 { 0.0f, 480.0f, 0.0f, 1.0f},
3406 { 0.0f, 0.0f, 0.0f, 1.0f},
3407 {640.0f, 480.0f, 0.0f, 1.0f},
3408 {640.0f, 0.0f, 0.0f, 1.0f},
3411 IDirect3DDevice7 *device;
3412 IDirect3D7 *d3d;
3413 IDirect3DVertexBuffer7 *buffer;
3414 HWND window;
3415 HRESULT hr;
3416 D3DVERTEXBUFFERDESC desc;
3417 BYTE *data;
3418 static const unsigned int vbsize = 16;
3419 unsigned int i;
3421 window = create_window();
3422 if (!(device = create_device(window, DDSCL_NORMAL)))
3424 skip("Failed to create a 3D device, skipping test.\n");
3425 DestroyWindow(window);
3426 return;
3429 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
3430 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
3432 memset(&desc, 0, sizeof(desc));
3433 desc.dwSize = sizeof(desc);
3434 desc.dwCaps = D3DVBCAPS_WRITEONLY;
3435 desc.dwFVF = D3DFVF_XYZRHW;
3436 desc.dwNumVertices = vbsize;
3437 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &buffer, 0);
3438 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
3440 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3441 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3442 memcpy(data, quad, sizeof(quad));
3443 hr = IDirect3DVertexBuffer7_Unlock(buffer);
3444 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3446 hr = IDirect3DDevice7_BeginScene(device);
3447 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3448 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
3449 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3450 hr = IDirect3DDevice7_EndScene(device);
3451 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3453 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3454 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3455 memset(data, 0xaa, sizeof(struct vec4) * vbsize);
3456 hr = IDirect3DVertexBuffer7_Unlock(buffer);
3457 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3459 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3460 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3461 for (i = 0; i < sizeof(struct vec4) * vbsize; i++)
3463 if (data[i] != 0xaa)
3465 ok(FALSE, "Vertex buffer data byte %u is 0x%02x, expected 0xaa\n", i, data[i]);
3466 break;
3469 hr = IDirect3DVertexBuffer7_Unlock(buffer);
3470 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3472 IDirect3DVertexBuffer7_Release(buffer);
3473 IDirect3D7_Release(d3d);
3474 IDirect3DDevice7_Release(device);
3475 DestroyWindow(window);
3478 static void test_coop_level_multi_window(void)
3480 HWND window1, window2;
3481 IDirectDraw7 *ddraw;
3482 HRESULT hr;
3484 window1 = create_window();
3485 window2 = create_window();
3486 ddraw = create_ddraw();
3487 ok(!!ddraw, "Failed to create a ddraw object.\n");
3489 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
3490 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3491 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3492 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3493 ok(IsWindow(window1), "Window 1 was destroyed.\n");
3494 ok(IsWindow(window2), "Window 2 was destroyed.\n");
3496 IDirectDraw7_Release(ddraw);
3497 DestroyWindow(window2);
3498 DestroyWindow(window1);
3501 static void test_draw_strided(void)
3503 static struct vec3 position[] =
3505 {-1.0, -1.0, 0.0},
3506 {-1.0, 1.0, 0.0},
3507 { 1.0, 1.0, 0.0},
3508 { 1.0, -1.0, 0.0},
3510 static DWORD diffuse[] =
3512 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
3514 static WORD indices[] =
3516 0, 1, 2, 2, 3, 0
3519 IDirectDrawSurface7 *rt;
3520 IDirect3DDevice7 *device;
3521 D3DCOLOR color;
3522 HWND window;
3523 HRESULT hr;
3524 D3DDRAWPRIMITIVESTRIDEDDATA strided;
3526 window = create_window();
3527 if (!(device = create_device(window, DDSCL_NORMAL)))
3529 skip("Failed to create a 3D device, skipping test.\n");
3530 DestroyWindow(window);
3531 return;
3534 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
3535 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3537 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
3538 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
3539 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 1.0f, 0);
3540 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
3541 hr = IDirect3DDevice7_BeginScene(device);
3542 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3544 memset(&strided, 0x55, sizeof(strided));
3545 strided.position.lpvData = position;
3546 strided.position.dwStride = sizeof(*position);
3547 strided.diffuse.lpvData = diffuse;
3548 strided.diffuse.dwStride = sizeof(*diffuse);
3549 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device, D3DPT_TRIANGLELIST, D3DFVF_XYZ | D3DFVF_DIFFUSE,
3550 &strided, 4, indices, 6, 0);
3551 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3553 hr = IDirect3DDevice7_EndScene(device);
3554 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3556 color = get_surface_color(rt, 320, 240);
3557 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
3559 IDirectDrawSurface7_Release(rt);
3560 IDirect3DDevice7_Release(device);
3561 DestroyWindow(window);
3564 static void test_lighting(void)
3566 static D3DMATRIX mat =
3568 1.0f, 0.0f, 0.0f, 0.0f,
3569 0.0f, 1.0f, 0.0f, 0.0f,
3570 0.0f, 0.0f, 1.0f, 0.0f,
3571 0.0f, 0.0f, 0.0f, 1.0f,
3573 mat_singular =
3575 1.0f, 0.0f, 1.0f, 0.0f,
3576 0.0f, 1.0f, 0.0f, 0.0f,
3577 1.0f, 0.0f, 1.0f, 0.0f,
3578 0.0f, 0.0f, 0.5f, 1.0f,
3580 mat_transf =
3582 0.0f, 0.0f, 1.0f, 0.0f,
3583 0.0f, 1.0f, 0.0f, 0.0f,
3584 -1.0f, 0.0f, 0.0f, 0.0f,
3585 10.f, 10.0f, 10.0f, 1.0f,
3587 mat_nonaffine =
3589 1.0f, 0.0f, 0.0f, 0.0f,
3590 0.0f, 1.0f, 0.0f, 0.0f,
3591 0.0f, 0.0f, 1.0f, -1.0f,
3592 10.f, 10.0f, 10.0f, 0.0f,
3594 static struct
3596 struct vec3 position;
3597 DWORD diffuse;
3599 unlitquad[] =
3601 {{-1.0f, -1.0f, 0.1f}, 0xffff0000},
3602 {{-1.0f, 0.0f, 0.1f}, 0xffff0000},
3603 {{ 0.0f, 0.0f, 0.1f}, 0xffff0000},
3604 {{ 0.0f, -1.0f, 0.1f}, 0xffff0000},
3606 litquad[] =
3608 {{-1.0f, 0.0f, 0.1f}, 0xff00ff00},
3609 {{-1.0f, 1.0f, 0.1f}, 0xff00ff00},
3610 {{ 0.0f, 1.0f, 0.1f}, 0xff00ff00},
3611 {{ 0.0f, 0.0f, 0.1f}, 0xff00ff00},
3613 static struct
3615 struct vec3 position;
3616 struct vec3 normal;
3617 DWORD diffuse;
3619 unlitnquad[] =
3621 {{0.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3622 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3623 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3624 {{1.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3626 litnquad[] =
3628 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3629 {{0.0f, 1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3630 {{1.0f, 1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3631 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3633 nquad[] =
3635 {{-1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3636 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3637 {{ 1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3638 {{ 1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3640 rotatedquad[] =
3642 {{-10.0f, -11.0f, 11.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3643 {{-10.0f, -9.0f, 11.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3644 {{-10.0f, -9.0f, 9.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3645 {{-10.0f, -11.0f, 9.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3647 translatedquad[] =
3649 {{-11.0f, -11.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3650 {{-11.0f, -9.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3651 {{ -9.0f, -9.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3652 {{ -9.0f, -11.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3654 static WORD indices[] = {0, 1, 2, 2, 3, 0};
3655 static const struct
3657 D3DMATRIX *world_matrix;
3658 void *quad;
3659 DWORD expected;
3660 const char *message;
3662 tests[] =
3664 {&mat, nquad, 0x000000ff, "Lit quad with light"},
3665 {&mat_singular, nquad, 0x000000ff, "Lit quad with singular world matrix"},
3666 {&mat_transf, rotatedquad, 0x000000ff, "Lit quad with transformation matrix"},
3667 {&mat_nonaffine, translatedquad, 0x00000000, "Lit quad with non-affine matrix"},
3670 HWND window;
3671 IDirect3DDevice7 *device;
3672 IDirectDrawSurface7 *rt;
3673 HRESULT hr;
3674 DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
3675 DWORD nfvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL;
3676 D3DCOLOR color;
3677 ULONG refcount;
3678 unsigned int i;
3680 window = create_window();
3681 if (!(device = create_device(window, DDSCL_NORMAL)))
3683 skip("Failed to create a 3D device, skipping test.\n");
3684 DestroyWindow(window);
3685 return;
3688 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
3689 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3691 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
3692 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
3694 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
3695 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
3696 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
3697 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
3698 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
3699 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
3700 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
3701 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
3702 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
3703 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
3704 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
3705 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
3706 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
3707 ok(SUCCEEDED(hr), "Failed to disable stencil buffering, hr %#x.\n", hr);
3708 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
3709 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
3711 hr = IDirect3DDevice7_BeginScene(device);
3712 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3714 /* No lights are defined... That means, lit vertices should be entirely black. */
3715 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
3716 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
3717 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, unlitquad, 4,
3718 indices, 6, 0);
3719 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3721 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
3722 ok(SUCCEEDED(hr), "Failed to enable lighting, hr %#x.\n", hr);
3723 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, litquad, 4,
3724 indices, 6, 0);
3725 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3727 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
3728 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
3729 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, unlitnquad, 4,
3730 indices, 6, 0);
3731 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3733 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
3734 ok(SUCCEEDED(hr), "Failed to enable lighting, hr %#x.\n", hr);
3735 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, litnquad, 4,
3736 indices, 6, 0);
3737 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3739 hr = IDirect3DDevice7_EndScene(device);
3740 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3742 color = get_surface_color(rt, 160, 360);
3743 ok(color == 0x00ff0000, "Unlit quad without normals has color 0x%08x, expected 0x00ff0000.\n", color);
3744 color = get_surface_color(rt, 160, 120);
3745 ok(color == 0x00000000, "Lit quad without normals has color 0x%08x, expected 0x00000000.\n", color);
3746 color = get_surface_color(rt, 480, 360);
3747 ok(color == 0x000000ff, "Unlit quad with normals has color 0x%08x, expected 0x000000ff.\n", color);
3748 color = get_surface_color(rt, 480, 120);
3749 ok(color == 0x00000000, "Lit quad with normals has color 0x%08x, expected 0x00000000.\n", color);
3751 hr = IDirect3DDevice7_LightEnable(device, 0, TRUE);
3752 ok(SUCCEEDED(hr), "Failed to enable light 0, hr %#x.\n", hr);
3754 for (i = 0; i < ARRAY_SIZE(tests); ++i)
3756 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, tests[i].world_matrix);
3757 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
3759 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
3760 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
3762 hr = IDirect3DDevice7_BeginScene(device);
3763 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3765 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, tests[i].quad,
3766 4, indices, 6, 0);
3767 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3769 hr = IDirect3DDevice7_EndScene(device);
3770 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3772 color = get_surface_color(rt, 320, 240);
3773 ok(color == tests[i].expected, "%s has color 0x%08x.\n", tests[i].message, color);
3776 IDirectDrawSurface7_Release(rt);
3778 refcount = IDirect3DDevice7_Release(device);
3779 ok(!refcount, "Device has %u references left.\n", refcount);
3780 DestroyWindow(window);
3783 static void test_specular_lighting(void)
3785 static const unsigned int vertices_side = 5;
3786 const unsigned int indices_count = (vertices_side - 1) * (vertices_side - 1) * 2 * 3;
3787 static const DWORD fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3788 static D3DMATRIX mat =
3790 1.0f, 0.0f, 0.0f, 0.0f,
3791 0.0f, 1.0f, 0.0f, 0.0f,
3792 0.0f, 0.0f, 1.0f, 0.0f,
3793 0.0f, 0.0f, 0.0f, 1.0f,
3795 static D3DLIGHT7 directional =
3797 D3DLIGHT_DIRECTIONAL,
3798 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3799 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
3800 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3801 {{0.0f}, {0.0f}, {0.0f}},
3802 {{0.0f}, {0.0f}, {1.0f}},
3804 point =
3806 D3DLIGHT_POINT,
3807 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3808 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
3809 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3810 {{0.0f}, {0.0f}, {0.0f}},
3811 {{0.0f}, {0.0f}, {0.0f}},
3812 100.0f,
3813 0.0f,
3814 0.0f, 0.0f, 1.0f,
3816 spot =
3818 D3DLIGHT_SPOT,
3819 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3820 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
3821 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3822 {{0.0f}, {0.0f}, {0.0f}},
3823 {{0.0f}, {0.0f}, {1.0f}},
3824 100.0f,
3825 1.0f,
3826 0.0f, 0.0f, 1.0f,
3827 M_PI / 12.0f, M_PI / 3.0f
3829 /* The chosen range value makes the test fail when using a manhattan
3830 * distance metric vs the correct euclidean distance. */
3831 point_range =
3833 D3DLIGHT_POINT,
3834 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3835 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
3836 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3837 {{0.0f}, {0.0f}, {0.0f}},
3838 {{0.0f}, {0.0f}, {0.0f}},
3839 1.2f,
3840 0.0f,
3841 0.0f, 0.0f, 1.0f,
3843 point_side =
3845 D3DLIGHT_POINT,
3846 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3847 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
3848 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3849 {{-1.1f}, {0.0f}, {1.1f}},
3850 {{0.0f}, {0.0f}, {0.0f}},
3851 100.0f,
3852 0.0f,
3853 1.0f, 0.0f, 0.0f,
3855 static const struct expected_color
3857 unsigned int x, y;
3858 D3DCOLOR color;
3860 expected_directional[] =
3862 {160, 120, 0x00ffffff},
3863 {320, 120, 0x00ffffff},
3864 {480, 120, 0x00ffffff},
3865 {160, 240, 0x00ffffff},
3866 {320, 240, 0x00ffffff},
3867 {480, 240, 0x00ffffff},
3868 {160, 360, 0x00ffffff},
3869 {320, 360, 0x00ffffff},
3870 {480, 360, 0x00ffffff},
3872 expected_directional_local[] =
3874 {160, 120, 0x003c3c3c},
3875 {320, 120, 0x00717171},
3876 {480, 120, 0x003c3c3c},
3877 {160, 240, 0x00717171},
3878 {320, 240, 0x00ffffff},
3879 {480, 240, 0x00717171},
3880 {160, 360, 0x003c3c3c},
3881 {320, 360, 0x00717171},
3882 {480, 360, 0x003c3c3c},
3884 expected_point[] =
3886 {160, 120, 0x00282828},
3887 {320, 120, 0x005a5a5a},
3888 {480, 120, 0x00282828},
3889 {160, 240, 0x005a5a5a},
3890 {320, 240, 0x00ffffff},
3891 {480, 240, 0x005a5a5a},
3892 {160, 360, 0x00282828},
3893 {320, 360, 0x005a5a5a},
3894 {480, 360, 0x00282828},
3896 expected_point_local[] =
3898 {160, 120, 0x00000000},
3899 {320, 120, 0x00070707},
3900 {480, 120, 0x00000000},
3901 {160, 240, 0x00070707},
3902 {320, 240, 0x00ffffff},
3903 {480, 240, 0x00070707},
3904 {160, 360, 0x00000000},
3905 {320, 360, 0x00070707},
3906 {480, 360, 0x00000000},
3908 expected_spot[] =
3910 {160, 120, 0x00000000},
3911 {320, 120, 0x00141414},
3912 {480, 120, 0x00000000},
3913 {160, 240, 0x00141414},
3914 {320, 240, 0x00ffffff},
3915 {480, 240, 0x00141414},
3916 {160, 360, 0x00000000},
3917 {320, 360, 0x00141414},
3918 {480, 360, 0x00000000},
3920 expected_spot_local[] =
3922 {160, 120, 0x00000000},
3923 {320, 120, 0x00020202},
3924 {480, 120, 0x00000000},
3925 {160, 240, 0x00020202},
3926 {320, 240, 0x00ffffff},
3927 {480, 240, 0x00020202},
3928 {160, 360, 0x00000000},
3929 {320, 360, 0x00020202},
3930 {480, 360, 0x00000000},
3932 expected_point_range[] =
3934 {160, 120, 0x00000000},
3935 {320, 120, 0x005a5a5a},
3936 {480, 120, 0x00000000},
3937 {160, 240, 0x005a5a5a},
3938 {320, 240, 0x00ffffff},
3939 {480, 240, 0x005a5a5a},
3940 {160, 360, 0x00000000},
3941 {320, 360, 0x005a5a5a},
3942 {480, 360, 0x00000000},
3944 expected_point_side[] =
3946 {160, 120, 0x00000000},
3947 {320, 120, 0x00000000},
3948 {480, 120, 0x00000000},
3949 {160, 240, 0x00000000},
3950 {320, 240, 0x00000000},
3951 {480, 240, 0x00000000},
3952 {160, 360, 0x00000000},
3953 {320, 360, 0x00000000},
3954 {480, 360, 0x00000000},
3956 static const struct
3958 D3DLIGHT7 *light;
3959 BOOL local_viewer;
3960 float specular_power;
3961 const struct expected_color *expected;
3962 unsigned int expected_count;
3964 tests[] =
3966 {&directional, FALSE, 30.0f, expected_directional, ARRAY_SIZE(expected_directional)},
3967 {&directional, TRUE, 30.0f, expected_directional_local, ARRAY_SIZE(expected_directional_local)},
3968 {&point, FALSE, 30.0f, expected_point, ARRAY_SIZE(expected_point)},
3969 {&point, TRUE, 30.0f, expected_point_local, ARRAY_SIZE(expected_point_local)},
3970 {&spot, FALSE, 30.0f, expected_spot, ARRAY_SIZE(expected_spot)},
3971 {&spot, TRUE, 30.0f, expected_spot_local, ARRAY_SIZE(expected_spot_local)},
3972 {&point_range, FALSE, 30.0f, expected_point_range, ARRAY_SIZE(expected_point_range)},
3973 {&point_side, TRUE, 0.0f, expected_point_side, ARRAY_SIZE(expected_point_side)},
3975 IDirect3DDevice7 *device;
3976 IDirectDrawSurface7 *rt;
3977 D3DMATERIAL7 material;
3978 D3DCOLOR color;
3979 ULONG refcount;
3980 HWND window;
3981 HRESULT hr;
3982 unsigned int i, j, x, y;
3983 struct
3985 struct vec3 position;
3986 struct vec3 normal;
3987 } *quad;
3988 WORD *indices;
3990 window = create_window();
3991 if (!(device = create_device(window, DDSCL_NORMAL)))
3993 skip("Failed to create a 3D device, skipping test.\n");
3994 DestroyWindow(window);
3995 return;
3998 quad = HeapAlloc(GetProcessHeap(), 0, vertices_side * vertices_side * sizeof(*quad));
3999 indices = HeapAlloc(GetProcessHeap(), 0, indices_count * sizeof(*indices));
4000 for (i = 0, y = 0; y < vertices_side; ++y)
4002 for (x = 0; x < vertices_side; ++x)
4004 quad[i].position.x = x * 2.0f / (vertices_side - 1) - 1.0f;
4005 quad[i].position.y = y * 2.0f / (vertices_side - 1) - 1.0f;
4006 quad[i].position.z = 1.0f;
4007 quad[i].normal.x = 0.0f;
4008 quad[i].normal.y = 0.0f;
4009 quad[i++].normal.z = -1.0f;
4012 for (i = 0, y = 0; y < (vertices_side - 1); ++y)
4014 for (x = 0; x < (vertices_side - 1); ++x)
4016 indices[i++] = y * vertices_side + x + 1;
4017 indices[i++] = y * vertices_side + x;
4018 indices[i++] = (y + 1) * vertices_side + x;
4019 indices[i++] = y * vertices_side + x + 1;
4020 indices[i++] = (y + 1) * vertices_side + x;
4021 indices[i++] = (y + 1) * vertices_side + x + 1;
4025 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
4026 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4028 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
4029 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
4030 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
4031 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
4032 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
4033 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
4034 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
4035 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
4036 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
4037 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
4038 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
4039 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
4041 hr = IDirect3DDevice7_LightEnable(device, 0, TRUE);
4042 ok(SUCCEEDED(hr), "Failed to enable light 0, hr %#x.\n", hr);
4043 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, TRUE);
4044 ok(SUCCEEDED(hr), "Failed to enable specular lighting, hr %#x.\n", hr);
4046 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4048 hr = IDirect3DDevice7_SetLight(device, 0, tests[i].light);
4049 ok(SUCCEEDED(hr), "Failed to set light parameters, hr %#x.\n", hr);
4051 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LOCALVIEWER, tests[i].local_viewer);
4052 ok(SUCCEEDED(hr), "Failed to set local viewer state, hr %#x.\n", hr);
4054 memset(&material, 0, sizeof(material));
4055 U1(U2(material).specular).r = 1.0f;
4056 U2(U2(material).specular).g = 1.0f;
4057 U3(U2(material).specular).b = 1.0f;
4058 U4(U2(material).specular).a = 1.0f;
4059 U4(material).power = tests[i].specular_power;
4060 hr = IDirect3DDevice7_SetMaterial(device, &material);
4061 ok(SUCCEEDED(hr), "Failed to set material, hr %#x.\n", hr);
4063 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
4064 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
4066 hr = IDirect3DDevice7_BeginScene(device);
4067 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4069 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, quad,
4070 vertices_side * vertices_side, indices, indices_count, 0);
4071 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4073 hr = IDirect3DDevice7_EndScene(device);
4074 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4076 for (j = 0; j < tests[i].expected_count; ++j)
4078 color = get_surface_color(rt, tests[i].expected[j].x, tests[i].expected[j].y);
4079 ok(compare_color(color, tests[i].expected[j].color, 1),
4080 "Expected color 0x%08x at location (%u, %u), got 0x%08x, case %u.\n",
4081 tests[i].expected[j].color, tests[i].expected[j].x,
4082 tests[i].expected[j].y, color, i);
4086 IDirectDrawSurface7_Release(rt);
4088 refcount = IDirect3DDevice7_Release(device);
4089 ok(!refcount, "Device has %u references left.\n", refcount);
4090 DestroyWindow(window);
4091 HeapFree(GetProcessHeap(), 0, indices);
4092 HeapFree(GetProcessHeap(), 0, quad);
4095 static void test_clear_rect_count(void)
4097 IDirectDrawSurface7 *rt;
4098 IDirect3DDevice7 *device;
4099 D3DCOLOR color;
4100 HWND window;
4101 HRESULT hr;
4102 D3DRECT rect = {{0}, {0}, {640}, {480}};
4104 window = create_window();
4105 if (!(device = create_device(window, DDSCL_NORMAL)))
4107 skip("Failed to create a 3D device, skipping test.\n");
4108 DestroyWindow(window);
4109 return;
4112 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
4113 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4115 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ffffff, 1.0f, 0);
4116 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4117 hr = IDirect3DDevice7_Clear(device, 0, &rect, D3DCLEAR_TARGET, 0x00ff0000, 1.0f, 0);
4118 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4120 color = get_surface_color(rt, 320, 240);
4121 ok(compare_color(color, 0x00ffffff, 1) || broken(compare_color(color, 0x00ff0000, 1)),
4122 "Clear with count = 0, rect != NULL has color %#08x.\n", color);
4124 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ffffff, 1.0f, 0);
4125 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4126 hr = IDirect3DDevice7_Clear(device, 1, NULL, D3DCLEAR_TARGET, 0x0000ff00, 1.0f, 0);
4127 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4129 color = get_surface_color(rt, 320, 240);
4130 ok(compare_color(color, 0x0000ff00, 1),
4131 "Clear with count = 1, rect = NULL has color %#08x.\n", color);
4133 IDirectDrawSurface7_Release(rt);
4134 IDirect3DDevice7_Release(device);
4135 DestroyWindow(window);
4138 static BOOL test_mode_restored(IDirectDraw7 *ddraw, HWND window)
4140 DDSURFACEDESC2 ddsd1, ddsd2;
4141 HRESULT hr;
4143 memset(&ddsd1, 0, sizeof(ddsd1));
4144 ddsd1.dwSize = sizeof(ddsd1);
4145 hr = IDirectDraw7_GetDisplayMode(ddraw, &ddsd1);
4146 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
4148 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4149 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4150 hr = set_display_mode(ddraw, 640, 480);
4151 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
4152 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4153 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4155 memset(&ddsd2, 0, sizeof(ddsd2));
4156 ddsd2.dwSize = sizeof(ddsd2);
4157 hr = IDirectDraw7_GetDisplayMode(ddraw, &ddsd2);
4158 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
4159 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
4160 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
4162 return ddsd1.dwWidth == ddsd2.dwWidth && ddsd1.dwHeight == ddsd2.dwHeight;
4165 static void test_coop_level_versions(void)
4167 HWND window;
4168 IDirectDraw *ddraw;
4169 HRESULT hr;
4170 BOOL restored;
4171 IDirectDrawSurface *surface;
4172 IDirectDraw7 *ddraw7;
4173 DDSURFACEDESC ddsd;
4175 window = create_window();
4176 ddraw7 = create_ddraw();
4177 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4178 /* Newly created ddraw objects restore the mode on ddraw2+::SetCooperativeLevel(NORMAL) */
4179 restored = test_mode_restored(ddraw7, window);
4180 ok(restored, "Display mode not restored in new ddraw object\n");
4182 /* A failing ddraw1::SetCooperativeLevel call does not have an effect */
4183 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4184 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4186 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4187 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
4188 restored = test_mode_restored(ddraw7, window);
4189 ok(restored, "Display mode not restored after bad ddraw1::SetCooperativeLevel call\n");
4191 /* A successful one does */
4192 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4193 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4194 restored = test_mode_restored(ddraw7, window);
4195 ok(!restored, "Display mode restored after good ddraw1::SetCooperativeLevel call\n");
4197 IDirectDraw_Release(ddraw);
4198 IDirectDraw7_Release(ddraw7);
4200 ddraw7 = create_ddraw();
4201 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4202 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4203 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4205 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_SETFOCUSWINDOW);
4206 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4207 restored = test_mode_restored(ddraw7, window);
4208 ok(!restored, "Display mode restored after ddraw1::SetCooperativeLevel(SETFOCUSWINDOW) call\n");
4210 IDirectDraw_Release(ddraw);
4211 IDirectDraw7_Release(ddraw7);
4213 /* A failing call does not restore the ddraw2+ behavior */
4214 ddraw7 = create_ddraw();
4215 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4216 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4217 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4219 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4220 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4221 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4222 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
4223 restored = test_mode_restored(ddraw7, window);
4224 ok(!restored, "Display mode restored after good-bad ddraw1::SetCooperativeLevel() call sequence\n");
4226 IDirectDraw_Release(ddraw);
4227 IDirectDraw7_Release(ddraw7);
4229 /* Neither does a sequence of successful calls with the new interface */
4230 ddraw7 = create_ddraw();
4231 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4232 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4233 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4235 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4236 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4237 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4238 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4239 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
4240 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4242 restored = test_mode_restored(ddraw7, window);
4243 ok(!restored, "Display mode restored after ddraw1-ddraw7 SetCooperativeLevel() call sequence\n");
4244 IDirectDraw_Release(ddraw);
4245 IDirectDraw7_Release(ddraw7);
4247 /* ddraw1::CreateSurface does not triger the ddraw1 behavior */
4248 ddraw7 = create_ddraw();
4249 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4250 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4251 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4253 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
4254 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4256 memset(&ddsd, 0, sizeof(ddsd));
4257 ddsd.dwSize = sizeof(ddsd);
4258 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
4259 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4260 ddsd.dwWidth = ddsd.dwHeight = 8;
4261 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
4262 ok(SUCCEEDED(hr), "CreateSurface failed, hr %#x.\n", hr);
4263 IDirectDrawSurface_Release(surface);
4264 restored = test_mode_restored(ddraw7, window);
4265 ok(restored, "Display mode not restored after ddraw1::CreateSurface() call\n");
4267 IDirectDraw_Release(ddraw);
4268 IDirectDraw7_Release(ddraw7);
4269 DestroyWindow(window);
4272 static void test_fog_special(void)
4274 static struct
4276 struct vec3 position;
4277 D3DCOLOR diffuse;
4279 quad[] =
4281 {{ -1.0f, 1.0f, 0.0f}, 0xff00ff00},
4282 {{ 1.0f, 1.0f, 1.0f}, 0xff00ff00},
4283 {{ -1.0f, -1.0f, 0.0f}, 0xff00ff00},
4284 {{ 1.0f, -1.0f, 1.0f}, 0xff00ff00},
4286 static const struct
4288 DWORD vertexmode, tablemode;
4289 D3DCOLOR color_left, color_right;
4291 tests[] =
4293 {D3DFOG_LINEAR, D3DFOG_NONE, 0x00ff0000, 0x00ff0000},
4294 {D3DFOG_NONE, D3DFOG_LINEAR, 0x0000ff00, 0x00ff0000},
4296 union
4298 float f;
4299 DWORD d;
4300 } conv;
4301 D3DCOLOR color;
4302 HRESULT hr;
4303 unsigned int i;
4304 HWND window;
4305 IDirect3DDevice7 *device;
4306 IDirectDrawSurface7 *rt;
4308 window = create_window();
4309 if (!(device = create_device(window, DDSCL_NORMAL)))
4311 skip("Failed to create a 3D device, skipping test.\n");
4312 DestroyWindow(window);
4313 return;
4316 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
4317 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4319 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
4320 ok(SUCCEEDED(hr), "Failed to enable fog, hr %#x.\n", hr);
4321 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0xffff0000);
4322 ok(SUCCEEDED(hr), "Failed to set fog color, hr %#x.\n", hr);
4323 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
4324 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
4325 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
4326 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
4328 conv.f = 0.5f;
4329 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGSTART, conv.d);
4330 ok(SUCCEEDED(hr), "Failed to set fog start, hr %#x.\n", hr);
4331 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGEND, conv.d);
4332 ok(SUCCEEDED(hr), "Failed to set fog end, hr %#x.\n", hr);
4334 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4336 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x000000ff, 1.0f, 0);
4337 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4339 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, tests[i].vertexmode);
4340 ok(SUCCEEDED(hr), "Failed to set fogvertexmode, hr %#x.\n", hr);
4341 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, tests[i].tablemode);
4342 ok(SUCCEEDED(hr), "Failed to set fogtablemode, hr %#x.\n", hr);
4344 hr = IDirect3DDevice7_BeginScene(device);
4345 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4346 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, 4, 0);
4347 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4348 hr = IDirect3DDevice7_EndScene(device);
4349 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4351 color = get_surface_color(rt, 310, 240);
4352 ok(compare_color(color, tests[i].color_left, 1),
4353 "Expected left color 0x%08x, got 0x%08x, case %u.\n", tests[i].color_left, color, i);
4354 color = get_surface_color(rt, 330, 240);
4355 ok(compare_color(color, tests[i].color_right, 1),
4356 "Expected right color 0x%08x, got 0x%08x, case %u.\n", tests[i].color_right, color, i);
4359 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
4360 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
4362 IDirectDrawSurface7_Release(rt);
4363 IDirect3DDevice7_Release(device);
4364 DestroyWindow(window);
4367 static void test_lighting_interface_versions(void)
4369 IDirect3DDevice7 *device;
4370 IDirectDrawSurface7 *rt;
4371 D3DCOLOR color;
4372 HWND window;
4373 HRESULT hr;
4374 DWORD rs;
4375 unsigned int i;
4376 ULONG ref;
4377 D3DMATERIAL7 material;
4378 static D3DVERTEX quad[] =
4380 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4381 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4382 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4383 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4386 #define FVF_COLORVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_SPECULAR)
4387 static struct
4389 struct vec3 position;
4390 struct vec3 normal;
4391 DWORD diffuse, specular;
4393 quad2[] =
4395 {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4396 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4397 {{-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4398 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4401 static D3DLVERTEX lquad[] =
4403 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4404 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4405 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4406 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4409 #define FVF_LVERTEX2 (D3DFVF_LVERTEX & ~D3DFVF_RESERVED1)
4410 static struct
4412 struct vec3 position;
4413 DWORD diffuse, specular;
4414 struct vec2 texcoord;
4416 lquad2[] =
4418 {{-1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
4419 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
4420 {{-1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
4421 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
4424 static D3DTLVERTEX tlquad[] =
4426 {{ 0.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4427 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4428 {{ 640.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4429 {{ 640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4432 static const struct
4434 DWORD vertextype;
4435 void *data;
4436 DWORD d3drs_lighting, d3drs_specular;
4437 DWORD draw_flags;
4438 D3DCOLOR color;
4440 tests[] =
4442 /* Lighting is enabled when D3DFVF_XYZ is used and D3DRENDERSTATE_LIGHTING is
4443 * enabled. D3DDP_DONOTLIGHT is ignored. Lighting is also enabled when normals
4444 * are not available
4446 * Note that the specular result is 0x00000000 when lighting is on even if the
4447 * input vertex has specular color because D3DRENDERSTATE_COLORVERTEX is not
4448 * enabled */
4450 /* 0 */
4451 { D3DFVF_VERTEX, quad, FALSE, FALSE, 0, 0x00ffffff},
4452 { D3DFVF_VERTEX, quad, TRUE, FALSE, 0, 0x0000ff00},
4453 { D3DFVF_VERTEX, quad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
4454 { D3DFVF_VERTEX, quad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
4455 { D3DFVF_VERTEX, quad, FALSE, TRUE, 0, 0x00ffffff},
4456 { D3DFVF_VERTEX, quad, TRUE, TRUE, 0, 0x0000ff00},
4457 { D3DFVF_VERTEX, quad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
4458 { D3DFVF_VERTEX, quad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
4460 /* 8 */
4461 { FVF_COLORVERTEX, quad2, FALSE, FALSE, 0, 0x00ff0000},
4462 { FVF_COLORVERTEX, quad2, TRUE, FALSE, 0, 0x0000ff00},
4463 { FVF_COLORVERTEX, quad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4464 { FVF_COLORVERTEX, quad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
4465 { FVF_COLORVERTEX, quad2, FALSE, TRUE, 0, 0x00ff8080},
4466 { FVF_COLORVERTEX, quad2, TRUE, TRUE, 0, 0x0000ff00},
4467 { FVF_COLORVERTEX, quad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4468 { FVF_COLORVERTEX, quad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
4470 /* 16 */
4471 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, 0, 0x00ff0000},
4472 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, 0, 0x0000ff00},
4473 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4474 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
4475 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, 0, 0x00ff8080},
4476 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, 0, 0x0000ff00},
4477 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4478 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
4480 /* 24 */
4481 { FVF_LVERTEX2, lquad2, FALSE, FALSE, 0, 0x00ff0000},
4482 { FVF_LVERTEX2, lquad2, TRUE, FALSE, 0, 0x0000ff00},
4483 { FVF_LVERTEX2, lquad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4484 { FVF_LVERTEX2, lquad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
4485 { FVF_LVERTEX2, lquad2, FALSE, TRUE, 0, 0x00ff8080},
4486 { FVF_LVERTEX2, lquad2, TRUE, TRUE, 0, 0x0000ff00},
4487 { FVF_LVERTEX2, lquad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4488 { FVF_LVERTEX2, lquad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
4490 /* 32 */
4491 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, 0, 0x000000ff},
4492 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, 0, 0x000000ff},
4493 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
4494 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
4495 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, 0, 0x008080ff},
4496 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, 0, 0x008080ff},
4497 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
4498 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
4501 window = create_window();
4502 if (!(device = create_device(window, DDSCL_NORMAL)))
4504 skip("Failed to create a 3D device, skipping test.\n");
4505 DestroyWindow(window);
4506 return;
4509 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
4510 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4512 memset(&material, 0, sizeof(material));
4513 U2(U3(material).emissive).g = 1.0f;
4514 hr = IDirect3DDevice7_SetMaterial(device, &material);
4515 ok(SUCCEEDED(hr), "Failed set material, hr %#x.\n", hr);
4516 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
4517 ok(SUCCEEDED(hr), "Failed to disable z test, hr %#x.\n", hr);
4519 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &rs);
4520 ok(SUCCEEDED(hr), "Failed to get lighting render state, hr %#x.\n", hr);
4521 ok(rs == TRUE, "Initial D3DRENDERSTATE_LIGHTING is %#x, expected TRUE.\n", rs);
4522 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, &rs);
4523 ok(SUCCEEDED(hr), "Failed to get specularenable render state, hr %#x.\n", hr);
4524 ok(rs == FALSE, "Initial D3DRENDERSTATE_SPECULARENABLE is %#x, expected FALSE.\n", rs);
4526 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4528 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff202020, 0.0f, 0);
4529 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
4531 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, tests[i].d3drs_lighting);
4532 ok(SUCCEEDED(hr), "Failed to set lighting render state, hr %#x.\n", hr);
4533 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE,
4534 tests[i].d3drs_specular);
4535 ok(SUCCEEDED(hr), "Failed to set specularenable render state, hr %#x.\n", hr);
4537 hr = IDirect3DDevice7_BeginScene(device);
4538 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4539 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
4540 tests[i].vertextype, tests[i].data, 4, tests[i].draw_flags | D3DDP_WAIT);
4541 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4542 hr = IDirect3DDevice7_EndScene(device);
4543 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4545 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &rs);
4546 ok(SUCCEEDED(hr), "Failed to get lighting render state, hr %#x.\n", hr);
4547 ok(rs == tests[i].d3drs_lighting, "D3DRENDERSTATE_LIGHTING is %#x, expected %#x.\n",
4548 rs, tests[i].d3drs_lighting);
4550 color = get_surface_color(rt, 320, 240);
4551 ok(compare_color(color, tests[i].color, 1),
4552 "Got unexpected color 0x%08x, expected 0x%08x, test %u.\n",
4553 color, tests[i].color, i);
4556 IDirectDrawSurface7_Release(rt);
4557 ref = IDirect3DDevice7_Release(device);
4558 ok(ref == 0, "Device not properly released, refcount %u.\n", ref);
4559 DestroyWindow(window);
4562 static struct
4564 BOOL received;
4565 IDirectDraw7 *ddraw;
4566 HWND window;
4567 DWORD coop_level;
4568 } activateapp_testdata;
4570 static LRESULT CALLBACK activateapp_test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
4572 if (message == WM_ACTIVATEAPP)
4574 if (activateapp_testdata.ddraw)
4576 HRESULT hr;
4577 activateapp_testdata.received = FALSE;
4578 hr = IDirectDraw7_SetCooperativeLevel(activateapp_testdata.ddraw,
4579 activateapp_testdata.window, activateapp_testdata.coop_level);
4580 ok(SUCCEEDED(hr), "Recursive SetCooperativeLevel call failed, hr %#x.\n", hr);
4581 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP during recursive SetCooperativeLevel call.\n");
4583 activateapp_testdata.received = TRUE;
4586 return DefWindowProcA(hwnd, message, wparam, lparam);
4589 static void test_coop_level_activateapp(void)
4591 IDirectDraw7 *ddraw;
4592 HRESULT hr;
4593 HWND window;
4594 WNDCLASSA wc = {0};
4595 DDSURFACEDESC2 ddsd;
4596 IDirectDrawSurface7 *surface;
4598 ddraw = create_ddraw();
4599 ok(!!ddraw, "Failed to create a ddraw object.\n");
4601 wc.lpfnWndProc = activateapp_test_proc;
4602 wc.lpszClassName = "ddraw_test_wndproc_wc";
4603 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4605 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
4606 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
4608 /* Exclusive with window already active. */
4609 SetForegroundWindow(window);
4610 activateapp_testdata.received = FALSE;
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, "Received WM_ACTIVATEAPP although window was already active.\n");
4614 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4615 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4617 /* Exclusive with window not active. */
4618 SetForegroundWindow(GetDesktopWindow());
4619 activateapp_testdata.received = FALSE;
4620 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4621 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4622 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4623 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4624 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4626 /* Normal with window not active, then exclusive with the same window. */
4627 SetForegroundWindow(GetDesktopWindow());
4628 activateapp_testdata.received = FALSE;
4629 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4630 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4631 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP when setting DDSCL_NORMAL.\n");
4632 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4633 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4634 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4635 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4636 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4638 /* Recursive set of DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. */
4639 SetForegroundWindow(GetDesktopWindow());
4640 activateapp_testdata.received = FALSE;
4641 activateapp_testdata.ddraw = ddraw;
4642 activateapp_testdata.window = window;
4643 activateapp_testdata.coop_level = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
4644 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4645 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4646 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4647 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4648 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4650 /* The recursive call seems to have some bad effect on native ddraw, despite (apparently)
4651 * succeeding. Another switch to exclusive and back to normal is needed to release the
4652 * window properly. Without doing this, SetCooperativeLevel(EXCLUSIVE) will not send
4653 * WM_ACTIVATEAPP messages. */
4654 activateapp_testdata.ddraw = NULL;
4655 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4656 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4657 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4658 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4660 /* Setting DDSCL_NORMAL with recursive invocation. */
4661 SetForegroundWindow(GetDesktopWindow());
4662 activateapp_testdata.received = FALSE;
4663 activateapp_testdata.ddraw = ddraw;
4664 activateapp_testdata.window = window;
4665 activateapp_testdata.coop_level = DDSCL_NORMAL;
4666 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4667 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4668 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4670 /* DDraw is in exclusive mode now. */
4671 memset(&ddsd, 0, sizeof(ddsd));
4672 ddsd.dwSize = sizeof(ddsd);
4673 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
4674 U5(ddsd).dwBackBufferCount = 1;
4675 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
4676 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
4677 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4678 IDirectDrawSurface7_Release(surface);
4680 /* Recover again, just to be sure. */
4681 activateapp_testdata.ddraw = NULL;
4682 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4683 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4684 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4685 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4687 DestroyWindow(window);
4688 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
4689 IDirectDraw7_Release(ddraw);
4692 static void test_texturemanage(void)
4694 IDirectDraw7 *ddraw;
4695 HRESULT hr;
4696 DDSURFACEDESC2 ddsd;
4697 IDirectDrawSurface7 *surface;
4698 unsigned int i;
4699 DDCAPS hal_caps, hel_caps;
4700 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
4701 static const struct
4703 DWORD caps_in, caps2_in;
4704 HRESULT hr;
4705 DWORD caps_out, caps2_out;
4707 tests[] =
4709 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4710 ~0U, ~0U},
4711 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4712 ~0U, ~0U},
4713 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4714 ~0U, ~0U},
4715 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4716 ~0U, ~0U},
4717 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DD_OK,
4718 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE},
4719 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DD_OK,
4720 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE},
4721 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
4722 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_LOCALVIDMEM, 0},
4723 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
4724 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0},
4726 {0, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4727 ~0U, ~0U},
4728 {0, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4729 ~0U, ~0U},
4730 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4731 ~0U, ~0U},
4732 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4733 ~0U, ~0U},
4734 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
4735 ~0U, ~0U},
4736 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
4737 ~0U, ~0U},
4738 {DDSCAPS_VIDEOMEMORY, 0, DD_OK,
4739 DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY, 0},
4740 {DDSCAPS_SYSTEMMEMORY, 0, DD_OK,
4741 DDSCAPS_SYSTEMMEMORY, 0},
4744 ddraw = create_ddraw();
4745 ok(!!ddraw, "Failed to create a ddraw object.\n");
4746 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4747 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4749 memset(&hal_caps, 0, sizeof(hal_caps));
4750 hal_caps.dwSize = sizeof(hal_caps);
4751 memset(&hel_caps, 0, sizeof(hel_caps));
4752 hel_caps.dwSize = sizeof(hel_caps);
4753 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, &hel_caps);
4754 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
4755 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps)
4757 skip("Managed textures not supported, skipping managed texture test.\n");
4758 IDirectDraw7_Release(ddraw);
4759 return;
4762 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4764 memset(&ddsd, 0, sizeof(ddsd));
4765 ddsd.dwSize = sizeof(ddsd);
4766 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
4767 ddsd.ddsCaps.dwCaps = tests[i].caps_in;
4768 ddsd.ddsCaps.dwCaps2 = tests[i].caps2_in;
4769 ddsd.dwWidth = 4;
4770 ddsd.dwHeight = 4;
4772 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
4773 if (tests[i].hr == DD_OK && is_ddraw64 && (tests[i].caps_in & DDSCAPS_TEXTURE))
4774 todo_wine ok(hr == E_NOINTERFACE, "Test %u: Got unexpected hr %#x.\n", i, hr);
4775 else
4776 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, tests[i].hr);
4777 if (FAILED(hr))
4778 continue;
4780 memset(&ddsd, 0, sizeof(ddsd));
4781 ddsd.dwSize = sizeof(ddsd);
4782 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
4783 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4785 ok(ddsd.ddsCaps.dwCaps == tests[i].caps_out,
4786 "Input caps %#x, %#x, expected output caps %#x, got %#x, case %u.\n",
4787 tests[i].caps_in, tests[i].caps2_in, tests[i].caps_out, ddsd.ddsCaps.dwCaps, i);
4788 ok(ddsd.ddsCaps.dwCaps2 == tests[i].caps2_out,
4789 "Input caps %#x, %#x, expected output caps %#x, got %#x, case %u.\n",
4790 tests[i].caps_in, tests[i].caps2_in, tests[i].caps2_out, ddsd.ddsCaps.dwCaps2, i);
4792 IDirectDrawSurface7_Release(surface);
4795 IDirectDraw7_Release(ddraw);
4798 #define SUPPORT_DXT1 0x01
4799 #define SUPPORT_DXT2 0x02
4800 #define SUPPORT_DXT3 0x04
4801 #define SUPPORT_DXT4 0x08
4802 #define SUPPORT_DXT5 0x10
4803 #define SUPPORT_YUY2 0x20
4804 #define SUPPORT_UYVY 0x40
4806 static HRESULT WINAPI test_block_formats_creation_cb(DDPIXELFORMAT *fmt, void *ctx)
4808 DWORD *supported_fmts = ctx;
4810 if (!(fmt->dwFlags & DDPF_FOURCC))
4811 return DDENUMRET_OK;
4813 switch (fmt->dwFourCC)
4815 case MAKEFOURCC('D','X','T','1'):
4816 *supported_fmts |= SUPPORT_DXT1;
4817 break;
4818 case MAKEFOURCC('D','X','T','2'):
4819 *supported_fmts |= SUPPORT_DXT2;
4820 break;
4821 case MAKEFOURCC('D','X','T','3'):
4822 *supported_fmts |= SUPPORT_DXT3;
4823 break;
4824 case MAKEFOURCC('D','X','T','4'):
4825 *supported_fmts |= SUPPORT_DXT4;
4826 break;
4827 case MAKEFOURCC('D','X','T','5'):
4828 *supported_fmts |= SUPPORT_DXT5;
4829 break;
4830 case MAKEFOURCC('Y','U','Y','2'):
4831 *supported_fmts |= SUPPORT_YUY2;
4832 break;
4833 case MAKEFOURCC('U','Y','V','Y'):
4834 *supported_fmts |= SUPPORT_UYVY;
4835 break;
4836 default:
4837 break;
4840 return DDENUMRET_OK;
4843 static void test_block_formats_creation(void)
4845 HRESULT hr, expect_hr;
4846 unsigned int i, j, w, h;
4847 HWND window;
4848 IDirectDraw7 *ddraw;
4849 IDirect3D7 *d3d;
4850 IDirect3DDevice7 *device;
4851 IDirectDrawSurface7 *surface;
4852 DWORD supported_fmts = 0, supported_overlay_fmts = 0;
4853 DWORD num_fourcc_codes = 0, *fourcc_codes;
4854 DDSURFACEDESC2 ddsd;
4855 DDCAPS hal_caps;
4856 void *mem;
4858 static const struct
4860 DWORD fourcc;
4861 const char *name;
4862 DWORD support_flag;
4863 unsigned int block_width;
4864 unsigned int block_height;
4865 unsigned int block_size;
4866 BOOL create_size_checked, overlay;
4868 formats[] =
4870 {MAKEFOURCC('D','X','T','1'), "D3DFMT_DXT1", SUPPORT_DXT1, 4, 4, 8, TRUE, FALSE},
4871 {MAKEFOURCC('D','X','T','2'), "D3DFMT_DXT2", SUPPORT_DXT2, 4, 4, 16, TRUE, FALSE},
4872 {MAKEFOURCC('D','X','T','3'), "D3DFMT_DXT3", SUPPORT_DXT3, 4, 4, 16, TRUE, FALSE},
4873 {MAKEFOURCC('D','X','T','4'), "D3DFMT_DXT4", SUPPORT_DXT4, 4, 4, 16, TRUE, FALSE},
4874 {MAKEFOURCC('D','X','T','5'), "D3DFMT_DXT5", SUPPORT_DXT5, 4, 4, 16, TRUE, FALSE},
4875 {MAKEFOURCC('Y','U','Y','2'), "D3DFMT_YUY2", SUPPORT_YUY2, 2, 1, 4, FALSE, TRUE },
4876 {MAKEFOURCC('U','Y','V','Y'), "D3DFMT_UYVY", SUPPORT_UYVY, 2, 1, 4, FALSE, TRUE },
4878 static const struct
4880 DWORD caps, caps2;
4881 const char *name;
4882 BOOL overlay;
4884 types[] =
4886 /* DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY fails to create any fourcc
4887 * surface with DDERR_INVALIDPIXELFORMAT. Don't care about it for now.
4889 * Nvidia returns E_FAIL on DXTN DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY.
4890 * Other hw / drivers successfully create those surfaces. Ignore them, this
4891 * suggests that no game uses this, otherwise Nvidia would support it. */
4893 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0,
4894 "videomemory texture", FALSE
4897 DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY, 0,
4898 "videomemory overlay", TRUE
4901 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0,
4902 "systemmemory texture", FALSE
4905 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
4906 "managed texture", FALSE
4909 enum size_type
4911 SIZE_TYPE_ZERO,
4912 SIZE_TYPE_PITCH,
4913 SIZE_TYPE_SIZE,
4915 static const struct
4917 DWORD flags;
4918 enum size_type size_type;
4919 int rel_size;
4920 HRESULT hr;
4922 user_mem_tests[] =
4924 {DDSD_LINEARSIZE, SIZE_TYPE_ZERO, 0, DD_OK},
4925 {DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
4926 {DDSD_PITCH, SIZE_TYPE_ZERO, 0, DD_OK},
4927 {DDSD_PITCH, SIZE_TYPE_PITCH, 0, DD_OK},
4928 {DDSD_LPSURFACE, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
4929 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
4930 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_PITCH, 0, DDERR_INVALIDPARAMS},
4931 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
4932 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 1, DD_OK},
4933 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, -1, DDERR_INVALIDPARAMS},
4934 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
4935 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_PITCH, 0, DDERR_INVALIDPARAMS},
4936 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_SIZE, 0, DDERR_INVALIDPARAMS},
4937 {DDSD_LPSURFACE | DDSD_PITCH | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DDERR_INVALIDPARAMS},
4940 window = create_window();
4941 if (!(device = create_device(window, DDSCL_NORMAL)))
4943 skip("Failed to create a 3D device, skipping test.\n");
4944 DestroyWindow(window);
4945 return;
4948 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
4949 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
4950 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **) &ddraw);
4951 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
4952 IDirect3D7_Release(d3d);
4954 hr = IDirect3DDevice7_EnumTextureFormats(device, test_block_formats_creation_cb,
4955 &supported_fmts);
4956 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
4958 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
4959 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
4960 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
4961 num_fourcc_codes * sizeof(*fourcc_codes));
4962 if (!fourcc_codes)
4963 goto cleanup;
4964 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
4965 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
4966 for (i = 0; i < num_fourcc_codes; i++)
4968 for (j = 0; j < ARRAY_SIZE(formats); ++j)
4970 if (fourcc_codes[i] == formats[j].fourcc)
4971 supported_overlay_fmts |= formats[j].support_flag;
4974 HeapFree(GetProcessHeap(), 0, fourcc_codes);
4976 memset(&hal_caps, 0, sizeof(hal_caps));
4977 hal_caps.dwSize = sizeof(hal_caps);
4978 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
4979 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
4981 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 2 * 2 * 16 + 1);
4983 for (i = 0; i < ARRAY_SIZE(formats); ++i)
4985 for (j = 0; j < ARRAY_SIZE(types); ++j)
4987 BOOL support;
4989 if (formats[i].overlay != types[j].overlay
4990 || (types[j].overlay && !(hal_caps.dwCaps & DDCAPS_OVERLAY)))
4991 continue;
4993 if (formats[i].overlay)
4994 support = supported_overlay_fmts & formats[i].support_flag;
4995 else
4996 support = supported_fmts & formats[i].support_flag;
4998 for (w = 1; w <= 8; w++)
5000 for (h = 1; h <= 8; h++)
5002 BOOL block_aligned = TRUE;
5003 BOOL todo = FALSE;
5005 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
5006 block_aligned = FALSE;
5008 memset(&ddsd, 0, sizeof(ddsd));
5009 ddsd.dwSize = sizeof(ddsd);
5010 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
5011 ddsd.ddsCaps.dwCaps = types[j].caps;
5012 ddsd.ddsCaps.dwCaps2 = types[j].caps2;
5013 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
5014 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
5015 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
5016 ddsd.dwWidth = w;
5017 ddsd.dwHeight = h;
5019 /* TODO: Handle power of two limitations. I cannot test the pow2
5020 * behavior on windows because I have no hardware that doesn't at
5021 * least support np2_conditional. There's probably no HW that
5022 * supports DXTN textures but no conditional np2 textures. */
5023 if (!support && !(types[j].caps & DDSCAPS_SYSTEMMEMORY))
5024 expect_hr = DDERR_INVALIDPARAMS;
5025 else if (formats[i].create_size_checked && !block_aligned)
5027 expect_hr = DDERR_INVALIDPARAMS;
5028 if (!(types[j].caps & DDSCAPS_TEXTURE))
5029 todo = TRUE;
5031 else
5032 expect_hr = D3D_OK;
5034 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5035 todo_wine_if (todo)
5036 ok(hr == expect_hr,
5037 "Got unexpected hr %#x for format %s, resource type %s, size %ux%u, expected %#x.\n",
5038 hr, formats[i].name, types[j].name, w, h, expect_hr);
5040 if (SUCCEEDED(hr))
5041 IDirectDrawSurface7_Release(surface);
5046 if (formats[i].overlay)
5047 continue;
5049 for (j = 0; j < ARRAY_SIZE(user_mem_tests); ++j)
5051 memset(&ddsd, 0, sizeof(ddsd));
5052 ddsd.dwSize = sizeof(ddsd);
5053 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | user_mem_tests[j].flags;
5054 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE;
5056 switch (user_mem_tests[j].size_type)
5058 case SIZE_TYPE_ZERO:
5059 U1(ddsd).dwLinearSize = 0;
5060 break;
5062 case SIZE_TYPE_PITCH:
5063 U1(ddsd).dwLinearSize = 2 * formats[i].block_size;
5064 break;
5066 case SIZE_TYPE_SIZE:
5067 U1(ddsd).dwLinearSize = 2 * 2 * formats[i].block_size;
5068 break;
5070 U1(ddsd).dwLinearSize += user_mem_tests[j].rel_size;
5072 ddsd.lpSurface = mem;
5073 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
5074 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
5075 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
5076 ddsd.dwWidth = 8;
5077 ddsd.dwHeight = 8;
5079 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5080 ok(hr == user_mem_tests[j].hr, "Test %u: Got unexpected hr %#x, format %s.\n", j, hr, formats[i].name);
5082 if (FAILED(hr))
5083 continue;
5085 memset(&ddsd, 0, sizeof(ddsd));
5086 ddsd.dwSize = sizeof(ddsd);
5087 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
5088 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", j, hr);
5089 ok(ddsd.dwFlags == (DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_LINEARSIZE),
5090 "Test %u: Got unexpected flags %#x.\n", j, ddsd.dwFlags);
5091 if (user_mem_tests[j].flags & DDSD_LPSURFACE)
5092 ok(U1(ddsd).dwLinearSize == ~0u, "Test %u: Got unexpected linear size %#x.\n",
5093 j, U1(ddsd).dwLinearSize);
5094 else
5095 ok(U1(ddsd).dwLinearSize == 2 * 2 * formats[i].block_size,
5096 "Test %u: Got unexpected linear size %#x, expected %#x.\n",
5097 j, U1(ddsd).dwLinearSize, 2 * 2 * formats[i].block_size);
5098 IDirectDrawSurface7_Release(surface);
5102 HeapFree(GetProcessHeap(), 0, mem);
5103 cleanup:
5104 IDirectDraw7_Release(ddraw);
5105 IDirect3DDevice7_Release(device);
5106 DestroyWindow(window);
5109 struct format_support_check
5111 const DDPIXELFORMAT *format;
5112 BOOL supported;
5115 static HRESULT WINAPI test_unsupported_formats_cb(DDPIXELFORMAT *fmt, void *ctx)
5117 struct format_support_check *format = ctx;
5119 if (!memcmp(format->format, fmt, sizeof(*fmt)))
5121 format->supported = TRUE;
5122 return DDENUMRET_CANCEL;
5125 return DDENUMRET_OK;
5128 static void test_unsupported_formats(void)
5130 HRESULT hr;
5131 BOOL expect_success;
5132 HWND window;
5133 IDirectDraw7 *ddraw;
5134 IDirect3D7 *d3d;
5135 IDirect3DDevice7 *device;
5136 IDirectDrawSurface7 *surface;
5137 DDSURFACEDESC2 ddsd;
5138 unsigned int i, j;
5139 DWORD expected_caps;
5140 static const struct
5142 const char *name;
5143 DDPIXELFORMAT fmt;
5145 formats[] =
5148 "D3DFMT_A8R8G8B8",
5150 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
5151 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
5155 "D3DFMT_P8",
5157 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
5158 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
5162 static const DWORD caps[] = {0, DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY};
5164 window = create_window();
5165 if (!(device = create_device(window, DDSCL_NORMAL)))
5167 skip("Failed to create a 3D device, skipping test.\n");
5168 DestroyWindow(window);
5169 return;
5172 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
5173 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
5174 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **) &ddraw);
5175 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
5176 IDirect3D7_Release(d3d);
5178 for (i = 0; i < ARRAY_SIZE(formats); ++i)
5180 struct format_support_check check = {&formats[i].fmt, FALSE};
5181 hr = IDirect3DDevice7_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
5182 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
5184 for (j = 0; j < ARRAY_SIZE(caps); ++j)
5186 memset(&ddsd, 0, sizeof(ddsd));
5187 ddsd.dwSize = sizeof(ddsd);
5188 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
5189 U4(ddsd).ddpfPixelFormat = formats[i].fmt;
5190 ddsd.dwWidth = 4;
5191 ddsd.dwHeight = 4;
5192 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | caps[j];
5194 if (caps[j] & DDSCAPS_VIDEOMEMORY && !check.supported)
5195 expect_success = FALSE;
5196 else
5197 expect_success = TRUE;
5199 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5200 ok(SUCCEEDED(hr) == expect_success,
5201 "Got unexpected hr %#x for format %s, caps %#x, expected %s.\n",
5202 hr, formats[i].name, caps[j], expect_success ? "success" : "failure");
5203 if (FAILED(hr))
5204 continue;
5206 memset(&ddsd, 0, sizeof(ddsd));
5207 ddsd.dwSize = sizeof(ddsd);
5208 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
5209 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5211 if (caps[j] & DDSCAPS_VIDEOMEMORY)
5212 expected_caps = DDSCAPS_VIDEOMEMORY;
5213 else if (caps[j] & DDSCAPS_SYSTEMMEMORY)
5214 expected_caps = DDSCAPS_SYSTEMMEMORY;
5215 else if (check.supported)
5216 expected_caps = DDSCAPS_VIDEOMEMORY;
5217 else
5218 expected_caps = DDSCAPS_SYSTEMMEMORY;
5220 ok(ddsd.ddsCaps.dwCaps & expected_caps,
5221 "Expected capability %#x, format %s, input cap %#x.\n",
5222 expected_caps, formats[i].name, caps[j]);
5224 IDirectDrawSurface7_Release(surface);
5228 IDirectDraw7_Release(ddraw);
5229 IDirect3DDevice7_Release(device);
5230 DestroyWindow(window);
5233 static void test_rt_caps(void)
5235 const GUID *devtype = &IID_IDirect3DHALDevice;
5236 PALETTEENTRY palette_entries[256];
5237 IDirectDrawPalette *palette;
5238 IDirectDraw7 *ddraw;
5239 BOOL hal_ok = FALSE;
5240 DDPIXELFORMAT z_fmt;
5241 IDirect3D7 *d3d;
5242 unsigned int i;
5243 ULONG refcount;
5244 HWND window;
5245 HRESULT hr;
5247 static const DDPIXELFORMAT p8_fmt =
5249 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
5250 {8}, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000},
5253 const struct
5255 const DDPIXELFORMAT *pf;
5256 DWORD caps_in;
5257 DWORD caps_out;
5258 HRESULT create_device_hr;
5259 HRESULT set_rt_hr, alternative_set_rt_hr;
5261 test_data[] =
5264 NULL,
5265 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
5266 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5267 D3D_OK,
5268 D3D_OK,
5269 D3D_OK,
5272 NULL,
5273 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5274 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5275 D3D_OK,
5276 D3D_OK,
5277 D3D_OK,
5280 NULL,
5281 DDSCAPS_OFFSCREENPLAIN,
5282 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5283 DDERR_INVALIDCAPS,
5284 DDERR_INVALIDCAPS,
5285 DDERR_INVALIDCAPS,
5288 NULL,
5289 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5290 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5291 D3DERR_SURFACENOTINVIDMEM,
5292 DDERR_INVALIDPARAMS,
5293 D3D_OK,
5296 NULL,
5297 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5298 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5299 DDERR_INVALIDCAPS,
5300 DDERR_INVALIDCAPS,
5301 DDERR_INVALIDCAPS,
5304 NULL,
5305 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
5306 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5307 D3D_OK,
5308 D3D_OK,
5309 D3D_OK,
5312 NULL,
5313 DDSCAPS_3DDEVICE,
5314 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5315 D3D_OK,
5316 D3D_OK,
5317 D3D_OK,
5320 NULL,
5322 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5323 DDERR_INVALIDCAPS,
5324 DDERR_INVALIDCAPS,
5325 DDERR_INVALIDCAPS,
5328 NULL,
5329 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5330 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5331 D3DERR_SURFACENOTINVIDMEM,
5332 DDERR_INVALIDPARAMS,
5333 D3D_OK,
5336 NULL,
5337 DDSCAPS_SYSTEMMEMORY,
5338 DDSCAPS_SYSTEMMEMORY,
5339 DDERR_INVALIDCAPS,
5340 DDERR_INVALIDCAPS,
5341 DDERR_INVALIDCAPS,
5344 &p8_fmt,
5346 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5347 DDERR_INVALIDCAPS,
5348 DDERR_INVALIDCAPS,
5349 DDERR_INVALIDCAPS,
5352 &p8_fmt,
5353 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5354 ~0U /* AMD r200 */,
5355 DDERR_NOPALETTEATTACHED,
5356 DDERR_INVALIDCAPS,
5357 DDERR_INVALIDCAPS,
5360 &p8_fmt,
5361 DDSCAPS_OFFSCREENPLAIN,
5362 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5363 DDERR_INVALIDCAPS,
5364 DDERR_INVALIDCAPS,
5365 DDERR_INVALIDCAPS,
5368 &p8_fmt,
5369 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5370 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5371 DDERR_NOPALETTEATTACHED,
5372 DDERR_INVALIDCAPS,
5373 DDERR_INVALIDCAPS,
5376 &p8_fmt,
5377 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5378 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5379 DDERR_INVALIDCAPS,
5380 DDERR_INVALIDCAPS,
5381 DDERR_INVALIDCAPS,
5384 &z_fmt,
5385 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
5386 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5387 DDERR_INVALIDCAPS,
5388 DDERR_INVALIDPIXELFORMAT,
5389 DDERR_INVALIDPIXELFORMAT,
5392 &z_fmt,
5393 DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5394 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5395 DDERR_INVALIDCAPS,
5396 DDERR_INVALIDPIXELFORMAT,
5397 DDERR_INVALIDPIXELFORMAT,
5400 &z_fmt,
5401 DDSCAPS_ZBUFFER,
5402 DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5403 DDERR_INVALIDCAPS,
5404 DDERR_INVALIDCAPS,
5405 DDERR_INVALIDCAPS,
5408 &z_fmt,
5409 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5410 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5411 DDERR_INVALIDCAPS,
5412 DDERR_INVALIDPARAMS,
5413 DDERR_INVALIDPIXELFORMAT,
5416 &z_fmt,
5417 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
5418 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
5419 DDERR_INVALIDCAPS,
5420 DDERR_INVALIDCAPS,
5421 DDERR_INVALIDCAPS,
5425 window = create_window();
5426 ddraw = create_ddraw();
5427 ok(!!ddraw, "Failed to create a ddraw object.\n");
5428 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5429 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5431 if (FAILED(IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d)))
5433 skip("D3D interface is not available, skipping test.\n");
5434 goto done;
5437 hr = IDirect3D7_EnumDevices(d3d, enum_devtype_cb, &hal_ok);
5438 ok(SUCCEEDED(hr), "Failed to enumerate devices, hr %#x.\n", hr);
5439 if (hal_ok)
5440 devtype = &IID_IDirect3DTnLHalDevice;
5442 memset(&z_fmt, 0, sizeof(z_fmt));
5443 hr = IDirect3D7_EnumZBufferFormats(d3d, devtype, enum_z_fmt, &z_fmt);
5444 if (FAILED(hr) || !z_fmt.dwSize)
5446 skip("No depth buffer formats available, skipping test.\n");
5447 IDirect3D7_Release(d3d);
5448 goto done;
5451 memset(palette_entries, 0, sizeof(palette_entries));
5452 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
5453 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
5455 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
5457 IDirectDrawSurface7 *surface, *rt, *expected_rt, *tmp;
5458 DDSURFACEDESC2 surface_desc;
5459 IDirect3DDevice7 *device;
5461 memset(&surface_desc, 0, sizeof(surface_desc));
5462 surface_desc.dwSize = sizeof(surface_desc);
5463 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5464 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5465 if (test_data[i].pf)
5467 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
5468 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
5470 surface_desc.dwWidth = 640;
5471 surface_desc.dwHeight = 480;
5472 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5473 ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
5474 i, test_data[i].caps_in, hr);
5476 memset(&surface_desc, 0, sizeof(surface_desc));
5477 surface_desc.dwSize = sizeof(surface_desc);
5478 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
5479 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
5480 ok(test_data[i].caps_out == ~0U || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out,
5481 "Test %u: Got unexpected caps %#x, expected %#x.\n",
5482 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
5484 hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
5485 ok(hr == test_data[i].create_device_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n",
5486 i, hr, test_data[i].create_device_hr);
5487 if (FAILED(hr))
5489 if (hr == DDERR_NOPALETTEATTACHED)
5491 hr = IDirectDrawSurface7_SetPalette(surface, palette);
5492 ok(SUCCEEDED(hr), "Test %u: Failed to set palette, hr %#x.\n", i, hr);
5493 hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
5494 if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
5495 ok(hr == DDERR_INVALIDPIXELFORMAT, "Test %u: Got unexpected hr %#x.\n", i, hr);
5496 else
5497 ok(hr == D3DERR_SURFACENOTINVIDMEM, "Test %u: Got unexpected hr %#x.\n", i, hr);
5499 IDirectDrawSurface7_Release(surface);
5501 memset(&surface_desc, 0, sizeof(surface_desc));
5502 surface_desc.dwSize = sizeof(surface_desc);
5503 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5504 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
5505 surface_desc.dwWidth = 640;
5506 surface_desc.dwHeight = 480;
5507 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5508 ok(SUCCEEDED(hr), "Test %u: Failed to create surface, hr %#x.\n", i, hr);
5510 hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
5511 ok(SUCCEEDED(hr), "Test %u: Failed to create device, hr %#x.\n", i, hr);
5514 memset(&surface_desc, 0, sizeof(surface_desc));
5515 surface_desc.dwSize = sizeof(surface_desc);
5516 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5517 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5518 if (test_data[i].pf)
5520 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
5521 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
5523 surface_desc.dwWidth = 640;
5524 surface_desc.dwHeight = 480;
5525 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &rt, NULL);
5526 ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
5527 i, test_data[i].caps_in, hr);
5529 hr = IDirect3DDevice7_SetRenderTarget(device, rt, 0);
5530 ok(hr == test_data[i].set_rt_hr || broken(hr == test_data[i].alternative_set_rt_hr),
5531 "Test %u: Got unexpected hr %#x, expected %#x.\n",
5532 i, hr, test_data[i].set_rt_hr);
5533 if (SUCCEEDED(hr) || hr == DDERR_INVALIDPIXELFORMAT)
5534 expected_rt = rt;
5535 else
5536 expected_rt = surface;
5538 hr = IDirect3DDevice7_GetRenderTarget(device, &tmp);
5539 ok(SUCCEEDED(hr), "Test %u: Failed to get render target, hr %#x.\n", i, hr);
5540 ok(tmp == expected_rt, "Test %u: Got unexpected rt %p.\n", i, tmp);
5542 IDirectDrawSurface7_Release(tmp);
5543 IDirectDrawSurface7_Release(rt);
5544 refcount = IDirect3DDevice7_Release(device);
5545 ok(refcount == 0, "Test %u: The device was not properly freed, refcount %u.\n", i, refcount);
5546 refcount = IDirectDrawSurface7_Release(surface);
5547 ok(refcount == 0, "Test %u: The surface was not properly freed, refcount %u.\n", i, refcount);
5550 IDirectDrawPalette_Release(palette);
5551 IDirect3D7_Release(d3d);
5553 done:
5554 refcount = IDirectDraw7_Release(ddraw);
5555 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5556 DestroyWindow(window);
5559 static void test_primary_caps(void)
5561 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
5562 IDirectDrawSurface7 *surface;
5563 DDSURFACEDESC2 surface_desc;
5564 IDirectDraw7 *ddraw;
5565 unsigned int i;
5566 ULONG refcount;
5567 HWND window;
5568 HRESULT hr;
5570 static const struct
5572 DWORD coop_level;
5573 DWORD caps_in;
5574 DWORD back_buffer_count;
5575 HRESULT hr;
5576 DWORD caps_out;
5578 test_data[] =
5581 DDSCL_NORMAL,
5582 DDSCAPS_PRIMARYSURFACE,
5583 ~0u,
5584 DD_OK,
5585 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE,
5588 DDSCL_NORMAL,
5589 DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE,
5590 ~0u,
5591 DDERR_INVALIDCAPS,
5592 ~0u,
5595 DDSCL_NORMAL,
5596 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
5597 ~0u,
5598 DDERR_INVALIDCAPS,
5599 ~0u,
5602 DDSCL_NORMAL,
5603 DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER,
5604 ~0u,
5605 DDERR_INVALIDCAPS,
5606 ~0u,
5609 DDSCL_NORMAL,
5610 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP,
5611 ~0u,
5612 DDERR_INVALIDCAPS,
5613 ~0u,
5616 DDSCL_NORMAL,
5617 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX,
5618 ~0u,
5619 DDERR_INVALIDCAPS,
5620 ~0u,
5623 DDSCL_NORMAL,
5624 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5625 ~0u,
5626 DDERR_INVALIDCAPS,
5627 ~0u,
5630 DDSCL_NORMAL,
5631 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5633 DDERR_INVALIDCAPS,
5634 ~0u,
5637 DDSCL_NORMAL,
5638 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5640 DDERR_NOEXCLUSIVEMODE,
5641 ~0u,
5644 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5645 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5647 DDERR_INVALIDCAPS,
5648 ~0u,
5651 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5652 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5654 DD_OK,
5655 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX,
5658 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5659 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER,
5661 DDERR_INVALIDCAPS,
5662 ~0u,
5665 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5666 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_BACKBUFFER,
5668 DDERR_INVALIDCAPS,
5669 ~0u,
5673 window = create_window();
5674 ddraw = create_ddraw();
5675 ok(!!ddraw, "Failed to create a ddraw object.\n");
5677 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
5679 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, test_data[i].coop_level);
5680 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5682 memset(&surface_desc, 0, sizeof(surface_desc));
5683 surface_desc.dwSize = sizeof(surface_desc);
5684 surface_desc.dwFlags = DDSD_CAPS;
5685 if (test_data[i].back_buffer_count != ~0u)
5686 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
5687 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5688 U5(surface_desc).dwBackBufferCount = test_data[i].back_buffer_count;
5689 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5690 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
5691 if (FAILED(hr))
5692 continue;
5694 memset(&surface_desc, 0, sizeof(surface_desc));
5695 surface_desc.dwSize = sizeof(surface_desc);
5696 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
5697 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
5698 ok((surface_desc.ddsCaps.dwCaps & ~placement) == test_data[i].caps_out,
5699 "Test %u: Got unexpected caps %#x, expected %#x.\n",
5700 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
5702 IDirectDrawSurface7_Release(surface);
5705 refcount = IDirectDraw7_Release(ddraw);
5706 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5707 DestroyWindow(window);
5710 static void test_surface_lock(void)
5712 IDirectDraw7 *ddraw;
5713 IDirect3D7 *d3d = NULL;
5714 IDirectDrawSurface7 *surface;
5715 IDirect3DDevice7 *device;
5716 HRESULT hr, expected_hr;
5717 HWND window;
5718 unsigned int i;
5719 DDSURFACEDESC2 ddsd;
5720 ULONG refcount;
5721 DDPIXELFORMAT z_fmt;
5722 BOOL hal_ok = FALSE;
5723 const GUID *devtype = &IID_IDirect3DHALDevice;
5724 D3DDEVICEDESC7 device_desc;
5725 BOOL cubemap_supported;
5726 static const struct
5728 DWORD caps;
5729 DWORD caps2;
5730 const char *name;
5732 tests[] =
5735 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
5737 "videomemory offscreenplain"
5740 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5742 "systemmemory offscreenplain"
5745 DDSCAPS_PRIMARYSURFACE,
5747 "primary"
5750 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
5752 "videomemory texture"
5755 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
5756 DDSCAPS2_OPAQUE,
5757 "opaque videomemory texture"
5760 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
5762 "systemmemory texture"
5765 DDSCAPS_TEXTURE,
5766 DDSCAPS2_TEXTUREMANAGE,
5767 "managed texture"
5770 DDSCAPS_TEXTURE,
5771 DDSCAPS2_D3DTEXTUREMANAGE,
5772 "managed texture"
5775 DDSCAPS_TEXTURE,
5776 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_OPAQUE,
5777 "opaque managed texture"
5780 DDSCAPS_TEXTURE,
5781 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_OPAQUE,
5782 "opaque managed texture"
5785 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5787 "render target"
5790 DDSCAPS_ZBUFFER,
5792 "Z buffer"
5795 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY,
5796 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
5797 "videomemory cube"
5800 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY,
5801 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_OPAQUE,
5802 "opaque videomemory cube"
5805 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_SYSTEMMEMORY,
5806 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
5807 "systemmemory cube"
5810 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
5811 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
5812 "managed cube"
5815 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
5816 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
5817 "managed cube"
5820 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
5821 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_OPAQUE,
5822 "opaque managed cube"
5825 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
5826 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_OPAQUE,
5827 "opaque managed cube"
5831 window = create_window();
5832 ddraw = create_ddraw();
5833 ok(!!ddraw, "Failed to create a ddraw object.\n");
5834 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5835 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5837 if (FAILED(IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d)))
5839 skip("D3D interface is not available, skipping test.\n");
5840 goto done;
5843 hr = IDirect3D7_EnumDevices(d3d, enum_devtype_cb, &hal_ok);
5844 ok(SUCCEEDED(hr), "Failed to enumerate devices, hr %#x.\n", hr);
5845 if (hal_ok)
5846 devtype = &IID_IDirect3DTnLHalDevice;
5848 memset(&z_fmt, 0, sizeof(z_fmt));
5849 hr = IDirect3D7_EnumZBufferFormats(d3d, devtype, enum_z_fmt, &z_fmt);
5850 if (FAILED(hr) || !z_fmt.dwSize)
5852 skip("No depth buffer formats available, skipping test.\n");
5853 goto done;
5856 memset(&ddsd, 0, sizeof(ddsd));
5857 ddsd.dwSize = sizeof(ddsd);
5858 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5859 ddsd.dwWidth = 64;
5860 ddsd.dwHeight = 64;
5861 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
5862 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5863 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5865 hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
5866 ok(SUCCEEDED(hr), "Failed to create device, hr %#x.\n", hr);
5867 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
5868 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5869 cubemap_supported = !!(device_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP);
5870 IDirect3DDevice7_Release(device);
5872 IDirectDrawSurface7_Release(surface);
5874 for (i = 0; i < ARRAY_SIZE(tests); ++i)
5876 if (!cubemap_supported && tests[i].caps2 & DDSCAPS2_CUBEMAP)
5877 continue;
5879 memset(&ddsd, 0, sizeof(ddsd));
5880 ddsd.dwSize = sizeof(ddsd);
5881 ddsd.dwFlags = DDSD_CAPS;
5882 if (!(tests[i].caps & DDSCAPS_PRIMARYSURFACE))
5884 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
5885 ddsd.dwWidth = 64;
5886 ddsd.dwHeight = 64;
5888 if (tests[i].caps & DDSCAPS_ZBUFFER)
5890 ddsd.dwFlags |= DDSD_PIXELFORMAT;
5891 U4(ddsd).ddpfPixelFormat = z_fmt;
5893 ddsd.ddsCaps.dwCaps = tests[i].caps;
5894 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
5896 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5897 ok(SUCCEEDED(hr), "Failed to create surface, type %s, hr %#x.\n", tests[i].name, hr);
5899 memset(&ddsd, 0, sizeof(ddsd));
5900 ddsd.dwSize = sizeof(ddsd);
5901 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
5902 ok(SUCCEEDED(hr), "Failed to lock surface, type %s, hr %#x.\n", tests[i].name, hr);
5903 if (SUCCEEDED(hr))
5905 ok(ddsd.dwSize == sizeof(ddsd), "Got unexpected dwSize %u, type %s.\n", ddsd.dwSize, tests[i].name);
5906 hr = IDirectDrawSurface7_Unlock(surface, NULL);
5907 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
5910 memset(&ddsd, 0, sizeof(ddsd));
5911 expected_hr = tests[i].caps & DDSCAPS_TEXTURE && !(tests[i].caps & DDSCAPS_VIDEOMEMORY)
5912 ? DD_OK : DDERR_INVALIDPARAMS;
5913 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
5914 ok(hr == expected_hr, "Got hr %#x, expected %#x, type %s.\n", hr, expected_hr, tests[i].name);
5915 if (SUCCEEDED(hr))
5917 ok(!ddsd.dwSize, "Got unexpected dwSize %u, type %s.\n", ddsd.dwSize, tests[i].name);
5918 ok(!!ddsd.lpSurface, "Got NULL lpSurface, type %s.\n", tests[i].name);
5919 hr = IDirectDrawSurface7_Unlock(surface, NULL);
5920 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
5923 IDirectDrawSurface7_Release(surface);
5926 done:
5927 if (d3d)
5928 IDirect3D7_Release(d3d);
5929 refcount = IDirectDraw7_Release(ddraw);
5930 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5931 DestroyWindow(window);
5934 static void test_surface_discard(void)
5936 IDirect3DDevice7 *device;
5937 IDirect3D7 *d3d;
5938 IDirectDraw7 *ddraw;
5939 HRESULT hr;
5940 HWND window;
5941 DDSURFACEDESC2 ddsd;
5942 IDirectDrawSurface7 *surface, *target;
5943 void *addr;
5944 static const struct
5946 DWORD caps, caps2;
5947 BOOL discard;
5949 tests[] =
5951 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, TRUE},
5952 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
5953 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, TRUE},
5954 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
5955 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE},
5956 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
5957 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE},
5958 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
5960 unsigned int i;
5962 window = create_window();
5963 if (!(device = create_device(window, DDSCL_NORMAL)))
5965 skip("Failed to create a 3D device, skipping test.\n");
5966 DestroyWindow(window);
5967 return;
5969 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
5970 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
5971 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
5972 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
5973 hr = IDirect3DDevice7_GetRenderTarget(device, &target);
5974 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
5976 for (i = 0; i < ARRAY_SIZE(tests); ++i)
5978 BOOL discarded;
5980 memset(&ddsd, 0, sizeof(ddsd));
5981 ddsd.dwSize = sizeof(ddsd);
5982 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5983 ddsd.ddsCaps.dwCaps = tests[i].caps;
5984 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
5985 ddsd.dwWidth = 64;
5986 ddsd.dwHeight = 64;
5987 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5988 ok(SUCCEEDED(hr), "Failed to create offscreen surface, hr %#x, case %u.\n", hr, i);
5990 memset(&ddsd, 0, sizeof(ddsd));
5991 ddsd.dwSize = sizeof(ddsd);
5992 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, 0, NULL);
5993 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5994 addr = ddsd.lpSurface;
5995 hr = IDirectDrawSurface7_Unlock(surface, NULL);
5996 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5998 memset(&ddsd, 0, sizeof(ddsd));
5999 ddsd.dwSize = sizeof(ddsd);
6000 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
6001 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6002 discarded = ddsd.lpSurface != addr;
6003 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6004 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6006 hr = IDirectDrawSurface7_Blt(target, NULL, surface, NULL, DDBLT_WAIT, NULL);
6007 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
6009 memset(&ddsd, 0, sizeof(ddsd));
6010 ddsd.dwSize = sizeof(ddsd);
6011 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
6012 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6013 discarded |= ddsd.lpSurface != addr;
6014 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6015 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6017 IDirectDrawSurface7_Release(surface);
6019 /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler,
6020 * AMD r500, evergreen). Windows XP, at least on AMD r200, does not. */
6021 ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i);
6024 IDirectDrawSurface7_Release(target);
6025 IDirectDraw7_Release(ddraw);
6026 IDirect3D7_Release(d3d);
6027 IDirect3DDevice7_Release(device);
6028 DestroyWindow(window);
6031 static void fill_surface(IDirectDrawSurface7 *surface, D3DCOLOR color)
6033 DDSURFACEDESC2 surface_desc = {sizeof(surface_desc)};
6034 HRESULT hr;
6035 unsigned int x, y;
6036 DWORD *ptr;
6038 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
6039 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6041 for (y = 0; y < surface_desc.dwHeight; ++y)
6043 ptr = (DWORD *)((BYTE *)surface_desc.lpSurface + y * surface_desc.lPitch);
6044 for (x = 0; x < surface_desc.dwWidth; ++x)
6046 ptr[x] = color;
6050 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6051 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6054 static void test_flip(void)
6056 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
6057 IDirectDrawSurface7 *frontbuffer, *backbuffer1, *backbuffer2, *backbuffer3, *surface;
6058 DDSCAPS2 caps = {DDSCAPS_FLIP, 0, 0, {0}};
6059 DDSURFACEDESC2 surface_desc;
6060 D3DDEVICEDESC7 device_desc;
6061 IDirect3DDevice7 *device;
6062 BOOL sysmem_primary;
6063 IDirectDraw7 *ddraw;
6064 DWORD expected_caps;
6065 unsigned int i;
6066 D3DCOLOR color;
6067 ULONG refcount;
6068 HWND window;
6069 HRESULT hr;
6071 static const struct
6073 const char *name;
6074 DWORD caps;
6076 test_data[] =
6078 {"PRIMARYSURFACE", DDSCAPS_PRIMARYSURFACE},
6079 {"OFFSCREENPLAIN", DDSCAPS_OFFSCREENPLAIN},
6080 {"TEXTURE", DDSCAPS_TEXTURE},
6083 window = create_window();
6084 ddraw = create_ddraw();
6085 ok(!!ddraw, "Failed to create a ddraw object.\n");
6087 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6088 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6090 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
6092 /* Creating a flippable texture induces a BSoD on some versions of the
6093 * Intel graphics driver. At least Intel GMA 950 with driver version
6094 * 6.14.10.4926 on Windows XP SP3 is affected. */
6095 if ((test_data[i].caps & DDSCAPS_TEXTURE) && ddraw_is_intel(ddraw))
6097 win_skip("Skipping flippable texture test.\n");
6098 continue;
6101 memset(&surface_desc, 0, sizeof(surface_desc));
6102 surface_desc.dwSize = sizeof(surface_desc);
6103 surface_desc.dwFlags = DDSD_CAPS;
6104 if (!(test_data[i].caps & DDSCAPS_PRIMARYSURFACE))
6105 surface_desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
6106 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
6107 surface_desc.dwWidth = 512;
6108 surface_desc.dwHeight = 512;
6109 U5(surface_desc).dwBackBufferCount = 3;
6110 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6111 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6113 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_FLIP;
6114 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
6115 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6116 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6118 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_COMPLEX;
6119 surface_desc.ddsCaps.dwCaps |= DDSCAPS_FLIP;
6120 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6121 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6123 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
6124 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6125 if (is_ddraw64 && test_data[i].caps & DDSCAPS_TEXTURE)
6126 todo_wine ok(hr == E_NOINTERFACE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6127 else todo_wine_if(test_data[i].caps & DDSCAPS_TEXTURE)
6128 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
6129 if (FAILED(hr))
6130 continue;
6132 memset(&surface_desc, 0, sizeof(surface_desc));
6133 surface_desc.dwSize = sizeof(surface_desc);
6134 hr = IDirectDrawSurface7_GetSurfaceDesc(frontbuffer, &surface_desc);
6135 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6136 expected_caps = DDSCAPS_FRONTBUFFER | DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
6137 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
6138 expected_caps |= DDSCAPS_VISIBLE;
6139 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6140 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6141 sysmem_primary = surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
6143 hr = IDirectDrawSurface7_GetAttachedSurface(frontbuffer, &caps, &backbuffer1);
6144 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6145 memset(&surface_desc, 0, sizeof(surface_desc));
6146 surface_desc.dwSize = sizeof(surface_desc);
6147 hr = IDirectDrawSurface7_GetSurfaceDesc(backbuffer1, &surface_desc);
6148 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6149 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
6150 test_data[i].name, U5(surface_desc).dwBackBufferCount);
6151 expected_caps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER);
6152 expected_caps |= DDSCAPS_BACKBUFFER;
6153 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6154 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6156 hr = IDirectDrawSurface7_GetAttachedSurface(backbuffer1, &caps, &backbuffer2);
6157 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6158 memset(&surface_desc, 0, sizeof(surface_desc));
6159 surface_desc.dwSize = sizeof(surface_desc);
6160 hr = IDirectDrawSurface7_GetSurfaceDesc(backbuffer2, &surface_desc);
6161 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6162 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
6163 test_data[i].name, U5(surface_desc).dwBackBufferCount);
6164 expected_caps &= ~DDSCAPS_BACKBUFFER;
6165 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6166 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6168 hr = IDirectDrawSurface7_GetAttachedSurface(backbuffer2, &caps, &backbuffer3);
6169 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6170 memset(&surface_desc, 0, sizeof(surface_desc));
6171 surface_desc.dwSize = sizeof(surface_desc);
6172 hr = IDirectDrawSurface7_GetSurfaceDesc(backbuffer3, &surface_desc);
6173 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6174 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
6175 test_data[i].name, U5(surface_desc).dwBackBufferCount);
6176 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6177 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6179 hr = IDirectDrawSurface7_GetAttachedSurface(backbuffer3, &caps, &surface);
6180 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6181 ok(surface == frontbuffer, "%s: Got unexpected surface %p, expected %p.\n",
6182 test_data[i].name, surface, frontbuffer);
6183 IDirectDrawSurface7_Release(surface);
6185 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
6186 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
6187 hr = IDirectDrawSurface7_IsLost(frontbuffer);
6188 ok(hr == DD_OK, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6189 hr = IDirectDrawSurface7_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6190 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
6191 ok(hr == DDERR_NOEXCLUSIVEMODE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6192 else
6193 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6194 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6195 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
6196 hr = IDirectDrawSurface7_IsLost(frontbuffer);
6197 todo_wine ok(hr == DDERR_SURFACELOST, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6198 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
6199 ok(SUCCEEDED(hr), "%s: Failed to restore surfaces, hr %#x.\n", test_data[i].name, hr);
6201 memset(&surface_desc, 0, sizeof(surface_desc));
6202 surface_desc.dwSize = sizeof(surface_desc);
6203 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6204 surface_desc.ddsCaps.dwCaps = 0;
6205 surface_desc.dwWidth = 640;
6206 surface_desc.dwHeight = 480;
6207 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6208 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
6209 hr = IDirectDrawSurface7_Flip(frontbuffer, surface, DDFLIP_WAIT);
6210 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6211 IDirectDrawSurface7_Release(surface);
6213 hr = IDirectDrawSurface7_Flip(frontbuffer, frontbuffer, DDFLIP_WAIT);
6214 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6215 hr = IDirectDrawSurface7_Flip(backbuffer1, NULL, DDFLIP_WAIT);
6216 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6217 hr = IDirectDrawSurface7_Flip(backbuffer2, NULL, DDFLIP_WAIT);
6218 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6219 hr = IDirectDrawSurface7_Flip(backbuffer3, NULL, DDFLIP_WAIT);
6220 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6222 /* The Nvidia Geforce 7 driver cannot do a color fill on a texture backbuffer after
6223 * the backbuffer has been locked. Do it ourselves as a workaround. Unlike ddraw1
6224 * and 2 GetSurfaceDesc does not cause issues in ddraw4 and ddraw7. */
6225 fill_surface(backbuffer1, 0xffff0000);
6226 fill_surface(backbuffer2, 0xff00ff00);
6227 fill_surface(backbuffer3, 0xff0000ff);
6229 hr = IDirectDrawSurface7_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6230 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6231 color = get_surface_color(backbuffer1, 320, 240);
6232 /* The testbot seems to just copy the contents of one surface to all the
6233 * others, instead of properly flipping. */
6234 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
6235 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6236 color = get_surface_color(backbuffer2, 320, 240);
6237 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6238 fill_surface(backbuffer3, 0xffff0000);
6240 hr = IDirectDrawSurface7_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6241 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6242 color = get_surface_color(backbuffer1, 320, 240);
6243 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
6244 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6245 color = get_surface_color(backbuffer2, 320, 240);
6246 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6247 fill_surface(backbuffer3, 0xff00ff00);
6249 hr = IDirectDrawSurface7_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6250 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6251 color = get_surface_color(backbuffer1, 320, 240);
6252 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
6253 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6254 color = get_surface_color(backbuffer2, 320, 240);
6255 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6256 fill_surface(backbuffer3, 0xff0000ff);
6258 hr = IDirectDrawSurface7_Flip(frontbuffer, backbuffer1, DDFLIP_WAIT);
6259 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6260 color = get_surface_color(backbuffer2, 320, 240);
6261 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
6262 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6263 color = get_surface_color(backbuffer3, 320, 240);
6264 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6265 fill_surface(backbuffer1, 0xffff0000);
6267 hr = IDirectDrawSurface7_Flip(frontbuffer, backbuffer2, DDFLIP_WAIT);
6268 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6269 color = get_surface_color(backbuffer1, 320, 240);
6270 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6271 color = get_surface_color(backbuffer3, 320, 240);
6272 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
6273 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6274 fill_surface(backbuffer2, 0xff00ff00);
6276 hr = IDirectDrawSurface7_Flip(frontbuffer, backbuffer3, DDFLIP_WAIT);
6277 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6278 color = get_surface_color(backbuffer1, 320, 240);
6279 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
6280 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6281 color = get_surface_color(backbuffer2, 320, 240);
6282 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6284 IDirectDrawSurface7_Release(backbuffer3);
6285 IDirectDrawSurface7_Release(backbuffer2);
6286 IDirectDrawSurface7_Release(backbuffer1);
6287 IDirectDrawSurface7_Release(frontbuffer);
6290 if (!(device = create_device(window, DDSCL_NORMAL)))
6292 skip("Failed to create 3D device.\n");
6293 goto done;
6295 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
6296 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6297 IDirect3DDevice7_Release(device);
6298 if (!(device_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP))
6300 skip("Cubemaps are not supported.\n");
6301 goto done;
6304 memset(&surface_desc, 0, sizeof(surface_desc));
6305 surface_desc.dwSize = sizeof(surface_desc);
6306 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6307 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_TEXTURE;
6308 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
6309 surface_desc.dwWidth = 128;
6310 surface_desc.dwHeight = 128;
6311 U5(surface_desc).dwBackBufferCount = 3;
6312 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6313 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x.\n", hr);
6315 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_FLIP;
6316 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
6317 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6318 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6320 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_COMPLEX;
6321 surface_desc.ddsCaps.dwCaps |= DDSCAPS_FLIP;
6322 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6323 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x.\n", hr);
6325 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
6326 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6327 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6329 U5(surface_desc).dwBackBufferCount = 1;
6330 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6331 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6333 U5(surface_desc).dwBackBufferCount = 0;
6334 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6335 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x.\n", hr);
6337 done:
6338 refcount = IDirectDraw7_Release(ddraw);
6339 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
6340 DestroyWindow(window);
6343 static void reset_ddsd(DDSURFACEDESC2 *ddsd)
6345 memset(ddsd, 0, sizeof(*ddsd));
6346 ddsd->dwSize = sizeof(*ddsd);
6349 static void test_set_surface_desc(void)
6351 IDirectDraw7 *ddraw;
6352 HWND window;
6353 HRESULT hr;
6354 DDSURFACEDESC2 ddsd;
6355 IDirectDrawSurface7 *surface;
6356 BYTE data[16*16*4];
6357 ULONG ref;
6358 unsigned int i;
6359 static const struct
6361 DWORD caps, caps2;
6362 BOOL supported;
6363 const char *name;
6365 invalid_caps_tests[] =
6367 {DDSCAPS_VIDEOMEMORY, 0, FALSE, "videomemory plain"},
6368 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, TRUE, "systemmemory texture"},
6369 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE, "managed texture"},
6370 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE, "managed texture"},
6371 {DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY, 0, FALSE, "systemmemory primary"},
6374 window = create_window();
6375 ddraw = create_ddraw();
6376 ok(!!ddraw, "Failed to create a ddraw object.\n");
6377 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6378 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6380 reset_ddsd(&ddsd);
6381 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
6382 ddsd.dwWidth = 8;
6383 ddsd.dwHeight = 8;
6384 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6385 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6386 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6387 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6388 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6389 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6390 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6392 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6393 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6395 reset_ddsd(&ddsd);
6396 ddsd.dwFlags = DDSD_LPSURFACE;
6397 ddsd.lpSurface = data;
6398 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6399 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6401 /* Redundantly setting the same lpSurface is not an error. */
6402 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6403 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6405 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6406 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6407 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
6408 ok(ddsd.lpSurface == NULL, "lpSurface is %p, expected NULL.\n", ddsd.lpSurface);
6410 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, 0, NULL);
6411 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6412 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
6413 ok(ddsd.lpSurface == data, "lpSurface is %p, expected %p.\n", data, data);
6414 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6415 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6417 reset_ddsd(&ddsd);
6418 ddsd.dwFlags = DDSD_LPSURFACE;
6419 ddsd.lpSurface = data;
6420 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 1);
6421 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with flags=1 returned %#x.\n", hr);
6423 ddsd.lpSurface = NULL;
6424 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6425 ok(hr == DDERR_INVALIDPARAMS, "Setting lpSurface=NULL returned %#x.\n", hr);
6427 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, NULL, 0);
6428 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with NULL desc returned %#x.\n", hr);
6430 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6431 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6432 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
6433 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
6434 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#x.\n", 0);
6436 /* Setting the caps is an error. This also means the original description cannot be reapplied. */
6437 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6438 ok(hr == DDERR_INVALIDPARAMS, "Setting the original desc returned %#x.\n", hr);
6440 ddsd.dwFlags = DDSD_CAPS;
6441 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6442 ok(hr == DDERR_INVALIDPARAMS, "Setting DDSD_CAPS returned %#x.\n", hr);
6444 /* dwCaps = 0 is allowed, but ignored. Caps2 can be anything and is ignored too. */
6445 ddsd.dwFlags = DDSD_CAPS | DDSD_LPSURFACE;
6446 ddsd.lpSurface = data;
6447 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6448 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
6449 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6450 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6451 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
6452 ddsd.ddsCaps.dwCaps = 0;
6453 ddsd.ddsCaps.dwCaps2 = 0xdeadbeef;
6454 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6455 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6457 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6458 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6459 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
6460 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
6461 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#x.\n", 0);
6463 /* Setting the height is allowed, but it cannot be set to 0, and only if LPSURFACE is set too. */
6464 reset_ddsd(&ddsd);
6465 ddsd.dwFlags = DDSD_HEIGHT;
6466 ddsd.dwHeight = 16;
6467 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6468 ok(hr == DDERR_INVALIDPARAMS, "Setting height without lpSurface returned %#x.\n", hr);
6470 ddsd.lpSurface = data;
6471 ddsd.dwFlags = DDSD_HEIGHT | DDSD_LPSURFACE;
6472 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6473 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6475 ddsd.dwHeight = 0;
6476 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6477 ok(hr == DDERR_INVALIDPARAMS, "Setting height=0 returned %#x.\n", hr);
6479 reset_ddsd(&ddsd);
6480 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6481 ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr);
6482 ok(ddsd.dwWidth == 8, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
6483 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
6485 /* Pitch and width can be set, but only together, and only with LPSURFACE. They must not be 0. */
6486 reset_ddsd(&ddsd);
6487 ddsd.dwFlags = DDSD_PITCH;
6488 U1(ddsd).lPitch = 8 * 4;
6489 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6490 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch without lpSurface or width returned %#x.\n", hr);
6492 ddsd.dwFlags = DDSD_WIDTH;
6493 ddsd.dwWidth = 16;
6494 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6495 ok(hr == DDERR_INVALIDPARAMS, "Setting width without lpSurface or pitch returned %#x.\n", hr);
6497 ddsd.dwFlags = DDSD_PITCH | DDSD_LPSURFACE;
6498 ddsd.lpSurface = data;
6499 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6500 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch and lpSurface without width returned %#x.\n", hr);
6502 ddsd.dwFlags = DDSD_WIDTH | DDSD_LPSURFACE;
6503 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6504 ok(hr == DDERR_INVALIDPARAMS, "Setting width and lpSurface without pitch returned %#x.\n", hr);
6506 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6507 U1(ddsd).lPitch = 16 * 4;
6508 ddsd.dwWidth = 16;
6509 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6510 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6512 reset_ddsd(&ddsd);
6513 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6514 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6515 ok(ddsd.dwWidth == 16, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
6516 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
6517 ok(U1(ddsd).lPitch == 16 * 4, "SetSurfaceDesc: Expected pitch 64, got %u.\n", U1(ddsd).lPitch);
6519 /* The pitch must be 32 bit aligned and > 0, but is not verified for sanity otherwise.
6521 * VMware rejects those calls, but all real drivers accept it. Mark the VMware behavior broken. */
6522 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6523 U1(ddsd).lPitch = 4 * 4;
6524 ddsd.lpSurface = data;
6525 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6526 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
6528 U1(ddsd).lPitch = 4;
6529 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6530 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
6532 U1(ddsd).lPitch = 16 * 4 + 1;
6533 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6534 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
6536 U1(ddsd).lPitch = 16 * 4 + 3;
6537 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6538 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
6540 U1(ddsd).lPitch = -4;
6541 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6542 ok(hr == DDERR_INVALIDPARAMS, "Setting negative pitch returned %#x.\n", hr);
6544 U1(ddsd).lPitch = 16 * 4;
6545 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6546 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6548 reset_ddsd(&ddsd);
6549 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6550 U1(ddsd).lPitch = 0;
6551 ddsd.dwWidth = 16;
6552 ddsd.lpSurface = data;
6553 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6554 ok(hr == DDERR_INVALIDPARAMS, "Setting zero pitch returned %#x.\n", hr);
6556 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6557 U1(ddsd).lPitch = 16 * 4;
6558 ddsd.dwWidth = 0;
6559 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6560 ok(hr == DDERR_INVALIDPARAMS, "Setting zero width returned %#x.\n", hr);
6562 /* Setting the pixelformat without LPSURFACE is an error, but with LPSURFACE it works. */
6563 ddsd.dwFlags = DDSD_PIXELFORMAT;
6564 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6565 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6566 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6567 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6568 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6569 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6570 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6571 ok(hr == DDERR_INVALIDPARAMS, "Setting the pixel format returned %#x.\n", hr);
6573 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_LPSURFACE;
6574 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6575 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6577 /* Can't set color keys. */
6578 reset_ddsd(&ddsd);
6579 ddsd.dwFlags = DDSD_CKSRCBLT;
6580 ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff0000;
6581 ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff0000;
6582 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6583 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
6585 ddsd.dwFlags = DDSD_CKSRCBLT | DDSD_LPSURFACE;
6586 ddsd.lpSurface = data;
6587 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6588 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
6590 IDirectDrawSurface7_Release(surface);
6592 /* SetSurfaceDesc needs systemmemory surfaces.
6594 * As a sidenote, fourcc surfaces aren't allowed in sysmem, thus testing
6595 * DDSD_LINEARSIZE is moot. */
6596 for (i = 0; i < ARRAY_SIZE(invalid_caps_tests); ++i)
6598 reset_ddsd(&ddsd);
6599 ddsd.dwFlags = DDSD_CAPS;
6600 ddsd.ddsCaps.dwCaps = invalid_caps_tests[i].caps;
6601 ddsd.ddsCaps.dwCaps2 = invalid_caps_tests[i].caps2;
6602 if (!(invalid_caps_tests[i].caps & DDSCAPS_PRIMARYSURFACE))
6604 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6605 ddsd.dwWidth = 8;
6606 ddsd.dwHeight = 8;
6607 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6608 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6609 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6610 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6611 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6612 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6615 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6616 if (is_ddraw64 && (invalid_caps_tests[i].caps & DDSCAPS_TEXTURE))
6617 todo_wine ok(hr == E_NOINTERFACE, "Test %u: Got unexpected hr %#x.\n", i, hr);
6618 else
6619 ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWHW, "Test %u: Got unexpected hr %#x.\n", i, hr);
6620 if (FAILED(hr))
6621 continue;
6623 reset_ddsd(&ddsd);
6624 ddsd.dwFlags = DDSD_LPSURFACE;
6625 ddsd.lpSurface = data;
6626 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6627 if (invalid_caps_tests[i].supported)
6629 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6631 else
6633 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
6634 invalid_caps_tests[i].name, hr);
6636 /* Check priority of error conditions. */
6637 ddsd.dwFlags = DDSD_WIDTH;
6638 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6639 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
6640 invalid_caps_tests[i].name, hr);
6643 IDirectDrawSurface7_Release(surface);
6646 ref = IDirectDraw7_Release(ddraw);
6647 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
6648 DestroyWindow(window);
6651 static void test_user_memory_getdc(void)
6653 IDirectDraw7 *ddraw;
6654 HWND window;
6655 HRESULT hr;
6656 DDSURFACEDESC2 ddsd;
6657 IDirectDrawSurface7 *surface;
6658 DWORD data[16][16];
6659 HGDIOBJ *bitmap;
6660 DIBSECTION dib;
6661 ULONG ref;
6662 int size;
6663 HDC dc;
6664 unsigned int x, y;
6666 window = create_window();
6667 ddraw = create_ddraw();
6668 ok(!!ddraw, "Failed to create a ddraw object.\n");
6669 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6670 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6672 reset_ddsd(&ddsd);
6673 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
6674 ddsd.dwWidth = 16;
6675 ddsd.dwHeight = 16;
6676 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6677 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6678 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6679 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6680 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6681 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6682 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6683 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6684 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6686 memset(data, 0xaa, sizeof(data));
6687 reset_ddsd(&ddsd);
6688 ddsd.dwFlags = DDSD_LPSURFACE;
6689 ddsd.lpSurface = data;
6690 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6691 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6693 hr = IDirectDrawSurface7_GetDC(surface, &dc);
6694 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
6695 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
6696 ok(!!bitmap, "Failed to get bitmap.\n");
6697 size = GetObjectA(bitmap, sizeof(dib), &dib);
6698 ok(size == sizeof(dib), "Got unexpected size %d.\n", size);
6699 ok(dib.dsBm.bmBits == data, "Got unexpected bits %p, expected %p.\n", dib.dsBm.bmBits, data);
6700 BitBlt(dc, 0, 0, 16, 8, NULL, 0, 0, WHITENESS);
6701 BitBlt(dc, 0, 8, 16, 8, NULL, 0, 0, BLACKNESS);
6702 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
6703 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
6705 ok(data[0][0] == 0xffffffff, "Expected color 0xffffffff, got %#x.\n", data[0][0]);
6706 ok(data[15][15] == 0x00000000, "Expected color 0x00000000, got %#x.\n", data[15][15]);
6708 ddsd.dwFlags = DDSD_LPSURFACE | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH;
6709 ddsd.lpSurface = data;
6710 ddsd.dwWidth = 4;
6711 ddsd.dwHeight = 8;
6712 U1(ddsd).lPitch = sizeof(*data);
6713 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6714 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6716 memset(data, 0xaa, sizeof(data));
6717 hr = IDirectDrawSurface7_GetDC(surface, &dc);
6718 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
6719 BitBlt(dc, 0, 0, 4, 8, NULL, 0, 0, BLACKNESS);
6720 BitBlt(dc, 1, 1, 2, 2, NULL, 0, 0, WHITENESS);
6721 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
6722 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
6724 for (y = 0; y < 4; y++)
6726 for (x = 0; x < 4; x++)
6728 if ((x == 1 || x == 2) && (y == 1 || y == 2))
6729 ok(data[y][x] == 0xffffffff, "Expected color 0xffffffff on position %ux%u, got %#x.\n",
6730 x, y, data[y][x]);
6731 else
6732 ok(data[y][x] == 0x00000000, "Expected color 0x00000000 on position %ux%u, got %#x.\n",
6733 x, y, data[y][x]);
6736 ok(data[0][5] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 5x0, got %#x.\n",
6737 data[0][5]);
6738 ok(data[7][3] == 0x00000000, "Expected color 0x00000000 on position 3x7, got %#x.\n",
6739 data[7][3]);
6740 ok(data[7][4] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 4x7, got %#x.\n",
6741 data[7][4]);
6742 ok(data[8][0] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 0x8, got %#x.\n",
6743 data[8][0]);
6745 IDirectDrawSurface7_Release(surface);
6746 ref = IDirectDraw7_Release(ddraw);
6747 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
6748 DestroyWindow(window);
6751 static void test_sysmem_overlay(void)
6753 IDirectDraw7 *ddraw;
6754 HWND window;
6755 HRESULT hr;
6756 DDSURFACEDESC2 ddsd;
6757 IDirectDrawSurface7 *surface;
6758 ULONG ref;
6760 window = create_window();
6761 ddraw = create_ddraw();
6762 ok(!!ddraw, "Failed to create a ddraw object.\n");
6763 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6764 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6766 reset_ddsd(&ddsd);
6767 ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
6768 ddsd.dwWidth = 16;
6769 ddsd.dwHeight = 16;
6770 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OVERLAY;
6771 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6772 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6773 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6774 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6775 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6776 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6777 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6778 ok(hr == DDERR_NOOVERLAYHW, "Got unexpected hr %#x.\n", hr);
6780 ref = IDirectDraw7_Release(ddraw);
6781 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
6782 DestroyWindow(window);
6785 static void test_primary_palette(void)
6787 DDSCAPS2 surface_caps = {DDSCAPS_FLIP, 0, 0, {0}};
6788 IDirectDrawSurface7 *primary, *backbuffer;
6789 PALETTEENTRY palette_entries[256];
6790 IDirectDrawPalette *palette, *tmp;
6791 DDSURFACEDESC2 surface_desc;
6792 IDirectDraw7 *ddraw;
6793 DWORD palette_caps;
6794 ULONG refcount;
6795 HWND window;
6796 HRESULT hr;
6798 window = create_window();
6799 ddraw = create_ddraw();
6800 ok(!!ddraw, "Failed to create a ddraw object.\n");
6801 if (FAILED(IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
6803 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
6804 IDirectDraw7_Release(ddraw);
6805 DestroyWindow(window);
6806 return;
6808 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6809 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6811 memset(&surface_desc, 0, sizeof(surface_desc));
6812 surface_desc.dwSize = sizeof(surface_desc);
6813 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
6814 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
6815 U5(surface_desc).dwBackBufferCount = 1;
6816 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
6817 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6818 hr = IDirectDrawSurface7_GetAttachedSurface(primary, &surface_caps, &backbuffer);
6819 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
6821 memset(palette_entries, 0, sizeof(palette_entries));
6822 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_entries, &palette, NULL);
6823 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
6824 refcount = get_refcount((IUnknown *)palette);
6825 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6827 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
6828 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
6829 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
6831 hr = IDirectDrawSurface7_SetPalette(primary, palette);
6832 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6834 /* The Windows 8 testbot attaches the palette to the backbuffer as well,
6835 * and is generally somewhat broken with respect to 8 bpp / palette
6836 * handling. */
6837 if (SUCCEEDED(IDirectDrawSurface7_GetPalette(backbuffer, &tmp)))
6839 win_skip("Broken palette handling detected, skipping tests.\n");
6840 IDirectDrawPalette_Release(tmp);
6841 IDirectDrawPalette_Release(palette);
6842 /* The Windows 8 testbot keeps extra references to the primary and
6843 * backbuffer while in 8 bpp mode. */
6844 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
6845 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
6846 goto done;
6849 refcount = get_refcount((IUnknown *)palette);
6850 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
6852 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
6853 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
6854 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE | DDPCAPS_ALLOW256),
6855 "Got unexpected palette caps %#x.\n", palette_caps);
6857 hr = IDirectDrawSurface7_SetPalette(primary, NULL);
6858 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6859 refcount = get_refcount((IUnknown *)palette);
6860 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6862 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
6863 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
6864 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
6866 hr = IDirectDrawSurface7_SetPalette(primary, palette);
6867 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
6868 refcount = get_refcount((IUnknown *)palette);
6869 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
6871 hr = IDirectDrawSurface7_GetPalette(primary, &tmp);
6872 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
6873 ok(tmp == palette, "Got unexpected palette %p, expected %p.\n", tmp, palette);
6874 IDirectDrawPalette_Release(tmp);
6875 hr = IDirectDrawSurface7_GetPalette(backbuffer, &tmp);
6876 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
6878 refcount = IDirectDrawPalette_Release(palette);
6879 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6880 refcount = IDirectDrawPalette_Release(palette);
6881 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6883 /* Note that this only seems to work when the palette is attached to the
6884 * primary surface. When attached to a regular surface, attempting to get
6885 * the palette here will cause an access violation. */
6886 hr = IDirectDrawSurface7_GetPalette(primary, &tmp);
6887 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
6889 hr = IDirectDrawSurface7_IsLost(primary);
6890 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6892 memset(&surface_desc, 0, sizeof(surface_desc));
6893 surface_desc.dwSize = sizeof(surface_desc);
6894 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &surface_desc);
6895 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6896 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
6897 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
6898 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 8, "Got unexpected bit count %u.\n",
6899 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
6901 hr = set_display_mode(ddraw, 640, 480);
6902 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
6904 memset(&surface_desc, 0, sizeof(surface_desc));
6905 surface_desc.dwSize = sizeof(surface_desc);
6906 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &surface_desc);
6907 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6908 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
6909 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
6910 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 32
6911 || U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 24,
6912 "Got unexpected bit count %u.\n", U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
6914 hr = IDirectDrawSurface7_IsLost(primary);
6915 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
6916 hr = IDirectDrawSurface7_Restore(primary);
6917 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
6918 hr = IDirectDrawSurface7_IsLost(primary);
6919 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
6921 memset(&surface_desc, 0, sizeof(surface_desc));
6922 surface_desc.dwSize = sizeof(surface_desc);
6923 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &surface_desc);
6924 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6925 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
6926 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
6927 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 32
6928 || U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 24,
6929 "Got unexpected bit count %u.\n", U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
6931 done:
6932 refcount = IDirectDrawSurface7_Release(backbuffer);
6933 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
6934 refcount = IDirectDrawSurface7_Release(primary);
6935 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6936 refcount = IDirectDraw7_Release(ddraw);
6937 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6938 DestroyWindow(window);
6941 static HRESULT WINAPI surface_counter(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
6943 UINT *surface_count = context;
6945 ++(*surface_count);
6946 IDirectDrawSurface_Release(surface);
6948 return DDENUMRET_OK;
6951 static void test_surface_attachment(void)
6953 IDirectDrawSurface7 *surface1, *surface2, *surface3, *surface4;
6954 IDirectDrawSurface *surface1v1, *surface2v1;
6955 DDSCAPS2 caps = {DDSCAPS_TEXTURE, 0, 0, {0}};
6956 DDSURFACEDESC2 surface_desc;
6957 IDirectDraw7 *ddraw;
6958 UINT surface_count;
6959 ULONG refcount;
6960 HWND window;
6961 HRESULT hr;
6963 window = create_window();
6964 ddraw = create_ddraw();
6965 ok(!!ddraw, "Failed to create a ddraw object.\n");
6966 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6967 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6969 memset(&surface_desc, 0, sizeof(surface_desc));
6970 surface_desc.dwSize = sizeof(surface_desc);
6971 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
6972 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
6973 U2(surface_desc).dwMipMapCount = 3;
6974 surface_desc.dwWidth = 128;
6975 surface_desc.dwHeight = 128;
6976 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL)))
6978 skip("Failed to create a texture, skipping tests.\n");
6979 IDirectDraw7_Release(ddraw);
6980 DestroyWindow(window);
6981 return;
6984 hr = IDirectDrawSurface7_GetAttachedSurface(surface1, &caps, &surface2);
6985 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
6986 hr = IDirectDrawSurface7_GetAttachedSurface(surface2, &caps, &surface3);
6987 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
6988 hr = IDirectDrawSurface7_GetAttachedSurface(surface3, &caps, &surface4);
6989 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
6991 surface_count = 0;
6992 IDirectDrawSurface7_EnumAttachedSurfaces(surface1, &surface_count, surface_counter);
6993 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
6994 surface_count = 0;
6995 IDirectDrawSurface7_EnumAttachedSurfaces(surface2, &surface_count, surface_counter);
6996 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
6997 surface_count = 0;
6998 IDirectDrawSurface7_EnumAttachedSurfaces(surface3, &surface_count, surface_counter);
6999 ok(!surface_count, "Got unexpected surface_count %u.\n", surface_count);
7001 memset(&surface_desc, 0, sizeof(surface_desc));
7002 surface_desc.dwSize = sizeof(surface_desc);
7003 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7004 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
7005 surface_desc.dwWidth = 16;
7006 surface_desc.dwHeight = 16;
7007 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
7008 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7010 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
7011 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7012 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
7013 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7014 hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface4);
7015 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7016 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface3);
7017 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7018 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface4);
7019 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7020 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface2);
7021 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7023 IDirectDrawSurface7_Release(surface4);
7025 memset(&surface_desc, 0, sizeof(surface_desc));
7026 surface_desc.dwSize = sizeof(surface_desc);
7027 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7028 surface_desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
7029 surface_desc.dwWidth = 16;
7030 surface_desc.dwHeight = 16;
7031 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
7032 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7034 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
7035 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7036 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
7037 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7038 hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface4);
7039 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7040 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface3);
7041 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7042 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface4);
7043 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7044 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface2);
7045 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7047 IDirectDrawSurface7_Release(surface4);
7048 IDirectDrawSurface7_Release(surface3);
7049 IDirectDrawSurface7_Release(surface2);
7050 IDirectDrawSurface7_Release(surface1);
7052 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7053 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7055 /* Try a single primary and two offscreen plain surfaces. */
7056 memset(&surface_desc, 0, sizeof(surface_desc));
7057 surface_desc.dwSize = sizeof(surface_desc);
7058 surface_desc.dwFlags = DDSD_CAPS;
7059 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7060 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7061 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7063 memset(&surface_desc, 0, sizeof(surface_desc));
7064 surface_desc.dwSize = sizeof(surface_desc);
7065 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7066 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7067 surface_desc.dwWidth = registry_mode.dmPelsWidth;
7068 surface_desc.dwHeight = registry_mode.dmPelsHeight;
7069 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
7070 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7072 memset(&surface_desc, 0, sizeof(surface_desc));
7073 surface_desc.dwSize = sizeof(surface_desc);
7074 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7075 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7076 surface_desc.dwWidth = registry_mode.dmPelsWidth;
7077 surface_desc.dwHeight = registry_mode.dmPelsHeight;
7078 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
7079 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7081 /* This one has a different size. */
7082 memset(&surface_desc, 0, sizeof(surface_desc));
7083 surface_desc.dwSize = sizeof(surface_desc);
7084 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7085 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7086 surface_desc.dwWidth = 128;
7087 surface_desc.dwHeight = 128;
7088 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
7089 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7091 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
7092 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7093 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface1);
7094 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7095 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface3);
7096 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7097 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
7098 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7099 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
7100 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7102 IDirectDrawSurface7_Release(surface4);
7103 IDirectDrawSurface7_Release(surface3);
7104 IDirectDrawSurface7_Release(surface2);
7105 IDirectDrawSurface7_Release(surface1);
7107 /* Test DeleteAttachedSurface() and automatic detachment of attached surfaces on release. */
7108 memset(&surface_desc, 0, sizeof(surface_desc));
7109 surface_desc.dwSize = sizeof(surface_desc);
7110 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7111 surface_desc.dwWidth = 64;
7112 surface_desc.dwHeight = 64;
7113 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
7114 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7115 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
7116 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
7117 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
7118 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
7119 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
7120 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7121 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7122 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
7123 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7125 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
7126 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
7127 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = 16;
7128 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = 0x0000ffff;
7129 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
7130 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7132 hr = IDirectDrawSurface7_QueryInterface(surface1, &IID_IDirectDrawSurface, (void **)&surface1v1);
7133 ok(SUCCEEDED(hr), "Failed to get interface, hr %#x.\n", hr);
7134 hr = IDirectDrawSurface7_QueryInterface(surface2, &IID_IDirectDrawSurface, (void **)&surface2v1);
7135 ok(SUCCEEDED(hr), "Failed to get interface, hr %#x.\n", hr);
7137 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
7138 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7139 refcount = get_refcount((IUnknown *)surface2);
7140 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
7141 refcount = get_refcount((IUnknown *)surface2v1);
7142 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7143 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
7144 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
7145 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
7146 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7147 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
7148 ok(hr == DDERR_SURFACENOTATTACHED, "Got unexpected hr %#x.\n", hr);
7150 /* Attaching while already attached to other surface. */
7151 hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface2);
7152 todo_wine ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7153 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface3, 0, surface2);
7154 todo_wine ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7155 IDirectDrawSurface7_Release(surface3);
7157 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface2);
7158 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7159 refcount = get_refcount((IUnknown *)surface2);
7160 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7161 refcount = get_refcount((IUnknown *)surface2v1);
7162 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7164 /* DeleteAttachedSurface() when attaching via IDirectDrawSurface. */
7165 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
7166 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7167 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface2);
7168 ok(hr == DDERR_SURFACENOTATTACHED, "Got unexpected hr %#x.\n", hr);
7169 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
7170 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7171 refcount = IDirectDrawSurface7_Release(surface2);
7172 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7173 refcount = IDirectDrawSurface7_Release(surface1);
7174 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7176 /* Automatic detachment on release. */
7177 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
7178 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7179 refcount = get_refcount((IUnknown *)surface2v1);
7180 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
7181 refcount = IDirectDrawSurface_Release(surface1v1);
7182 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7183 refcount = IDirectDrawSurface_Release(surface2v1);
7184 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7185 refcount = IDirectDraw7_Release(ddraw);
7186 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7187 DestroyWindow(window);
7190 static void test_private_data(void)
7192 IDirectDraw7 *ddraw;
7193 IDirectDrawSurface7 *surface, *surface2;
7194 DDSURFACEDESC2 surface_desc;
7195 ULONG refcount, refcount2, refcount3;
7196 IUnknown *ptr;
7197 DWORD size = sizeof(ptr);
7198 HRESULT hr;
7199 HWND window;
7200 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
7201 DWORD data[] = {1, 2, 3, 4};
7202 DDCAPS hal_caps;
7203 static const GUID ddraw_private_data_test_guid =
7205 0xfdb37466,
7206 0x428f,
7207 0x4edf,
7208 {0xa3,0x7f,0x9b,0x1d,0xf4,0x88,0xc5,0xfc}
7210 static const GUID ddraw_private_data_test_guid2 =
7212 0x2e5afac2,
7213 0x87b5,
7214 0x4c10,
7215 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
7218 window = create_window();
7219 ddraw = create_ddraw();
7220 ok(!!ddraw, "Failed to create a ddraw object.\n");
7221 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7222 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7224 reset_ddsd(&surface_desc);
7225 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
7226 surface_desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
7227 surface_desc.dwHeight = 4;
7228 surface_desc.dwWidth = 4;
7229 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7230 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7232 /* NULL pointers are not valid, but don't cause a crash. */
7233 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL,
7234 sizeof(IUnknown *), DDSPD_IUNKNOWNPOINTER);
7235 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7236 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL, 0, 0);
7237 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7238 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL, 1, 0);
7239 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7241 /* DDSPD_IUNKNOWNPOINTER needs sizeof(IUnknown *) bytes of data. */
7242 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7243 0, DDSPD_IUNKNOWNPOINTER);
7244 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7245 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7246 5, DDSPD_IUNKNOWNPOINTER);
7247 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7248 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7249 sizeof(ddraw) * 2, DDSPD_IUNKNOWNPOINTER);
7250 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7252 /* Note that with a size != 0 and size != sizeof(IUnknown *) and
7253 * DDSPD_IUNKNOWNPOINTER set SetPrivateData in ddraw4 and ddraw7
7254 * erases the old content and returns an error. This behavior has
7255 * been fixed in d3d8 and d3d9. Unless an application is found
7256 * that depends on this we don't care about this behavior. */
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 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7261 0, DDSPD_IUNKNOWNPOINTER);
7262 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7263 size = sizeof(ptr);
7264 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
7265 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7266 hr = IDirectDrawSurface7_FreePrivateData(surface, &ddraw_private_data_test_guid);
7267 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7269 refcount = get_refcount((IUnknown *)ddraw);
7270 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7271 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7272 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7273 refcount2 = get_refcount((IUnknown *)ddraw);
7274 ok(refcount2 == refcount + 1, "Got unexpected refcount %u.\n", refcount2);
7276 hr = IDirectDrawSurface7_FreePrivateData(surface, &ddraw_private_data_test_guid);
7277 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7278 refcount2 = get_refcount((IUnknown *)ddraw);
7279 ok(refcount2 == refcount, "Got unexpected refcount %u.\n", refcount2);
7281 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7282 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7283 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7284 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, surface,
7285 sizeof(surface), DDSPD_IUNKNOWNPOINTER);
7286 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7287 refcount2 = get_refcount((IUnknown *)ddraw);
7288 ok(refcount2 == refcount, "Got unexpected refcount %u.\n", refcount2);
7290 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7291 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7292 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7293 size = 2 * sizeof(ptr);
7294 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
7295 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7296 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
7297 refcount2 = get_refcount(ptr);
7298 /* Object is NOT addref'ed by the getter. */
7299 ok(ptr == (IUnknown *)ddraw, "Returned interface pointer is %p, expected %p.\n", ptr, ddraw);
7300 ok(refcount2 == refcount + 1, "Got unexpected refcount %u.\n", refcount2);
7302 ptr = (IUnknown *)0xdeadbeef;
7303 size = 1;
7304 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, &size);
7305 ok(hr == DDERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
7306 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
7307 size = 2 * sizeof(ptr);
7308 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, &size);
7309 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7310 ok(size == 2 * sizeof(ptr), "Got unexpected size %u.\n", size);
7311 size = 1;
7312 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
7313 ok(hr == DDERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
7314 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
7315 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7316 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid2, NULL, NULL);
7317 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7318 size = 0xdeadbabe;
7319 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid2, &ptr, &size);
7320 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7321 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7322 ok(size == 0xdeadbabe, "Got unexpected size %u.\n", size);
7323 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, NULL);
7324 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7326 refcount3 = IDirectDrawSurface7_Release(surface);
7327 ok(!refcount3, "Got unexpected refcount %u.\n", refcount3);
7329 /* Destroying the surface frees the reference held on the private data. It also frees
7330 * the reference the surface is holding on its creating object. */
7331 refcount2 = get_refcount((IUnknown *)ddraw);
7332 ok(refcount2 == refcount - 1, "Got unexpected refcount %u.\n", refcount2);
7334 memset(&hal_caps, 0, sizeof(hal_caps));
7335 hal_caps.dwSize = sizeof(hal_caps);
7336 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
7337 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7338 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) == (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)
7339 && !is_ddraw64)
7341 reset_ddsd(&surface_desc);
7342 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_MIPMAPCOUNT;
7343 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7344 surface_desc.dwHeight = 4;
7345 surface_desc.dwWidth = 4;
7346 U2(surface_desc).dwMipMapCount = 2;
7347 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7348 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7349 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &surface2);
7350 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
7352 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, data, sizeof(data), 0);
7353 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7354 hr = IDirectDrawSurface7_GetPrivateData(surface2, &ddraw_private_data_test_guid, NULL, NULL);
7355 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7357 IDirectDrawSurface7_Release(surface2);
7358 IDirectDrawSurface7_Release(surface);
7360 else
7361 skip("Mipmapped textures not supported, skipping mipmap private data test.\n");
7363 refcount = IDirectDraw7_Release(ddraw);
7364 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7365 DestroyWindow(window);
7368 static void test_pixel_format(void)
7370 HWND window, window2 = NULL;
7371 HDC hdc, hdc2 = NULL;
7372 HMODULE gl = NULL;
7373 int format, test_format;
7374 PIXELFORMATDESCRIPTOR pfd;
7375 IDirectDraw7 *ddraw = NULL;
7376 IDirectDrawClipper *clipper = NULL;
7377 DDSURFACEDESC2 ddsd;
7378 IDirectDrawSurface7 *primary = NULL;
7379 DDBLTFX fx;
7380 HRESULT hr;
7382 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
7383 100, 100, 160, 160, NULL, NULL, NULL, NULL);
7384 if (!window)
7386 skip("Failed to create window\n");
7387 return;
7390 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
7391 100, 100, 160, 160, NULL, NULL, NULL, NULL);
7393 hdc = GetDC(window);
7394 if (!hdc)
7396 skip("Failed to get DC\n");
7397 goto cleanup;
7400 if (window2)
7401 hdc2 = GetDC(window2);
7403 gl = LoadLibraryA("opengl32.dll");
7404 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
7406 format = GetPixelFormat(hdc);
7407 ok(format == 0, "new window has pixel format %d\n", format);
7409 ZeroMemory(&pfd, sizeof(pfd));
7410 pfd.nSize = sizeof(pfd);
7411 pfd.nVersion = 1;
7412 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
7413 pfd.iPixelType = PFD_TYPE_RGBA;
7414 pfd.iLayerType = PFD_MAIN_PLANE;
7415 format = ChoosePixelFormat(hdc, &pfd);
7416 if (format <= 0)
7418 skip("no pixel format available\n");
7419 goto cleanup;
7422 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
7424 skip("failed to set pixel format\n");
7425 goto cleanup;
7428 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
7430 skip("failed to set pixel format on second window\n");
7431 if (hdc2)
7433 ReleaseDC(window2, hdc2);
7434 hdc2 = NULL;
7438 ddraw = create_ddraw();
7439 ok(!!ddraw, "Failed to create a ddraw object.\n");
7441 test_format = GetPixelFormat(hdc);
7442 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7444 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7445 if (FAILED(hr))
7447 skip("Failed to set cooperative level, hr %#x.\n", hr);
7448 goto cleanup;
7451 test_format = GetPixelFormat(hdc);
7452 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7454 if (hdc2)
7456 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
7457 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
7458 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window2);
7459 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
7461 test_format = GetPixelFormat(hdc);
7462 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7464 test_format = GetPixelFormat(hdc2);
7465 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7468 memset(&ddsd, 0, sizeof(ddsd));
7469 ddsd.dwSize = sizeof(ddsd);
7470 ddsd.dwFlags = DDSD_CAPS;
7471 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7473 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
7474 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
7476 test_format = GetPixelFormat(hdc);
7477 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7479 if (hdc2)
7481 test_format = GetPixelFormat(hdc2);
7482 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7485 if (clipper)
7487 hr = IDirectDrawSurface7_SetClipper(primary, clipper);
7488 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
7490 test_format = GetPixelFormat(hdc);
7491 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7493 test_format = GetPixelFormat(hdc2);
7494 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7497 memset(&fx, 0, sizeof(fx));
7498 fx.dwSize = sizeof(fx);
7499 hr = IDirectDrawSurface7_Blt(primary, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7500 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
7502 test_format = GetPixelFormat(hdc);
7503 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7505 if (hdc2)
7507 test_format = GetPixelFormat(hdc2);
7508 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7511 cleanup:
7512 if (primary) IDirectDrawSurface7_Release(primary);
7513 if (clipper) IDirectDrawClipper_Release(clipper);
7514 if (ddraw) IDirectDraw7_Release(ddraw);
7515 if (gl) FreeLibrary(gl);
7516 if (hdc) ReleaseDC(window, hdc);
7517 if (hdc2) ReleaseDC(window2, hdc2);
7518 if (window) DestroyWindow(window);
7519 if (window2) DestroyWindow(window2);
7522 static void test_create_surface_pitch(void)
7524 IDirectDrawSurface7 *surface;
7525 DDSURFACEDESC2 surface_desc;
7526 IDirectDraw7 *ddraw;
7527 unsigned int i;
7528 ULONG refcount;
7529 HWND window;
7530 HRESULT hr;
7531 void *mem;
7533 static const struct
7535 DWORD caps;
7536 DWORD flags_in;
7537 DWORD pitch_in;
7538 HRESULT hr;
7539 DWORD flags_out;
7540 DWORD pitch_out32;
7541 DWORD pitch_out64;
7543 test_data[] =
7545 /* 0 */
7546 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7547 0, 0, DD_OK,
7548 DDSD_PITCH, 0x100, 0x100},
7549 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7550 DDSD_PITCH, 0x104, DD_OK,
7551 DDSD_PITCH, 0x100, 0x100},
7552 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7553 DDSD_PITCH, 0x0f8, DD_OK,
7554 DDSD_PITCH, 0x100, 0x100},
7555 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7556 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
7557 0, 0, 0 },
7558 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7559 0, 0, DD_OK,
7560 DDSD_PITCH, 0x100, 0x0fc},
7561 /* 5 */
7562 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7563 DDSD_PITCH, 0x104, DD_OK,
7564 DDSD_PITCH, 0x100, 0x0fc},
7565 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7566 DDSD_PITCH, 0x0f8, DD_OK,
7567 DDSD_PITCH, 0x100, 0x0fc},
7568 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7569 DDSD_PITCH | DDSD_LINEARSIZE, 0, DD_OK,
7570 DDSD_PITCH, 0x100, 0x0fc},
7571 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7572 DDSD_LPSURFACE, 0, DDERR_INVALIDPARAMS,
7573 0, 0, 0 },
7574 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7575 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DD_OK,
7576 DDSD_PITCH, 0x100, 0x100},
7577 /* 10 */
7578 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7579 DDSD_LPSURFACE | DDSD_PITCH, 0x0fe, DDERR_INVALIDPARAMS,
7580 0, 0, 0 },
7581 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7582 DDSD_LPSURFACE | DDSD_PITCH, 0x0fc, DD_OK,
7583 DDSD_PITCH, 0x0fc, 0x0fc},
7584 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7585 DDSD_LPSURFACE | DDSD_PITCH, 0x0f8, DDERR_INVALIDPARAMS,
7586 0, 0, 0 },
7587 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7588 DDSD_LPSURFACE | DDSD_LINEARSIZE, 0x100, DDERR_INVALIDPARAMS,
7589 0, 0, 0 },
7590 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7591 DDSD_LPSURFACE | DDSD_LINEARSIZE, 0x3f00, DDERR_INVALIDPARAMS,
7592 0, 0, 0 },
7593 /* 15 */
7594 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7595 DDSD_LPSURFACE | DDSD_PITCH | DDSD_LINEARSIZE, 0x100, DD_OK,
7596 DDSD_PITCH, 0x100, 0x100},
7597 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
7598 0, 0, DDERR_INVALIDCAPS,
7599 0, 0, 0 },
7600 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7601 0, 0, DD_OK,
7602 DDSD_PITCH, 0x100, 0 },
7603 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7604 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
7605 0, 0, 0 },
7606 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
7607 0, 0, DDERR_INVALIDCAPS,
7608 0, 0, 0 },
7609 /* 20 */
7610 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7611 0, 0, DD_OK,
7612 DDSD_PITCH, 0x100, 0 },
7613 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7614 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DD_OK,
7615 DDSD_PITCH, 0x100, 0 },
7617 DWORD flags_mask = DDSD_PITCH | DDSD_LPSURFACE | DDSD_LINEARSIZE;
7619 window = create_window();
7620 ddraw = create_ddraw();
7621 ok(!!ddraw, "Failed to create a ddraw object.\n");
7622 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7623 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7625 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((63 * 4) + 8) * 63);
7627 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
7629 memset(&surface_desc, 0, sizeof(surface_desc));
7630 surface_desc.dwSize = sizeof(surface_desc);
7631 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | test_data[i].flags_in;
7632 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
7633 surface_desc.dwWidth = 63;
7634 surface_desc.dwHeight = 63;
7635 U1(surface_desc).lPitch = test_data[i].pitch_in;
7636 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7637 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
7638 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
7639 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7640 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7641 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7642 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7643 if (test_data[i].flags_in & DDSD_LPSURFACE)
7645 HRESULT expected_hr = SUCCEEDED(test_data[i].hr) ? DDERR_INVALIDPARAMS : test_data[i].hr;
7646 ok(hr == expected_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, expected_hr);
7647 surface_desc.lpSurface = mem;
7648 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7650 if ((test_data[i].caps & DDSCAPS_VIDEOMEMORY) && hr == DDERR_NODIRECTDRAWHW)
7651 continue;
7652 if (is_ddraw64 && (test_data[i].caps & DDSCAPS_TEXTURE) && SUCCEEDED(test_data[i].hr))
7653 todo_wine ok(hr == E_NOINTERFACE, "Test %u: Got unexpected hr %#x.\n", i, hr);
7654 else
7655 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
7656 if (FAILED(hr))
7657 continue;
7659 memset(&surface_desc, 0, sizeof(surface_desc));
7660 surface_desc.dwSize = sizeof(surface_desc);
7661 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
7662 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
7663 ok((surface_desc.dwFlags & flags_mask) == test_data[i].flags_out,
7664 "Test %u: Got unexpected flags %#x, expected %#x.\n",
7665 i, surface_desc.dwFlags & flags_mask, test_data[i].flags_out);
7666 /* The pitch for textures seems to be implementation specific. */
7667 if (!(test_data[i].caps & DDSCAPS_TEXTURE))
7669 if (is_ddraw64 && test_data[i].pitch_out32 != test_data[i].pitch_out64)
7670 todo_wine ok(U1(surface_desc).lPitch == test_data[i].pitch_out64,
7671 "Test %u: Got unexpected pitch %u, expected %u.\n",
7672 i, U1(surface_desc).lPitch, test_data[i].pitch_out64);
7673 else
7674 ok(U1(surface_desc).lPitch == test_data[i].pitch_out32,
7675 "Test %u: Got unexpected pitch %u, expected %u.\n",
7676 i, U1(surface_desc).lPitch, test_data[i].pitch_out32);
7678 ok(!surface_desc.lpSurface, "Test %u: Got unexpected lpSurface %p.\n", i, surface_desc.lpSurface);
7680 IDirectDrawSurface7_Release(surface);
7683 HeapFree(GetProcessHeap(), 0, mem);
7684 refcount = IDirectDraw7_Release(ddraw);
7685 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7686 DestroyWindow(window);
7689 static void test_mipmap(void)
7691 IDirectDrawSurface7 *surface, *surface2;
7692 DDSURFACEDESC2 surface_desc;
7693 IDirectDraw7 *ddraw;
7694 unsigned int i;
7695 ULONG refcount;
7696 HWND window;
7697 HRESULT hr;
7698 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
7699 DDCAPS hal_caps;
7701 static const struct
7703 DWORD flags;
7704 DWORD caps;
7705 DWORD width;
7706 DWORD height;
7707 DWORD mipmap_count_in;
7708 HRESULT hr;
7709 DWORD mipmap_count_out;
7711 tests[] =
7713 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 3, DD_OK, 3},
7714 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDPARAMS, 0},
7715 {0, DDSCAPS_TEXTURE | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 1},
7716 {0, DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDCAPS, 0},
7717 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 8},
7718 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 32, 64, 0, DD_OK, 7},
7721 window = create_window();
7722 ddraw = create_ddraw();
7723 ok(!!ddraw, "Failed to create a ddraw object.\n");
7724 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7725 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7727 memset(&hal_caps, 0, sizeof(hal_caps));
7728 hal_caps.dwSize = sizeof(hal_caps);
7729 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
7730 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7731 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)
7732 || is_ddraw64)
7734 skip("Mipmapped textures not supported, skipping tests.\n");
7735 IDirectDraw7_Release(ddraw);
7736 DestroyWindow(window);
7737 return;
7740 for (i = 0; i < ARRAY_SIZE(tests); ++i)
7742 memset(&surface_desc, 0, sizeof(surface_desc));
7743 surface_desc.dwSize = sizeof(surface_desc);
7744 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | tests[i].flags;
7745 surface_desc.ddsCaps.dwCaps = tests[i].caps;
7746 surface_desc.dwWidth = tests[i].width;
7747 surface_desc.dwHeight = tests[i].height;
7748 if (tests[i].flags & DDSD_MIPMAPCOUNT)
7749 U2(surface_desc).dwMipMapCount = tests[i].mipmap_count_in;
7750 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7751 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x.\n", i, hr);
7752 if (FAILED(hr))
7753 continue;
7755 memset(&surface_desc, 0, sizeof(surface_desc));
7756 surface_desc.dwSize = sizeof(surface_desc);
7757 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
7758 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
7759 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
7760 "Test %u: Got unexpected flags %#x.\n", i, surface_desc.dwFlags);
7761 ok(U2(surface_desc).dwMipMapCount == tests[i].mipmap_count_out,
7762 "Test %u: Got unexpected mipmap count %u.\n", i, U2(surface_desc).dwMipMapCount);
7764 if (U2(surface_desc).dwMipMapCount > 1)
7766 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &surface2);
7767 ok(SUCCEEDED(hr), "Test %u: Failed to get attached surface, hr %#x.\n", i, hr);
7769 memset(&surface_desc, 0, sizeof(surface_desc));
7770 surface_desc.dwSize = sizeof(surface_desc);
7771 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, 0, NULL);
7772 ok(SUCCEEDED(hr), "Test %u: Failed to lock surface, hr %#x.\n", i, hr);
7773 memset(&surface_desc, 0, sizeof(surface_desc));
7774 surface_desc.dwSize = sizeof(surface_desc);
7775 hr = IDirectDrawSurface7_Lock(surface2, NULL, &surface_desc, 0, NULL);
7776 ok(SUCCEEDED(hr), "Test %u: Failed to lock surface, hr %#x.\n", i, hr);
7777 IDirectDrawSurface7_Unlock(surface2, NULL);
7778 IDirectDrawSurface7_Unlock(surface, NULL);
7780 IDirectDrawSurface7_Release(surface2);
7783 IDirectDrawSurface7_Release(surface);
7786 refcount = IDirectDraw7_Release(ddraw);
7787 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7788 DestroyWindow(window);
7791 static void test_palette_complex(void)
7793 IDirectDrawSurface7 *surface, *mipmap, *tmp;
7794 DDSURFACEDESC2 surface_desc;
7795 IDirectDraw7 *ddraw;
7796 IDirectDrawPalette *palette, *palette2;
7797 ULONG refcount;
7798 HWND window;
7799 HRESULT hr;
7800 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
7801 DDCAPS hal_caps;
7802 PALETTEENTRY palette_entries[256];
7803 unsigned int i;
7805 window = create_window();
7806 ddraw = create_ddraw();
7807 ok(!!ddraw, "Failed to create a ddraw object.\n");
7808 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7809 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7811 memset(&hal_caps, 0, sizeof(hal_caps));
7812 hal_caps.dwSize = sizeof(hal_caps);
7813 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
7814 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7815 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)
7816 || is_ddraw64)
7818 skip("Mipmapped textures not supported, skipping mipmap palette test.\n");
7819 IDirectDraw7_Release(ddraw);
7820 DestroyWindow(window);
7821 return;
7824 memset(&surface_desc, 0, sizeof(surface_desc));
7825 surface_desc.dwSize = sizeof(surface_desc);
7826 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7827 surface_desc.dwWidth = 128;
7828 surface_desc.dwHeight = 128;
7829 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7830 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7831 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
7832 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
7833 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7834 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7836 memset(palette_entries, 0, sizeof(palette_entries));
7837 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7838 palette_entries, &palette, NULL);
7839 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7841 palette2 = (void *)0xdeadbeef;
7842 hr = IDirectDrawSurface7_GetPalette(surface, &palette2);
7843 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
7844 ok(!palette2, "Got unexpected palette %p.\n", palette2);
7845 hr = IDirectDrawSurface7_SetPalette(surface, palette);
7846 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7847 hr = IDirectDrawSurface7_GetPalette(surface, &palette2);
7848 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
7849 ok(palette == palette2, "Got unexpected palette %p.\n", palette2);
7850 IDirectDrawPalette_Release(palette2);
7852 mipmap = surface;
7853 IDirectDrawSurface7_AddRef(mipmap);
7854 for (i = 0; i < 7; ++i)
7856 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
7857 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
7858 palette2 = (void *)0xdeadbeef;
7859 hr = IDirectDrawSurface7_GetPalette(tmp, &palette2);
7860 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x, i %u.\n", hr, i);
7861 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
7863 hr = IDirectDrawSurface7_SetPalette(tmp, palette);
7864 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x, i %u.\n", hr, i);
7866 hr = IDirectDrawSurface7_GetPalette(tmp, &palette2);
7867 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x, i %u.\n", hr, i);
7868 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
7870 /* Ddraw7 uses the palette of the mipmap for GetDC, just like previous
7871 * ddraw versions. Combined with the test results above this means no
7872 * palette is available. So depending on the driver either GetDC fails
7873 * or the DIB color table contains random data. */
7875 IDirectDrawSurface7_Release(mipmap);
7876 mipmap = tmp;
7879 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
7880 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7881 IDirectDrawSurface7_Release(mipmap);
7882 refcount = IDirectDrawSurface7_Release(surface);
7883 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7885 /* Test DDERR_INVALIDPIXELFORMAT vs DDERR_NOTONMIPMAPSUBLEVEL. */
7886 memset(&surface_desc, 0, sizeof(surface_desc));
7887 surface_desc.dwSize = sizeof(surface_desc);
7888 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7889 surface_desc.dwWidth = 128;
7890 surface_desc.dwHeight = 128;
7891 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7892 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7893 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
7894 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
7895 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7896 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7897 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7898 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7899 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7901 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
7902 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
7903 hr = IDirectDrawSurface7_SetPalette(mipmap, palette);
7904 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x.\n", hr);
7906 IDirectDrawSurface7_Release(mipmap);
7907 refcount = IDirectDrawSurface7_Release(surface);
7908 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7909 refcount = IDirectDrawPalette_Release(palette);
7910 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7912 refcount = IDirectDraw7_Release(ddraw);
7913 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7914 DestroyWindow(window);
7917 static void test_p8_blit(void)
7919 IDirectDrawSurface7 *src, *dst, *dst_p8;
7920 DDSURFACEDESC2 surface_desc;
7921 IDirectDraw7 *ddraw;
7922 IDirectDrawPalette *palette, *palette2;
7923 ULONG refcount;
7924 HWND window;
7925 HRESULT hr;
7926 PALETTEENTRY palette_entries[256];
7927 unsigned int x;
7928 DDBLTFX fx;
7929 BOOL is_warp;
7930 static const BYTE src_data[] = {0x10, 0x1, 0x2, 0x3, 0x4, 0x5, 0xff, 0x80};
7931 static const BYTE src_data2[] = {0x10, 0x5, 0x4, 0x3, 0x2, 0x1, 0xff, 0x80};
7932 static const BYTE expected_p8[] = {0x10, 0x1, 0x4, 0x3, 0x4, 0x5, 0xff, 0x80};
7933 static const D3DCOLOR expected[] =
7935 0x00101010, 0x00010101, 0x00020202, 0x00030303,
7936 0x00040404, 0x00050505, 0x00ffffff, 0x00808080,
7938 D3DCOLOR color;
7940 window = create_window();
7941 ddraw = create_ddraw();
7942 ok(!!ddraw, "Failed to create a ddraw object.\n");
7943 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7944 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7945 is_warp = ddraw_is_warp(ddraw);
7947 memset(palette_entries, 0, sizeof(palette_entries));
7948 palette_entries[1].peGreen = 0xff;
7949 palette_entries[2].peBlue = 0xff;
7950 palette_entries[3].peFlags = 0xff;
7951 palette_entries[4].peRed = 0xff;
7952 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7953 palette_entries, &palette, NULL);
7954 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7955 palette_entries[1].peBlue = 0xff;
7956 palette_entries[2].peGreen = 0xff;
7957 palette_entries[3].peRed = 0xff;
7958 palette_entries[4].peFlags = 0x0;
7959 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
7960 palette_entries, &palette2, NULL);
7961 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7963 memset(&surface_desc, 0, sizeof(surface_desc));
7964 surface_desc.dwSize = sizeof(surface_desc);
7965 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7966 surface_desc.dwWidth = 8;
7967 surface_desc.dwHeight = 1;
7968 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7969 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7970 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
7971 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
7972 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
7973 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7974 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_p8, NULL);
7975 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7976 hr = IDirectDrawSurface7_SetPalette(dst_p8, palette2);
7977 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7979 memset(&surface_desc, 0, sizeof(surface_desc));
7980 surface_desc.dwSize = sizeof(surface_desc);
7981 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7982 surface_desc.dwWidth = 8;
7983 surface_desc.dwHeight = 1;
7984 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7985 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7986 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
7987 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
7988 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7989 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7990 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7991 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
7992 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
7993 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7995 memset(&surface_desc, 0, sizeof(surface_desc));
7996 surface_desc.dwSize = sizeof(surface_desc);
7997 hr = IDirectDrawSurface7_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
7998 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
7999 memcpy(surface_desc.lpSurface, src_data, sizeof(src_data));
8000 hr = IDirectDrawSurface7_Unlock(src, NULL);
8001 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
8003 hr = IDirectDrawSurface7_Lock(dst_p8, NULL, &surface_desc, DDLOCK_WAIT, NULL);
8004 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#x.\n", hr);
8005 memcpy(surface_desc.lpSurface, src_data2, sizeof(src_data2));
8006 hr = IDirectDrawSurface7_Unlock(dst_p8, NULL);
8007 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#x.\n", hr);
8009 hr = IDirectDrawSurface7_SetPalette(src, palette);
8010 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8011 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_WAIT, NULL);
8012 /* The r500 Windows 7 driver returns E_NOTIMPL. r200 on Windows XP works.
8013 * The Geforce 7 driver on Windows Vista returns E_FAIL. Newer Nvidia GPUs work. */
8014 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL) || broken(hr == E_FAIL),
8015 "Failed to blit, hr %#x.\n", hr);
8017 if (SUCCEEDED(hr))
8019 for (x = 0; x < ARRAY_SIZE(expected); ++x)
8021 color = get_surface_color(dst, x, 0);
8022 todo_wine ok(compare_color(color, expected[x], 0),
8023 "Pixel %u: Got color %#x, expected %#x.\n",
8024 x, color, expected[x]);
8028 memset(&fx, 0, sizeof(fx));
8029 fx.dwSize = sizeof(fx);
8030 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x2;
8031 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x2;
8032 hr = IDirectDrawSurface7_Blt(dst_p8, NULL, src, NULL, DDBLT_WAIT | DDBLT_KEYSRCOVERRIDE, &fx);
8033 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
8035 hr = IDirectDrawSurface7_Lock(dst_p8, NULL, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
8036 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#x.\n", hr);
8037 /* A color keyed P8 blit doesn't do anything on WARP - it just leaves the data in the destination
8038 * surface untouched. P8 blits without color keys work. Error checking (DDBLT_KEYSRC without a key
8039 * for example) also works as expected.
8041 * Using DDBLT_KEYSRC instead of DDBLT_KEYSRCOVERRIDE doesn't change this. Doing this blit with
8042 * the display mode set to P8 doesn't help either. */
8043 ok(!memcmp(surface_desc.lpSurface, expected_p8, sizeof(expected_p8))
8044 || broken(is_warp && !memcmp(surface_desc.lpSurface, src_data2, sizeof(src_data2))),
8045 "Got unexpected P8 color key blit result.\n");
8046 hr = IDirectDrawSurface7_Unlock(dst_p8, NULL);
8047 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#x.\n", hr);
8049 IDirectDrawSurface7_Release(src);
8050 IDirectDrawSurface7_Release(dst);
8051 IDirectDrawSurface7_Release(dst_p8);
8052 IDirectDrawPalette_Release(palette);
8053 IDirectDrawPalette_Release(palette2);
8055 refcount = IDirectDraw7_Release(ddraw);
8056 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8057 DestroyWindow(window);
8060 static void test_material(void)
8062 static const D3DCOLORVALUE null_color;
8063 IDirect3DDevice7 *device;
8064 D3DMATERIAL7 material;
8065 ULONG refcount;
8066 HWND window;
8067 HRESULT hr;
8069 window = create_window();
8070 if (!(device = create_device(window, DDSCL_NORMAL)))
8072 skip("Failed to create a 3D device, skipping test.\n");
8073 DestroyWindow(window);
8074 return;
8077 hr = IDirect3DDevice7_GetMaterial(device, &material);
8078 ok(SUCCEEDED(hr), "Failed to get material, hr %#x.\n", hr);
8079 ok(!memcmp(&U(material).diffuse, &null_color, sizeof(null_color)),
8080 "Got unexpected diffuse color {%.8e, %.8e, %.8e, %.8e}.\n",
8081 U1(U(material).diffuse).r, U2(U(material).diffuse).g,
8082 U3(U(material).diffuse).b, U4(U(material).diffuse).a);
8083 ok(!memcmp(&U1(material).ambient, &null_color, sizeof(null_color)),
8084 "Got unexpected ambient color {%.8e, %.8e, %.8e, %.8e}.\n",
8085 U1(U1(material).ambient).r, U2(U1(material).ambient).g,
8086 U3(U1(material).ambient).b, U4(U1(material).ambient).a);
8087 ok(!memcmp(&U2(material).specular, &null_color, sizeof(null_color)),
8088 "Got unexpected specular color {%.8e, %.8e, %.8e, %.8e}.\n",
8089 U1(U2(material).specular).r, U2(U2(material).specular).g,
8090 U3(U2(material).specular).b, U4(U2(material).specular).a);
8091 ok(!memcmp(&U3(material).emissive, &null_color, sizeof(null_color)),
8092 "Got unexpected emissive color {%.8e, %.8e, %.8e, %.8e}.\n",
8093 U1(U3(material).emissive).r, U2(U3(material).emissive).g,
8094 U3(U3(material).emissive).b, U4(U3(material).emissive).a);
8095 ok(U4(material).power == 0.0f, "Got unexpected power %.8e.\n", U4(material).power);
8097 refcount = IDirect3DDevice7_Release(device);
8098 ok(!refcount, "Device has %u references left.\n", refcount);
8099 DestroyWindow(window);
8102 static void test_palette_gdi(void)
8104 IDirectDrawSurface7 *surface, *primary;
8105 DDSURFACEDESC2 surface_desc;
8106 IDirectDraw7 *ddraw;
8107 IDirectDrawPalette *palette, *palette2;
8108 ULONG refcount;
8109 HWND window;
8110 HRESULT hr;
8111 PALETTEENTRY palette_entries[256];
8112 UINT i;
8113 HDC dc;
8114 DDBLTFX fx;
8115 RECT r;
8116 COLORREF color;
8117 /* On the Windows 8 testbot palette index 0 of the onscreen palette is forced to
8118 * r = 0, g = 0, b = 0. Do not attempt to set it to something else as this is
8119 * not the point of this test. */
8120 static const RGBQUAD expected1[] =
8122 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
8123 {0x03, 0x00, 0x00, 0x00}, {0x15, 0x14, 0x13, 0x00},
8125 static const RGBQUAD expected2[] =
8127 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
8128 {0x03, 0x00, 0x00, 0x00}, {0x25, 0x24, 0x23, 0x00},
8130 static const RGBQUAD expected3[] =
8132 {0x00, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x40, 0x00},
8133 {0x00, 0x40, 0x00, 0x00}, {0x56, 0x34, 0x12, 0x00},
8135 HPALETTE ddraw_palette_handle;
8136 /* Similar to index 0, index 255 is r = 0xff, g = 0xff, b = 0xff on the Win8 VMs. */
8137 RGBQUAD rgbquad[255];
8138 static const RGBQUAD rgb_zero = {0, 0, 0, 0};
8140 window = create_window();
8141 ddraw = create_ddraw();
8142 ok(!!ddraw, "Failed to create a ddraw object.\n");
8143 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8144 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8146 memset(&surface_desc, 0, sizeof(surface_desc));
8147 surface_desc.dwSize = sizeof(surface_desc);
8148 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8149 surface_desc.dwWidth = 16;
8150 surface_desc.dwHeight = 16;
8151 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8152 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8153 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
8154 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
8155 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8156 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8158 /* Avoid colors from the Windows default palette. */
8159 memset(palette_entries, 0, sizeof(palette_entries));
8160 palette_entries[1].peRed = 0x01;
8161 palette_entries[2].peGreen = 0x02;
8162 palette_entries[3].peBlue = 0x03;
8163 palette_entries[4].peRed = 0x13;
8164 palette_entries[4].peGreen = 0x14;
8165 palette_entries[4].peBlue = 0x15;
8166 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8167 palette_entries, &palette, NULL);
8168 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8170 /* If there is no palette assigned and the display mode is not 8 bpp, some
8171 * drivers refuse to create a DC while others allow it. If a DC is created,
8172 * the DIB color table is uninitialized and contains random colors. No error
8173 * is generated when trying to read pixels and random garbage is returned.
8175 * The most likely explanation is that if the driver creates a DC, it (or
8176 * the higher-level runtime) uses GetSystemPaletteEntries to find the
8177 * palette, but GetSystemPaletteEntries fails when bpp > 8 and the palette
8178 * contains uninitialized garbage. See comments below for the P8 case. */
8180 hr = IDirectDrawSurface7_SetPalette(surface, palette);
8181 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8182 hr = IDirectDrawSurface7_GetDC(surface, &dc);
8183 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8184 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
8185 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
8186 "Got unexpected palette %p, expected %p.\n",
8187 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
8189 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8190 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8191 for (i = 0; i < ARRAY_SIZE(expected1); ++i)
8193 ok(!memcmp(&rgbquad[i], &expected1[i], sizeof(rgbquad[i])),
8194 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8195 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8196 expected1[i].rgbRed, expected1[i].rgbGreen, expected1[i].rgbBlue);
8198 for (; i < ARRAY_SIZE(rgbquad); ++i)
8200 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8201 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8202 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8205 /* Update the palette while the DC is in use. This does not modify the DC. */
8206 palette_entries[4].peRed = 0x23;
8207 palette_entries[4].peGreen = 0x24;
8208 palette_entries[4].peBlue = 0x25;
8209 hr = IDirectDrawPalette_SetEntries(palette, 0, 4, 1, &palette_entries[4]);
8210 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
8212 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
8213 ok(i == 1, "Expected count 1, got %u.\n", i);
8214 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
8215 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8216 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
8217 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
8219 /* Neither does re-setting the palette. */
8220 hr = IDirectDrawSurface7_SetPalette(surface, NULL);
8221 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8222 hr = IDirectDrawSurface7_SetPalette(surface, palette);
8223 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8225 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
8226 ok(i == 1, "Expected count 1, got %u.\n", i);
8227 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
8228 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8229 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
8230 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
8232 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
8233 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8235 /* Refresh the DC. This updates the palette. */
8236 hr = IDirectDrawSurface7_GetDC(surface, &dc);
8237 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8238 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8239 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8240 for (i = 0; i < ARRAY_SIZE(expected2); ++i)
8242 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8243 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8244 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8245 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8247 for (; i < ARRAY_SIZE(rgbquad); ++i)
8249 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8250 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8251 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8253 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
8254 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8256 refcount = IDirectDrawSurface7_Release(surface);
8257 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8259 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
8260 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8261 if (FAILED(IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
8263 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
8264 IDirectDrawPalette_Release(palette);
8265 IDirectDraw7_Release(ddraw);
8266 DestroyWindow(window);
8267 return;
8269 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
8271 memset(&surface_desc, 0, sizeof(surface_desc));
8272 surface_desc.dwSize = sizeof(surface_desc);
8273 surface_desc.dwFlags = DDSD_CAPS;
8274 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8275 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
8276 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8278 memset(&fx, 0, sizeof(fx));
8279 fx.dwSize = sizeof(fx);
8280 U5(fx).dwFillColor = 3;
8281 SetRect(&r, 0, 0, 319, 479);
8282 hr = IDirectDrawSurface7_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8283 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#x.\n", hr);
8284 SetRect(&r, 320, 0, 639, 479);
8285 U5(fx).dwFillColor = 4;
8286 hr = IDirectDrawSurface7_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8287 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#x.\n", hr);
8289 hr = IDirectDrawSurface7_SetPalette(primary, palette);
8290 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8291 hr = IDirectDrawSurface7_GetDC(primary, &dc);
8292 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8294 color = GetPixel(dc, 160, 240);
8295 ok(color == 0x00030000, "Clear index 3: Got unexpected color 0x%08x.\n", color);
8296 color = GetPixel(dc, 480, 240);
8297 ok(color == 0x00252423, "Clear index 4: Got unexpected color 0x%08x.\n", color);
8299 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
8300 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
8301 "Got unexpected palette %p, expected %p.\n",
8302 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
8303 SelectPalette(dc, ddraw_palette_handle, FALSE);
8305 /* The primary uses the system palette. In exclusive mode, the system palette matches
8306 * the ddraw palette attached to the primary, so the result is what you would expect
8307 * from a regular surface. Tests for the interaction between the ddraw palette and
8308 * the system palette are not included pending an application that depends on this.
8309 * The relation between those causes problems on Windows Vista and newer for games
8310 * like Age of Empires or StarcCaft. Don't emulate it without a real need. */
8311 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8312 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8313 for (i = 0; i < ARRAY_SIZE(expected2); ++i)
8315 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8316 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8317 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8318 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8320 for (; i < ARRAY_SIZE(rgbquad); ++i)
8322 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8323 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8324 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8326 hr = IDirectDrawSurface7_ReleaseDC(primary, dc);
8327 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8329 memset(&surface_desc, 0, sizeof(surface_desc));
8330 surface_desc.dwSize = sizeof(surface_desc);
8331 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8332 surface_desc.dwWidth = 16;
8333 surface_desc.dwHeight = 16;
8334 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8335 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8336 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8338 /* Here the offscreen surface appears to use the primary's palette,
8339 * but in all likelihood it is actually the system palette. */
8340 hr = IDirectDrawSurface7_GetDC(surface, &dc);
8341 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8342 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8343 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8344 for (i = 0; i < ARRAY_SIZE(expected2); ++i)
8346 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8347 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8348 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8349 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8351 for (; i < ARRAY_SIZE(rgbquad); ++i)
8353 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8354 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8355 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8357 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
8358 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8360 /* On real hardware a change to the primary surface's palette applies immediately,
8361 * even on device contexts from offscreen surfaces that do not have their own
8362 * palette. On the testbot VMs this is not the case. Don't test this until we
8363 * know of an application that depends on this. */
8365 memset(palette_entries, 0, sizeof(palette_entries));
8366 palette_entries[1].peBlue = 0x40;
8367 palette_entries[2].peRed = 0x40;
8368 palette_entries[3].peGreen = 0x40;
8369 palette_entries[4].peRed = 0x12;
8370 palette_entries[4].peGreen = 0x34;
8371 palette_entries[4].peBlue = 0x56;
8372 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8373 palette_entries, &palette2, NULL);
8374 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8375 hr = IDirectDrawSurface7_SetPalette(surface, palette2);
8376 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8378 /* A palette assigned to the offscreen surface overrides the primary / system
8379 * palette. */
8380 hr = IDirectDrawSurface7_GetDC(surface, &dc);
8381 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8382 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8383 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8384 for (i = 0; i < ARRAY_SIZE(expected3); ++i)
8386 ok(!memcmp(&rgbquad[i], &expected3[i], sizeof(rgbquad[i])),
8387 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8388 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8389 expected3[i].rgbRed, expected3[i].rgbGreen, expected3[i].rgbBlue);
8391 for (; i < ARRAY_SIZE(rgbquad); ++i)
8393 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8394 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8395 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8397 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
8398 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8400 refcount = IDirectDrawSurface7_Release(surface);
8401 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8403 /* The Windows 8 testbot keeps extra references to the primary and
8404 * backbuffer while in 8 bpp mode. */
8405 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
8406 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
8408 refcount = IDirectDrawSurface7_Release(primary);
8409 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8410 refcount = IDirectDrawPalette_Release(palette2);
8411 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8412 refcount = IDirectDrawPalette_Release(palette);
8413 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8414 refcount = IDirectDraw7_Release(ddraw);
8415 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8416 DestroyWindow(window);
8419 static void test_palette_alpha(void)
8421 IDirectDrawSurface7 *surface;
8422 DDSURFACEDESC2 surface_desc;
8423 IDirectDraw7 *ddraw;
8424 IDirectDrawPalette *palette;
8425 ULONG refcount;
8426 HWND window;
8427 HRESULT hr;
8428 PALETTEENTRY palette_entries[256];
8429 unsigned int i;
8430 static const struct
8432 DWORD caps, flags;
8433 BOOL attach_allowed;
8434 const char *name;
8436 test_data[] =
8438 {DDSCAPS_OFFSCREENPLAIN, DDSD_WIDTH | DDSD_HEIGHT, FALSE, "offscreenplain"},
8439 {DDSCAPS_TEXTURE, DDSD_WIDTH | DDSD_HEIGHT, TRUE, "texture"},
8440 {DDSCAPS_PRIMARYSURFACE, 0, FALSE, "primary"}
8443 window = create_window();
8444 ddraw = create_ddraw();
8445 ok(!!ddraw, "Failed to create a ddraw object.\n");
8446 if (FAILED(IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
8448 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
8449 IDirectDraw7_Release(ddraw);
8450 DestroyWindow(window);
8451 return;
8453 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8454 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8456 memset(palette_entries, 0, sizeof(palette_entries));
8457 palette_entries[1].peFlags = 0x42;
8458 palette_entries[2].peFlags = 0xff;
8459 palette_entries[3].peFlags = 0x80;
8460 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
8461 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8463 memset(palette_entries, 0x66, sizeof(palette_entries));
8464 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
8465 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
8466 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8467 palette_entries[0].peFlags);
8468 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8469 palette_entries[1].peFlags);
8470 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
8471 palette_entries[2].peFlags);
8472 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
8473 palette_entries[3].peFlags);
8475 IDirectDrawPalette_Release(palette);
8477 memset(palette_entries, 0, sizeof(palette_entries));
8478 palette_entries[1].peFlags = 0x42;
8479 palette_entries[1].peRed = 0xff;
8480 palette_entries[2].peFlags = 0xff;
8481 palette_entries[3].peFlags = 0x80;
8482 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT | DDPCAPS_ALPHA,
8483 palette_entries, &palette, NULL);
8484 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8486 memset(palette_entries, 0x66, sizeof(palette_entries));
8487 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
8488 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
8489 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8490 palette_entries[0].peFlags);
8491 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8492 palette_entries[1].peFlags);
8493 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
8494 palette_entries[2].peFlags);
8495 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
8496 palette_entries[3].peFlags);
8498 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
8500 memset(&surface_desc, 0, sizeof(surface_desc));
8501 surface_desc.dwSize = sizeof(surface_desc);
8502 surface_desc.dwFlags = DDSD_CAPS | test_data[i].flags;
8503 surface_desc.dwWidth = 128;
8504 surface_desc.dwHeight = 128;
8505 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
8506 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8507 ok(SUCCEEDED(hr), "Failed to create %s surface, hr %#x.\n", test_data[i].name, hr);
8509 hr = IDirectDrawSurface7_SetPalette(surface, palette);
8510 if (test_data[i].attach_allowed)
8511 ok(SUCCEEDED(hr), "Failed to attach palette to %s surface, hr %#x.\n", test_data[i].name, hr);
8512 else
8513 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x, %s surface.\n", hr, test_data[i].name);
8515 if (SUCCEEDED(hr))
8517 HDC dc;
8518 RGBQUAD rgbquad;
8519 UINT retval;
8521 hr = IDirectDrawSurface7_GetDC(surface, &dc);
8522 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x, %s surface.\n", hr, test_data[i].name);
8523 retval = GetDIBColorTable(dc, 1, 1, &rgbquad);
8524 ok(retval == 1, "GetDIBColorTable returned unexpected result %u.\n", retval);
8525 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x, %s surface.\n",
8526 rgbquad.rgbRed, test_data[i].name);
8527 ok(rgbquad.rgbGreen == 0, "Expected rgbGreen = 0, got %#x, %s surface.\n",
8528 rgbquad.rgbGreen, test_data[i].name);
8529 ok(rgbquad.rgbBlue == 0, "Expected rgbBlue = 0, got %#x, %s surface.\n",
8530 rgbquad.rgbBlue, test_data[i].name);
8531 ok(rgbquad.rgbReserved == 0, "Expected rgbReserved = 0, got %u, %s surface.\n",
8532 rgbquad.rgbReserved, test_data[i].name);
8533 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
8534 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8536 IDirectDrawSurface7_Release(surface);
8539 /* Test INVALIDSURFACETYPE vs INVALIDPIXELFORMAT. */
8540 memset(&surface_desc, 0, sizeof(surface_desc));
8541 surface_desc.dwSize = sizeof(surface_desc);
8542 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8543 surface_desc.dwWidth = 128;
8544 surface_desc.dwHeight = 128;
8545 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8546 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8547 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
8548 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
8549 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8550 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8551 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
8552 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8553 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8554 hr = IDirectDrawSurface7_SetPalette(surface, palette);
8555 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x.\n", hr);
8556 IDirectDrawSurface7_Release(surface);
8558 /* The Windows 8 testbot keeps extra references to the primary
8559 * while in 8 bpp mode. */
8560 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
8561 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
8563 refcount = IDirectDrawPalette_Release(palette);
8564 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8565 refcount = IDirectDraw7_Release(ddraw);
8566 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8567 DestroyWindow(window);
8570 static void test_vb_writeonly(void)
8572 IDirect3DDevice7 *device;
8573 IDirect3D7 *d3d;
8574 IDirect3DVertexBuffer7 *buffer;
8575 HWND window;
8576 HRESULT hr;
8577 D3DVERTEXBUFFERDESC desc;
8578 void *ptr;
8579 static const struct vec4 quad[] =
8581 { 0.0f, 480.0f, 0.0f, 1.0f},
8582 { 0.0f, 0.0f, 0.0f, 1.0f},
8583 {640.0f, 480.0f, 0.0f, 1.0f},
8584 {640.0f, 0.0f, 0.0f, 1.0f},
8587 window = create_window();
8588 if (!(device = create_device(window, DDSCL_NORMAL)))
8590 skip("Failed to create a 3D device, skipping test.\n");
8591 DestroyWindow(window);
8592 return;
8595 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
8596 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
8598 memset(&desc, 0, sizeof(desc));
8599 desc.dwSize = sizeof(desc);
8600 desc.dwCaps = D3DVBCAPS_WRITEONLY;
8601 desc.dwFVF = D3DFVF_XYZRHW;
8602 desc.dwNumVertices = ARRAY_SIZE(quad);
8603 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &buffer, 0);
8604 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
8606 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, &ptr, NULL);
8607 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
8608 memcpy(ptr, quad, sizeof(quad));
8609 hr = IDirect3DVertexBuffer7_Unlock(buffer);
8610 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
8612 hr = IDirect3DDevice7_BeginScene(device);
8613 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8614 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
8615 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8616 hr = IDirect3DDevice7_EndScene(device);
8617 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8619 hr = IDirect3DVertexBuffer7_Lock(buffer, 0, &ptr, NULL);
8620 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
8621 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
8622 hr = IDirect3DVertexBuffer7_Unlock(buffer);
8623 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
8625 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_READONLY, &ptr, NULL);
8626 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
8627 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
8628 hr = IDirect3DVertexBuffer7_Unlock(buffer);
8629 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
8631 IDirect3DVertexBuffer7_Release(buffer);
8632 IDirect3D7_Release(d3d);
8633 IDirect3DDevice7_Release(device);
8634 DestroyWindow(window);
8637 static void test_lost_device(void)
8639 IDirectDrawSurface7 *surface;
8640 DDSURFACEDESC2 surface_desc;
8641 HWND window1, window2;
8642 IDirectDraw7 *ddraw;
8643 ULONG refcount;
8644 HRESULT hr;
8645 BOOL ret;
8647 window1 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8648 0, 0, 640, 480, 0, 0, 0, 0);
8649 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
8650 0, 0, 640, 480, 0, 0, 0, 0);
8651 ddraw = create_ddraw();
8652 ok(!!ddraw, "Failed to create a ddraw object.\n");
8653 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8654 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8656 memset(&surface_desc, 0, sizeof(surface_desc));
8657 surface_desc.dwSize = sizeof(surface_desc);
8658 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
8659 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
8660 U5(surface_desc).dwBackBufferCount = 1;
8661 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8662 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8664 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8665 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8666 hr = IDirectDrawSurface7_IsLost(surface);
8667 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8668 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8669 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8671 ret = SetForegroundWindow(GetDesktopWindow());
8672 ok(ret, "Failed to set foreground window.\n");
8673 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8674 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8675 hr = IDirectDrawSurface7_IsLost(surface);
8676 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8677 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8678 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8680 ret = SetForegroundWindow(window1);
8681 ok(ret, "Failed to set foreground window.\n");
8682 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8683 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8684 hr = IDirectDrawSurface7_IsLost(surface);
8685 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8686 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8687 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8689 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
8690 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8691 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8692 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8693 hr = IDirectDrawSurface7_IsLost(surface);
8694 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8695 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8696 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8698 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
8699 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8700 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8701 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8702 hr = IDirectDrawSurface7_IsLost(surface);
8703 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8704 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8705 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8707 /* Trying to restore the primary will crash, probably because flippable
8708 * surfaces can't exist in DDSCL_NORMAL. */
8709 IDirectDrawSurface7_Release(surface);
8710 memset(&surface_desc, 0, sizeof(surface_desc));
8711 surface_desc.dwSize = sizeof(surface_desc);
8712 surface_desc.dwFlags = DDSD_CAPS;
8713 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8714 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8715 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8717 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8718 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8719 hr = IDirectDrawSurface7_IsLost(surface);
8720 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8722 ret = SetForegroundWindow(GetDesktopWindow());
8723 ok(ret, "Failed to set foreground window.\n");
8724 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8725 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8726 hr = IDirectDrawSurface7_IsLost(surface);
8727 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8729 ret = SetForegroundWindow(window1);
8730 ok(ret, "Failed to set foreground window.\n");
8731 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8732 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8733 hr = IDirectDrawSurface7_IsLost(surface);
8734 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8736 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8737 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8738 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8739 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8740 hr = IDirectDrawSurface7_IsLost(surface);
8741 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8743 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
8744 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8745 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8746 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8747 hr = IDirectDrawSurface7_IsLost(surface);
8748 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8750 IDirectDrawSurface7_Release(surface);
8751 memset(&surface_desc, 0, sizeof(surface_desc));
8752 surface_desc.dwSize = sizeof(surface_desc);
8753 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
8754 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
8755 U5(surface_desc).dwBackBufferCount = 1;
8756 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8757 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8759 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8760 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8761 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8762 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8763 hr = IDirectDrawSurface7_IsLost(surface);
8764 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8765 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8766 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8768 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL | DDSCL_FULLSCREEN);
8769 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8770 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8771 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8772 hr = IDirectDrawSurface7_IsLost(surface);
8773 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8774 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8775 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8777 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
8778 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8779 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8780 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8781 hr = IDirectDrawSurface7_IsLost(surface);
8782 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8783 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8784 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8786 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
8787 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8788 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8789 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8790 hr = IDirectDrawSurface7_IsLost(surface);
8791 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8792 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8793 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8795 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL | DDSCL_FULLSCREEN);
8796 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8797 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8798 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8799 hr = IDirectDrawSurface7_IsLost(surface);
8800 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8801 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8802 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
8804 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8805 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8806 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
8807 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8808 hr = IDirectDrawSurface7_IsLost(surface);
8809 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8810 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
8811 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8813 IDirectDrawSurface7_Release(surface);
8814 refcount = IDirectDraw7_Release(ddraw);
8815 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8816 DestroyWindow(window2);
8817 DestroyWindow(window1);
8820 static void test_resource_priority(void)
8822 IDirectDrawSurface7 *surface, *mipmap;
8823 DDSURFACEDESC2 surface_desc;
8824 IDirectDraw7 *ddraw;
8825 ULONG refcount;
8826 HWND window;
8827 HRESULT hr;
8828 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
8829 DDCAPS hal_caps;
8830 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_MIPMAP;
8831 unsigned int i;
8832 DWORD priority;
8833 static const struct
8835 DWORD caps, caps2;
8836 const char *name;
8837 HRESULT hr;
8838 /* SetPriority on offscreenplain surfaces crashes on AMD GPUs on Win7. */
8839 BOOL crash;
8841 test_data[] =
8843 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, "vidmem texture", DDERR_INVALIDPARAMS, FALSE},
8844 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, "sysmem texture", DDERR_INVALIDPARAMS, FALSE},
8845 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, "managed texture", DD_OK, FALSE},
8846 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, "managed texture", DD_OK, FALSE},
8847 {DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP,
8848 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_TEXTUREMANAGE,
8849 "cubemap", DD_OK, FALSE},
8850 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, "vidmem offscreenplain", DDERR_INVALIDOBJECT, TRUE},
8851 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, "sysmem offscreenplain", DDERR_INVALIDOBJECT, TRUE},
8854 window = create_window();
8855 ddraw = create_ddraw();
8856 ok(!!ddraw, "Failed to create a ddraw object.\n");
8857 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8858 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8860 memset(&hal_caps, 0, sizeof(hal_caps));
8861 hal_caps.dwSize = sizeof(hal_caps);
8862 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
8863 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8864 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps
8865 || !(hal_caps.ddsCaps.dwCaps & DDSCAPS2_TEXTUREMANAGE))
8867 skip("Required surface types not supported, skipping test.\n");
8868 goto done;
8871 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
8873 memset(&surface_desc, 0, sizeof(surface_desc));
8874 surface_desc.dwSize = sizeof(surface_desc);
8875 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
8876 surface_desc.dwWidth = 32;
8877 surface_desc.dwHeight = 32;
8878 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
8879 surface_desc.ddsCaps.dwCaps2 = test_data[i].caps2;
8880 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8881 if (is_ddraw64 && (test_data[i].caps & DDSCAPS_TEXTURE))
8883 todo_wine ok(hr == E_NOINTERFACE, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
8884 if (SUCCEEDED(hr))
8885 IDirectDrawSurface7_Release(surface);
8886 continue;
8888 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n", hr, test_data[i].name);
8890 /* Priority == NULL segfaults. */
8891 priority = 0xdeadbeef;
8892 hr = IDirectDrawSurface7_GetPriority(surface, &priority);
8893 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
8894 if (SUCCEEDED(test_data[i].hr))
8895 ok(priority == 0, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
8896 else
8897 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
8899 if (!test_data[i].crash)
8901 hr = IDirectDrawSurface7_SetPriority(surface, 1);
8902 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
8903 hr = IDirectDrawSurface7_GetPriority(surface, &priority);
8904 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
8905 if (SUCCEEDED(test_data[i].hr))
8907 ok(priority == 1, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
8908 hr = IDirectDrawSurface7_SetPriority(surface, 2);
8909 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
8911 else
8912 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
8915 if (test_data[i].caps2 & DDSCAPS2_CUBEMAP)
8917 caps.dwCaps2 = DDSCAPS2_CUBEMAP_NEGATIVEZ;
8918 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
8919 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
8920 /* IDirectDrawSurface7_SetPriority crashes when called on non-positive X surfaces on Windows */
8921 priority = 0xdeadbeef;
8922 hr = IDirectDrawSurface7_GetPriority(mipmap, &priority);
8923 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
8924 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
8926 IDirectDrawSurface7_Release(mipmap);
8929 IDirectDrawSurface7_Release(surface);
8932 if (is_ddraw64)
8933 goto done;
8935 memset(&surface_desc, 0, sizeof(surface_desc));
8936 surface_desc.dwSize = sizeof(surface_desc);
8937 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_MIPMAPCOUNT;
8938 surface_desc.dwWidth = 32;
8939 surface_desc.dwHeight = 32;
8940 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
8941 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
8942 U2(surface_desc).dwMipMapCount = 2;
8943 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8944 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8945 caps.dwCaps2 = 0;
8946 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
8947 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
8949 priority = 0xdeadbeef;
8950 hr = IDirectDrawSurface7_GetPriority(mipmap, &priority);
8951 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type managed mipmap.\n", hr);
8952 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type managed mipmap.\n", priority);
8953 /* SetPriority on the mipmap surface crashes. */
8954 hr = IDirectDrawSurface7_GetPriority(surface, &priority);
8955 ok(SUCCEEDED(hr), "Failed to get priority, hr %#x.\n", hr);
8956 ok(priority == 0, "Got unexpected priority %u, type managed mipmap.\n", priority);
8958 IDirectDrawSurface7_Release(mipmap);
8959 refcount = IDirectDrawSurface7_Release(surface);
8960 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8962 done:
8963 refcount = IDirectDraw7_Release(ddraw);
8964 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8965 DestroyWindow(window);
8968 static void test_surface_desc_lock(void)
8970 IDirectDrawSurface7 *surface;
8971 DDSURFACEDESC2 surface_desc;
8972 IDirectDraw7 *ddraw;
8973 ULONG refcount;
8974 HWND window;
8975 HRESULT hr;
8977 window = create_window();
8978 ddraw = create_ddraw();
8979 ok(!!ddraw, "Failed to create a ddraw object.\n");
8980 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8981 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8983 memset(&surface_desc, 0, sizeof(surface_desc));
8984 surface_desc.dwSize = sizeof(surface_desc);
8985 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8986 surface_desc.dwWidth = 16;
8987 surface_desc.dwHeight = 16;
8988 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8989 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8990 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8992 memset(&surface_desc, 0xaa, sizeof(surface_desc));
8993 surface_desc.dwSize = sizeof(surface_desc);
8994 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
8995 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8996 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
8998 memset(&surface_desc, 0xaa, sizeof(surface_desc));
8999 surface_desc.dwSize = sizeof(surface_desc);
9000 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, 0, NULL);
9001 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
9002 ok(surface_desc.lpSurface != NULL, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9003 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9004 surface_desc.dwSize = sizeof(surface_desc);
9005 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
9006 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
9007 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9008 hr = IDirectDrawSurface7_Unlock(surface, NULL);
9009 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9011 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9012 surface_desc.dwSize = sizeof(surface_desc);
9013 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
9014 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
9015 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9017 IDirectDrawSurface7_Release(surface);
9018 refcount = IDirectDraw7_Release(ddraw);
9019 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9020 DestroyWindow(window);
9023 static void test_fog_interpolation(void)
9025 HRESULT hr;
9026 IDirect3DDevice7 *device;
9027 IDirectDrawSurface7 *rt;
9028 ULONG refcount;
9029 HWND window;
9030 D3DCOLOR color;
9031 static struct
9033 struct vec3 position;
9034 D3DCOLOR diffuse;
9035 D3DCOLOR specular;
9037 quad[] =
9039 {{-1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff000000},
9040 {{-1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff000000},
9041 {{ 1.0f, -1.0f, 1.0f}, 0xffff0000, 0x00000000},
9042 {{ 1.0f, 1.0f, 1.0f}, 0xffff0000, 0x00000000},
9044 union
9046 DWORD d;
9047 float f;
9048 } conv;
9049 unsigned int i;
9050 static const struct
9052 D3DFOGMODE vfog, tfog;
9053 D3DSHADEMODE shade;
9054 D3DCOLOR middle_color;
9055 BOOL todo;
9057 tests[] =
9059 {D3DFOG_NONE, D3DFOG_NONE, D3DSHADE_FLAT, 0x00007f80, FALSE},
9060 {D3DFOG_NONE, D3DFOG_NONE, D3DSHADE_GOURAUD, 0x00007f80, FALSE},
9061 {D3DFOG_EXP, D3DFOG_NONE, D3DSHADE_FLAT, 0x00007f80, TRUE},
9062 {D3DFOG_EXP, D3DFOG_NONE, D3DSHADE_GOURAUD, 0x00007f80, TRUE},
9063 {D3DFOG_NONE, D3DFOG_EXP, D3DSHADE_FLAT, 0x0000ea15, FALSE},
9064 {D3DFOG_NONE, D3DFOG_EXP, D3DSHADE_GOURAUD, 0x0000ea15, FALSE},
9065 {D3DFOG_EXP, D3DFOG_EXP, D3DSHADE_FLAT, 0x0000ea15, FALSE},
9066 {D3DFOG_EXP, D3DFOG_EXP, D3DSHADE_GOURAUD, 0x0000ea15, FALSE},
9068 D3DDEVICEDESC7 caps;
9070 window = create_window();
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 < ARRAY_SIZE(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 = create_window();
9228 if (!(device = create_device(window, DDSCL_NORMAL)))
9230 skip("Failed to create a 3D device, skipping test.\n");
9231 DestroyWindow(window);
9232 return;
9235 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
9236 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9237 hr = IDirect3DDevice7_GetCaps(device, &caps);
9238 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
9239 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE))
9240 skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping some fog tests.\n");
9242 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
9243 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9244 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
9245 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9246 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
9247 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9248 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x0000ff00);
9249 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9250 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
9251 ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
9253 for (i = 0; i < ARRAY_SIZE(tests); ++i)
9255 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE) && tests[i].tfog)
9256 continue;
9258 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0);
9259 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
9261 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, tests[i].matrix);
9262 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
9263 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGSTART, tests[i].start.d);
9264 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9265 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGEND, tests[i].end.d);
9266 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9267 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, tests[i].vfog);
9268 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9269 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, tests[i].tfog);
9270 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9272 hr = IDirect3DDevice7_BeginScene(device);
9273 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9274 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9275 tests[i].pos_type | D3DFVF_DIFFUSE, tests[i].quad, 4, 0);
9276 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9277 hr = IDirect3DDevice7_EndScene(device);
9278 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9280 color = get_surface_color(rt, 0, 240);
9281 ok(compare_color(color, tests[i].color, 2) || broken(compare_color(color, tests[i].color_broken, 2))
9282 || broken(compare_color(color, tests[i].color_broken2, 2)),
9283 "Got unexpected color 0x%08x, case %u.\n", color, i);
9286 IDirectDrawSurface7_Release(rt);
9287 refcount = IDirect3DDevice7_Release(device);
9288 ok(!refcount, "Device has %u references left.\n", refcount);
9289 DestroyWindow(window);
9292 static void test_table_fog_zw(void)
9294 HRESULT hr;
9295 IDirect3DDevice7 *device;
9296 IDirectDrawSurface7 *rt;
9297 ULONG refcount;
9298 HWND window;
9299 D3DCOLOR color;
9300 static struct
9302 struct vec4 position;
9303 D3DCOLOR diffuse;
9305 quad[] =
9307 {{ 0.0f, 0.0f, 0.0f, 0.0f}, 0xffff0000},
9308 {{640.0f, 0.0f, 0.0f, 0.0f}, 0xffff0000},
9309 {{ 0.0f, 480.0f, 0.0f, 0.0f}, 0xffff0000},
9310 {{640.0f, 480.0f, 0.0f, 0.0f}, 0xffff0000},
9312 static D3DMATRIX identity =
9314 1.0f, 0.0f, 0.0f, 0.0f,
9315 0.0f, 1.0f, 0.0f, 0.0f,
9316 0.0f, 0.0f, 1.0f, 0.0f,
9317 0.0f, 0.0f, 0.0f, 1.0f
9319 D3DDEVICEDESC7 caps;
9320 static const struct
9322 float z, w;
9323 D3DZBUFFERTYPE z_test;
9324 D3DCOLOR color;
9326 tests[] =
9328 {0.7f, 0.0f, D3DZB_TRUE, 0x004cb200},
9329 {0.7f, 0.0f, D3DZB_FALSE, 0x004cb200},
9330 {0.7f, 0.3f, D3DZB_TRUE, 0x004cb200},
9331 {0.7f, 0.3f, D3DZB_FALSE, 0x004cb200},
9332 {0.7f, 3.0f, D3DZB_TRUE, 0x004cb200},
9333 {0.7f, 3.0f, D3DZB_FALSE, 0x004cb200},
9334 {0.3f, 0.0f, D3DZB_TRUE, 0x00b24c00},
9335 {0.3f, 0.0f, D3DZB_FALSE, 0x00b24c00},
9337 unsigned int i;
9339 window = create_window();
9340 if (!(device = create_device(window, DDSCL_NORMAL)))
9342 skip("Failed to create a 3D device, skipping test.\n");
9343 DestroyWindow(window);
9344 return;
9347 hr = IDirect3DDevice7_GetCaps(device, &caps);
9348 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
9349 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE))
9351 skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping POSITIONT table fog test.\n");
9352 goto done;
9354 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
9355 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9357 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
9358 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9359 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
9360 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9361 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x0000ff00);
9362 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9363 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
9364 ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
9365 /* Work around an AMD Windows driver bug. Needs a proj matrix applied redundantly. */
9366 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &identity);
9367 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
9368 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_LINEAR);
9369 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9371 for (i = 0; i < ARRAY_SIZE(tests); ++i)
9373 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x000000ff, 1.0f, 0);
9374 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
9376 quad[0].position.z = tests[i].z;
9377 quad[1].position.z = tests[i].z;
9378 quad[2].position.z = tests[i].z;
9379 quad[3].position.z = tests[i].z;
9380 quad[0].position.w = tests[i].w;
9381 quad[1].position.w = tests[i].w;
9382 quad[2].position.w = tests[i].w;
9383 quad[3].position.w = tests[i].w;
9384 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, tests[i].z_test);
9385 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9387 hr = IDirect3DDevice7_BeginScene(device);
9388 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9389 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9390 D3DFVF_XYZRHW | D3DFVF_DIFFUSE, quad, 4, 0);
9391 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9392 hr = IDirect3DDevice7_EndScene(device);
9393 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9395 color = get_surface_color(rt, 0, 240);
9396 ok(compare_color(color, tests[i].color, 2),
9397 "Got unexpected color 0x%08x, expected 0x%8x, case %u.\n", color, tests[i].color, i);
9400 IDirectDrawSurface7_Release(rt);
9401 done:
9402 refcount = IDirect3DDevice7_Release(device);
9403 ok(!refcount, "Device has %u references left.\n", refcount);
9404 DestroyWindow(window);
9407 static void test_signed_formats(void)
9409 HRESULT hr;
9410 IDirect3DDevice7 *device;
9411 IDirect3D7 *d3d;
9412 IDirectDraw7 *ddraw;
9413 IDirectDrawSurface7 *surface, *rt;
9414 DDSURFACEDESC2 surface_desc;
9415 ULONG refcount;
9416 HWND window;
9417 D3DCOLOR color, expected_color;
9418 static struct
9420 struct vec3 position;
9421 struct vec2 texcoord;
9423 quad[] =
9425 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
9426 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
9427 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
9428 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
9430 /* See test_signed_formats() in dlls/d3d9/tests/visual.c for an explanation
9431 * of these values. */
9432 static const USHORT content_v8u8[4][4] =
9434 {0x0000, 0x7f7f, 0x8880, 0x0000},
9435 {0x0080, 0x8000, 0x7f00, 0x007f},
9436 {0x193b, 0xe8c8, 0x0808, 0xf8f8},
9437 {0x4444, 0xc0c0, 0xa066, 0x22e0},
9439 static const DWORD content_x8l8v8u8[4][4] =
9441 {0x00000000, 0x00ff7f7f, 0x00008880, 0x00ff0000},
9442 {0x00000080, 0x00008000, 0x00007f00, 0x0000007f},
9443 {0x0041193b, 0x0051e8c8, 0x00040808, 0x00fff8f8},
9444 {0x00824444, 0x0000c0c0, 0x00c2a066, 0x009222e0},
9446 static const USHORT content_l6v5u5[4][4] =
9448 {0x0000, 0xfdef, 0x0230, 0xfc00},
9449 {0x0010, 0x0200, 0x01e0, 0x000f},
9450 {0x4067, 0x53b9, 0x0421, 0xffff},
9451 {0x8108, 0x0318, 0xc28c, 0x909c},
9453 static const struct
9455 const char *name;
9456 const void *content;
9457 SIZE_T pixel_size;
9458 BOOL blue;
9459 unsigned int slop, slop_broken;
9460 DDPIXELFORMAT format;
9462 formats[] =
9465 "D3DFMT_V8U8", content_v8u8, sizeof(WORD), FALSE, 1, 0,
9467 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV, 0,
9468 {16}, {0x000000ff}, {0x0000ff00}, {0x00000000}, {0x00000000}
9472 "D3DFMT_X8L8V8U8", content_x8l8v8u8, sizeof(DWORD), TRUE, 1, 0,
9474 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE, 0,
9475 {32}, {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}
9479 "D3DFMT_L6V5U5", content_l6v5u5, sizeof(WORD), TRUE, 4, 7,
9481 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE, 0,
9482 {16}, {0x0000001f}, {0x000003e0}, {0x0000fc00}, {0x00000000}
9486 /* No V16U16 or Q8W8V8U8 support in ddraw. */
9488 static const D3DCOLOR expected_colors[4][4] =
9490 {0x00808080, 0x00fefeff, 0x00010780, 0x008080ff},
9491 {0x00018080, 0x00800180, 0x0080fe80, 0x00fe8080},
9492 {0x00ba98a0, 0x004767a8, 0x00888881, 0x007878ff},
9493 {0x00c3c3c0, 0x003f3f80, 0x00e51fe1, 0x005fa2c8},
9495 unsigned int i, width, x, y;
9496 D3DDEVICEDESC7 device_desc;
9498 window = create_window();
9499 if (!(device = create_device(window, DDSCL_NORMAL)))
9501 skip("Failed to create a 3D device, skipping test.\n");
9502 DestroyWindow(window);
9503 return;
9506 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
9507 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
9508 if (!(device_desc.dwTextureOpCaps & D3DTEXOPCAPS_BLENDFACTORALPHA))
9510 skip("D3DTOP_BLENDFACTORALPHA not supported, skipping bumpmap format tests.\n");
9511 goto done;
9514 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
9515 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
9516 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
9517 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
9518 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
9519 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9521 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
9522 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9524 /* dst = tex * 0.5 + 1.0 * (1.0 - 0.5) = tex * 0.5 + 0.5 */
9525 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x80ffffff);
9526 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9527 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_BLENDFACTORALPHA);
9528 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
9529 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
9530 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
9531 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
9532 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
9534 for (i = 0; i < ARRAY_SIZE(formats); ++i)
9536 for (width = 1; width < 5; width += 3)
9538 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
9539 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
9541 memset(&surface_desc, 0, sizeof(surface_desc));
9542 surface_desc.dwSize = sizeof(surface_desc);
9543 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
9544 surface_desc.dwWidth = width;
9545 surface_desc.dwHeight = 4;
9546 U4(surface_desc).ddpfPixelFormat = formats[i].format;
9547 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
9548 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9549 if (FAILED(hr))
9551 skip("%s textures not supported, skipping.\n", formats[i].name);
9552 continue;
9554 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, format %s.\n", hr, formats[i].name);
9555 hr = IDirect3DDevice7_SetTexture(device, 0, surface);
9556 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x, format %s.\n", hr, formats[i].name);
9558 memset(&surface_desc, 0, sizeof(surface_desc));
9559 surface_desc.dwSize = sizeof(surface_desc);
9560 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, 0, NULL);
9561 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, format %s.\n", hr, formats[i].name);
9562 for (y = 0; y < 4; y++)
9564 memcpy((char *)surface_desc.lpSurface + y * U1(surface_desc).lPitch,
9565 (char *)formats[i].content + y * 4 * formats[i].pixel_size,
9566 width * formats[i].pixel_size);
9568 hr = IDirectDrawSurface7_Unlock(surface, NULL);
9569 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, format %s.\n", hr, formats[i].name);
9571 hr = IDirect3DDevice7_BeginScene(device);
9572 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9573 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9574 D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
9575 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9576 hr = IDirect3DDevice7_EndScene(device);
9577 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9579 for (y = 0; y < 4; y++)
9581 for (x = 0; x < width; x++)
9583 expected_color = expected_colors[y][x];
9584 if (!formats[i].blue)
9585 expected_color |= 0x000000ff;
9587 color = get_surface_color(rt, 80 + 160 * x, 60 + 120 * y);
9588 ok(compare_color(color, expected_color, formats[i].slop)
9589 || broken(compare_color(color, expected_color, formats[i].slop_broken)),
9590 "Expected color 0x%08x, got 0x%08x, format %s, location %ux%u.\n",
9591 expected_color, color, formats[i].name, x, y);
9595 IDirectDrawSurface7_Release(surface);
9600 IDirectDrawSurface7_Release(rt);
9601 IDirectDraw7_Release(ddraw);
9602 IDirect3D7_Release(d3d);
9604 done:
9605 refcount = IDirect3DDevice7_Release(device);
9606 ok(!refcount, "Device has %u references left.\n", refcount);
9607 DestroyWindow(window);
9610 static void test_color_fill(void)
9612 HRESULT hr;
9613 IDirect3DDevice7 *device;
9614 IDirect3D7 *d3d;
9615 IDirectDraw7 *ddraw;
9616 IDirectDrawSurface7 *surface, *surface2;
9617 DDSURFACEDESC2 surface_desc;
9618 DDPIXELFORMAT z_fmt;
9619 ULONG refcount;
9620 HWND window;
9621 unsigned int i;
9622 DDBLTFX fx;
9623 RECT rect = {5, 5, 7, 7};
9624 DWORD *color;
9625 DWORD supported_fmts = 0, num_fourcc_codes, *fourcc_codes;
9626 DDCAPS hal_caps;
9627 static const struct
9629 DWORD caps, caps2;
9630 HRESULT colorfill_hr, depthfill_hr;
9631 BOOL rop_success;
9632 const char *name;
9633 DWORD result;
9634 BOOL check_result;
9635 DDPIXELFORMAT format;
9637 tests[] =
9640 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
9641 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain RGB", 0xdeadbeef, TRUE,
9643 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9644 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9648 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0,
9649 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain RGB", 0xdeadbeef, TRUE,
9651 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9652 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9656 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0,
9657 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem texture RGB", 0xdeadbeef, TRUE,
9659 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9660 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9664 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0,
9665 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem texture RGB", 0xdeadbeef, TRUE,
9667 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9668 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9672 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
9673 DD_OK, DDERR_INVALIDPARAMS, TRUE, "managed texture RGB", 0xdeadbeef, TRUE,
9675 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
9676 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
9680 DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY, 0,
9681 DDERR_INVALIDPARAMS, DD_OK, TRUE, "vidmem zbuffer", 0xdeadbeef, TRUE,
9682 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
9685 DDSCAPS_ZBUFFER | DDSCAPS_SYSTEMMEMORY, 0,
9686 DDERR_INVALIDPARAMS, DD_OK, TRUE, "sysmem zbuffer", 0xdeadbeef, TRUE,
9687 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
9690 /* Colorfill on YUV surfaces always returns DD_OK, but the content is
9691 * different afterwards. DX9+ GPUs set one of the two luminance values
9692 * in each block, but AMD and Nvidia GPUs disagree on which luminance
9693 * value they set. r200 (dx8) just sets the entire block to the clear
9694 * value. */
9695 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
9696 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain YUY2", 0, FALSE,
9698 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
9699 {0}, {0}, {0}, {0}, {0}
9703 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
9704 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain UYVY", 0, FALSE,
9706 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
9707 {0}, {0}, {0}, {0}, {0}
9711 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY, 0,
9712 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay YUY2", 0, FALSE,
9714 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
9715 {0}, {0}, {0}, {0}, {0}
9719 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY, 0,
9720 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay UYVY", 0, FALSE,
9722 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
9723 {0}, {0}, {0}, {0}, {0}
9727 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0,
9728 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "vidmem texture DXT1", 0, FALSE,
9730 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
9731 {0}, {0}, {0}, {0}, {0}
9735 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0,
9736 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "sysmem texture DXT1", 0, FALSE,
9738 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
9739 {0}, {0}, {0}, {0}, {0}
9743 /* The testbot fills this with 0x00 instead of the blue channel. The sysmem
9744 * surface works, presumably because it is handled by the runtime instead of
9745 * the driver. */
9746 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
9747 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain P8", 0xefefefef, FALSE,
9749 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
9750 {8}, {0}, {0}, {0}, {0}
9754 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0,
9755 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain P8", 0xefefefef, TRUE,
9757 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
9758 {8}, {0}, {0}, {0}, {0}
9762 static const struct
9764 DWORD rop;
9765 const char *name;
9766 HRESULT hr;
9768 rops[] =
9770 {SRCCOPY, "SRCCOPY", DD_OK},
9771 {SRCPAINT, "SRCPAINT", DDERR_NORASTEROPHW},
9772 {SRCAND, "SRCAND", DDERR_NORASTEROPHW},
9773 {SRCINVERT, "SRCINVERT", DDERR_NORASTEROPHW},
9774 {SRCERASE, "SRCERASE", DDERR_NORASTEROPHW},
9775 {NOTSRCCOPY, "NOTSRCCOPY", DDERR_NORASTEROPHW},
9776 {NOTSRCERASE, "NOTSRCERASE", DDERR_NORASTEROPHW},
9777 {MERGECOPY, "MERGECOPY", DDERR_NORASTEROPHW},
9778 {MERGEPAINT, "MERGEPAINT", DDERR_NORASTEROPHW},
9779 {PATCOPY, "PATCOPY", DDERR_NORASTEROPHW},
9780 {PATPAINT, "PATPAINT", DDERR_NORASTEROPHW},
9781 {PATINVERT, "PATINVERT", DDERR_NORASTEROPHW},
9782 {DSTINVERT, "DSTINVERT", DDERR_NORASTEROPHW},
9783 {BLACKNESS, "BLACKNESS", DD_OK},
9784 {WHITENESS, "WHITENESS", DD_OK},
9785 {0xaa0029, "0xaa0029", DDERR_NORASTEROPHW} /* noop */
9788 window = create_window();
9789 if (!(device = create_device(window, DDSCL_NORMAL)))
9791 skip("Failed to create a 3D device, skipping test.\n");
9792 DestroyWindow(window);
9793 return;
9796 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
9797 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
9798 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
9799 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
9801 memset(&z_fmt, 0, sizeof(z_fmt));
9802 IDirect3D7_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
9803 if (!z_fmt.dwSize)
9804 skip("No Z buffer formats supported, skipping Z buffer colorfill test.\n");
9806 IDirect3DDevice7_EnumTextureFormats(device, test_block_formats_creation_cb, &supported_fmts);
9807 if (!(supported_fmts & SUPPORT_DXT1))
9808 skip("DXT1 textures not supported, skipping DXT1 colorfill test.\n");
9810 IDirect3D7_Release(d3d);
9812 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
9813 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
9814 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
9815 num_fourcc_codes * sizeof(*fourcc_codes));
9816 if (!fourcc_codes)
9817 goto done;
9818 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
9819 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
9820 for (i = 0; i < num_fourcc_codes; i++)
9822 if (fourcc_codes[i] == MAKEFOURCC('Y', 'U', 'Y', '2'))
9823 supported_fmts |= SUPPORT_YUY2;
9824 else if (fourcc_codes[i] == MAKEFOURCC('U', 'Y', 'V', 'Y'))
9825 supported_fmts |= SUPPORT_UYVY;
9827 HeapFree(GetProcessHeap(), 0, fourcc_codes);
9829 memset(&hal_caps, 0, sizeof(hal_caps));
9830 hal_caps.dwSize = sizeof(hal_caps);
9831 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
9832 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9834 if (!(supported_fmts & (SUPPORT_YUY2 | SUPPORT_UYVY)) || !(hal_caps.dwCaps & DDCAPS_OVERLAY))
9835 skip("Overlays or some YUV formats not supported, skipping YUV colorfill tests.\n");
9837 for (i = 0; i < ARRAY_SIZE(tests); ++i)
9839 DWORD expected_broken = tests[i].result;
9841 /* Some Windows drivers modify dwFillColor when it is used on P8 or FourCC formats. */
9842 memset(&fx, 0, sizeof(fx));
9843 fx.dwSize = sizeof(fx);
9844 U5(fx).dwFillColor = 0xdeadbeef;
9846 memset(&surface_desc, 0, sizeof(surface_desc));
9847 surface_desc.dwSize = sizeof(surface_desc);
9848 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9849 surface_desc.dwWidth = 64;
9850 surface_desc.dwHeight = 64;
9851 U4(surface_desc).ddpfPixelFormat = tests[i].format;
9852 surface_desc.ddsCaps.dwCaps = tests[i].caps;
9853 surface_desc.ddsCaps.dwCaps2 = tests[i].caps2;
9855 if (tests[i].format.dwFourCC == MAKEFOURCC('D','X','T','1') && !(supported_fmts & SUPPORT_DXT1))
9856 continue;
9857 if (tests[i].format.dwFourCC == MAKEFOURCC('Y','U','Y','2') && !(supported_fmts & SUPPORT_YUY2))
9858 continue;
9859 if (tests[i].format.dwFourCC == MAKEFOURCC('U','Y','V','Y') && !(supported_fmts & SUPPORT_UYVY))
9860 continue;
9861 if (tests[i].caps & DDSCAPS_OVERLAY && !(hal_caps.dwCaps & DDCAPS_OVERLAY))
9862 continue;
9864 if (tests[i].caps & DDSCAPS_ZBUFFER)
9866 if (!z_fmt.dwSize)
9867 continue;
9869 U4(surface_desc).ddpfPixelFormat = z_fmt;
9870 /* Some drivers seem to convert depth values incorrectly or not at
9871 * all. Affects at least AMD PALM, 8.17.10.1247. */
9872 if (tests[i].caps & DDSCAPS_VIDEOMEMORY)
9874 DWORD expected;
9875 float f, g;
9877 expected = tests[i].result & U3(z_fmt).dwZBitMask;
9878 f = ceilf(log2f(expected + 1.0f));
9879 g = (f + 1.0f) / 2.0f;
9880 g -= (int)g;
9881 expected_broken = (expected / exp2f(f) - g) * 256;
9882 expected_broken *= 0x01010101;
9886 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9887 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, surface %s.\n", hr, tests[i].name);
9889 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9890 todo_wine_if (tests[i].format.dwFourCC)
9891 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9892 hr, tests[i].colorfill_hr, tests[i].name);
9894 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9895 todo_wine_if (tests[i].format.dwFourCC)
9896 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9897 hr, tests[i].colorfill_hr, tests[i].name);
9899 if (SUCCEEDED(hr) && tests[i].check_result)
9901 memset(&surface_desc, 0, sizeof(surface_desc));
9902 surface_desc.dwSize = sizeof(surface_desc);
9903 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9904 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9905 color = surface_desc.lpSurface;
9906 ok(*color == tests[i].result, "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
9907 *color, tests[i].result, tests[i].name);
9908 hr = IDirectDrawSurface7_Unlock(surface, NULL);
9909 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9912 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9913 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9914 hr, tests[i].depthfill_hr, tests[i].name);
9915 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
9916 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
9917 hr, tests[i].depthfill_hr, tests[i].name);
9919 if (SUCCEEDED(hr) && tests[i].check_result)
9921 memset(&surface_desc, 0, sizeof(surface_desc));
9922 surface_desc.dwSize = sizeof(surface_desc);
9923 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9924 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9925 color = surface_desc.lpSurface;
9926 ok((*color & U3(z_fmt).dwZBitMask) == (tests[i].result & U3(z_fmt).dwZBitMask)
9927 || broken((*color & U3(z_fmt).dwZBitMask) == (expected_broken & U3(z_fmt).dwZBitMask)),
9928 "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
9929 *color & U3(z_fmt).dwZBitMask, tests[i].result & U3(z_fmt).dwZBitMask, tests[i].name);
9930 hr = IDirectDrawSurface7_Unlock(surface, NULL);
9931 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9934 U5(fx).dwFillColor = 0xdeadbeef;
9935 fx.dwROP = BLACKNESS;
9936 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
9937 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
9938 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
9939 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
9940 U5(fx).dwFillColor, tests[i].name);
9942 if (SUCCEEDED(hr) && tests[i].check_result)
9944 memset(&surface_desc, 0, sizeof(surface_desc));
9945 surface_desc.dwSize = sizeof(surface_desc);
9946 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9947 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9948 color = surface_desc.lpSurface;
9949 ok(*color == 0, "Got clear result 0x%08x, expected 0x00000000, surface %s.\n",
9950 *color, tests[i].name);
9951 hr = IDirectDrawSurface7_Unlock(surface, NULL);
9952 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9955 fx.dwROP = WHITENESS;
9956 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
9957 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
9958 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
9959 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
9960 U5(fx).dwFillColor, tests[i].name);
9962 if (SUCCEEDED(hr) && tests[i].check_result)
9964 memset(&surface_desc, 0, sizeof(surface_desc));
9965 surface_desc.dwSize = sizeof(surface_desc);
9966 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
9967 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9968 color = surface_desc.lpSurface;
9969 /* WHITENESS sets the alpha channel to 0x00. Ignore this for now. */
9970 ok((*color & 0x00ffffff) == 0x00ffffff, "Got clear result 0x%08x, expected 0xffffffff, surface %s.\n",
9971 *color, tests[i].name);
9972 hr = IDirectDrawSurface7_Unlock(surface, NULL);
9973 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
9976 IDirectDrawSurface7_Release(surface);
9979 memset(&fx, 0, sizeof(fx));
9980 fx.dwSize = sizeof(fx);
9981 U5(fx).dwFillColor = 0xdeadbeef;
9982 fx.dwROP = WHITENESS;
9984 memset(&surface_desc, 0, sizeof(surface_desc));
9985 surface_desc.dwSize = sizeof(surface_desc);
9986 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9987 surface_desc.dwWidth = 64;
9988 surface_desc.dwHeight = 64;
9989 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9990 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
9991 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
9992 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9993 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9994 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
9995 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
9996 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9997 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9998 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
9999 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10001 /* No DDBLTFX. */
10002 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, NULL);
10003 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10004 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, NULL);
10005 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10007 /* Unused source rectangle. */
10008 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10009 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10010 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10011 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10013 /* Unused source surface. */
10014 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10015 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10016 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
10017 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10018 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10019 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10020 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10021 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10023 /* Inverted destination or source rectangle. */
10024 SetRect(&rect, 5, 7, 7, 5);
10025 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10026 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10027 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10028 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10029 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10030 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10031 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10032 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10033 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10034 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10036 /* Negative rectangle. */
10037 SetRect(&rect, -1, -1, 5, 5);
10038 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10039 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10040 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10041 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10042 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10043 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10044 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10045 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10046 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10047 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10049 /* Out of bounds rectangle. */
10050 SetRect(&rect, 0, 0, 65, 65);
10051 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10052 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10053 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10054 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10056 /* Combine multiple flags. */
10057 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10058 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10059 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
10060 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10061 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
10062 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10064 for (i = 0; i < ARRAY_SIZE(rops); ++i)
10066 fx.dwROP = rops[i].rop;
10067 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
10068 ok(hr == rops[i].hr, "Got unexpected hr %#x for rop %s.\n", hr, rops[i].name);
10071 IDirectDrawSurface7_Release(surface2);
10072 IDirectDrawSurface7_Release(surface);
10074 if (!z_fmt.dwSize)
10075 goto done;
10077 memset(&surface_desc, 0, sizeof(surface_desc));
10078 surface_desc.dwSize = sizeof(surface_desc);
10079 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10080 surface_desc.dwWidth = 64;
10081 surface_desc.dwHeight = 64;
10082 U4(surface_desc).ddpfPixelFormat = z_fmt;
10083 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
10084 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10085 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10086 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
10087 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10089 /* No DDBLTFX. */
10090 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, NULL);
10091 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10093 /* Unused source rectangle. */
10094 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10095 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10097 /* Unused source surface. */
10098 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10099 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10100 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10101 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10103 /* Inverted destination or source rectangle. */
10104 SetRect(&rect, 5, 7, 7, 5);
10105 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10106 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10107 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10108 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10109 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10110 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10111 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10112 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10114 /* Negative rectangle. */
10115 SetRect(&rect, -1, -1, 5, 5);
10116 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10117 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10118 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10119 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10120 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10121 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10122 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10123 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10125 /* Out of bounds rectangle. */
10126 SetRect(&rect, 0, 0, 65, 65);
10127 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10128 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10130 /* Combine multiple flags. */
10131 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10132 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10134 IDirectDrawSurface7_Release(surface2);
10135 IDirectDrawSurface7_Release(surface);
10137 done:
10138 IDirectDraw7_Release(ddraw);
10139 refcount = IDirect3DDevice7_Release(device);
10140 ok(!refcount, "Device has %u references left.\n", refcount);
10141 DestroyWindow(window);
10144 static void test_texcoordindex(void)
10146 static D3DMATRIX mat =
10148 1.0f, 0.0f, 0.0f, 0.0f,
10149 0.0f, 0.0f, 0.0f, 0.0f,
10150 0.0f, 0.0f, 0.0f, 0.0f,
10151 0.0f, 0.0f, 0.0f, 0.0f,
10153 static struct
10155 struct vec3 pos;
10156 struct vec2 texcoord1;
10157 struct vec2 texcoord2;
10158 struct vec2 texcoord3;
10160 quad[] =
10162 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f}},
10163 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 0.0f}},
10164 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}},
10165 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}},
10167 static const DWORD fvf = D3DFVF_XYZ | D3DFVF_TEX3;
10168 IDirect3DDevice7 *device;
10169 IDirect3D7 *d3d;
10170 IDirectDraw7 *ddraw;
10171 IDirectDrawSurface7 *rt;
10172 HWND window;
10173 HRESULT hr;
10174 IDirectDrawSurface7 *texture1, *texture2;
10175 DDSURFACEDESC2 surface_desc;
10176 ULONG refcount;
10177 D3DCOLOR color;
10178 DWORD *ptr;
10180 window = create_window();
10181 if (!(device = create_device(window, DDSCL_NORMAL)))
10183 skip("Failed to create a 3D device, skipping test.\n");
10184 DestroyWindow(window);
10185 return;
10188 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
10189 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
10190 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
10191 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
10192 IDirect3D7_Release(d3d);
10194 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
10195 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10197 memset(&surface_desc, 0, sizeof(surface_desc));
10198 surface_desc.dwSize = sizeof(surface_desc);
10199 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10200 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
10201 surface_desc.dwWidth = 2;
10202 surface_desc.dwHeight = 2;
10203 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
10204 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
10205 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
10206 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
10207 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
10208 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
10209 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
10210 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture1, NULL);
10211 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10212 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture2, NULL);
10213 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10215 memset(&surface_desc, 0, sizeof(surface_desc));
10216 surface_desc.dwSize = sizeof(surface_desc);
10217 hr = IDirectDrawSurface7_Lock(texture1, 0, &surface_desc, 0, NULL);
10218 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10219 ptr = surface_desc.lpSurface;
10220 ptr[0] = 0xff000000;
10221 ptr[1] = 0xff00ff00;
10222 ptr += U1(surface_desc).lPitch / sizeof(*ptr);
10223 ptr[0] = 0xff0000ff;
10224 ptr[1] = 0xff00ffff;
10225 hr = IDirectDrawSurface7_Unlock(texture1, NULL);
10226 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10228 memset(&surface_desc, 0, sizeof(surface_desc));
10229 surface_desc.dwSize = sizeof(surface_desc);
10230 hr = IDirectDrawSurface7_Lock(texture2, 0, &surface_desc, 0, NULL);
10231 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10232 ptr = surface_desc.lpSurface;
10233 ptr[0] = 0xff000000;
10234 ptr[1] = 0xff0000ff;
10235 ptr += U1(surface_desc).lPitch / sizeof(*ptr);
10236 ptr[0] = 0xffff0000;
10237 ptr[1] = 0xffff00ff;
10238 hr = IDirectDrawSurface7_Unlock(texture2, 0);
10239 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10241 hr = IDirect3DDevice7_SetTexture(device, 0, texture1);
10242 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
10243 hr = IDirect3DDevice7_SetTexture(device, 1, texture2);
10244 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
10245 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
10246 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
10247 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
10248 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
10249 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
10250 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10251 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_ADD);
10252 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
10253 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
10254 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10255 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
10256 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10257 hr = IDirect3DDevice7_SetTextureStageState(device, 2, D3DTSS_COLOROP, D3DTOP_DISABLE);
10258 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
10260 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_TEXCOORDINDEX, 1);
10261 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
10262 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXCOORDINDEX, 0);
10263 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
10265 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
10266 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
10268 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
10269 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10271 hr = IDirect3DDevice7_BeginScene(device);
10272 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10273 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
10274 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10275 hr = IDirect3DDevice7_EndScene(device);
10276 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10278 color = get_surface_color(rt, 160, 120);
10279 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
10280 color = get_surface_color(rt, 480, 120);
10281 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
10282 color = get_surface_color(rt, 160, 360);
10283 ok(compare_color(color, 0x00ff0000, 2), "Got unexpected color 0x%08x.\n", color);
10284 color = get_surface_color(rt, 480, 360);
10285 ok(compare_color(color, 0x00ffffff, 2), "Got unexpected color 0x%08x.\n", color);
10287 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
10288 ok(SUCCEEDED(hr), "Failed to set texture transform flags, hr %#x.\n", hr);
10289 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_TEXTURE1, &mat);
10290 ok(SUCCEEDED(hr), "Failed to set transformation matrix, hr %#x.\n", hr);
10292 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
10293 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10295 hr = IDirect3DDevice7_BeginScene(device);
10296 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10297 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
10298 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10299 hr = IDirect3DDevice7_EndScene(device);
10300 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10302 color = get_surface_color(rt, 160, 120);
10303 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
10304 color = get_surface_color(rt, 480, 120);
10305 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
10306 color = get_surface_color(rt, 160, 360);
10307 ok(compare_color(color, 0x00000000, 2), "Got unexpected color 0x%08x.\n", color);
10308 color = get_surface_color(rt, 480, 360);
10309 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
10311 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
10312 ok(SUCCEEDED(hr), "Failed to set texture transform flags, hr %#x.\n", hr);
10313 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXCOORDINDEX, 2);
10314 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
10316 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
10317 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10319 hr = IDirect3DDevice7_BeginScene(device);
10320 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10321 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
10322 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10323 hr = IDirect3DDevice7_EndScene(device);
10324 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10326 color = get_surface_color(rt, 160, 120);
10327 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
10328 color = get_surface_color(rt, 480, 120);
10329 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
10330 color = get_surface_color(rt, 160, 360);
10331 ok(compare_color(color, 0x00ff00ff, 2), "Got unexpected color 0x%08x.\n", color);
10332 color = get_surface_color(rt, 480, 360);
10333 ok(compare_color(color, 0x00ffff00, 2), "Got unexpected color 0x%08x.\n", color);
10335 IDirectDrawSurface7_Release(texture1);
10336 IDirectDrawSurface7_Release(texture2);
10338 IDirectDrawSurface7_Release(rt);
10339 IDirectDraw_Release(ddraw);
10340 refcount = IDirect3DDevice7_Release(device);
10341 ok(!refcount, "Device has %u references left.\n", refcount);
10342 DestroyWindow(window);
10345 static void test_colorkey_precision(void)
10347 static struct
10349 struct vec3 pos;
10350 struct vec2 texcoord;
10352 quad[] =
10354 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
10355 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
10356 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
10357 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
10359 IDirect3DDevice7 *device;
10360 IDirect3D7 *d3d;
10361 IDirectDraw7 *ddraw;
10362 IDirectDrawSurface7 *rt;
10363 HWND window;
10364 HRESULT hr;
10365 IDirectDrawSurface7 *src, *dst, *texture;
10366 DDSURFACEDESC2 surface_desc, lock_desc;
10367 ULONG refcount;
10368 D3DCOLOR color;
10369 unsigned int t, c;
10370 DDCOLORKEY ckey;
10371 DDBLTFX fx;
10372 DWORD data[4] = {0}, color_mask;
10373 BOOL is_nvidia, is_warp;
10374 static const struct
10376 unsigned int max, shift, bpp, clear;
10377 const char *name;
10378 BOOL skip_nv;
10379 DDPIXELFORMAT fmt;
10381 tests[] =
10384 255, 0, 4, 0x00345678, "D3DFMT_X8R8G8B8", FALSE,
10386 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
10387 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
10392 63, 5, 2, 0x5678, "D3DFMT_R5G6B5, G channel", FALSE,
10394 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
10395 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
10400 31, 0, 2, 0x5678, "D3DFMT_R5G6B5, B channel", FALSE,
10402 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
10403 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
10408 15, 0, 2, 0x0678, "D3DFMT_A4R4G4B4", TRUE,
10410 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
10411 {16}, {0x0f00}, {0x00f0}, {0x000f}, {0xf000}
10416 window = create_window();
10417 if (!(device = create_device(window, DDSCL_NORMAL)))
10419 skip("Failed to create a 3D device, skipping test.\n");
10420 DestroyWindow(window);
10421 return;
10424 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
10425 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
10426 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
10427 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
10428 IDirect3D7_Release(d3d);
10429 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
10430 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10432 is_nvidia = ddraw_is_nvidia(ddraw);
10433 /* The Windows 8 WARP driver has plenty of false negatives in X8R8G8B8
10434 * (color key doesn't match although the values are equal), and a false
10435 * positive when the color key is 0 and the texture contains the value 1.
10436 * I don't want to mark this broken unconditionally since this would
10437 * essentially disable the test on Windows. Also on random occasions
10438 * 254 == 255 and 255 != 255.*/
10439 is_warp = ddraw_is_warp(ddraw);
10441 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
10442 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
10443 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
10444 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
10445 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
10446 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
10447 /* Multiply the texture read result with 0, that way the result color if the key doesn't
10448 * match is constant. In theory color keying works without reading the texture result
10449 * (meaning we could just op=arg1, arg1=tfactor), but the Geforce7 Windows driver begs
10450 * to differ. */
10451 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
10452 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
10453 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
10454 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10455 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
10456 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10457 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x00000000);
10458 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10460 memset(&fx, 0, sizeof(fx));
10461 fx.dwSize = sizeof(fx);
10462 memset(&lock_desc, 0, sizeof(lock_desc));
10463 lock_desc.dwSize = sizeof(lock_desc);
10465 for (t = 0; t < ARRAY_SIZE(tests); ++t)
10467 if (is_nvidia && tests[t].skip_nv)
10469 win_skip("Skipping test %s on Nvidia Windows drivers.\n", tests[t].name);
10470 continue;
10473 memset(&surface_desc, 0, sizeof(surface_desc));
10474 surface_desc.dwSize = sizeof(surface_desc);
10475 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10476 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10477 surface_desc.dwWidth = 4;
10478 surface_desc.dwHeight = 1;
10479 U4(surface_desc).ddpfPixelFormat = tests[t].fmt;
10480 /* Windows XP (at least with the r200 driver, other drivers untested) produces
10481 * garbage when doing color keyed texture->texture blits. */
10482 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
10483 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10484 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
10485 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10487 U5(fx).dwFillColor = tests[t].clear;
10488 /* On the w8 testbot (WARP driver) the blit result has different values in the
10489 * X channel. */
10490 color_mask = U2(tests[t].fmt).dwRBitMask
10491 | U3(tests[t].fmt).dwGBitMask
10492 | U4(tests[t].fmt).dwBBitMask;
10494 for (c = 0; c <= tests[t].max; ++c)
10496 /* The idiotic Nvidia Windows driver can't change the color key on a d3d
10497 * texture after it has been set once... */
10498 surface_desc.dwFlags |= DDSD_CKSRCBLT;
10499 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
10500 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = c << tests[t].shift;
10501 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = c << tests[t].shift;
10502 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
10503 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10504 hr = IDirect3DDevice7_SetTexture(device, 0, texture);
10505 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
10507 hr = IDirectDrawSurface7_Blt(dst, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10508 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
10510 hr = IDirectDrawSurface7_Lock(src, NULL, &lock_desc, DDLOCK_WAIT, NULL);
10511 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10512 switch (tests[t].bpp)
10514 case 4:
10515 ((DWORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
10516 ((DWORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
10517 ((DWORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
10518 ((DWORD *)lock_desc.lpSurface)[3] = 0xffffffff;
10519 break;
10521 case 2:
10522 ((WORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
10523 ((WORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
10524 ((WORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
10525 ((WORD *)lock_desc.lpSurface)[3] = 0xffff;
10526 break;
10528 hr = IDirectDrawSurface7_Unlock(src, 0);
10529 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10530 hr = IDirectDrawSurface7_Blt(texture, NULL, src, NULL, DDBLT_WAIT, NULL);
10531 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
10533 ckey.dwColorSpaceLowValue = c << tests[t].shift;
10534 ckey.dwColorSpaceHighValue = c << tests[t].shift;
10535 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
10536 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10538 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_WAIT, NULL);
10539 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
10541 /* Don't make this read only, it somehow breaks the detection of the Nvidia bug below. */
10542 hr = IDirectDrawSurface7_Lock(dst, NULL, &lock_desc, DDLOCK_WAIT, NULL);
10543 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10544 switch (tests[t].bpp)
10546 case 4:
10547 data[0] = ((DWORD *)lock_desc.lpSurface)[0] & color_mask;
10548 data[1] = ((DWORD *)lock_desc.lpSurface)[1] & color_mask;
10549 data[2] = ((DWORD *)lock_desc.lpSurface)[2] & color_mask;
10550 data[3] = ((DWORD *)lock_desc.lpSurface)[3] & color_mask;
10551 break;
10553 case 2:
10554 data[0] = ((WORD *)lock_desc.lpSurface)[0] & color_mask;
10555 data[1] = ((WORD *)lock_desc.lpSurface)[1] & color_mask;
10556 data[2] = ((WORD *)lock_desc.lpSurface)[2] & color_mask;
10557 data[3] = ((WORD *)lock_desc.lpSurface)[3] & color_mask;
10558 break;
10560 hr = IDirectDrawSurface7_Unlock(dst, 0);
10561 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10563 if (!c)
10565 ok(data[0] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10566 tests[t].clear, data[0], tests[t].name, c);
10568 if (data[3] == tests[t].clear)
10570 /* My Geforce GTX 460 on Windows 7 misbehaves when A4R4G4B4 is blitted with color
10571 * keying: The blit takes ~0.5 seconds, and subsequent color keying draws are broken,
10572 * even when a different surface is used. The blit itself doesn't draw anything,
10573 * so we can detect the bug by looking at the otherwise unused 4th texel. It should
10574 * never be masked out by the key.
10576 * On Windows 10 the problem is worse, Blt just hangs. For this reason the ARGB4444
10577 * test is disabled on Nvidia.
10579 * Also appears to affect the testbot in some way with R5G6B5. Color keying is
10580 * terrible on WARP. */
10581 skip("Nvidia A4R4G4B4 color keying blit bug detected, skipping.\n");
10582 IDirectDrawSurface7_Release(texture);
10583 IDirectDrawSurface7_Release(src);
10584 IDirectDrawSurface7_Release(dst);
10585 goto done;
10588 else
10589 ok(data[0] == (c - 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10590 (c - 1) << tests[t].shift, data[0], tests[t].name, c);
10592 ok(data[1] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10593 tests[t].clear, data[1], tests[t].name, c);
10595 if (c == tests[t].max)
10596 ok(data[2] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10597 tests[t].clear, data[2], tests[t].name, c);
10598 else
10599 ok(data[2] == (c + 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
10600 (c + 1) << tests[t].shift, data[2], tests[t].name, c);
10602 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x0000ff00, 1.0f, 0);
10603 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10605 hr = IDirect3DDevice7_BeginScene(device);
10606 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10607 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
10608 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10609 hr = IDirect3DDevice7_EndScene(device);
10610 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10612 color = get_surface_color(rt, 80, 240);
10613 if (!c)
10614 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
10615 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10616 color, tests[t].name, c);
10617 else
10618 ok(compare_color(color, 0x00000000, 1) || broken(is_warp && compare_color(color, 0x0000ff00, 1)),
10619 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10620 color, tests[t].name, c);
10622 color = get_surface_color(rt, 240, 240);
10623 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
10624 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10625 color, tests[t].name, c);
10627 color = get_surface_color(rt, 400, 240);
10628 if (c == tests[t].max)
10629 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
10630 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10631 color, tests[t].name, c);
10632 else
10633 ok(compare_color(color, 0x00000000, 1) || broken(is_warp && compare_color(color, 0x0000ff00, 1)),
10634 "Got unexpected color 0x%08x, format %s, c=%u.\n",
10635 color, tests[t].name, c);
10637 IDirectDrawSurface7_Release(texture);
10639 IDirectDrawSurface7_Release(src);
10640 IDirectDrawSurface7_Release(dst);
10642 done:
10644 IDirectDrawSurface7_Release(rt);
10645 IDirectDraw7_Release(ddraw);
10646 refcount = IDirect3DDevice7_Release(device);
10647 ok(!refcount, "Device has %u references left.\n", refcount);
10648 DestroyWindow(window);
10651 static void test_range_colorkey(void)
10653 IDirectDraw7 *ddraw;
10654 HWND window;
10655 HRESULT hr;
10656 IDirectDrawSurface7 *surface;
10657 DDSURFACEDESC2 surface_desc;
10658 ULONG refcount;
10659 DDCOLORKEY ckey;
10661 window = create_window();
10662 ddraw = create_ddraw();
10663 ok(!!ddraw, "Failed to create a ddraw object.\n");
10664 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10665 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
10667 memset(&surface_desc, 0, sizeof(surface_desc));
10668 surface_desc.dwSize = sizeof(surface_desc);
10669 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
10670 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
10671 surface_desc.dwWidth = 1;
10672 surface_desc.dwHeight = 1;
10673 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
10674 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
10675 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
10676 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
10677 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
10678 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0x00000000;
10680 /* Creating a surface with a range color key fails with DDERR_NOCOLORKEY. */
10681 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
10682 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
10683 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10684 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10686 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
10687 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
10688 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10689 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10691 /* Same for DDSCAPS_OFFSCREENPLAIN. */
10692 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
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 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
10704 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
10705 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10706 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10708 /* Setting a range color key without DDCKEY_COLORSPACE collapses the key. */
10709 ckey.dwColorSpaceLowValue = 0x00000000;
10710 ckey.dwColorSpaceHighValue = 0x00000001;
10711 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10712 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10714 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10715 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
10716 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
10717 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
10719 ckey.dwColorSpaceLowValue = 0x00000001;
10720 ckey.dwColorSpaceHighValue = 0x00000000;
10721 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10722 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10724 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10725 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
10726 ok(ckey.dwColorSpaceLowValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
10727 ok(ckey.dwColorSpaceHighValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
10729 /* DDCKEY_COLORSPACE is ignored if the key is a single value. */
10730 ckey.dwColorSpaceLowValue = 0x00000000;
10731 ckey.dwColorSpaceHighValue = 0x00000000;
10732 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10733 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
10735 /* Using it with a range key results in DDERR_NOCOLORKEYHW. */
10736 ckey.dwColorSpaceLowValue = 0x00000001;
10737 ckey.dwColorSpaceHighValue = 0x00000000;
10738 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10739 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10740 ckey.dwColorSpaceLowValue = 0x00000000;
10741 ckey.dwColorSpaceHighValue = 0x00000001;
10742 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10743 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10744 /* Range destination keys don't work either. */
10745 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_DESTBLT | DDCKEY_COLORSPACE, &ckey);
10746 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10748 /* Just to show it's not because of A, R, and G having equal values. */
10749 ckey.dwColorSpaceLowValue = 0x00000000;
10750 ckey.dwColorSpaceHighValue = 0x01010101;
10751 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
10752 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
10754 /* None of these operations modified the key. */
10755 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
10756 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
10757 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
10758 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
10760 IDirectDrawSurface7_Release(surface),
10761 refcount = IDirectDraw7_Release(ddraw);
10762 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
10763 DestroyWindow(window);
10766 static void test_shademode(void)
10768 IDirect3DVertexBuffer7 *vb_strip, *vb_list, *buffer;
10769 IDirect3DDevice7 *device;
10770 D3DVERTEXBUFFERDESC desc;
10771 IDirectDrawSurface7 *rt;
10772 DWORD color0, color1;
10773 void *data = NULL;
10774 IDirect3D7 *d3d;
10775 ULONG refcount;
10776 UINT i, count;
10777 HWND window;
10778 HRESULT hr;
10779 static const struct
10781 struct vec3 position;
10782 DWORD diffuse;
10784 quad_strip[] =
10786 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
10787 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
10788 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
10789 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
10791 quad_list[] =
10793 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
10794 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
10795 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
10797 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
10798 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
10799 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
10801 static const struct
10803 DWORD primtype;
10804 DWORD shademode;
10805 DWORD color0, color1;
10807 tests[] =
10809 {D3DPT_TRIANGLESTRIP, D3DSHADE_FLAT, 0x00ff0000, 0x0000ff00},
10810 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
10811 {D3DPT_TRIANGLESTRIP, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
10812 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
10813 {D3DPT_TRIANGLELIST, D3DSHADE_FLAT, 0x00ff0000, 0x000000ff},
10814 {D3DPT_TRIANGLELIST, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
10817 window = create_window();
10818 if (!(device = create_device(window, DDSCL_NORMAL)))
10820 skip("Failed to create a 3D device, skipping test.\n");
10821 DestroyWindow(window);
10822 return;
10825 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
10826 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
10827 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
10828 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10830 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
10831 ok(hr == D3D_OK, "Failed to disable lighting, hr %#x.\n", hr);
10832 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
10833 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
10835 memset(&desc, 0, sizeof(desc));
10836 desc.dwSize = sizeof(desc);
10837 desc.dwCaps = D3DVBCAPS_WRITEONLY;
10838 desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
10839 desc.dwNumVertices = ARRAY_SIZE(quad_strip);
10840 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &vb_strip, 0);
10841 ok(hr == D3D_OK, "Failed to create vertex buffer, hr %#x.\n", hr);
10842 hr = IDirect3DVertexBuffer7_Lock(vb_strip, 0, &data, NULL);
10843 ok(hr == D3D_OK, "Failed to lock vertex buffer, hr %#x.\n", hr);
10844 memcpy(data, quad_strip, sizeof(quad_strip));
10845 hr = IDirect3DVertexBuffer7_Unlock(vb_strip);
10846 ok(hr == D3D_OK, "Failed to unlock vertex buffer, hr %#x.\n", hr);
10848 desc.dwNumVertices = ARRAY_SIZE(quad_list);
10849 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &vb_list, 0);
10850 ok(hr == D3D_OK, "Failed to create vertex buffer, hr %#x.\n", hr);
10851 hr = IDirect3DVertexBuffer7_Lock(vb_list, 0, &data, NULL);
10852 ok(hr == D3D_OK, "Failed to lock vertex buffer, hr %#x.\n", hr);
10853 memcpy(data, quad_list, sizeof(quad_list));
10854 hr = IDirect3DVertexBuffer7_Unlock(vb_list);
10855 ok(hr == D3D_OK, "Failed to unlock vertex buffer, hr %#x.\n", hr);
10857 /* Try it first with a TRIANGLESTRIP. Do it with different geometry because
10858 * the color fixups we have to do for FLAT shading will be dependent on that. */
10860 for (i = 0; i < ARRAY_SIZE(tests); ++i)
10862 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
10863 ok(hr == D3D_OK, "Failed to clear, hr %#x.\n", hr);
10865 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SHADEMODE, tests[i].shademode);
10866 ok(hr == D3D_OK, "Failed to set shade mode, hr %#x.\n", hr);
10868 hr = IDirect3DDevice7_BeginScene(device);
10869 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10870 buffer = tests[i].primtype == D3DPT_TRIANGLESTRIP ? vb_strip : vb_list;
10871 count = tests[i].primtype == D3DPT_TRIANGLESTRIP ? 4 : 6;
10872 hr = IDirect3DDevice7_DrawPrimitiveVB(device, tests[i].primtype, buffer, 0, count, 0);
10873 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10874 hr = IDirect3DDevice7_EndScene(device);
10875 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10877 color0 = get_surface_color(rt, 100, 100); /* Inside first triangle */
10878 color1 = get_surface_color(rt, 500, 350); /* Inside second triangle */
10880 /* For D3DSHADE_FLAT it should take the color of the first vertex of
10881 * each triangle. This requires EXT_provoking_vertex or similar
10882 * functionality being available. */
10883 /* PHONG should be the same as GOURAUD, since no hardware implements
10884 * this. */
10885 ok(compare_color(color0, tests[i].color0, 1), "Test %u shading has color0 %08x, expected %08x.\n",
10886 i, color0, tests[i].color0);
10887 ok(compare_color(color1, tests[i].color1, 1), "Test %u shading has color1 %08x, expected %08x.\n",
10888 i, color1, tests[i].color1);
10891 IDirect3DVertexBuffer7_Release(vb_strip);
10892 IDirect3DVertexBuffer7_Release(vb_list);
10893 IDirectDrawSurface7_Release(rt);
10894 IDirect3D7_Release(d3d);
10895 refcount = IDirect3DDevice7_Release(device);
10896 ok(!refcount, "Device has %u references left.\n", refcount);
10897 DestroyWindow(window);
10900 static void test_lockrect_invalid(void)
10902 unsigned int i, r;
10903 IDirectDraw7 *ddraw;
10904 IDirectDrawSurface7 *surface;
10905 HWND window;
10906 HRESULT hr;
10907 DDSURFACEDESC2 surface_desc;
10908 DDSURFACEDESC2 locked_desc;
10909 DDCAPS hal_caps;
10910 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
10911 static RECT valid[] =
10913 {60, 60, 68, 68},
10914 {60, 60, 60, 68},
10915 {60, 60, 68, 60},
10916 {120, 60, 128, 68},
10917 {60, 120, 68, 128},
10919 static RECT invalid[] =
10921 {68, 60, 60, 68}, /* left > right */
10922 {60, 68, 68, 60}, /* top > bottom */
10923 {-8, 60, 0, 68}, /* left < surface */
10924 {60, -8, 68, 0}, /* top < surface */
10925 {-16, 60, -8, 68}, /* right < surface */
10926 {60, -16, 68, -8}, /* bottom < surface */
10927 {60, 60, 136, 68}, /* right > surface */
10928 {60, 60, 68, 136}, /* bottom > surface */
10929 {136, 60, 144, 68}, /* left > surface */
10930 {60, 136, 68, 144}, /* top > surface */
10932 static const struct
10934 DWORD caps, caps2;
10935 const char *name;
10936 HRESULT hr;
10938 resources[] =
10940 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, "sysmem offscreenplain", DDERR_INVALIDPARAMS},
10941 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, "vidmem offscreenplain", DDERR_INVALIDPARAMS},
10942 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, "sysmem texture", DD_OK},
10943 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, "vidmem texture", DDERR_INVALIDPARAMS},
10944 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, "managed texture", DD_OK},
10947 window = create_window();
10948 ddraw = create_ddraw();
10949 ok(!!ddraw, "Failed to create a ddraw object.\n");
10950 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10951 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
10953 memset(&hal_caps, 0, sizeof(hal_caps));
10954 hal_caps.dwSize = sizeof(hal_caps);
10955 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
10956 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
10957 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps
10958 || !(hal_caps.ddsCaps.dwCaps & DDSCAPS2_TEXTUREMANAGE))
10960 skip("Required surface types not supported, skipping test.\n");
10961 goto done;
10964 for (r = 0; r < ARRAY_SIZE(resources); ++r)
10966 memset(&surface_desc, 0, sizeof(surface_desc));
10967 surface_desc.dwSize = sizeof(surface_desc);
10968 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10969 surface_desc.ddsCaps.dwCaps = resources[r].caps;
10970 surface_desc.ddsCaps.dwCaps2 = resources[r].caps2;
10971 surface_desc.dwWidth = 128;
10972 surface_desc.dwHeight = 128;
10973 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
10974 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
10975 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
10976 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xff0000;
10977 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x00ff00;
10978 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x0000ff;
10980 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10981 if (is_ddraw64 && (resources[r].caps & DDSCAPS_TEXTURE))
10983 todo_wine ok(hr == E_NOINTERFACE, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
10984 if (SUCCEEDED(hr))
10985 IDirectDrawSurface7_Release(surface);
10986 continue;
10988 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n", hr, resources[r].name);
10990 /* Crashes in ddraw7
10991 hr = IDirectDrawSurface7_Lock(surface, NULL, NULL, DDLOCK_WAIT, NULL);
10992 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
10995 for (i = 0; i < ARRAY_SIZE(valid); ++i)
10997 RECT *rect = &valid[i];
10999 memset(&locked_desc, 0, sizeof(locked_desc));
11000 locked_desc.dwSize = sizeof(locked_desc);
11002 hr = IDirectDrawSurface7_Lock(surface, rect, &locked_desc, DDLOCK_WAIT, NULL);
11003 ok(SUCCEEDED(hr), "Lock failed (%#x) for rect %s, type %s.\n",
11004 hr, wine_dbgstr_rect(rect), resources[r].name);
11006 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11007 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11010 for (i = 0; i < ARRAY_SIZE(invalid); ++i)
11012 RECT *rect = &invalid[i];
11014 memset(&locked_desc, 1, sizeof(locked_desc));
11015 locked_desc.dwSize = sizeof(locked_desc);
11017 hr = IDirectDrawSurface7_Lock(surface, rect, &locked_desc, DDLOCK_WAIT, NULL);
11018 todo_wine_if (SUCCEEDED(resources[r].hr))
11019 ok(hr == resources[r].hr, "Lock returned %#x for rect %s, type %s.\n",
11020 hr, wine_dbgstr_rect(rect), resources[r].name);
11021 if (SUCCEEDED(hr))
11023 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11024 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11026 else
11027 ok(!locked_desc.lpSurface, "Got unexpected lpSurface %p.\n", locked_desc.lpSurface);
11030 hr = IDirectDrawSurface7_Lock(surface, NULL, &locked_desc, DDLOCK_WAIT, NULL);
11031 ok(SUCCEEDED(hr), "Lock(rect = NULL) failed, hr %#x, type %s.\n",
11032 hr, resources[r].name);
11033 hr = IDirectDrawSurface7_Lock(surface, NULL, &locked_desc, DDLOCK_WAIT, NULL);
11034 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = NULL) returned %#x, type %s.\n",
11035 hr, resources[r].name);
11036 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11037 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11039 hr = IDirectDrawSurface7_Lock(surface, &valid[0], &locked_desc, DDLOCK_WAIT, NULL);
11040 ok(SUCCEEDED(hr), "Lock(rect = %s) failed (%#x).\n", wine_dbgstr_rect(&valid[0]), hr);
11041 hr = IDirectDrawSurface7_Lock(surface, &valid[0], &locked_desc, DDLOCK_WAIT, NULL);
11042 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = %s) failed (%#x).\n",
11043 wine_dbgstr_rect(&valid[0]), hr);
11045 /* Locking a different rectangle returns DD_OK, but it seems to break the surface.
11046 * Afterwards unlocking the surface fails(NULL rectangle or both locked rectangles) */
11048 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11049 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11051 IDirectDrawSurface7_Release(surface);
11054 done:
11055 IDirectDraw7_Release(ddraw);
11056 DestroyWindow(window);
11059 static void test_yv12_overlay(void)
11061 IDirectDrawSurface7 *src_surface, *dst_surface;
11062 RECT rect = {13, 17, 14, 18};
11063 unsigned int offset, y;
11064 DDSURFACEDESC2 desc;
11065 unsigned char *base;
11066 IDirectDraw7 *ddraw;
11067 HWND window;
11068 HRESULT hr;
11070 window = create_window();
11071 ddraw = create_ddraw();
11072 ok(!!ddraw, "Failed to create a ddraw object.\n");
11073 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11074 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11076 if (!(src_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
11078 skip("Failed to create a YV12 overlay, skipping test.\n");
11079 goto done;
11082 memset(&desc, 0, sizeof(desc));
11083 desc.dwSize = sizeof(desc);
11084 hr = IDirectDrawSurface7_Lock(src_surface, NULL, &desc, DDLOCK_WAIT, NULL);
11085 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11087 ok(desc.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH),
11088 "Got unexpected flags %#x.\n", desc.dwFlags);
11089 ok(desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_HWCODEC)
11090 || desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
11091 "Got unexpected caps %#x.\n", desc.ddsCaps.dwCaps);
11092 ok(desc.dwWidth == 256, "Got unexpected width %u.\n", desc.dwWidth);
11093 ok(desc.dwHeight == 256, "Got unexpected height %u.\n", desc.dwHeight);
11094 /* The overlay pitch seems to have 256 byte alignment. */
11095 ok(!(U1(desc).lPitch & 0xff), "Got unexpected pitch %u.\n", U1(desc).lPitch);
11097 /* Fill the surface with some data for the blit test. */
11098 base = desc.lpSurface;
11099 /* Luminance */
11100 for (y = 0; y < desc.dwHeight; ++y)
11102 memset(base + U1(desc).lPitch * y, 0x10, desc.dwWidth);
11104 /* V */
11105 for (; y < desc.dwHeight + desc.dwHeight / 4; ++y)
11107 memset(base + U1(desc).lPitch * y, 0x20, desc.dwWidth);
11109 /* U */
11110 for (; y < desc.dwHeight + desc.dwHeight / 2; ++y)
11112 memset(base + U1(desc).lPitch * y, 0x30, desc.dwWidth);
11115 hr = IDirectDrawSurface7_Unlock(src_surface, NULL);
11116 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11118 /* YV12 uses 2x2 blocks with 6 bytes per block (4*Y, 1*U, 1*V). Unlike
11119 * other block-based formats like DXT the entire Y channel is stored in
11120 * one big chunk of memory, followed by the chroma channels. So partial
11121 * locks do not really make sense. Show that they are allowed nevertheless
11122 * and the offset points into the luminance data. */
11123 hr = IDirectDrawSurface7_Lock(src_surface, &rect, &desc, DDLOCK_WAIT, NULL);
11124 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11125 offset = ((const unsigned char *)desc.lpSurface - base);
11126 ok(offset == rect.top * U1(desc).lPitch + rect.left, "Got unexpected offset %u, expected %u.\n",
11127 offset, rect.top * U1(desc).lPitch + rect.left);
11128 hr = IDirectDrawSurface7_Unlock(src_surface, NULL);
11129 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11131 if (!(dst_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
11133 /* Windows XP with a Radeon X1600 GPU refuses to create a second
11134 * overlay surface, DDERR_NOOVERLAYHW, making the blit tests moot. */
11135 skip("Failed to create a second YV12 surface, skipping blit test.\n");
11136 IDirectDrawSurface7_Release(src_surface);
11137 goto done;
11140 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, src_surface, NULL, DDBLT_WAIT, NULL);
11141 /* VMware rejects YV12 blits. This behavior has not been seen on real
11142 * hardware yet, so mark it broken. */
11143 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL), "Failed to blit, hr %#x.\n", hr);
11145 if (SUCCEEDED(hr))
11147 memset(&desc, 0, sizeof(desc));
11148 desc.dwSize = sizeof(desc);
11149 hr = IDirectDrawSurface7_Lock(dst_surface, NULL, &desc, DDLOCK_WAIT, NULL);
11150 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11152 base = desc.lpSurface;
11153 ok(base[0] == 0x10, "Got unexpected Y data 0x%02x.\n", base[0]);
11154 base += desc.dwHeight * U1(desc).lPitch;
11155 todo_wine ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]);
11156 base += desc.dwHeight / 4 * U1(desc).lPitch;
11157 todo_wine ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]);
11159 hr = IDirectDrawSurface7_Unlock(dst_surface, NULL);
11160 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11163 IDirectDrawSurface7_Release(dst_surface);
11164 IDirectDrawSurface7_Release(src_surface);
11165 done:
11166 IDirectDraw7_Release(ddraw);
11167 DestroyWindow(window);
11170 static BOOL dwm_enabled(void)
11172 BOOL ret = FALSE;
11174 if (!strcmp(winetest_platform, "wine"))
11175 return FALSE;
11176 if (!pDwmIsCompositionEnabled)
11177 return FALSE;
11178 if (FAILED(pDwmIsCompositionEnabled(&ret)))
11179 return FALSE;
11180 return ret;
11183 static void test_offscreen_overlay(void)
11185 IDirectDrawSurface7 *overlay, *offscreen, *primary;
11186 DDSURFACEDESC2 surface_desc;
11187 IDirectDraw7 *ddraw;
11188 HWND window;
11189 HRESULT hr;
11190 HDC dc;
11192 window = create_window();
11193 ddraw = create_ddraw();
11194 ok(!!ddraw, "Failed to create a ddraw object.\n");
11195 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11196 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11198 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
11200 skip("Failed to create a UYVY overlay, skipping test.\n");
11201 goto done;
11204 memset(&surface_desc, 0, sizeof(surface_desc));
11205 surface_desc.dwSize = sizeof(surface_desc);
11206 surface_desc.dwFlags = DDSD_CAPS;
11207 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
11208 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
11209 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
11211 /* On Windows 7, and probably Vista, UpdateOverlay() will return
11212 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
11213 * surface prevents this by disabling the dwm. */
11214 hr = IDirectDrawSurface7_GetDC(primary, &dc);
11215 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
11216 hr = IDirectDrawSurface7_ReleaseDC(primary, dc);
11217 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
11219 /* Try to overlay a NULL surface. */
11220 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_SHOW, NULL);
11221 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11222 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_HIDE, NULL);
11223 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11225 /* Try to overlay an offscreen surface. */
11226 memset(&surface_desc, 0, sizeof(surface_desc));
11227 surface_desc.dwSize = sizeof(surface_desc);
11228 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
11229 surface_desc.dwWidth = 64;
11230 surface_desc.dwHeight = 64;
11231 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11232 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
11233 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
11234 U4(surface_desc).ddpfPixelFormat.dwFourCC = 0;
11235 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
11236 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
11237 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
11238 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
11239 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
11240 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
11242 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, offscreen, NULL, DDOVER_SHOW, NULL);
11243 ok(SUCCEEDED(hr) || broken(hr == DDERR_OUTOFCAPS && dwm_enabled())
11244 || broken(hr == E_NOTIMPL && ddraw_is_vmware(ddraw)),
11245 "Failed to update overlay, hr %#x.\n", hr);
11247 /* Try to overlay the primary with a non-overlay surface. */
11248 hr = IDirectDrawSurface7_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_SHOW, NULL);
11249 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
11250 hr = IDirectDrawSurface7_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_HIDE, NULL);
11251 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
11253 IDirectDrawSurface7_Release(offscreen);
11254 IDirectDrawSurface7_Release(primary);
11255 IDirectDrawSurface7_Release(overlay);
11256 done:
11257 IDirectDraw7_Release(ddraw);
11258 DestroyWindow(window);
11261 static void test_overlay_rect(void)
11263 IDirectDrawSurface7 *overlay, *primary = NULL;
11264 DDSURFACEDESC2 surface_desc;
11265 RECT rect = {0, 0, 64, 64};
11266 IDirectDraw7 *ddraw;
11267 LONG pos_x, pos_y;
11268 HRESULT hr, hr2;
11269 HWND window;
11270 HDC dc;
11272 window = create_window();
11273 ddraw = create_ddraw();
11274 ok(!!ddraw, "Failed to create a ddraw object.\n");
11275 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11276 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11278 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
11280 skip("Failed to create a UYVY overlay, skipping test.\n");
11281 goto done;
11284 memset(&surface_desc, 0, sizeof(surface_desc));
11285 surface_desc.dwSize = sizeof(surface_desc);
11286 surface_desc.dwFlags = DDSD_CAPS;
11287 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
11288 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
11289 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
11291 /* On Windows 7, and probably Vista, UpdateOverlay() will return
11292 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
11293 * surface prevents this by disabling the dwm. */
11294 hr = IDirectDrawSurface7_GetDC(primary, &dc);
11295 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
11296 hr = IDirectDrawSurface7_ReleaseDC(primary, dc);
11297 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
11299 /* On Windows 8 and newer DWM can't be turned off, making overlays unusable. */
11300 if (dwm_enabled())
11302 win_skip("Cannot disable DWM, skipping overlay test.\n");
11303 goto done;
11306 /* The dx sdk sort of implies that rect must be set when DDOVER_SHOW is
11307 * used. This is not true in Windows Vista and earlier, but changed in
11308 * Windows 7. */
11309 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
11310 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
11311 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_HIDE, NULL);
11312 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
11313 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_SHOW, NULL);
11314 ok(hr == DD_OK || hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11316 /* Show that the overlay position is the (top, left) coordinate of the
11317 * destination rectangle. */
11318 OffsetRect(&rect, 32, 16);
11319 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
11320 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
11321 pos_x = -1; pos_y = -1;
11322 hr = IDirectDrawSurface7_GetOverlayPosition(overlay, &pos_x, &pos_y);
11323 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
11324 ok(pos_x == rect.left, "Got unexpected pos_x %d, expected %d.\n", pos_x, rect.left);
11325 ok(pos_y == rect.top, "Got unexpected pos_y %d, expected %d.\n", pos_y, rect.top);
11327 /* Passing a NULL dest rect sets the position to 0/0. Visually it can be
11328 * seen that the overlay overlays the whole primary(==screen). */
11329 hr2 = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, NULL, 0, NULL);
11330 ok(hr2 == DD_OK || hr2 == DDERR_INVALIDPARAMS || hr2 == DDERR_OUTOFCAPS, "Got unexpected hr %#x.\n", hr2);
11331 hr = IDirectDrawSurface7_GetOverlayPosition(overlay, &pos_x, &pos_y);
11332 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
11333 if (SUCCEEDED(hr2))
11335 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
11336 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
11338 else
11340 ok(pos_x == 32, "Got unexpected pos_x %d.\n", pos_x);
11341 ok(pos_y == 16, "Got unexpected pos_y %d.\n", pos_y);
11344 /* The position cannot be retrieved when the overlay is not shown. */
11345 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_HIDE, NULL);
11346 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
11347 pos_x = -1; pos_y = -1;
11348 hr = IDirectDrawSurface7_GetOverlayPosition(overlay, &pos_x, &pos_y);
11349 ok(hr == DDERR_OVERLAYNOTVISIBLE, "Got unexpected hr %#x.\n", hr);
11350 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
11351 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
11353 IDirectDrawSurface7_Release(overlay);
11354 done:
11355 if (primary)
11356 IDirectDrawSurface7_Release(primary);
11357 IDirectDraw7_Release(ddraw);
11358 DestroyWindow(window);
11361 static void test_blt(void)
11363 IDirectDrawSurface7 *surface, *rt;
11364 DDSURFACEDESC2 surface_desc;
11365 IDirect3DDevice7 *device;
11366 IDirectDraw7 *ddraw;
11367 IDirect3D7 *d3d;
11368 unsigned int i;
11369 ULONG refcount;
11370 HWND window;
11371 HRESULT hr;
11373 static struct
11375 RECT src_rect;
11376 RECT dst_rect;
11377 HRESULT hr;
11379 test_data[] =
11381 {{160, 0, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit. */
11382 {{160, 480, 640, 0}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, flipped source. */
11383 {{640, 0, 160, 480}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, mirrored source. */
11384 {{160, 0, 480, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched x. */
11385 {{160, 160, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched y. */
11386 {{ 0, 0, 640, 480}, { 0, 0, 640, 480}, DD_OK}, /* Full surface blit. */
11387 {{ 0, 0, 640, 480}, { 0, 480, 640, 0}, DDERR_INVALIDRECT}, /* Full surface, flipped destination. */
11388 {{ 0, 0, 640, 480}, {640, 0, 0, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored destination. */
11389 {{ 0, 480, 640, 0}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, flipped source. */
11390 {{640, 0, 0, 480}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored source. */
11393 window = create_window();
11394 if (!(device = create_device(window, DDSCL_NORMAL)))
11396 skip("Failed to create a 3D device, skipping test.\n");
11397 DestroyWindow(window);
11398 return;
11401 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
11402 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
11403 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
11404 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
11405 IDirect3D7_Release(d3d);
11406 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
11407 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11409 memset(&surface_desc, 0, sizeof(surface_desc));
11410 surface_desc.dwSize = sizeof(surface_desc);
11411 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
11412 surface_desc.dwWidth = 640;
11413 surface_desc.dwHeight = 480;
11414 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11415 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11416 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11418 hr = IDirectDrawSurface7_Blt(surface, NULL, surface, NULL, 0, NULL);
11419 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
11421 hr = IDirectDrawSurface7_Blt(surface, NULL, rt, NULL, 0, NULL);
11422 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
11424 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
11426 hr = IDirectDrawSurface7_Blt(surface, &test_data[i].dst_rect,
11427 surface, &test_data[i].src_rect, DDBLT_WAIT, NULL);
11428 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
11430 hr = IDirectDrawSurface7_Blt(surface, &test_data[i].dst_rect,
11431 rt, &test_data[i].src_rect, DDBLT_WAIT, NULL);
11432 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
11434 hr = IDirectDrawSurface7_Blt(surface, &test_data[i].dst_rect,
11435 NULL, &test_data[i].src_rect, DDBLT_WAIT, NULL);
11436 ok(hr == DDERR_INVALIDPARAMS, "Test %u: Got unexpected hr %#x.\n", i, hr);
11438 hr = IDirectDrawSurface7_Blt(surface, &test_data[i].dst_rect, NULL, NULL, DDBLT_WAIT, NULL);
11439 ok(hr == DDERR_INVALIDPARAMS, "Test %u: Got unexpected hr %#x.\n", i, hr);
11442 IDirectDrawSurface7_Release(surface);
11443 IDirectDrawSurface7_Release(rt);
11444 IDirectDraw7_Release(ddraw);
11445 refcount = IDirect3DDevice7_Release(device);
11446 ok(!refcount, "Device has %u references left.\n", refcount);
11447 DestroyWindow(window);
11450 static void test_blt_z_alpha(void)
11452 DWORD blt_flags[] =
11454 /* 0 */
11455 DDBLT_ALPHADEST,
11456 DDBLT_ALPHADESTCONSTOVERRIDE,
11457 DDBLT_ALPHADESTNEG,
11458 DDBLT_ALPHADESTSURFACEOVERRIDE,
11459 DDBLT_ALPHAEDGEBLEND,
11460 /* 5 */
11461 DDBLT_ALPHASRC,
11462 DDBLT_ALPHASRCCONSTOVERRIDE,
11463 DDBLT_ALPHASRCNEG,
11464 DDBLT_ALPHASRCSURFACEOVERRIDE,
11465 DDBLT_ZBUFFER,
11466 /* 10 */
11467 DDBLT_ZBUFFERDESTCONSTOVERRIDE,
11468 DDBLT_ZBUFFERDESTOVERRIDE,
11469 DDBLT_ZBUFFERSRCCONSTOVERRIDE,
11470 DDBLT_ZBUFFERSRCOVERRIDE,
11472 IDirectDrawSurface7 *src_surface, *dst_surface;
11473 DDSURFACEDESC2 surface_desc;
11474 IDirectDraw7 *ddraw;
11475 DDPIXELFORMAT pf;
11476 ULONG refcount;
11477 unsigned int i;
11478 D3DCOLOR color;
11479 HWND window;
11480 HRESULT hr;
11481 DDBLTFX fx;
11483 window = create_window();
11484 ddraw = create_ddraw();
11485 ok(!!ddraw, "Failed to create a ddraw object.\n");
11486 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11487 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11489 memset(&pf, 0, sizeof(pf));
11490 pf.dwSize = sizeof(pf);
11491 pf.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
11492 U1(pf).dwRGBBitCount = 32;
11493 U2(pf).dwRBitMask = 0x00ff0000;
11494 U3(pf).dwGBitMask = 0x0000ff00;
11495 U4(pf).dwBBitMask = 0x000000ff;
11496 U5(pf).dwRGBAlphaBitMask = 0xff000000;
11498 memset(&surface_desc, 0, sizeof(surface_desc));
11499 surface_desc.dwSize = sizeof(surface_desc);
11500 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
11501 surface_desc.dwWidth = 64;
11502 surface_desc.dwHeight = 64;
11503 U4(surface_desc).ddpfPixelFormat = pf;
11504 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11506 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
11507 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
11508 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
11509 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
11511 memset(&fx, 0, sizeof(fx));
11512 fx.dwSize = sizeof(fx);
11513 fx.dwZBufferOpCode = D3DCMP_NEVER;
11514 fx.dwZDestConstBitDepth = 32;
11515 U1(fx).dwZDestConst = 0x11111111;
11516 fx.dwZSrcConstBitDepth = 32;
11517 U2(fx).dwZSrcConst = 0xeeeeeeee;
11518 fx.dwAlphaEdgeBlendBitDepth = 8;
11519 fx.dwAlphaEdgeBlend = 0x7f;
11520 fx.dwAlphaDestConstBitDepth = 8;
11521 U3(fx).dwAlphaDestConst = 0xdd;
11522 fx.dwAlphaSrcConstBitDepth = 8;
11523 U4(fx).dwAlphaSrcConst = 0x22;
11525 for (i = 0; i < ARRAY_SIZE(blt_flags); ++i)
11527 fx.dwFillColor = 0x3300ff00;
11528 hr = IDirectDrawSurface7_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11529 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
11531 fx.dwFillColor = 0xccff0000;
11532 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11533 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
11535 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, src_surface, NULL, blt_flags[i] | DDBLT_WAIT, &fx);
11536 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
11538 color = get_surface_color(dst_surface, 32, 32);
11539 ok(compare_color(color, 0x0000ff00, 0), "Test %u: Got unexpected color 0x%08x.\n", i, color);
11542 IDirectDrawSurface7_Release(dst_surface);
11543 IDirectDrawSurface7_Release(src_surface);
11544 refcount = IDirectDraw7_Release(ddraw);
11545 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
11546 DestroyWindow(window);
11549 static void test_color_clamping(void)
11551 static D3DMATRIX mat =
11553 1.0f, 0.0f, 0.0f, 0.0f,
11554 0.0f, 1.0f, 0.0f, 0.0f,
11555 0.0f, 0.0f, 1.0f, 0.0f,
11556 0.0f, 0.0f, 0.0f, 1.0f,
11558 static struct vec3 quad[] =
11560 {-1.0f, -1.0f, 0.1f},
11561 {-1.0f, 1.0f, 0.1f},
11562 { 1.0f, -1.0f, 0.1f},
11563 { 1.0f, 1.0f, 0.1f},
11565 IDirect3DDevice7 *device;
11566 IDirectDrawSurface7 *rt;
11567 ULONG refcount;
11568 D3DCOLOR color;
11569 HWND window;
11570 HRESULT hr;
11572 window = create_window();
11573 if (!(device = create_device(window, DDSCL_NORMAL)))
11575 skip("Failed to create a 3D device, skipping test.\n");
11576 DestroyWindow(window);
11577 return;
11580 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
11581 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11583 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
11584 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
11585 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
11586 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
11587 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
11588 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
11589 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
11590 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
11591 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
11592 ok(SUCCEEDED(hr), "Failed to disable Z test, hr %#x.\n", hr);
11593 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
11594 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
11595 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
11596 ok(SUCCEEDED(hr), "Failed to disable stencil test, hr %#x.\n", hr);
11597 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
11598 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
11599 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
11600 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
11602 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0xff404040);
11603 ok(SUCCEEDED(hr), "Failed to set texture factor, hr %#x.\n", hr);
11604 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_ADD);
11605 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
11606 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
11607 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11608 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_SPECULAR);
11609 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11610 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_MODULATE);
11611 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
11612 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TFACTOR);
11613 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11614 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
11615 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11617 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
11618 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
11620 hr = IDirect3DDevice7_BeginScene(device);
11621 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11623 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
11624 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11626 hr = IDirect3DDevice7_EndScene(device);
11627 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11629 color = get_surface_color(rt, 320, 240);
11630 ok(compare_color(color, 0x00404040, 1), "Got unexpected color 0x%08x.\n", color);
11632 IDirectDrawSurface7_Release(rt);
11633 refcount = IDirect3DDevice7_Release(device);
11634 ok(!refcount, "Device has %u references left.\n", refcount);
11635 DestroyWindow(window);
11638 static void test_getdc(void)
11640 DDSCAPS2 caps = {DDSCAPS_COMPLEX, DDSCAPS2_CUBEMAP_NEGATIVEZ, 0, {0}};
11641 IDirectDrawSurface7 *surface, *surface2, *tmp;
11642 DDSURFACEDESC2 surface_desc, map_desc;
11643 IDirectDraw7 *ddraw;
11644 unsigned int i;
11645 HWND window;
11646 HDC dc, dc2;
11647 HRESULT hr;
11649 static const struct
11651 const char *name;
11652 DDPIXELFORMAT format;
11653 BOOL getdc_supported;
11654 HRESULT alt_result;
11656 test_data[] =
11658 {"D3DFMT_A8R8G8B8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
11659 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}}, TRUE},
11660 {"D3DFMT_X8R8G8B8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
11661 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}}, TRUE},
11662 {"D3DFMT_R5G6B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
11663 {0x0000f800}, {0x000007e0}, {0x0000001f}, {0x00000000}}, TRUE},
11664 {"D3DFMT_X1R5G5B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
11665 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00000000}}, TRUE},
11666 {"D3DFMT_A1R5G5B5", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
11667 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00008000}}, TRUE},
11668 {"D3DFMT_A4R4G4B4", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
11669 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x0000f000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
11670 {"D3DFMT_X4R4G4B4", {sizeof(test_data->format), DDPF_RGB, 0, {16},
11671 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
11672 {"D3DFMT_A2R10G10B10", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
11673 {0xc0000000}, {0x3ff00000}, {0x000ffc00}, {0x000003ff}}, TRUE},
11674 {"D3DFMT_A8B8G8R8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
11675 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0xff000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
11676 {"D3DFMT_X8B8G8R8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
11677 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
11678 {"D3DFMT_R3G3B2", {sizeof(test_data->format), DDPF_RGB, 0, {8},
11679 {0x000000e0}, {0x0000001c}, {0x00000003}, {0x00000000}}, FALSE},
11680 /* GetDC() on a P8 surface fails unless the display mode is 8 bpp.
11681 * This is not implemented in wine yet, so disable the test for now.
11682 * Succeeding P8 GetDC() calls are tested in the ddraw:visual test.
11683 {"D3DFMT_P8", {sizeof(test_data->format), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0, {8 },
11684 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11686 {"D3DFMT_L8", {sizeof(test_data->format), DDPF_LUMINANCE, 0, {8},
11687 {0x000000ff}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11688 {"D3DFMT_A8L8", {sizeof(test_data->format), DDPF_ALPHAPIXELS | DDPF_LUMINANCE, 0, {16},
11689 {0x000000ff}, {0x00000000}, {0x00000000}, {0x0000ff00}}, FALSE},
11690 {"D3DFMT_DXT1", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','1'), {0},
11691 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11692 {"D3DFMT_DXT2", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','2'), {0},
11693 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11694 {"D3DFMT_DXT3", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','3'), {0},
11695 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11696 {"D3DFMT_DXT4", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','4'), {0},
11697 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11698 {"D3DFMT_DXT5", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','5'), {0},
11699 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
11702 window = create_window();
11703 ddraw = create_ddraw();
11704 ok(!!ddraw, "Failed to create a ddraw object.\n");
11705 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11706 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11708 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
11710 memset(&surface_desc, 0, sizeof(surface_desc));
11711 surface_desc.dwSize = sizeof(surface_desc);
11712 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
11713 surface_desc.dwWidth = 64;
11714 surface_desc.dwHeight = 64;
11715 U4(surface_desc).ddpfPixelFormat = test_data[i].format;
11716 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11718 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
11720 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
11721 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
11722 if (FAILED(hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
11724 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", test_data[i].name, hr);
11725 continue;
11729 dc = (void *)0x1234;
11730 hr = IDirectDrawSurface7_GetDC(surface, &dc);
11731 if (test_data[i].getdc_supported)
11732 ok(SUCCEEDED(hr) || broken(hr == test_data[i].alt_result),
11733 "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11734 else
11735 ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11737 if (SUCCEEDED(hr))
11739 unsigned int width_bytes;
11740 DIBSECTION dib;
11741 HBITMAP bitmap;
11742 DWORD type;
11743 int size;
11745 type = GetObjectType(dc);
11746 ok(type == OBJ_MEMDC, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
11747 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
11748 type = GetObjectType(bitmap);
11749 ok(type == OBJ_BITMAP, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
11751 size = GetObjectA(bitmap, sizeof(dib), &dib);
11752 ok(size == sizeof(dib), "Got unexpected size %d for format %s.\n", size, test_data[i].name);
11753 ok(!dib.dsBm.bmType, "Got unexpected type %#x for format %s.\n",
11754 dib.dsBm.bmType, test_data[i].name);
11755 ok(dib.dsBm.bmWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
11756 dib.dsBm.bmWidth, test_data[i].name);
11757 ok(dib.dsBm.bmHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
11758 dib.dsBm.bmHeight, test_data[i].name);
11759 width_bytes = ((dib.dsBm.bmWidth * U1(test_data[i].format).dwRGBBitCount + 31) >> 3) & ~3;
11760 ok(dib.dsBm.bmWidthBytes == width_bytes, "Got unexpected width bytes %d for format %s.\n",
11761 dib.dsBm.bmWidthBytes, test_data[i].name);
11762 ok(dib.dsBm.bmPlanes == 1, "Got unexpected plane count %d for format %s.\n",
11763 dib.dsBm.bmPlanes, test_data[i].name);
11764 ok(dib.dsBm.bmBitsPixel == U1(test_data[i].format).dwRGBBitCount,
11765 "Got unexpected bit count %d for format %s.\n",
11766 dib.dsBm.bmBitsPixel, test_data[i].name);
11767 ok(!!dib.dsBm.bmBits, "Got unexpected bits %p for format %s.\n",
11768 dib.dsBm.bmBits, test_data[i].name);
11770 ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "Got unexpected size %u for format %s.\n",
11771 dib.dsBmih.biSize, test_data[i].name);
11772 ok(dib.dsBmih.biWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
11773 dib.dsBmih.biHeight, test_data[i].name);
11774 ok(dib.dsBmih.biHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
11775 dib.dsBmih.biHeight, test_data[i].name);
11776 ok(dib.dsBmih.biPlanes == 1, "Got unexpected plane count %u for format %s.\n",
11777 dib.dsBmih.biPlanes, test_data[i].name);
11778 ok(dib.dsBmih.biBitCount == U1(test_data[i].format).dwRGBBitCount,
11779 "Got unexpected bit count %u for format %s.\n",
11780 dib.dsBmih.biBitCount, test_data[i].name);
11781 ok(dib.dsBmih.biCompression == (U1(test_data[i].format).dwRGBBitCount == 16 ? BI_BITFIELDS : BI_RGB)
11782 || broken(U1(test_data[i].format).dwRGBBitCount == 32 && dib.dsBmih.biCompression == BI_BITFIELDS),
11783 "Got unexpected compression %#x for format %s.\n",
11784 dib.dsBmih.biCompression, test_data[i].name);
11785 ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
11786 dib.dsBmih.biSizeImage, test_data[i].name);
11787 ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n",
11788 dib.dsBmih.biXPelsPerMeter, test_data[i].name);
11789 ok(!dib.dsBmih.biYPelsPerMeter, "Got unexpected vertical resolution %d for format %s.\n",
11790 dib.dsBmih.biYPelsPerMeter, test_data[i].name);
11791 ok(!dib.dsBmih.biClrUsed, "Got unexpected used colour count %u for format %s.\n",
11792 dib.dsBmih.biClrUsed, test_data[i].name);
11793 ok(!dib.dsBmih.biClrImportant, "Got unexpected important colour count %u for format %s.\n",
11794 dib.dsBmih.biClrImportant, test_data[i].name);
11796 if (dib.dsBmih.biCompression == BI_BITFIELDS)
11798 ok((dib.dsBitfields[0] == U2(test_data[i].format).dwRBitMask
11799 && dib.dsBitfields[1] == U3(test_data[i].format).dwGBitMask
11800 && dib.dsBitfields[2] == U4(test_data[i].format).dwBBitMask)
11801 || broken(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2]),
11802 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
11803 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
11805 else
11807 ok(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2],
11808 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
11809 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
11811 ok(!dib.dshSection, "Got unexpected section %p for format %s.\n", dib.dshSection, test_data[i].name);
11812 ok(!dib.dsOffset, "Got unexpected offset %u for format %s.\n", dib.dsOffset, test_data[i].name);
11814 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
11815 ok(hr == DD_OK, "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11817 else
11819 ok(!dc, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
11822 IDirectDrawSurface7_Release(surface);
11824 if (FAILED(hr))
11825 continue;
11827 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
11828 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_TEXTUREMANAGE;
11829 if (FAILED(hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
11831 skip("Failed to create cube texture for format %s (hr %#x), skipping tests.\n", test_data[i].name, hr);
11832 continue;
11835 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &surface2);
11836 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
11837 hr = IDirectDrawSurface7_GetAttachedSurface(surface2, &caps, &tmp);
11838 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
11839 IDirectDrawSurface7_Release(surface2);
11840 hr = IDirectDrawSurface7_GetAttachedSurface(tmp, &caps, &surface2);
11841 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
11842 IDirectDrawSurface7_Release(tmp);
11844 hr = IDirectDrawSurface7_GetDC(surface, &dc);
11845 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11846 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
11847 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11848 hr = IDirectDrawSurface7_GetDC(surface2, &dc);
11849 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11850 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc);
11851 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11853 hr = IDirectDrawSurface7_GetDC(surface, &dc);
11854 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11855 dc2 = (void *)0x1234;
11856 hr = IDirectDrawSurface7_GetDC(surface, &dc2);
11857 ok(hr == DDERR_DCALREADYCREATED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11858 ok(dc2 == (void *)0x1234, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
11859 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
11860 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11861 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
11862 ok(hr == DDERR_NODC, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11864 map_desc.dwSize = sizeof(map_desc);
11865 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11866 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11867 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11868 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11869 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11870 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11871 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11872 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11874 hr = IDirectDrawSurface7_GetDC(surface, &dc);
11875 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11876 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11877 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11878 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
11879 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11881 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11882 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11883 hr = IDirectDrawSurface7_GetDC(surface, &dc);
11884 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
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(surface, NULL);
11888 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11890 hr = IDirectDrawSurface7_GetDC(surface, &dc);
11891 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11892 hr = IDirectDrawSurface7_GetDC(surface2, &dc2);
11893 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11894 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc2);
11895 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11896 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
11897 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11899 hr = IDirectDrawSurface7_GetDC(surface2, &dc);
11900 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11901 hr = IDirectDrawSurface7_GetDC(surface, &dc2);
11902 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11903 hr = IDirectDrawSurface7_ReleaseDC(surface, dc2);
11904 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11905 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc);
11906 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11908 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11909 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11910 hr = IDirectDrawSurface7_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11911 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11912 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
11913 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11914 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11915 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11917 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11918 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11919 hr = IDirectDrawSurface7_GetDC(surface, &dc);
11920 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11921 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
11922 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11923 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11924 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11926 hr = IDirectDrawSurface7_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11927 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11928 hr = IDirectDrawSurface7_GetDC(surface, &dc);
11929 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11930 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
11931 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11932 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
11933 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11935 hr = IDirectDrawSurface7_GetDC(surface, &dc);
11936 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11937 hr = IDirectDrawSurface7_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11938 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11939 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
11940 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11941 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
11942 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11944 hr = IDirectDrawSurface7_GetDC(surface2, &dc);
11945 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11946 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
11947 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
11948 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11949 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
11950 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc);
11951 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11953 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11954 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11955 hr = IDirectDrawSurface7_GetDC(surface2, &dc);
11956 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11957 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11958 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11959 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc);
11960 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11961 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11962 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11964 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
11965 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11966 hr = IDirectDrawSurface7_GetDC(surface, &dc);
11967 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
11968 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
11969 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11970 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
11971 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
11972 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
11973 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
11975 IDirectDrawSurface7_Release(surface2);
11976 IDirectDrawSurface7_Release(surface);
11979 IDirectDraw7_Release(ddraw);
11980 DestroyWindow(window);
11983 static void test_draw_primitive(void)
11985 static WORD indices[] = {0, 1, 2, 3};
11986 static struct vec3 quad[] =
11988 {-1.0f, -1.0f, 0.0f},
11989 {-1.0f, 1.0f, 0.0f},
11990 { 1.0f, -1.0f, 0.0f},
11991 { 1.0f, 1.0f, 0.0f},
11993 D3DDRAWPRIMITIVESTRIDEDDATA strided;
11994 D3DVERTEXBUFFERDESC vb_desc;
11995 IDirect3DVertexBuffer7 *vb;
11996 IDirect3DDevice7 *device;
11997 IDirect3D7 *d3d;
11998 ULONG refcount;
11999 HWND window;
12000 HRESULT hr;
12001 void *data;
12003 window = create_window();
12004 if (!(device = create_device(window, DDSCL_NORMAL)))
12006 skip("Failed to create a 3D device, skipping test.\n");
12007 DestroyWindow(window);
12008 return;
12011 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
12012 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
12014 memset(&vb_desc, 0, sizeof(vb_desc));
12015 vb_desc.dwSize = sizeof(vb_desc);
12016 vb_desc.dwFVF = D3DFVF_XYZ;
12017 vb_desc.dwNumVertices = 4;
12018 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &vb, 0);
12019 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
12021 IDirect3D7_Release(d3d);
12023 memset(&strided, 0, sizeof(strided));
12025 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, NULL, 0, 0);
12026 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12027 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device,
12028 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, NULL, 0, 0);
12029 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12030 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, NULL, 0, 0);
12031 todo_wine ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
12032 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, NULL, 0, 0);
12033 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12034 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, 0);
12035 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12036 hr = IDirect3DDevice7_DrawPrimitiveStrided(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, 0);
12037 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12038 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, 0);
12039 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12041 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, indices, 4, 0);
12042 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12043 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device,
12044 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, indices, 4, 0);
12045 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12046 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, indices, 4, 0);
12047 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12049 strided.position.lpvData = quad;
12050 strided.position.dwStride = sizeof(*quad);
12051 hr = IDirect3DVertexBuffer7_Lock(vb, 0, &data, NULL);
12052 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
12053 memcpy(data, quad, sizeof(quad));
12054 hr = IDirect3DVertexBuffer7_Unlock(vb);
12055 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
12057 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, NULL, 0, 0);
12058 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12059 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device,
12060 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, NULL, 0, 0);
12061 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12062 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, NULL, 0, 0);
12063 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12064 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
12065 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12066 hr = IDirect3DDevice7_DrawPrimitiveStrided(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, 0);
12067 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12068 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, 0);
12069 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12071 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, indices, 4, 0);
12072 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12073 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device,
12074 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, indices, 4, 0);
12075 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12076 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, indices, 4, 0);
12077 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12079 IDirect3DVertexBuffer7_Release(vb);
12080 refcount = IDirect3DDevice7_Release(device);
12081 ok(!refcount, "Device has %u references left.\n", refcount);
12082 DestroyWindow(window);
12085 static void test_edge_antialiasing_blending(void)
12087 IDirectDrawSurface7 *offscreen;
12088 DDSURFACEDESC2 surface_desc;
12089 D3DDEVICEDESC7 device_desc;
12090 IDirect3DDevice7 *device;
12091 IDirectDraw7 *ddraw;
12092 IDirect3D7 *d3d;
12093 ULONG refcount;
12094 D3DCOLOR color;
12095 HWND window;
12096 HRESULT hr;
12098 static D3DMATRIX mat =
12100 1.0f, 0.0f, 0.0f, 0.0f,
12101 0.0f, 1.0f, 0.0f, 0.0f,
12102 0.0f, 0.0f, 1.0f, 0.0f,
12103 0.0f, 0.0f, 0.0f, 1.0f,
12105 static struct
12107 struct vec3 position;
12108 DWORD diffuse;
12110 green_quad[] =
12112 {{-1.0f, -1.0f, 0.1f}, 0x7f00ff00},
12113 {{-1.0f, 1.0f, 0.1f}, 0x7f00ff00},
12114 {{ 1.0f, -1.0f, 0.1f}, 0x7f00ff00},
12115 {{ 1.0f, 1.0f, 0.1f}, 0x7f00ff00},
12117 static struct
12119 struct vec3 position;
12120 DWORD diffuse;
12122 red_quad[] =
12124 {{-1.0f, -1.0f, 0.1f}, 0xccff0000},
12125 {{-1.0f, 1.0f, 0.1f}, 0xccff0000},
12126 {{ 1.0f, -1.0f, 0.1f}, 0xccff0000},
12127 {{ 1.0f, 1.0f, 0.1f}, 0xccff0000},
12130 window = create_window();
12131 if (!(device = create_device(window, DDSCL_NORMAL)))
12133 skip("Failed to create a 3D device.\n");
12134 DestroyWindow(window);
12135 return;
12138 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
12139 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
12140 trace("Line edge antialiasing support: %#x.\n",
12141 device_desc.dpcLineCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
12142 trace("Triangle edge antialiasing support: %#x.\n",
12143 device_desc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
12145 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
12146 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
12147 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
12148 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
12149 IDirect3D7_Release(d3d);
12151 memset(&surface_desc, 0, sizeof(surface_desc));
12152 surface_desc.dwSize = sizeof(surface_desc);
12153 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
12154 surface_desc.dwWidth = 640;
12155 surface_desc.dwHeight = 480;
12156 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
12157 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
12158 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
12159 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
12160 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
12161 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
12162 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
12163 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
12164 ok(hr == D3D_OK, "Creating the offscreen render target failed, hr %#x.\n", hr);
12166 hr = IDirect3DDevice7_SetRenderTarget(device, offscreen, 0);
12167 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
12169 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
12170 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
12171 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
12172 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
12173 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
12174 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
12175 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
12176 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
12177 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
12178 ok(SUCCEEDED(hr), "Failed to disable Z test, hr %#x.\n", hr);
12179 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
12180 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
12181 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
12182 ok(SUCCEEDED(hr), "Failed to disable stencil test, hr %#x.\n", hr);
12183 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
12184 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
12185 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
12186 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
12188 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
12189 ok(SUCCEEDED(hr), "Failed to enable blending, hr %#x.\n", hr);
12190 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
12191 ok(SUCCEEDED(hr), "Failed to set src blend, hr %#x.\n", hr);
12192 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_DESTALPHA);
12193 ok(SUCCEEDED(hr), "Failed to set dest blend, hr %#x.\n", hr);
12195 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
12196 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
12197 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
12198 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
12199 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
12200 ok(SUCCEEDED(hr), "Failed to set alpha op, hr %#x.\n", hr);
12201 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
12202 ok(SUCCEEDED(hr), "Failed to set alpha arg, hr %#x.\n", hr);
12204 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
12205 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12206 hr = IDirect3DDevice7_BeginScene(device);
12207 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12208 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12209 green_quad, 4, 0);
12210 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12211 hr = IDirect3DDevice7_EndScene(device);
12212 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12213 color = get_surface_color(offscreen, 320, 240);
12214 ok(compare_color(color, 0x00cc7f00, 1), "Got unexpected color 0x%08x.\n", color);
12216 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
12217 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12218 hr = IDirect3DDevice7_BeginScene(device);
12219 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12220 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12221 red_quad, 4, 0);
12222 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12223 hr = IDirect3DDevice7_EndScene(device);
12224 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12225 color = get_surface_color(offscreen, 320, 240);
12226 ok(compare_color(color, 0x00cc7f00, 1), "Got unexpected color 0x%08x.\n", color);
12228 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
12229 ok(SUCCEEDED(hr), "Failed to disable blending, hr %#x.\n", hr);
12231 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
12232 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12233 hr = IDirect3DDevice7_BeginScene(device);
12234 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12235 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12236 green_quad, 4, 0);
12237 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12238 hr = IDirect3DDevice7_EndScene(device);
12239 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12240 color = get_surface_color(offscreen, 320, 240);
12241 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12243 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
12244 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12245 hr = IDirect3DDevice7_BeginScene(device);
12246 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12247 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12248 red_quad, 4, 0);
12249 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12250 hr = IDirect3DDevice7_EndScene(device);
12251 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12252 color = get_surface_color(offscreen, 320, 240);
12253 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
12255 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_EDGEANTIALIAS, TRUE);
12256 ok(SUCCEEDED(hr), "Failed to enable edge antialiasing, hr %#x.\n", hr);
12258 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
12259 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12260 hr = IDirect3DDevice7_BeginScene(device);
12261 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12262 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12263 green_quad, 4, 0);
12264 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12265 hr = IDirect3DDevice7_EndScene(device);
12266 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12267 color = get_surface_color(offscreen, 320, 240);
12268 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12270 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
12271 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12272 hr = IDirect3DDevice7_BeginScene(device);
12273 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12274 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12275 red_quad, 4, 0);
12276 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12277 hr = IDirect3DDevice7_EndScene(device);
12278 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12279 color = get_surface_color(offscreen, 320, 240);
12280 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
12282 IDirectDrawSurface7_Release(offscreen);
12283 IDirectDraw7_Release(ddraw);
12284 refcount = IDirect3DDevice7_Release(device);
12285 ok(!refcount, "Device has %u references left.\n", refcount);
12286 DestroyWindow(window);
12289 static void test_display_mode_surface_pixel_format(void)
12291 unsigned int width, height, bpp;
12292 IDirectDrawSurface7 *surface;
12293 DDSURFACEDESC2 surface_desc;
12294 IDirectDraw7 *ddraw;
12295 ULONG refcount;
12296 HWND window;
12297 HRESULT hr;
12299 if (!(ddraw = create_ddraw()))
12301 skip("Failed to create ddraw.\n");
12302 return;
12305 surface_desc.dwSize = sizeof(surface_desc);
12306 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
12307 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr);
12308 width = surface_desc.dwWidth;
12309 height = surface_desc.dwHeight;
12311 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
12312 0, 0, width, height, NULL, NULL, NULL, NULL);
12313 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
12314 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12316 bpp = 0;
12317 if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 16, 0, 0)))
12318 bpp = 16;
12319 if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 24, 0, 0)))
12320 bpp = 24;
12321 if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
12322 bpp = 32;
12323 ok(bpp, "Set display mode failed.\n");
12325 surface_desc.dwSize = sizeof(surface_desc);
12326 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
12327 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr);
12328 ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width);
12329 ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height);
12330 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
12331 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
12333 memset(&surface_desc, 0, sizeof(surface_desc));
12334 surface_desc.dwSize = sizeof(surface_desc);
12335 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
12336 U5(surface_desc).dwBackBufferCount = 1;
12337 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE;
12338 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12339 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
12340 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
12341 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
12342 ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width);
12343 ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height);
12344 ok(U4(surface_desc).ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n",
12345 U4(surface_desc).ddpfPixelFormat.dwFlags);
12346 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
12347 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
12348 IDirectDrawSurface7_Release(surface);
12350 memset(&surface_desc, 0, sizeof(surface_desc));
12351 surface_desc.dwSize = sizeof(surface_desc);
12352 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
12353 surface_desc.dwWidth = width;
12354 surface_desc.dwHeight = height;
12355 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12356 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12357 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
12358 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
12359 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
12360 ok(U4(surface_desc).ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n",
12361 U4(surface_desc).ddpfPixelFormat.dwFlags);
12362 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
12363 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
12364 IDirectDrawSurface7_Release(surface);
12366 refcount = IDirectDraw7_Release(ddraw);
12367 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
12368 DestroyWindow(window);
12371 static void test_surface_desc_size(void)
12373 union
12375 DWORD dwSize;
12376 DDSURFACEDESC desc1;
12377 DDSURFACEDESC2 desc2;
12378 BYTE blob[1024];
12379 } desc;
12380 IDirectDrawSurface7 *surface7;
12381 IDirectDrawSurface3 *surface3;
12382 IDirectDrawSurface *surface;
12383 DDSURFACEDESC2 surface_desc;
12384 HRESULT expected_hr, hr;
12385 IDirectDraw7 *ddraw;
12386 unsigned int i, j;
12387 ULONG refcount;
12389 static const struct
12391 unsigned int caps;
12392 const char *name;
12394 surface_caps[] =
12396 {DDSCAPS_OFFSCREENPLAIN, "offscreenplain"},
12397 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, "systemmemory texture"},
12398 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, "videomemory texture"},
12400 static const unsigned int desc_sizes[] =
12402 sizeof(DDSURFACEDESC),
12403 sizeof(DDSURFACEDESC2),
12404 sizeof(DDSURFACEDESC) + 1,
12405 sizeof(DDSURFACEDESC2) + 1,
12406 2 * sizeof(DDSURFACEDESC),
12407 2 * sizeof(DDSURFACEDESC2),
12408 sizeof(DDSURFACEDESC) - 1,
12409 sizeof(DDSURFACEDESC2) - 1,
12410 sizeof(DDSURFACEDESC) / 2,
12411 sizeof(DDSURFACEDESC2) / 2,
12415 sizeof(desc) / 2,
12416 sizeof(desc) - 100,
12419 if (!(ddraw = create_ddraw()))
12421 skip("Failed to create ddraw.\n");
12422 return;
12424 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
12425 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12427 for (i = 0; i < ARRAY_SIZE(surface_caps); ++i)
12429 memset(&surface_desc, 0, sizeof(surface_desc));
12430 surface_desc.dwSize = sizeof(surface_desc);
12431 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
12432 surface_desc.ddsCaps.dwCaps = surface_caps[i].caps;
12433 surface_desc.dwHeight = 128;
12434 surface_desc.dwWidth = 128;
12435 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface7, NULL)))
12437 skip("Failed to create surface, type %s.\n", surface_caps[i].name);
12438 continue;
12440 hr = IDirectDrawSurface_QueryInterface(surface7, &IID_IDirectDrawSurface, (void **)&surface);
12441 ok(hr == DD_OK, "Failed to query IDirectDrawSurface, hr %#x, type %s.\n", hr, surface_caps[i].name);
12442 hr = IDirectDrawSurface_QueryInterface(surface7, &IID_IDirectDrawSurface3, (void **)&surface3);
12443 ok(hr == DD_OK, "Failed to query IDirectDrawSurface3, hr %#x, type %s.\n", hr, surface_caps[i].name);
12445 /* GetSurfaceDesc() */
12446 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
12448 memset(&desc, 0, sizeof(desc));
12449 desc.dwSize = desc_sizes[j];
12450 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC) ? DD_OK : DDERR_INVALIDPARAMS;
12451 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &desc.desc1);
12452 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
12453 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
12455 memset(&desc, 0, sizeof(desc));
12456 desc.dwSize = desc_sizes[j];
12457 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC) ? DD_OK : DDERR_INVALIDPARAMS;
12458 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &desc.desc1);
12459 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
12460 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
12462 memset(&desc, 0, sizeof(desc));
12463 desc.dwSize = desc_sizes[j];
12464 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC2) ? DD_OK : DDERR_INVALIDPARAMS;
12465 hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &desc.desc2);
12466 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
12467 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
12470 /* Lock() */
12471 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
12473 const BOOL ignore_size = surface_caps[i].caps & DDSCAPS_TEXTURE
12474 && !(surface_caps[i].caps & DDSCAPS_VIDEOMEMORY);
12475 const BOOL valid_size = desc_sizes[j] == sizeof(DDSURFACEDESC)
12476 || desc_sizes[j] == sizeof(DDSURFACEDESC2);
12477 DWORD expected_texture_stage;
12479 memset(&desc, 0, sizeof(desc));
12480 desc.dwSize = desc_sizes[j];
12481 desc.desc2.dwTextureStage = 0xdeadbeef;
12482 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
12483 hr = IDirectDrawSurface_Lock(surface, NULL, &desc.desc1, 0, 0);
12484 expected_hr = ignore_size || valid_size ? DD_OK : DDERR_INVALIDPARAMS;
12485 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
12486 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
12487 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
12488 desc_sizes[j], desc.dwSize, surface_caps[i].name);
12489 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
12490 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
12491 if (SUCCEEDED(hr))
12493 ok(desc.desc1.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
12494 desc.desc1.dwWidth, desc_sizes[j], surface_caps[i].name);
12495 ok(desc.desc1.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
12496 desc.desc1.dwHeight, desc_sizes[j], surface_caps[i].name);
12497 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
12498 todo_wine_if(!expected_texture_stage)
12499 ok(desc.desc2.dwTextureStage == expected_texture_stage,
12500 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
12501 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
12502 IDirectDrawSurface_Unlock(surface, NULL);
12505 memset(&desc, 0, sizeof(desc));
12506 desc.dwSize = desc_sizes[j];
12507 desc.desc2.dwTextureStage = 0xdeadbeef;
12508 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
12509 hr = IDirectDrawSurface3_Lock(surface3, NULL, &desc.desc1, 0, 0);
12510 expected_hr = ignore_size || valid_size ? DD_OK : DDERR_INVALIDPARAMS;
12511 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
12512 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
12513 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
12514 desc_sizes[j], desc.dwSize, surface_caps[i].name);
12515 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
12516 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
12517 if (SUCCEEDED(hr))
12519 ok(desc.desc1.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
12520 desc.desc1.dwWidth, desc_sizes[j], surface_caps[i].name);
12521 ok(desc.desc1.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
12522 desc.desc1.dwHeight, desc_sizes[j], surface_caps[i].name);
12523 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
12524 todo_wine_if(!expected_texture_stage)
12525 ok(desc.desc2.dwTextureStage == expected_texture_stage,
12526 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
12527 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
12528 IDirectDrawSurface3_Unlock(surface3, NULL);
12531 memset(&desc, 0, sizeof(desc));
12532 desc.dwSize = desc_sizes[j];
12533 desc.desc2.dwTextureStage = 0xdeadbeef;
12534 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
12535 hr = IDirectDrawSurface7_Lock(surface7, NULL, &desc.desc2, 0, 0);
12536 expected_hr = ignore_size || valid_size ? DD_OK : DDERR_INVALIDPARAMS;
12537 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
12538 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
12539 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
12540 desc_sizes[j], desc.dwSize, surface_caps[i].name);
12541 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
12542 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
12543 if (SUCCEEDED(hr))
12545 ok(desc.desc2.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
12546 desc.desc2.dwWidth, desc_sizes[j], surface_caps[i].name);
12547 ok(desc.desc2.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
12548 desc.desc2.dwHeight, desc_sizes[j], surface_caps[i].name);
12549 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
12550 ok(desc.desc2.dwTextureStage == expected_texture_stage,
12551 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
12552 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
12553 IDirectDrawSurface7_Unlock(surface7, NULL);
12557 IDirectDrawSurface7_Release(surface7);
12558 IDirectDrawSurface3_Release(surface3);
12559 IDirectDrawSurface_Release(surface);
12562 /* GetDisplayMode() */
12563 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
12565 memset(&desc, 0xcc, sizeof(desc));
12566 desc.dwSize = desc_sizes[j];
12567 expected_hr = (desc.dwSize == sizeof(DDSURFACEDESC) || desc.dwSize == sizeof(DDSURFACEDESC2))
12568 ? DD_OK : DDERR_INVALIDPARAMS;
12569 hr = IDirectDraw7_GetDisplayMode(ddraw, &desc.desc2);
12570 ok(hr == expected_hr, "Got hr %#x, expected %#x, size %u.\n", hr, expected_hr, desc_sizes[j]);
12571 if (SUCCEEDED(hr))
12573 ok(desc.dwSize == sizeof(DDSURFACEDESC2), "Wrong size %u for %u.\n", desc.dwSize, desc_sizes[j]);
12574 ok(desc.blob[desc_sizes[j]] == 0xcc, "Overflow for size %u.\n", desc_sizes[j]);
12575 ok(desc.blob[desc_sizes[j] - 1] != 0xcc, "Struct not cleared for size %u.\n", desc_sizes[j]);
12579 refcount = IDirectDraw7_Release(ddraw);
12580 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
12583 static void test_get_surface_from_dc(void)
12585 IDirectDrawSurface *surface1, *tmp1;
12586 IDirectDrawSurface7 *surface, *tmp;
12587 DDSURFACEDESC2 surface_desc;
12588 IDirectDraw7 *ddraw;
12589 HDC dc, device_dc;
12590 ULONG refcount;
12591 HWND window;
12592 HRESULT hr;
12593 DWORD ret;
12595 window = create_window();
12596 ddraw = create_ddraw();
12597 ok(!!ddraw, "Failed to create a ddraw object.\n");
12598 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12599 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12601 memset(&surface_desc, 0, sizeof(surface_desc));
12602 surface_desc.dwSize = sizeof(surface_desc);
12603 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
12604 surface_desc.dwWidth = 64;
12605 surface_desc.dwHeight = 64;
12606 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12608 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12609 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12610 hr = IDirectDrawSurface7_QueryInterface(surface, &IID_IDirectDrawSurface, (void **)&surface1);
12611 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
12613 refcount = get_refcount((IUnknown *)surface1);
12614 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
12615 refcount = get_refcount((IUnknown *)surface);
12616 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
12618 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12619 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
12621 tmp1 = (void *)0xdeadbeef;
12622 device_dc = (void *)0xdeadbeef;
12623 hr = GetSurfaceFromDC(NULL, &tmp1, &device_dc);
12624 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
12625 ok(!tmp1, "Got unexpected surface %p.\n", tmp1);
12626 ok(!device_dc, "Got unexpected device_dc %p.\n", device_dc);
12628 device_dc = (void *)0xdeadbeef;
12629 hr = GetSurfaceFromDC(dc, NULL, &device_dc);
12630 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
12631 ok(device_dc == (void *)0xdeadbeef, "Got unexpected device_dc %p.\n", device_dc);
12633 tmp1 = (void *)0xdeadbeef;
12634 hr = GetSurfaceFromDC(dc, &tmp1, NULL);
12635 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
12636 ok(!tmp1, "Got unexpected surface %p.\n", tmp1);
12638 hr = GetSurfaceFromDC(dc, &tmp1, &device_dc);
12639 ok(SUCCEEDED(hr), "GetSurfaceFromDC failed, hr %#x.\n", hr);
12640 ok(tmp1 == surface1, "Got unexpected surface %p, expected %p.\n", tmp1, surface1);
12641 IDirectDrawSurface_Release(tmp1);
12643 ret = GetObjectType(device_dc);
12644 todo_wine ok(ret == OBJ_DC, "Got unexpected object type %#x.\n", ret);
12645 ret = GetDeviceCaps(device_dc, TECHNOLOGY);
12646 todo_wine ok(ret == DT_RASDISPLAY, "Got unexpected technology %#x.\n", ret);
12648 hr = IDirectDraw7_GetSurfaceFromDC(ddraw, dc, NULL);
12649 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
12651 hr = IDirectDraw7_GetSurfaceFromDC(ddraw, dc, &tmp);
12652 ok(SUCCEEDED(hr), "GetSurfaceFromDC failed, hr %#x.\n", hr);
12653 ok(tmp == surface, "Got unexpected surface %p, expected %p.\n", tmp, surface);
12655 refcount = get_refcount((IUnknown *)surface1);
12656 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
12657 refcount = get_refcount((IUnknown *)surface);
12658 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
12660 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12661 ok(SUCCEEDED(hr), "ReleaseDC failed, hr %#x.\n", hr);
12663 IDirectDrawSurface_Release(tmp);
12665 dc = CreateCompatibleDC(NULL);
12666 ok(!!dc, "CreateCompatibleDC failed.\n");
12668 tmp1 = (void *)0xdeadbeef;
12669 device_dc = (void *)0xdeadbeef;
12670 hr = GetSurfaceFromDC(dc, &tmp1, &device_dc);
12671 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
12672 ok(!tmp1, "Got unexpected surface %p.\n", tmp1);
12673 ok(!device_dc, "Got unexpected device_dc %p.\n", device_dc);
12675 tmp = (void *)0xdeadbeef;
12676 hr = IDirectDraw7_GetSurfaceFromDC(ddraw, dc, &tmp);
12677 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
12678 ok(!tmp, "Got unexpected surface %p.\n", tmp);
12680 ok(DeleteDC(dc), "DeleteDC failed.\n");
12682 tmp = (void *)0xdeadbeef;
12683 hr = IDirectDraw7_GetSurfaceFromDC(ddraw, NULL, &tmp);
12684 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
12685 ok(!tmp, "Got unexpected surface %p.\n", tmp);
12687 IDirectDrawSurface7_Release(surface);
12688 IDirectDrawSurface_Release(surface1);
12689 IDirectDraw7_Release(ddraw);
12690 DestroyWindow(window);
12693 static void test_ck_operation(void)
12695 IDirectDrawSurface7 *src, *dst;
12696 IDirectDrawSurface *src1, *dst1;
12697 DDSURFACEDESC2 surface_desc;
12698 IDirectDraw7 *ddraw;
12699 ULONG refcount;
12700 HWND window;
12701 HRESULT hr;
12702 D3DCOLOR *color;
12703 unsigned int i;
12704 DDCOLORKEY ckey;
12705 DDBLTFX fx;
12707 window = create_window();
12708 ddraw = create_ddraw();
12709 ok(!!ddraw, "Failed to create a ddraw object.\n");
12710 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12711 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12713 memset(&surface_desc, 0, sizeof(surface_desc));
12714 surface_desc.dwSize = sizeof(surface_desc);
12715 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
12716 surface_desc.dwWidth = 4;
12717 surface_desc.dwHeight = 1;
12718 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12719 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
12720 U1(U4(surface_desc.ddpfPixelFormat)).dwRGBBitCount = 32;
12721 U2(U4(surface_desc.ddpfPixelFormat)).dwRBitMask = 0x00ff0000;
12722 U3(U4(surface_desc.ddpfPixelFormat)).dwGBitMask = 0x0000ff00;
12723 U4(U4(surface_desc.ddpfPixelFormat)).dwBBitMask = 0x000000ff;
12724 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
12725 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12727 surface_desc.dwFlags |= DDSD_CKSRCBLT;
12728 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff00ff;
12729 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff00ff;
12730 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
12731 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12733 hr = IDirectDrawSurface7_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12734 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12735 ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n");
12736 color = surface_desc.lpSurface;
12737 color[0] = 0x77010203;
12738 color[1] = 0x00010203;
12739 color[2] = 0x77ff00ff;
12740 color[3] = 0x00ff00ff;
12741 hr = IDirectDrawSurface7_Unlock(src, NULL);
12742 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12744 for (i = 0; i < 2; ++i)
12746 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12747 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12748 color = surface_desc.lpSurface;
12749 color[0] = 0xcccccccc;
12750 color[1] = 0xcccccccc;
12751 color[2] = 0xcccccccc;
12752 color[3] = 0xcccccccc;
12753 hr = IDirectDrawSurface7_Unlock(dst, NULL);
12754 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12756 if (i)
12758 hr = IDirectDrawSurface7_BltFast(dst, 0, 0, src, NULL, DDBLTFAST_SRCCOLORKEY);
12759 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12761 else
12763 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, NULL);
12764 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12767 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT | DDLOCK_READONLY, NULL);
12768 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12769 ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n");
12770 color = surface_desc.lpSurface;
12771 /* Different behavior on some drivers / windows versions. Some versions ignore the X channel when
12772 * color keying, but copy it to the destination surface. Others (sysmem surfaces) apply it for
12773 * color keying, but do not copy it into the destination surface. Nvidia neither uses it for
12774 * color keying nor copies it. */
12775 ok((color[0] == 0x77010203 && color[1] == 0x00010203
12776 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* AMD, Wine */
12777 || broken(color[0] == 0x00010203 && color[1] == 0x00010203
12778 && color[2] == 0x00ff00ff && color[3] == 0xcccccccc) /* Sysmem surfaces? */
12779 || broken(color[0] == 0x00010203 && color[1] == 0x00010203
12780 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Nvidia */
12781 || broken(color[0] == 0xff010203 && color[1] == 0xff010203
12782 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Testbot */,
12783 "Destination data after blitting is %08x %08x %08x %08x, i=%u.\n",
12784 color[0], color[1], color[2], color[3], i);
12785 hr = IDirectDrawSurface7_Unlock(dst, NULL);
12786 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12789 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
12790 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
12791 ok(ckey.dwColorSpaceLowValue == 0x00ff00ff && ckey.dwColorSpaceHighValue == 0x00ff00ff,
12792 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
12794 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
12795 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
12796 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12798 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
12799 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
12800 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
12801 ok(ckey.dwColorSpaceLowValue == 0x0000ff00 && ckey.dwColorSpaceHighValue == 0x0000ff00,
12802 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
12804 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0;
12805 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0;
12806 hr = IDirectDrawSurface7_GetSurfaceDesc(src, &surface_desc);
12807 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
12808 ok(surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue == 0x0000ff00
12809 && surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue == 0x0000ff00,
12810 "Got unexpected color key low=%08x high=%08x.\n", surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue,
12811 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue);
12813 /* Test SetColorKey with dwColorSpaceHighValue < dwColorSpaceLowValue */
12814 ckey.dwColorSpaceLowValue = 0x000000ff;
12815 ckey.dwColorSpaceHighValue = 0x00000000;
12816 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
12817 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12819 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
12820 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
12821 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
12822 ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff,
12823 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
12825 ckey.dwColorSpaceLowValue = 0x000000ff;
12826 ckey.dwColorSpaceHighValue = 0x00000001;
12827 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
12828 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12830 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
12831 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
12832 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
12833 ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff,
12834 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
12836 ckey.dwColorSpaceLowValue = 0x000000fe;
12837 ckey.dwColorSpaceHighValue = 0x000000fd;
12838 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
12839 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12841 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
12842 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
12843 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
12844 ok(ckey.dwColorSpaceLowValue == 0x000000fe && ckey.dwColorSpaceHighValue == 0x000000fe,
12845 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
12847 IDirectDrawSurface7_Release(src);
12848 IDirectDrawSurface7_Release(dst);
12850 /* Test source and destination keys and where they are read from. Use a surface with alpha
12851 * to avoid driver-dependent content in the X channel. */
12852 memset(&surface_desc, 0, sizeof(surface_desc));
12853 surface_desc.dwSize = sizeof(surface_desc);
12854 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
12855 surface_desc.dwWidth = 6;
12856 surface_desc.dwHeight = 1;
12857 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12858 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
12859 U1(U4(surface_desc.ddpfPixelFormat)).dwRGBBitCount = 32;
12860 U2(U4(surface_desc.ddpfPixelFormat)).dwRBitMask = 0x00ff0000;
12861 U3(U4(surface_desc.ddpfPixelFormat)).dwGBitMask = 0x0000ff00;
12862 U4(U4(surface_desc.ddpfPixelFormat)).dwBBitMask = 0x000000ff;
12863 U5(U4(surface_desc.ddpfPixelFormat)).dwRGBAlphaBitMask = 0xff000000;
12864 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
12865 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12866 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
12867 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12869 ckey.dwColorSpaceLowValue = 0x0000ff00;
12870 ckey.dwColorSpaceHighValue = 0x0000ff00;
12871 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
12872 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12873 ckey.dwColorSpaceLowValue = 0x00ff0000;
12874 ckey.dwColorSpaceHighValue = 0x00ff0000;
12875 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_DESTBLT, &ckey);
12876 ok(SUCCEEDED(hr) || hr == DDERR_NOCOLORKEYHW, "Failed to set color key, hr %#x.\n", hr);
12877 if (FAILED(hr))
12879 /* Nvidia reject dest keys, AMD allows them. This applies to vidmem and sysmem surfaces. */
12880 skip("Failed to set destination color key, skipping related tests.\n");
12881 goto done;
12884 ckey.dwColorSpaceLowValue = 0x000000ff;
12885 ckey.dwColorSpaceHighValue = 0x000000ff;
12886 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
12887 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12888 ckey.dwColorSpaceLowValue = 0x000000aa;
12889 ckey.dwColorSpaceHighValue = 0x000000aa;
12890 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_DESTBLT, &ckey);
12891 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12893 memset(&fx, 0, sizeof(fx));
12894 fx.dwSize = sizeof(fx);
12895 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x00110000;
12896 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x00110000;
12897 fx.ddckDestColorkey.dwColorSpaceHighValue = 0x00001100;
12898 fx.ddckDestColorkey.dwColorSpaceLowValue = 0x00001100;
12900 hr = IDirectDrawSurface7_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12901 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12902 color = surface_desc.lpSurface;
12903 color[0] = 0x000000ff; /* Applies to src blt key in src surface. */
12904 color[1] = 0x000000aa; /* Applies to dst blt key in src surface. */
12905 color[2] = 0x00ff0000; /* Dst color key in dst surface. */
12906 color[3] = 0x0000ff00; /* Src color key in dst surface. */
12907 color[4] = 0x00001100; /* Src color key in ddbltfx. */
12908 color[5] = 0x00110000; /* Dst color key in ddbltfx. */
12909 hr = IDirectDrawSurface7_Unlock(src, NULL);
12910 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12912 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12913 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12914 color = surface_desc.lpSurface;
12915 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
12916 hr = IDirectDrawSurface7_Unlock(dst, NULL);
12917 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12919 /* Test a blit without keying. */
12920 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, 0, &fx);
12921 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12923 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12924 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12925 color = surface_desc.lpSurface;
12926 /* Should have copied src data unmodified to dst. */
12927 ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
12928 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
12929 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12930 color[0], color[1], color[2], color[3], color[4], color[5]);
12932 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
12933 hr = IDirectDrawSurface7_Unlock(dst, NULL);
12934 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12936 /* Src key. */
12937 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx);
12938 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12940 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12941 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12942 color = surface_desc.lpSurface;
12943 /* Src key applied to color[0]. It is unmodified, the others are copied. */
12944 ok(color[0] == 0x55555555 && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
12945 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
12946 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12947 color[0], color[1], color[2], color[3], color[4], color[5]);
12949 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
12950 hr = IDirectDrawSurface7_Unlock(dst, NULL);
12951 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12953 /* Src override. */
12954 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, &fx);
12955 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12957 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12958 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12959 color = surface_desc.lpSurface;
12960 /* Override key applied to color[5]. It is unmodified, the others are copied. */
12961 ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
12962 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x55555555,
12963 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12964 color[0], color[1], color[2], color[3], color[4], color[5]);
12966 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
12967 hr = IDirectDrawSurface7_Unlock(dst, NULL);
12968 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12970 /* Src override AND src key. That is not supposed to work. */
12971 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE, &fx);
12972 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
12974 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12975 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12976 color = surface_desc.lpSurface;
12977 /* Ensure the destination was not changed. */
12978 ok(color[0] == 0x55555555 && color[1] == 0x55555555 && color[2] == 0x55555555 &&
12979 color[3] == 0x55555555 && color[4] == 0x55555555 && color[5] == 0x55555555,
12980 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
12981 color[0], color[1], color[2], color[3], color[4], color[5]);
12983 /* Use different dst colors for the dst key test. */
12984 color[0] = 0x00ff0000; /* Dest key in dst surface. */
12985 color[1] = 0x00ff0000; /* Dest key in dst surface. */
12986 color[2] = 0x00001100; /* Dest key in override. */
12987 color[3] = 0x00001100; /* Dest key in override. */
12988 color[4] = 0x000000aa; /* Dest key in src surface. */
12989 color[5] = 0x000000aa; /* Dest key in src surface. */
12990 hr = IDirectDrawSurface7_Unlock(dst, NULL);
12991 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12993 /* Dest key blit. The key is taken from the DESTINATION surface in v7! */
12994 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
12995 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12997 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
12998 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12999 color = surface_desc.lpSurface;
13000 /* Dst key applied to color[0,1], they are the only changed pixels. */
13001 todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 &&
13002 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
13003 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13004 color[0], color[1], color[2], color[3], color[4], color[5]);
13006 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13007 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13008 color[2] = 0x00001100; /* Dest key in override. */
13009 color[3] = 0x00001100; /* Dest key in override. */
13010 color[4] = 0x000000aa; /* Dest key in src surface. */
13011 color[5] = 0x000000aa; /* Dest key in src surface. */
13012 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13013 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13015 /* What happens with a QI'd older version of the interface? It takes the key
13016 * from the source surface. */
13017 hr = IDirectDrawSurface7_QueryInterface(src, &IID_IDirectDrawSurface, (void **)&src1);
13018 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
13019 hr = IDirectDrawSurface7_QueryInterface(dst, &IID_IDirectDrawSurface, (void **)&dst1);
13020 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
13022 hr = IDirectDrawSurface_Blt(dst1, NULL, src1, NULL, DDBLT_KEYDEST, &fx);
13023 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13025 IDirectDrawSurface_Release(dst1);
13026 IDirectDrawSurface_Release(src1);
13028 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13029 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13030 color = surface_desc.lpSurface;
13031 /* Dst key applied to color[4,5], they are the only changed pixels. */
13032 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
13033 color[3] == 0x00001100 && color[4] == 0x00001100 && color[5] == 0x00110000,
13034 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13035 color[0], color[1], color[2], color[3], color[4], color[5]);
13037 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13038 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13039 color[2] = 0x00001100; /* Dest key in override. */
13040 color[3] = 0x00001100; /* Dest key in override. */
13041 color[4] = 0x000000aa; /* Dest key in src surface. */
13042 color[5] = 0x000000aa; /* Dest key in src surface. */
13043 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13044 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13046 /* Dest override key blit. */
13047 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, &fx);
13048 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13050 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13051 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13052 color = surface_desc.lpSurface;
13053 /* Dst key applied to color[2,3], they are the only changed pixels. */
13054 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00ff0000 &&
13055 color[3] == 0x0000ff00 && color[4] == 0x000000aa && color[5] == 0x000000aa,
13056 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13057 color[0], color[1], color[2], color[3], color[4], color[5]);
13059 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13060 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13061 color[2] = 0x00001100; /* Dest key in override. */
13062 color[3] = 0x00001100; /* Dest key in override. */
13063 color[4] = 0x000000aa; /* Dest key in src surface. */
13064 color[5] = 0x000000aa; /* Dest key in src surface. */
13065 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13066 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13068 /* Dest override together with surface key. Supposed to fail. */
13069 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYDESTOVERRIDE, &fx);
13070 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13072 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13073 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13074 color = surface_desc.lpSurface;
13075 /* Destination is unchanged. */
13076 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
13077 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
13078 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13079 color[0], color[1], color[2], color[3], color[4], color[5]);
13080 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13081 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13083 /* Source and destination key. This is driver dependent. New HW treats it like
13084 * DDBLT_KEYSRC. Older HW and some software renderers apply both keys. */
13085 if (0)
13087 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYSRC, &fx);
13088 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13090 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13091 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13092 color = surface_desc.lpSurface;
13093 /* Color[0] is filtered by the src key, 2-5 are filtered by the dst key, if
13094 * the driver applies it. */
13095 ok(color[0] == 0x00ff0000 && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
13096 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
13097 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13098 color[0], color[1], color[2], color[3], color[4], color[5]);
13100 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13101 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13102 color[2] = 0x00001100; /* Dest key in override. */
13103 color[3] = 0x00001100; /* Dest key in override. */
13104 color[4] = 0x000000aa; /* Dest key in src surface. */
13105 color[5] = 0x000000aa; /* Dest key in src surface. */
13106 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13107 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13110 /* Override keys without ddbltfx parameter fail */
13111 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, NULL);
13112 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13113 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, NULL);
13114 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13116 /* Try blitting without keys in the source surface. */
13117 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, NULL);
13118 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13119 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_DESTBLT, NULL);
13120 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13122 /* That fails now. Do not bother to check that the data is unmodified. */
13123 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx);
13124 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13126 /* Dest key blit still works, the destination surface key is used in v7. */
13127 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
13128 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13130 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13131 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13132 color = surface_desc.lpSurface;
13133 /* Dst key applied to color[0,1], they are the only changed pixels. */
13134 todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 &&
13135 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
13136 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13137 color[0], color[1], color[2], color[3], color[4], color[5]);
13138 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13139 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13141 /* Try blitting without keys in the destination surface. */
13142 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_SRCBLT, NULL);
13143 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13144 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_DESTBLT, NULL);
13145 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13147 /* This fails, as sanity would dictate. */
13148 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
13149 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13151 done:
13152 IDirectDrawSurface7_Release(src);
13153 IDirectDrawSurface7_Release(dst);
13154 refcount = IDirectDraw7_Release(ddraw);
13155 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
13156 DestroyWindow(window);
13159 static void test_vb_refcount(void)
13161 ULONG prev_d3d_refcount, prev_device_refcount;
13162 ULONG cur_d3d_refcount, cur_device_refcount;
13163 IDirect3DVertexBuffer7 *vb, *vb7;
13164 D3DVERTEXBUFFERDESC vb_desc;
13165 IDirect3DVertexBuffer *vb1;
13166 IDirect3DDevice7 *device;
13167 IDirect3D7 *d3d;
13168 ULONG refcount;
13169 IUnknown *unk;
13170 HWND window;
13171 HRESULT hr;
13173 window = create_window();
13174 if (!(device = create_device(window, DDSCL_NORMAL)))
13176 skip("Failed to create a 3D device, skipping test.\n");
13177 DestroyWindow(window);
13178 return;
13181 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
13182 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
13184 prev_d3d_refcount = get_refcount((IUnknown *)d3d);
13185 prev_device_refcount = get_refcount((IUnknown *)device);
13187 memset(&vb_desc, 0, sizeof(vb_desc));
13188 vb_desc.dwSize = sizeof(vb_desc);
13189 vb_desc.dwFVF = D3DFVF_XYZ;
13190 vb_desc.dwNumVertices = 4;
13191 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &vb, 0);
13192 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
13194 cur_d3d_refcount = get_refcount((IUnknown *)d3d);
13195 cur_device_refcount = get_refcount((IUnknown *)device);
13196 ok(cur_d3d_refcount > prev_d3d_refcount, "D3D object refcount didn't change from %u.\n", prev_d3d_refcount);
13197 ok(cur_device_refcount == prev_device_refcount, "Device refcount changed from %u to %u.\n",
13198 prev_device_refcount, cur_device_refcount);
13200 prev_d3d_refcount = cur_d3d_refcount;
13201 hr = IDirect3DVertexBuffer7_QueryInterface(vb, &IID_IDirect3DVertexBuffer7, (void **)&vb7);
13202 ok(hr == DD_OK, "Failed to query IDirect3DVertexBuffer7, hr %#x.\n", hr);
13203 cur_d3d_refcount = get_refcount((IUnknown *)d3d);
13204 ok(cur_d3d_refcount == prev_d3d_refcount, "D3D object refcount changed from %u to %u.\n",
13205 prev_d3d_refcount, cur_d3d_refcount);
13206 IDirect3DVertexBuffer7_Release(vb7);
13208 hr = IDirect3DVertexBuffer7_QueryInterface(vb, &IID_IDirect3DVertexBuffer, (void **)&vb1);
13209 ok(hr == E_NOINTERFACE, "Querying IDirect3DVertexBuffer returned unexpected hr %#x.\n", hr);
13211 hr = IDirect3DVertexBuffer_QueryInterface(vb, &IID_IUnknown, (void **)&unk);
13212 ok(hr == DD_OK, "Failed to query IUnknown, hr %#x.\n", hr);
13213 ok((IUnknown *)vb == unk,
13214 "IDirect3DVertexBuffer7 and IUnknown interface pointers don't match, %p != %p.\n", vb, unk);
13215 IUnknown_Release(unk);
13217 refcount = IDirect3DVertexBuffer7_Release(vb);
13218 ok(!refcount, "Vertex buffer has %u references left.\n", refcount);
13220 IDirect3D7_Release(d3d);
13221 refcount = IDirect3DDevice7_Release(device);
13222 ok(!refcount, "Device has %u references left.\n", refcount);
13223 DestroyWindow(window);
13226 static void test_compute_sphere_visibility(void)
13228 static D3DVALUE clip_plane[4] = {1.0f, 0.0f, 0.0f, 0.5f};
13229 static D3DMATRIX proj_1 =
13231 1.810660f, 0.000000f, 0.000000f, 0.000000f,
13232 0.000000f, 2.414213f, 0.000000f, 0.000000f,
13233 0.000000f, 0.000000f, 1.020408f, 1.000000f,
13234 0.000000f, 0.000000f, -0.102041f, 0.000000f,
13236 static D3DMATRIX proj_2 =
13238 10.0f, 0.0f, 0.0f, 0.0f,
13239 0.0f, 10.0f, 0.0f, 0.0f,
13240 0.0f, 0.0f, 10.0f, 0.0f,
13241 0.0f, 0.0f, 0.0f, 1.0f,
13243 static D3DMATRIX view_1 =
13245 1.000000f, 0.000000f, 0.000000f, 0.000000f,
13246 0.000000f, 0.768221f, -0.640185f, 0.000000f,
13247 -0.000000f, 0.640185f, 0.768221f, 0.000000f,
13248 -14.852037f, 9.857489f, 11.600972f, 1.000000f,
13250 static D3DMATRIX identity =
13252 1.0f, 0.0f, 0.0f, 0.0f,
13253 0.0f, 1.0f, 0.0f, 0.0f,
13254 0.0f, 0.0f, 1.0f, 0.0f,
13255 0.0f, 0.0f, 0.0f, 1.0f,
13257 static struct
13259 D3DMATRIX *view, *proj;
13260 unsigned int sphere_count;
13261 D3DVECTOR center[3];
13262 D3DVALUE radius[3];
13263 DWORD enable_planes;
13264 const DWORD expected[3];
13266 tests[] =
13268 {&view_1, &proj_1, 1, {{{11.461533f}, {-4.761727f}, {-1.171646f}}}, {38.252632f}, 0, {0x3f}},
13269 {&view_1, &proj_1, 3, {{{-3.515620f}, {-1.560661f}, {-12.464638f}},
13270 {{14.290396f}, {-2.981143f}, {-24.311312f}},
13271 {{1.461626f}, {-6.093709f}, {-13.901010f}}},
13272 {4.354097f, 12.500704f, 17.251318f}, 0, {0x103d, 0x3f, 0x3f}},
13273 {&identity, &proj_2, 1, {{{0.0f}, {0.0f}, {0.05f}}}, {0.04f}, 0, {0}},
13274 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.5f}}}, {0.5f}, 0, {0}},
13275 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.0f}}}, {0.0f}, 0, {0}},
13276 {&identity, &identity, 1, {{{-1.0f}, {-1.0f}, {0.5f}}}, {0.25f}, 0, {0x9}}, /* 5 */
13277 {&identity, &identity, 1, {{{-20.0f}, {0.0f}, {0.5f}}}, {3.0f}, 0, {0x103d}},
13278 {&identity, &identity, 1, {{{20.0f}, {0.0f}, {0.5f}}}, {3.0f}, 0, {0x203e}},
13279 {&identity, &identity, 1, {{{0.0f}, {-20.0f}, {0.5f}}}, {3.0f}, 0, {0x803b}},
13280 {&identity, &identity, 1, {{{0.0f}, {20.0f}, {0.5f}}}, {3.0f}, 0, {0x4037}},
13281 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {-20.0f}}}, {3.0f}, 0, {0x1001f}}, /* 10 */
13282 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {20.0f}}}, {3.0f}, 0, {0x2002f}},
13283 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.0f}}}, {5.0f}, 1, {0x7f}},
13284 {&identity, &identity, 1, {{{-0.5f}, {0.0f}, {0.0f}}}, {5.0f}, 1, {0x7f}},
13285 {&identity, &identity, 1, {{{-0.5f}, {0.0f}, {0.0f}}}, {1.0f}, 1, {0x51}},
13286 {&identity, &identity, 1, {{{-2.5f}, {0.0f}, {0.0f}}}, {1.0f}, 1, {0x41051}}, /* 15 */
13288 IDirect3DDevice7 *device;
13289 unsigned int i, j;
13290 DWORD result[3];
13291 ULONG refcount;
13292 HWND window;
13293 HRESULT hr;
13295 window = create_window();
13296 if (!(device = create_device(window, DDSCL_NORMAL)))
13298 skip("Failed to create a 3D device, skipping test.\n");
13299 DestroyWindow(window);
13300 return;
13303 hr = IDirect3DDevice7_SetClipPlane(device, 0, clip_plane);
13304 ok(SUCCEEDED(hr), "Failed to set user clip plane, hr %#x.\n", hr);
13306 IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &identity);
13308 for (i = 0; i < ARRAY_SIZE(tests); ++i)
13310 IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, tests[i].view);
13311 IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, tests[i].proj);
13313 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE,
13314 tests[i].enable_planes);
13315 ok(SUCCEEDED(hr), "Failed to enable / disable user clip planes, hr %#x.\n", hr);
13317 hr = IDirect3DDevice7_ComputeSphereVisibility(device, tests[i].center, tests[i].radius,
13318 tests[i].sphere_count, 0, result);
13319 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13321 for (j = 0; j < tests[i].sphere_count; ++j)
13322 ok(result[j] == tests[i].expected[j], "Test %u sphere %u: expected %#x, got %#x.\n",
13323 i, j, tests[i].expected[j], result[j]);
13326 refcount = IDirect3DDevice7_Release(device);
13327 ok(!refcount, "Device has %u references left.\n", refcount);
13328 DestroyWindow(window);
13331 static void test_clip_planes_limits(void)
13333 IDirect3DDevice7 *device;
13334 D3DDEVICEDESC7 caps;
13335 unsigned int i;
13336 ULONG refcount;
13337 float plane[4];
13338 HWND window;
13339 DWORD state;
13340 HRESULT hr;
13342 window = create_window();
13343 if (!(device = create_device(window, DDSCL_NORMAL)))
13345 skip("Failed to create 3D device.\n");
13346 DestroyWindow(window);
13347 return;
13350 memset(&caps, 0, sizeof(caps));
13351 hr = IDirect3DDevice7_GetCaps(device, &caps);
13352 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
13354 trace("Max user clip planes: %u.\n", caps.wMaxUserClipPlanes);
13356 for (i = 0; i < caps.wMaxUserClipPlanes; ++i)
13358 memset(plane, 0xff, sizeof(plane));
13359 hr = IDirect3DDevice7_GetClipPlane(device, i, plane);
13360 ok(hr == D3D_OK, "Failed to get clip plane %u, hr %#x.\n", i, hr);
13361 ok(!plane[0] && !plane[1] && !plane[2] && !plane[3],
13362 "Got unexpected plane %u: %.8e, %.8e, %.8e, %.8e.\n",
13363 i, plane[0], plane[1], plane[2], plane[3]);
13366 plane[0] = 2.0f;
13367 plane[1] = 8.0f;
13368 plane[2] = 5.0f;
13369 for (i = 0; i < caps.wMaxUserClipPlanes; ++i)
13371 plane[3] = i;
13372 hr = IDirect3DDevice7_SetClipPlane(device, i, plane);
13373 ok(hr == D3D_OK, "Failed to set clip plane %u, hr %#x.\n", i, hr);
13375 for (i = 0; i < caps.wMaxUserClipPlanes; ++i)
13377 memset(plane, 0xff, sizeof(plane));
13378 hr = IDirect3DDevice7_GetClipPlane(device, i, plane);
13379 ok(hr == D3D_OK, "Failed to get clip plane %u, hr %#x.\n", i, hr);
13380 ok(plane[0] == 2.0f && plane[1] == 8.0f && plane[2] == 5.0f && plane[3] == i,
13381 "Got unexpected plane %u: %.8e, %.8e, %.8e, %.8e.\n",
13382 i, plane[0], plane[1], plane[2], plane[3]);
13385 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE, 0xffffffff);
13386 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
13387 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE, &state);
13388 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
13389 ok(state == 0xffffffff, "Got unexpected state %#x.\n", state);
13390 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE, 0x80000000);
13391 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
13392 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE, &state);
13393 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
13394 ok(state == 0x80000000, "Got unexpected state %#x.\n", state);
13396 refcount = IDirect3DDevice7_Release(device);
13397 ok(!refcount, "Device has %u references left.\n", refcount);
13398 DestroyWindow(window);
13401 static void test_texture_stages_limits(void)
13403 IDirectDrawSurface7 *texture;
13404 DDSURFACEDESC2 surface_desc;
13405 IDirect3DDevice7 *device;
13406 IDirectDraw7 *ddraw;
13407 IDirect3D7 *d3d;
13408 unsigned int i;
13409 ULONG refcount;
13410 HWND window;
13411 HRESULT hr;
13413 window = create_window();
13414 if (!(device = create_device(window, DDSCL_NORMAL)))
13416 skip("Failed to create 3D device.\n");
13417 DestroyWindow(window);
13418 return;
13420 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
13421 ok(SUCCEEDED(hr), "Failed to get Direct3D interface, hr %#x.\n", hr);
13422 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
13423 ok(SUCCEEDED(hr), "Failed to get DirectDraw interface, hr %#x.\n", hr);
13424 IDirect3D7_Release(d3d);
13426 memset(&surface_desc, 0, sizeof(surface_desc));
13427 surface_desc.dwSize = sizeof(surface_desc);
13428 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
13429 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
13430 surface_desc.dwWidth = 16;
13431 surface_desc.dwHeight = 16;
13432 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
13433 ok(hr == DD_OK, "Failed to create surface, hr %#x.\n", hr);
13435 for (i = 0; i < 8; ++i)
13437 hr = IDirect3DDevice7_SetTexture(device, i, texture);
13438 ok(hr == D3D_OK, "Failed to set texture %u, hr %#x.\n", i, hr);
13439 hr = IDirect3DDevice7_SetTexture(device, i, NULL);
13440 ok(hr == D3D_OK, "Failed to set texture %u, hr %#x.\n", i, hr);
13441 hr = IDirect3DDevice7_SetTextureStageState(device, i, D3DTSS_COLOROP, D3DTOP_ADD);
13442 ok(hr == D3D_OK, "Failed to set texture stage state %u, hr %#x.\n", i, hr);
13445 IDirectDrawSurface7_Release(texture);
13446 IDirectDraw7_Release(ddraw);
13447 refcount = IDirect3DDevice7_Release(device);
13448 ok(!refcount, "Device has %u references left.\n", refcount);
13449 DestroyWindow(window);
13452 static void test_set_render_state(void)
13454 IDirect3DDevice7 *device;
13455 ULONG refcount;
13456 HWND window;
13457 DWORD state;
13458 HRESULT hr;
13460 window = create_window();
13461 if (!(device = create_device(window, DDSCL_NORMAL)))
13463 skip("Failed to create 3D device.\n");
13464 DestroyWindow(window);
13465 return;
13468 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZVISIBLE, TRUE);
13469 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13470 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZVISIBLE, FALSE);
13471 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13473 /* States deprecated in D3D7 */
13474 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
13475 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13476 state = 0xdeadbeef;
13477 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, &state);
13478 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13479 ok(state == 0xdeadbeef, "Got unexpected render state %#x.\n", state);
13480 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
13481 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13482 state = 0xdeadbeef;
13483 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, &state);
13484 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13485 ok(state == 0xdeadbeef, "Got unexpected render state %#x.\n", state);
13487 refcount = IDirect3DDevice7_Release(device);
13488 ok(!refcount, "Device has %u references left.\n", refcount);
13489 DestroyWindow(window);
13492 static void test_map_synchronisation(void)
13494 LARGE_INTEGER frequency, diff, ts[3];
13495 IDirect3DVertexBuffer7 *buffer;
13496 unsigned int i, j, tri_count;
13497 D3DVERTEXBUFFERDESC vb_desc;
13498 IDirect3DDevice7 *device;
13499 BOOL unsynchronised, ret;
13500 IDirectDrawSurface7 *rt;
13501 IDirectDraw7 *ddraw;
13502 IDirect3D7 *d3d;
13503 D3DCOLOR colour;
13504 ULONG refcount;
13505 HWND window;
13506 HRESULT hr;
13508 static const struct
13510 unsigned int flags;
13511 BOOL unsynchronised;
13513 tests[] =
13515 {0, FALSE},
13516 {DDLOCK_NOOVERWRITE, TRUE},
13517 {DDLOCK_DISCARDCONTENTS, FALSE},
13518 {DDLOCK_NOOVERWRITE | DDLOCK_DISCARDCONTENTS, TRUE},
13521 static const struct quad
13523 struct
13525 struct vec3 position;
13526 DWORD diffuse;
13527 } strip[4];
13529 quad1 =
13532 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
13533 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
13534 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
13535 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
13538 quad2 =
13541 {{-1.0f, -1.0f, 0.0f}, 0xffffff00},
13542 {{-1.0f, 1.0f, 0.0f}, 0xffffff00},
13543 {{ 1.0f, -1.0f, 0.0f}, 0xffffff00},
13544 {{ 1.0f, 1.0f, 0.0f}, 0xffffff00},
13547 struct quad *quads;
13549 window = create_window();
13550 ok(!!window, "Failed to create a window.\n");
13552 if (!(device = create_device(window, DDSCL_NORMAL)))
13554 skip("Failed to create a D3D device, skipping tests.\n");
13555 DestroyWindow(window);
13556 return;
13559 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
13560 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
13561 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
13562 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
13563 /* Maps are always synchronised on WARP. */
13564 if (ddraw_is_warp(ddraw))
13566 skip("Running on WARP, skipping test.\n");
13567 goto done;
13570 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
13571 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
13573 tri_count = 0x1000;
13575 ret = QueryPerformanceFrequency(&frequency);
13576 ok(ret, "Failed to get performance counter frequency.\n");
13578 vb_desc.dwSize = sizeof(vb_desc);
13579 vb_desc.dwCaps = D3DVBCAPS_WRITEONLY;
13580 vb_desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
13581 vb_desc.dwNumVertices = tri_count + 2;
13582 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &buffer, 0);
13583 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
13584 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&quads, NULL);
13585 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
13586 for (j = 0; j < vb_desc.dwNumVertices / 4; ++j)
13588 quads[j] = quad1;
13590 hr = IDirect3DVertexBuffer7_Unlock(buffer);
13591 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
13593 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
13594 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
13596 /* Initial draw to initialise states, compile shaders, etc. */
13597 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
13598 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13599 hr = IDirect3DDevice7_BeginScene(device);
13600 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
13601 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, vb_desc.dwNumVertices, 0);
13602 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13603 hr = IDirect3DDevice7_EndScene(device);
13604 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
13605 /* Read the result to ensure the GPU has finished drawing. */
13606 colour = get_surface_color(rt, 320, 240);
13608 /* Time drawing tri_count triangles. */
13609 ret = QueryPerformanceCounter(&ts[0]);
13610 ok(ret, "Failed to read performance counter.\n");
13611 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
13612 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13613 hr = IDirect3DDevice7_BeginScene(device);
13614 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
13615 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, vb_desc.dwNumVertices, 0);
13616 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13617 hr = IDirect3DDevice7_EndScene(device);
13618 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
13619 colour = get_surface_color(rt, 320, 240);
13620 /* Time drawing a single triangle. */
13621 ret = QueryPerformanceCounter(&ts[1]);
13622 ok(ret, "Failed to read performance counter.\n");
13623 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
13624 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13625 hr = IDirect3DDevice7_BeginScene(device);
13626 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
13627 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 3, 0);
13628 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13629 hr = IDirect3DDevice7_EndScene(device);
13630 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
13631 colour = get_surface_color(rt, 320, 240);
13632 ret = QueryPerformanceCounter(&ts[2]);
13633 ok(ret, "Failed to read performance counter.\n");
13635 IDirect3DVertexBuffer7_Release(buffer);
13637 /* Estimate the number of triangles we can draw in 100ms. */
13638 diff.QuadPart = ts[1].QuadPart - ts[0].QuadPart + ts[1].QuadPart - ts[2].QuadPart;
13639 tri_count = (tri_count * frequency.QuadPart) / (diff.QuadPart * 10);
13640 tri_count = ((tri_count + 2 + 3) & ~3) - 2;
13641 vb_desc.dwNumVertices = tri_count + 2;
13643 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
13645 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &buffer, 0);
13646 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
13647 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&quads, NULL);
13648 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
13649 for (j = 0; j < vb_desc.dwNumVertices / 4; ++j)
13651 quads[j] = quad1;
13653 hr = IDirect3DVertexBuffer7_Unlock(buffer);
13654 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
13656 /* Start a draw operation. */
13657 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
13658 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13659 hr = IDirect3DDevice7_BeginScene(device);
13660 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
13661 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, vb_desc.dwNumVertices, 0);
13662 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13663 hr = IDirect3DDevice7_EndScene(device);
13664 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
13666 /* Map the last quad while the draw is in progress. */
13667 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_WAIT | tests[i].flags, (void **)&quads, NULL);
13668 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
13669 quads[(vb_desc.dwNumVertices / 4) - 1] = quad2;
13670 hr = IDirect3DVertexBuffer7_Unlock(buffer);
13671 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
13673 colour = get_surface_color(rt, 320, 240);
13674 unsynchronised = compare_color(colour, 0x00ffff00, 1);
13675 ok(tests[i].unsynchronised == unsynchronised, "Expected %s map for flags %#x.\n",
13676 tests[i].unsynchronised ? "unsynchronised" : "synchronised", tests[i].flags);
13678 IDirect3DVertexBuffer7_Release(buffer);
13681 IDirectDrawSurface7_Release(rt);
13682 done:
13683 IDirectDraw7_Release(ddraw);
13684 IDirect3D7_Release(d3d);
13685 refcount = IDirect3DDevice7_Release(device);
13686 ok(!refcount, "Device has %u references left.\n", refcount);
13687 DestroyWindow(window);
13690 static void test_depth_readback(void)
13692 DWORD depth, expected_depth, max_diff;
13693 IDirectDrawSurface7 *rt, *ds;
13694 DDSURFACEDESC2 surface_desc;
13695 IDirect3DDevice7 *device;
13696 unsigned int i, x, y;
13697 IDirectDraw7 *ddraw;
13698 IDirect3D7 *d3d;
13699 ULONG refcount;
13700 HWND window;
13701 HRESULT hr;
13702 RECT r;
13704 static struct
13706 struct vec3 position;
13707 DWORD diffuse;
13709 quad[] =
13711 {{-1.0f, -1.0f, 0.1f}, 0xff00ff00},
13712 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
13713 {{ 1.0f, -1.0f, 1.0f}, 0xff00ff00},
13714 {{ 1.0f, 1.0f, 0.9f}, 0xff00ff00},
13717 static const struct
13719 unsigned int z_depth, s_depth, z_mask, s_mask;
13720 BOOL todo;
13722 tests[] =
13724 {16, 0, 0x0000ffff, 0x00000000},
13725 {24, 0, 0x00ffffff, 0x00000000},
13726 {32, 0, 0x00ffffff, 0x00000000},
13727 {32, 8, 0x00ffffff, 0xff000000, TRUE},
13728 {32, 0, 0xffffffff, 0x00000000},
13731 window = create_window();
13732 ok(!!window, "Failed to create a window.\n");
13734 if (!(device = create_device(window, DDSCL_NORMAL)))
13736 skip("Failed to create a D3D device, skipping tests.\n");
13737 DestroyWindow(window);
13738 return;
13741 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
13742 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
13743 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
13744 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
13746 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
13747 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
13749 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
13750 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
13752 ds = get_depth_stencil(device);
13753 hr = IDirectDrawSurface7_DeleteAttachedSurface(rt, 0, ds);
13754 ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
13755 IDirectDrawSurface7_Release(ds);
13757 for (i = 0; i < ARRAY_SIZE(tests); ++i)
13759 memset(&surface_desc, 0, sizeof(surface_desc));
13760 surface_desc.dwSize = sizeof(surface_desc);
13761 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
13762 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
13763 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
13764 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
13765 if (tests[i].s_depth)
13766 U4(surface_desc).ddpfPixelFormat.dwFlags |= DDPF_STENCILBUFFER;
13767 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = tests[i].z_depth;
13768 U2(U4(surface_desc).ddpfPixelFormat).dwStencilBitDepth = tests[i].s_depth;
13769 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = tests[i].z_mask;
13770 U4(U4(surface_desc).ddpfPixelFormat).dwStencilBitMask = tests[i].s_mask;
13771 surface_desc.dwWidth = 640;
13772 surface_desc.dwHeight = 480;
13773 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL);
13774 if (FAILED(hr))
13776 skip("Format %u not supported, skipping test.\n", i);
13777 continue;
13780 hr = IDirectDrawSurface_AddAttachedSurface(rt, ds);
13781 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
13782 hr = IDirect3DDevice7_SetRenderTarget(device, rt, 0);
13783 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
13785 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 1.0f, 0);
13786 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13787 hr = IDirect3DDevice7_BeginScene(device);
13788 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
13789 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, 4, 0);
13790 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13791 hr = IDirect3DDevice7_EndScene(device);
13792 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
13794 for (y = 60; y < 480; y += 120)
13796 for (x = 80; x < 640; x += 160)
13798 SetRect(&r, x, y, x + 1, y + 1);
13799 memset(&surface_desc, 0, sizeof(surface_desc));
13800 surface_desc.dwSize = sizeof(surface_desc);
13801 hr = IDirectDrawSurface7_Lock(ds, &r, &surface_desc, DDLOCK_READONLY, NULL);
13802 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13804 depth = *((DWORD *)surface_desc.lpSurface) & tests[i].z_mask;
13805 expected_depth = (x * (0.9 / 640.0) + y * (0.1 / 480.0)) * tests[i].z_mask;
13806 max_diff = ((0.5f * 0.9f) / 640.0f) * tests[i].z_mask;
13807 todo_wine_if(tests[i].todo)
13808 ok(abs(expected_depth - depth) <= max_diff,
13809 "Test %u: Got depth 0x%08x (diff %d), expected 0x%08x+/-%u, at %u, %u.\n",
13810 i, depth, expected_depth - depth, expected_depth, max_diff, x, y);
13812 hr = IDirectDrawSurface7_Unlock(ds, &r);
13813 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13817 hr = IDirectDrawSurface7_DeleteAttachedSurface(rt, 0, ds);
13818 ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
13819 IDirectDrawSurface7_Release(ds);
13822 IDirectDrawSurface7_Release(rt);
13823 IDirectDraw7_Release(ddraw);
13824 IDirect3D7_Release(d3d);
13825 refcount = IDirect3DDevice7_Release(device);
13826 ok(!refcount, "Device has %u references left.\n", refcount);
13827 DestroyWindow(window);
13830 static void test_clear(void)
13832 IDirect3DDevice7 *device;
13833 IDirectDrawSurface7 *rt;
13834 D3DVIEWPORT7 vp, old_vp;
13835 IDirectDraw7 *ddraw;
13836 D3DRECT rect_negneg;
13837 IDirect3D7 *d3d;
13838 D3DRECT rect[2];
13839 D3DCOLOR color;
13840 ULONG refcount;
13841 HWND window;
13842 HRESULT hr;
13844 window = create_window();
13845 if (!(device = create_device(window, DDSCL_NORMAL)))
13847 skip("Failed to create 3D device.\n");
13848 DestroyWindow(window);
13849 return;
13852 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
13853 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
13854 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
13855 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
13857 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
13858 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
13860 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
13861 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13863 /* Positive x, negative y. */
13864 U1(rect[0]).x1 = 0;
13865 U2(rect[0]).y1 = 480;
13866 U3(rect[0]).x2 = 320;
13867 U4(rect[0]).y2 = 240;
13869 /* Positive x, positive y. */
13870 U1(rect[1]).x1 = 0;
13871 U2(rect[1]).y1 = 0;
13872 U3(rect[1]).x2 = 320;
13873 U4(rect[1]).y2 = 240;
13875 /* Clear 2 rectangles with one call. Unlike d3d8/9, the refrast does not
13876 * refuse negative rectangles, but it will not clear them either. */
13877 hr = IDirect3DDevice7_Clear(device, 2, rect, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
13878 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13880 color = get_surface_color(rt, 160, 360);
13881 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 3 (pos, neg) has color 0x%08x.\n", color);
13882 color = get_surface_color(rt, 160, 120);
13883 ok(compare_color(color, 0x00ff0000, 0), "Clear rectangle 1 (pos, pos) has color 0x%08x.\n", color);
13884 color = get_surface_color(rt, 480, 360);
13885 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 4 (NULL) has color 0x%08x.\n", color);
13886 color = get_surface_color(rt, 480, 120);
13887 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 4 (neg, neg) has color 0x%08x.\n", color);
13889 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
13890 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13891 /* negative x, negative y.
13892 * Also ignored, except on WARP, which clears the entire screen. */
13893 rect_negneg.x1 = 640;
13894 rect_negneg.y1 = 240;
13895 rect_negneg.x2 = 320;
13896 rect_negneg.y2 = 0;
13897 hr = IDirect3DDevice7_Clear(device, 1, &rect_negneg, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
13898 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13900 color = get_surface_color(rt, 160, 360);
13901 ok(compare_color(color, 0x00ffffff, 0)
13902 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
13903 "Got unexpected color 0x%08x.\n", color);
13904 color = get_surface_color(rt, 160, 120);
13905 ok(compare_color(color, 0x00ffffff, 0)
13906 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
13907 "Got unexpected color 0x%08x.\n", color);
13908 color = get_surface_color(rt, 480, 360);
13909 ok(compare_color(color, 0x00ffffff, 0)
13910 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
13911 "Got unexpected color 0x%08x.\n", color);
13912 color = get_surface_color(rt, 480, 120);
13913 ok(compare_color(color, 0x00ffffff, 0)
13914 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
13915 "Got unexpected color 0x%08x.\n", color);
13917 /* Test how the viewport affects clears. */
13918 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
13919 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13920 hr = IDirect3DDevice7_GetViewport(device, &old_vp);
13921 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
13923 vp.dwX = 160;
13924 vp.dwY = 120;
13925 vp.dwWidth = 160;
13926 vp.dwHeight = 120;
13927 vp.dvMinZ = 0.0f;
13928 vp.dvMaxZ = 1.0f;
13929 hr = IDirect3DDevice7_SetViewport(device, &vp);
13930 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
13931 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
13932 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13934 vp.dwX = 320;
13935 vp.dwY = 240;
13936 vp.dwWidth = 320;
13937 vp.dwHeight = 240;
13938 vp.dvMinZ = 0.0f;
13939 vp.dvMaxZ = 1.0f;
13940 hr = IDirect3DDevice7_SetViewport(device, &vp);
13941 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
13943 U1(rect[0]).x1 = 160;
13944 U2(rect[0]).y1 = 120;
13945 U3(rect[0]).x2 = 480;
13946 U4(rect[0]).y2 = 360;
13947 hr = IDirect3DDevice7_Clear(device, 1, &rect[0], D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
13948 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13950 hr = IDirect3DDevice7_SetViewport(device, &old_vp);
13951 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
13953 color = get_surface_color(rt, 158, 118);
13954 ok(compare_color(color, 0x00ffffff, 0), "(158, 118) has color 0x%08x.\n", color);
13955 color = get_surface_color(rt, 162, 118);
13956 ok(compare_color(color, 0x00ffffff, 0), "(162, 118) has color 0x%08x.\n", color);
13957 color = get_surface_color(rt, 158, 122);
13958 ok(compare_color(color, 0x00ffffff, 0), "(158, 122) has color 0x%08x.\n", color);
13959 color = get_surface_color(rt, 162, 122);
13960 ok(compare_color(color, 0x000000ff, 0), "(162, 122) has color 0x%08x.\n", color);
13962 color = get_surface_color(rt, 318, 238);
13963 ok(compare_color(color, 0x000000ff, 0), "(318, 238) has color 0x%08x.\n", color);
13964 color = get_surface_color(rt, 322, 238);
13965 ok(compare_color(color, 0x00ffffff, 0), "(322, 328) has color 0x%08x.\n", color);
13966 color = get_surface_color(rt, 318, 242);
13967 ok(compare_color(color, 0x00ffffff, 0), "(318, 242) has color 0x%08x.\n", color);
13968 color = get_surface_color(rt, 322, 242);
13969 ok(compare_color(color, 0x0000ff00, 0), "(322, 242) has color 0x%08x.\n", color);
13971 color = get_surface_color(rt, 478, 358);
13972 ok(compare_color(color, 0x0000ff00, 0), "(478, 358) has color 0x%08x.\n", color);
13973 color = get_surface_color(rt, 482, 358);
13974 ok(compare_color(color, 0x00ffffff, 0), "(482, 358) has color 0x%08x.\n", color);
13975 color = get_surface_color(rt, 478, 362);
13976 ok(compare_color(color, 0x00ffffff, 0), "(478, 362) has color 0x%08x.\n", color);
13977 color = get_surface_color(rt, 482, 362);
13978 ok(compare_color(color, 0x00ffffff, 0), "(482, 362) has color 0x%08x.\n", color);
13980 /* COLORWRITEENABLE, SRGBWRITEENABLE and scissor rectangles do not exist
13981 * in d3d7. */
13983 IDirectDrawSurface7_Release(rt);
13984 IDirectDraw7_Release(ddraw);
13985 IDirect3D7_Release(d3d);
13986 refcount = IDirect3DDevice7_Release(device);
13987 ok(!refcount, "Device has %u references left.\n", refcount);
13988 DestroyWindow(window);
13991 struct enum_surfaces_param
13993 IDirectDrawSurface7 *surfaces[8];
13994 unsigned int count;
13997 static HRESULT WINAPI enum_surfaces_cb(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
13999 struct enum_surfaces_param *param = context;
14000 BOOL found = FALSE;
14001 unsigned int i;
14003 for (i = 0; i < ARRAY_SIZE(param->surfaces); ++i)
14005 if (param->surfaces[i] == surface)
14007 found = TRUE;
14008 break;
14012 ok(found, "Unexpected surface %p enumerated.\n", surface);
14013 IDirectDrawSurface7_Release(surface);
14014 ++param->count;
14016 return DDENUMRET_OK;
14019 static void test_enum_surfaces(void)
14021 struct enum_surfaces_param param = {{0}};
14022 DDSURFACEDESC2 desc;
14023 IDirectDraw7 *ddraw;
14024 HRESULT hr;
14026 ddraw = create_ddraw();
14027 ok(!!ddraw, "Failed to create a ddraw object.\n");
14029 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
14030 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
14032 memset(&desc, 0, sizeof(desc));
14033 desc.dwSize = sizeof(desc);
14034 desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
14035 desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
14036 U2(desc).dwMipMapCount = 3;
14037 desc.dwWidth = 32;
14038 desc.dwHeight = 32;
14039 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &desc, &param.surfaces[0], NULL)))
14041 win_skip("Failed to create a texture, skipping tests.\n");
14042 IDirectDraw7_Release(ddraw);
14043 return;
14046 hr = IDirectDrawSurface7_GetAttachedSurface(param.surfaces[0], &desc.ddsCaps, &param.surfaces[1]);
14047 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
14048 hr = IDirectDrawSurface7_GetAttachedSurface(param.surfaces[1], &desc.ddsCaps, &param.surfaces[2]);
14049 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
14050 hr = IDirectDrawSurface7_GetAttachedSurface(param.surfaces[2], &desc.ddsCaps, &param.surfaces[3]);
14051 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
14052 ok(!param.surfaces[3], "Got unexpected pointer %p.\n", param.surfaces[3]);
14054 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
14055 &desc, &param, enum_surfaces_cb);
14056 ok(SUCCEEDED(hr), "Failed to enumerate surfaces, hr %#x.\n", hr);
14057 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
14059 param.count = 0;
14060 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
14061 NULL, &param, enum_surfaces_cb);
14062 ok(SUCCEEDED(hr), "Failed to enumerate surfaces, hr %#x.\n", hr);
14063 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
14065 IDirectDrawSurface7_Release(param.surfaces[2]);
14066 IDirectDrawSurface7_Release(param.surfaces[1]);
14067 IDirectDrawSurface7_Release(param.surfaces[0]);
14068 IDirectDraw7_Release(ddraw);
14071 START_TEST(ddraw7)
14073 DDDEVICEIDENTIFIER2 identifier;
14074 HMODULE module, dwmapi;
14075 DEVMODEW current_mode;
14076 IDirectDraw7 *ddraw;
14078 module = GetModuleHandleA("ddraw.dll");
14079 if (!(pDirectDrawCreateEx = (void *)GetProcAddress(module, "DirectDrawCreateEx")))
14081 win_skip("DirectDrawCreateEx not available, skipping tests.\n");
14082 return;
14085 if (!(ddraw = create_ddraw()))
14087 skip("Failed to create a ddraw object, skipping tests.\n");
14088 return;
14091 if (ddraw_get_identifier(ddraw, &identifier))
14093 trace("Driver string: \"%s\"\n", identifier.szDriver);
14094 trace("Description string: \"%s\"\n", identifier.szDescription);
14095 trace("Driver version %d.%d.%d.%d\n",
14096 HIWORD(U(identifier.liDriverVersion).HighPart), LOWORD(U(identifier.liDriverVersion).HighPart),
14097 HIWORD(U(identifier.liDriverVersion).LowPart), LOWORD(U(identifier.liDriverVersion).LowPart));
14099 IDirectDraw7_Release(ddraw);
14101 memset(&current_mode, 0, sizeof(current_mode));
14102 current_mode.dmSize = sizeof(current_mode);
14103 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
14104 registry_mode.dmSize = sizeof(registry_mode);
14105 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
14106 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
14107 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
14109 skip("Current mode does not match registry mode, skipping test.\n");
14110 return;
14113 if ((dwmapi = LoadLibraryA("dwmapi.dll")))
14114 pDwmIsCompositionEnabled = (void *)GetProcAddress(dwmapi, "DwmIsCompositionEnabled");
14116 test_process_vertices();
14117 test_coop_level_create_device_window();
14118 test_clipper_blt();
14119 test_coop_level_d3d_state();
14120 test_surface_interface_mismatch();
14121 test_coop_level_threaded();
14122 test_depth_blit();
14123 test_texture_load_ckey();
14124 test_zenable();
14125 test_ck_rgba();
14126 test_ck_default();
14127 test_ck_complex();
14128 test_surface_qi();
14129 test_device_qi();
14130 test_wndproc();
14131 test_window_style();
14132 test_redundant_mode_set();
14133 test_coop_level_mode_set();
14134 test_coop_level_mode_set_multi();
14135 test_initialize();
14136 test_coop_level_surf_create();
14137 test_vb_discard();
14138 test_coop_level_multi_window();
14139 test_draw_strided();
14140 test_lighting();
14141 test_specular_lighting();
14142 test_clear_rect_count();
14143 test_coop_level_versions();
14144 test_fog_special();
14145 test_lighting_interface_versions();
14146 test_coop_level_activateapp();
14147 test_texturemanage();
14148 test_block_formats_creation();
14149 test_unsupported_formats();
14150 test_rt_caps();
14151 test_primary_caps();
14152 test_surface_lock();
14153 test_surface_discard();
14154 test_flip();
14155 test_set_surface_desc();
14156 test_user_memory_getdc();
14157 test_sysmem_overlay();
14158 test_primary_palette();
14159 test_surface_attachment();
14160 test_private_data();
14161 test_pixel_format();
14162 test_create_surface_pitch();
14163 test_mipmap();
14164 test_palette_complex();
14165 test_p8_blit();
14166 test_material();
14167 test_palette_gdi();
14168 test_palette_alpha();
14169 test_vb_writeonly();
14170 test_lost_device();
14171 test_resource_priority();
14172 test_surface_desc_lock();
14173 test_fog_interpolation();
14174 test_negative_fixedfunction_fog();
14175 test_table_fog_zw();
14176 test_signed_formats();
14177 test_color_fill();
14178 test_texcoordindex();
14179 test_colorkey_precision();
14180 test_range_colorkey();
14181 test_shademode();
14182 test_lockrect_invalid();
14183 test_yv12_overlay();
14184 test_offscreen_overlay();
14185 test_overlay_rect();
14186 test_blt();
14187 test_blt_z_alpha();
14188 test_color_clamping();
14189 test_getdc();
14190 test_draw_primitive();
14191 test_edge_antialiasing_blending();
14192 test_display_mode_surface_pixel_format();
14193 test_surface_desc_size();
14194 test_get_surface_from_dc();
14195 test_ck_operation();
14196 test_vb_refcount();
14197 test_compute_sphere_visibility();
14198 test_clip_planes_limits();
14199 test_texture_stages_limits();
14200 test_set_render_state();
14201 test_map_synchronisation();
14202 test_depth_readback();
14203 test_clear();
14204 test_enum_surfaces();