ddraw/tests: Add test for fog calculation in _ProcessVertices for ddraw7.
[wine.git] / dlls / ddraw / tests / ddraw7.c
blobe1e3330e25302ad42b6cbdd259314ac09baacd2e
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 "wine/heap.h"
24 #include <limits.h>
25 #include <math.h>
26 #include "d3d.h"
28 HRESULT WINAPI GetSurfaceFromDC(HDC dc, struct IDirectDrawSurface **surface, HDC *device_dc);
30 static HRESULT (WINAPI *pDirectDrawCreateEx)(GUID *guid, void **ddraw, REFIID iid, IUnknown *outer_unknown);
31 static BOOL is_ddraw64 = sizeof(DWORD) != sizeof(DWORD *);
32 static DEVMODEW registry_mode;
34 static HRESULT (WINAPI *pDwmIsCompositionEnabled)(BOOL *);
36 struct vec2
38 float x, y;
41 struct vec3
43 float x, y, z;
46 struct vec4
48 float x, y, z, w;
51 struct create_window_thread_param
53 HWND window;
54 HANDLE window_created;
55 HANDLE destroy_window;
56 HANDLE thread;
59 static BOOL compare_float(float f, float g, unsigned int ulps)
61 int x = *(int *)&f;
62 int y = *(int *)&g;
64 if (x < 0)
65 x = INT_MIN - x;
66 if (y < 0)
67 y = INT_MIN - y;
69 if (abs(x - y) > ulps)
70 return FALSE;
72 return TRUE;
75 static BOOL compare_vec3(struct vec3 *vec, float x, float y, float z, unsigned int ulps)
77 return compare_float(vec->x, x, ulps)
78 && compare_float(vec->y, y, ulps)
79 && compare_float(vec->z, z, ulps);
82 static BOOL compare_vec4(const struct vec4 *vec, float x, float y, float z, float w, unsigned int ulps)
84 return compare_float(vec->x, x, ulps)
85 && compare_float(vec->y, y, ulps)
86 && compare_float(vec->z, z, ulps)
87 && compare_float(vec->w, w, ulps);
90 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
92 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
93 c1 >>= 8; c2 >>= 8;
94 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
95 c1 >>= 8; c2 >>= 8;
96 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
97 c1 >>= 8; c2 >>= 8;
98 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
99 return TRUE;
102 static ULONG get_refcount(IUnknown *iface)
104 IUnknown_AddRef(iface);
105 return IUnknown_Release(iface);
108 static BOOL ddraw_get_identifier(IDirectDraw7 *ddraw, DDDEVICEIDENTIFIER2 *identifier)
110 HRESULT hr;
112 hr = IDirectDraw7_GetDeviceIdentifier(ddraw, identifier, 0);
113 ok(SUCCEEDED(hr), "Failed to get device identifier, hr %#x.\n", hr);
115 return SUCCEEDED(hr);
118 static BOOL ddraw_is_warp(IDirectDraw7 *ddraw)
120 DDDEVICEIDENTIFIER2 identifier;
122 return strcmp(winetest_platform, "wine")
123 && ddraw_get_identifier(ddraw, &identifier)
124 && strstr(identifier.szDriver, "warp");
127 static BOOL ddraw_is_vendor(IDirectDraw7 *ddraw, DWORD vendor)
129 DDDEVICEIDENTIFIER2 identifier;
131 return strcmp(winetest_platform, "wine")
132 && ddraw_get_identifier(ddraw, &identifier)
133 && identifier.dwVendorId == vendor;
136 static BOOL ddraw_is_intel(IDirectDraw7 *ddraw)
138 return ddraw_is_vendor(ddraw, 0x8086);
141 static BOOL ddraw_is_nvidia(IDirectDraw7 *ddraw)
143 return ddraw_is_vendor(ddraw, 0x10de);
146 static BOOL ddraw_is_vmware(IDirectDraw7 *ddraw)
148 return ddraw_is_vendor(ddraw, 0x15ad);
151 static IDirectDrawSurface7 *create_overlay(IDirectDraw7 *ddraw,
152 unsigned int width, unsigned int height, DWORD format)
154 IDirectDrawSurface7 *surface;
155 DDSURFACEDESC2 desc;
157 memset(&desc, 0, sizeof(desc));
158 desc.dwSize = sizeof(desc);
159 desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
160 desc.dwWidth = width;
161 desc.dwHeight = height;
162 desc.ddsCaps.dwCaps = DDSCAPS_OVERLAY;
163 U4(desc).ddpfPixelFormat.dwSize = sizeof(U4(desc).ddpfPixelFormat);
164 U4(desc).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
165 U4(desc).ddpfPixelFormat.dwFourCC = format;
167 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &desc, &surface, NULL)))
168 return NULL;
169 return surface;
172 static HWND create_window(void)
174 RECT r = {0, 0, 640, 480};
176 AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
178 return CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
179 CW_USEDEFAULT, CW_USEDEFAULT, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL);
182 static DWORD WINAPI create_window_thread_proc(void *param)
184 struct create_window_thread_param *p = param;
185 DWORD res;
186 BOOL ret;
188 p->window = create_window();
189 ret = SetEvent(p->window_created);
190 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
192 for (;;)
194 MSG msg;
196 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
197 DispatchMessageA(&msg);
198 res = WaitForSingleObject(p->destroy_window, 100);
199 if (res == WAIT_OBJECT_0)
200 break;
201 if (res != WAIT_TIMEOUT)
203 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
204 break;
208 DestroyWindow(p->window);
210 return 0;
213 static void create_window_thread(struct create_window_thread_param *p)
215 DWORD res, tid;
217 p->window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
218 ok(!!p->window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
219 p->destroy_window = CreateEventA(NULL, FALSE, FALSE, NULL);
220 ok(!!p->destroy_window, "CreateEvent failed, last error %#x.\n", GetLastError());
221 p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
222 ok(!!p->thread, "Failed to create thread, last error %#x.\n", GetLastError());
223 res = WaitForSingleObject(p->window_created, INFINITE);
224 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
227 static void destroy_window_thread(struct create_window_thread_param *p)
229 SetEvent(p->destroy_window);
230 WaitForSingleObject(p->thread, INFINITE);
231 CloseHandle(p->destroy_window);
232 CloseHandle(p->window_created);
233 CloseHandle(p->thread);
236 static IDirectDrawSurface7 *get_depth_stencil(IDirect3DDevice7 *device)
238 IDirectDrawSurface7 *rt, *ret;
239 DDSCAPS2 caps = {DDSCAPS_ZBUFFER, 0, 0, {0}};
240 HRESULT hr;
242 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
243 ok(SUCCEEDED(hr), "Failed to get the render target, hr %#x.\n", hr);
244 hr = IDirectDrawSurface7_GetAttachedSurface(rt, &caps, &ret);
245 ok(SUCCEEDED(hr) || hr == DDERR_NOTFOUND, "Failed to get the z buffer, hr %#x.\n", hr);
246 IDirectDrawSurface7_Release(rt);
247 return ret;
250 static HRESULT set_display_mode(IDirectDraw7 *ddraw, DWORD width, DWORD height)
252 if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
253 return DD_OK;
254 return IDirectDraw7_SetDisplayMode(ddraw, width, height, 24, 0, 0);
257 static D3DCOLOR get_surface_color(IDirectDrawSurface7 *surface, UINT x, UINT y)
259 RECT rect = {x, y, x + 1, y + 1};
260 DDSURFACEDESC2 surface_desc;
261 D3DCOLOR color;
262 HRESULT hr;
264 memset(&surface_desc, 0, sizeof(surface_desc));
265 surface_desc.dwSize = sizeof(surface_desc);
267 hr = IDirectDrawSurface7_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY, NULL);
268 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
269 if (FAILED(hr))
270 return 0xdeadbeef;
272 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
274 hr = IDirectDrawSurface7_Unlock(surface, &rect);
275 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
277 return color;
280 static void check_rect(IDirectDrawSurface7 *surface, RECT r, const char *message)
282 LONG x_coords[2][2] =
284 {r.left - 1, r.left + 1},
285 {r.right + 1, r.right - 1},
287 LONG y_coords[2][2] =
289 {r.top - 1, r.top + 1},
290 {r.bottom + 1, r.bottom - 1}
292 unsigned int i, j, x_side, y_side;
293 DWORD color;
294 LONG x, y;
296 for (i = 0; i < 2; ++i)
298 for (j = 0; j < 2; ++j)
300 for (x_side = 0; x_side < 2; ++x_side)
302 for (y_side = 0; y_side < 2; ++y_side)
304 DWORD expected = (x_side == 1 && y_side == 1) ? 0x00ffffff : 0x00000000;
306 x = x_coords[i][x_side];
307 y = y_coords[j][y_side];
308 if (x < 0 || x >= 640 || y < 0 || y >= 480)
309 continue;
310 color = get_surface_color(surface, x, y);
311 ok(color == expected, "%s: Pixel (%d, %d) has color %08x, expected %08x.\n",
312 message, x, y, color, expected);
319 static HRESULT CALLBACK enum_z_fmt(DDPIXELFORMAT *format, void *ctx)
321 DDPIXELFORMAT *z_fmt = ctx;
323 if (U1(*format).dwZBufferBitDepth > U1(*z_fmt).dwZBufferBitDepth)
324 *z_fmt = *format;
326 return DDENUMRET_OK;
329 static IDirectDraw7 *create_ddraw(void)
331 IDirectDraw7 *ddraw;
333 if (FAILED(pDirectDrawCreateEx(NULL, (void **)&ddraw, &IID_IDirectDraw7, NULL)))
334 return NULL;
336 return ddraw;
339 static HRESULT WINAPI enum_devtype_cb(char *desc_str, char *name, D3DDEVICEDESC7 *desc, void *ctx)
341 BOOL *hal_ok = ctx;
342 if (IsEqualGUID(&desc->deviceGUID, &IID_IDirect3DTnLHalDevice))
344 *hal_ok = TRUE;
345 return DDENUMRET_CANCEL;
347 return DDENUMRET_OK;
350 static IDirect3DDevice7 *create_device(HWND window, DWORD coop_level)
352 IDirectDrawSurface7 *surface, *ds;
353 IDirect3DDevice7 *device = NULL;
354 DDSURFACEDESC2 surface_desc;
355 DDPIXELFORMAT z_fmt;
356 IDirectDraw7 *ddraw;
357 IDirect3D7 *d3d7;
358 HRESULT hr;
359 BOOL hal_ok = FALSE;
360 const GUID *devtype = &IID_IDirect3DHALDevice;
362 if (!(ddraw = create_ddraw()))
363 return NULL;
365 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, coop_level);
366 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
368 memset(&surface_desc, 0, sizeof(surface_desc));
369 surface_desc.dwSize = sizeof(surface_desc);
370 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
371 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
372 surface_desc.dwWidth = 640;
373 surface_desc.dwHeight = 480;
375 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
376 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
378 if (coop_level & DDSCL_NORMAL)
380 IDirectDrawClipper *clipper;
382 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
383 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
384 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
385 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
386 hr = IDirectDrawSurface7_SetClipper(surface, clipper);
387 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\n", hr);
388 IDirectDrawClipper_Release(clipper);
391 hr = IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d7);
392 IDirectDraw7_Release(ddraw);
393 if (FAILED(hr))
395 IDirectDrawSurface7_Release(surface);
396 return NULL;
399 hr = IDirect3D7_EnumDevices(d3d7, enum_devtype_cb, &hal_ok);
400 ok(SUCCEEDED(hr), "Failed to enumerate devices, hr %#x.\n", hr);
401 if (hal_ok) devtype = &IID_IDirect3DTnLHalDevice;
403 memset(&z_fmt, 0, sizeof(z_fmt));
404 hr = IDirect3D7_EnumZBufferFormats(d3d7, devtype, enum_z_fmt, &z_fmt);
405 if (FAILED(hr) || !z_fmt.dwSize)
407 IDirect3D7_Release(d3d7);
408 IDirectDrawSurface7_Release(surface);
409 return NULL;
412 memset(&surface_desc, 0, sizeof(surface_desc));
413 surface_desc.dwSize = sizeof(surface_desc);
414 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
415 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
416 U4(surface_desc).ddpfPixelFormat = z_fmt;
417 surface_desc.dwWidth = 640;
418 surface_desc.dwHeight = 480;
419 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL);
420 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
421 if (FAILED(hr))
423 IDirect3D7_Release(d3d7);
424 IDirectDrawSurface7_Release(surface);
425 return NULL;
428 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
429 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
430 IDirectDrawSurface7_Release(ds);
431 if (FAILED(hr))
433 IDirect3D7_Release(d3d7);
434 IDirectDrawSurface7_Release(surface);
435 return NULL;
438 hr = IDirect3D7_CreateDevice(d3d7, devtype, surface, &device);
439 IDirect3D7_Release(d3d7);
440 IDirectDrawSurface7_Release(surface);
441 if (FAILED(hr))
442 return NULL;
444 return device;
447 struct message
449 UINT message;
450 BOOL check_wparam;
451 WPARAM expect_wparam;
452 HRESULT ddraw_state;
455 static const struct message *expect_messages;
456 static IDirectDraw7 *focus_test_ddraw;
458 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
460 HRESULT hr;
462 if (expect_messages && message == expect_messages->message)
464 if (expect_messages->check_wparam)
465 ok (wparam == expect_messages->expect_wparam,
466 "Got unexpected wparam %lx for message %x, expected %lx.\n",
467 wparam, message, expect_messages->expect_wparam);
469 if (focus_test_ddraw)
471 hr = IDirectDraw7_TestCooperativeLevel(focus_test_ddraw);
472 ok(hr == expect_messages->ddraw_state, "Got ddraw state %#x on message %#x, expected %#x.\n",
473 hr, message, expect_messages->ddraw_state);
476 ++expect_messages;
479 return DefWindowProcA(hwnd, message, wparam, lparam);
482 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
483 * interface. This prevents subsequent SetCooperativeLevel() calls on a
484 * different window from failing with DDERR_HWNDALREADYSET. */
485 static void fix_wndproc(HWND window, LONG_PTR proc)
487 IDirectDraw7 *ddraw;
488 HRESULT hr;
490 if (!(ddraw = create_ddraw()))
491 return;
493 SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
494 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
495 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
496 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
497 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
499 IDirectDraw7_Release(ddraw);
502 static void test_process_vertices(void)
504 IDirect3DVertexBuffer7 *src_vb, *dst_vb1, *dst_vb2;
505 D3DVERTEXBUFFERDESC vb_desc;
506 IDirect3DDevice7 *device;
507 struct vec4 *dst_data;
508 struct vec3 *dst_data2;
509 struct vec3 *src_data;
510 IDirect3D7 *d3d7;
511 D3DVIEWPORT7 vp;
512 HWND window;
513 HRESULT hr;
515 static D3DMATRIX world =
517 0.0f, 1.0f, 0.0f, 0.0f,
518 1.0f, 0.0f, 0.0f, 0.0f,
519 0.0f, 0.0f, 0.0f, 1.0f,
520 0.0f, 1.0f, 1.0f, 1.0f,
522 static D3DMATRIX view =
524 2.0f, 0.0f, 0.0f, 0.0f,
525 0.0f, -1.0f, 0.0f, 0.0f,
526 0.0f, 0.0f, 1.0f, 0.0f,
527 0.0f, 0.0f, 0.0f, 3.0f,
529 static D3DMATRIX proj =
531 1.0f, 0.0f, 0.0f, 1.0f,
532 0.0f, 1.0f, 1.0f, 0.0f,
533 0.0f, 1.0f, 1.0f, 0.0f,
534 1.0f, 0.0f, 0.0f, 1.0f,
537 window = create_window();
538 if (!(device = create_device(window, DDSCL_NORMAL)))
540 skip("Failed to create a 3D device, skipping test.\n");
541 DestroyWindow(window);
542 return;
545 hr = IDirect3DDevice7_GetDirect3D(device, &d3d7);
546 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
548 memset(&vb_desc, 0, sizeof(vb_desc));
549 vb_desc.dwSize = sizeof(vb_desc);
550 vb_desc.dwFVF = D3DFVF_XYZ;
551 vb_desc.dwNumVertices = 4;
552 hr = IDirect3D7_CreateVertexBuffer(d3d7, &vb_desc, &src_vb, 0);
553 ok(SUCCEEDED(hr), "Failed to create source vertex buffer, hr %#x.\n", hr);
555 hr = IDirect3DVertexBuffer7_Lock(src_vb, 0, (void **)&src_data, NULL);
556 ok(SUCCEEDED(hr), "Failed to lock source vertex buffer, hr %#x.\n", hr);
557 src_data[0].x = 0.0f;
558 src_data[0].y = 0.0f;
559 src_data[0].z = 0.0f;
560 src_data[1].x = 1.0f;
561 src_data[1].y = 1.0f;
562 src_data[1].z = 1.0f;
563 src_data[2].x = -1.0f;
564 src_data[2].y = -1.0f;
565 src_data[2].z = 0.5f;
566 src_data[3].x = 0.5f;
567 src_data[3].y = -0.5f;
568 src_data[3].z = 0.25f;
569 hr = IDirect3DVertexBuffer7_Unlock(src_vb);
570 ok(SUCCEEDED(hr), "Failed to unlock source vertex buffer, hr %#x.\n", hr);
572 memset(&vb_desc, 0, sizeof(vb_desc));
573 vb_desc.dwSize = sizeof(vb_desc);
574 vb_desc.dwFVF = D3DFVF_XYZRHW;
575 vb_desc.dwNumVertices = 4;
576 /* MSDN says that the last parameter must be 0 - check that. */
577 hr = IDirect3D7_CreateVertexBuffer(d3d7, &vb_desc, &dst_vb1, 4);
578 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
580 memset(&vb_desc, 0, sizeof(vb_desc));
581 vb_desc.dwSize = sizeof(vb_desc);
582 vb_desc.dwFVF = D3DFVF_XYZ;
583 vb_desc.dwNumVertices = 5;
584 /* MSDN says that the last parameter must be 0 - check that. */
585 hr = IDirect3D7_CreateVertexBuffer(d3d7, &vb_desc, &dst_vb2, 12345678);
586 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
588 memset(&vp, 0, sizeof(vp));
589 vp.dwX = 64;
590 vp.dwY = 64;
591 vp.dwWidth = 128;
592 vp.dwHeight = 128;
593 vp.dvMinZ = 0.0f;
594 vp.dvMaxZ = 1.0f;
595 hr = IDirect3DDevice7_SetViewport(device, &vp);
596 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
598 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
599 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
600 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb2, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
601 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
603 hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
604 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
605 ok(compare_vec4(&dst_data[0], +1.280e+2f, +1.280e+2f, +0.000e+0f, +1.000e+0f, 4096),
606 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
607 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
608 ok(compare_vec4(&dst_data[1], +1.920e+2f, +6.400e+1f, +1.000e+0f, +1.000e+0f, 4096),
609 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
610 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
611 ok(compare_vec4(&dst_data[2], +6.400e+1f, +1.920e+2f, +5.000e-1f, +1.000e+0f, 4096),
612 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
613 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
614 ok(compare_vec4(&dst_data[3], +1.600e+2f, +1.600e+2f, +2.500e-1f, +1.000e+0f, 4096),
615 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
616 dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
617 hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
618 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
620 hr = IDirect3DVertexBuffer7_Lock(dst_vb2, 0, (void **)&dst_data2, NULL);
621 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
622 /* Small thing without much practical meaning, but I stumbled upon it,
623 * so let's check for it: If the output vertex buffer has no RHW value,
624 * the RHW value of the last vertex is written into the next vertex. */
625 ok(compare_vec3(&dst_data2[4], +1.000e+0f, +0.000e+0f, +0.000e+0f, 4096),
626 "Got unexpected vertex 4 {%.8e, %.8e, %.8e}.\n",
627 dst_data2[4].x, dst_data2[4].y, dst_data2[4].z);
628 hr = IDirect3DVertexBuffer7_Unlock(dst_vb2);
629 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
631 /* Try a more complicated viewport, same vertices. */
632 memset(&vp, 0, sizeof(vp));
633 vp.dwX = 10;
634 vp.dwY = 5;
635 vp.dwWidth = 246;
636 vp.dwHeight = 130;
637 vp.dvMinZ = -2.0f;
638 vp.dvMaxZ = 4.0f;
639 hr = IDirect3DDevice7_SetViewport(device, &vp);
640 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
642 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
643 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
645 hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
646 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
647 ok(compare_vec4(&dst_data[0], +1.330e+2f, +7.000e+1f, -2.000e+0f, +1.000e+0f, 4096),
648 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
649 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
650 ok(compare_vec4(&dst_data[1], +2.560e+2f, +5.000e+0f, +4.000e+0f, +1.000e+0f, 4096),
651 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
652 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
653 ok(compare_vec4(&dst_data[2], +1.000e+1f, +1.350e+2f, +1.000e+0f, +1.000e+0f, 4096),
654 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
655 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
656 ok(compare_vec4(&dst_data[3], +1.945e+2f, +1.025e+2f, -5.000e-1f, +1.000e+0f, 4096),
657 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
658 dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
659 hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
660 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
662 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &world);
663 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
664 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &view);
665 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
666 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &proj);
667 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
669 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
670 ok(SUCCEEDED(hr), "Failed to process vertices, hr %#x.\n", hr);
672 hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
673 ok(SUCCEEDED(hr), "Failed to lock destination vertex buffer, hr %#x.\n", hr);
674 ok(compare_vec4(&dst_data[0], +2.560e+2f, +7.000e+1f, -2.000e+0f, +3.333e-1f, 4096),
675 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
676 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
677 ok(compare_vec4(&dst_data[1], +2.560e+2f, +7.813e+1f, -2.750e+0f, +1.250e-1f, 4096),
678 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
679 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
680 ok(compare_vec4(&dst_data[2], +2.560e+2f, +4.400e+1f, +4.000e-1f, +4.000e-1f, 4096),
681 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
682 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
683 ok(compare_vec4(&dst_data[3], +2.560e+2f, +8.182e+1f, -3.091e+0f, +3.636e-1f, 4096),
684 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
685 dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
686 hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
687 ok(SUCCEEDED(hr), "Failed to unlock destination vertex buffer, hr %#x.\n", hr);
689 IDirect3DVertexBuffer7_Release(dst_vb2);
690 IDirect3DVertexBuffer7_Release(dst_vb1);
691 IDirect3DVertexBuffer7_Release(src_vb);
692 IDirect3D7_Release(d3d7);
693 IDirect3DDevice7_Release(device);
694 DestroyWindow(window);
697 static void test_coop_level_create_device_window(void)
699 HWND focus_window, device_window;
700 IDirectDraw7 *ddraw;
701 HRESULT hr;
703 focus_window = create_window();
704 ddraw = create_ddraw();
705 ok(!!ddraw, "Failed to create a ddraw object.\n");
707 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
708 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
709 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
710 ok(!device_window, "Unexpected device window found.\n");
711 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
712 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
713 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
714 ok(!device_window, "Unexpected device window found.\n");
715 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
716 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
717 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
718 ok(!device_window, "Unexpected device window found.\n");
719 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
720 ok(hr == DDERR_INVALIDPARAMS, "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 || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
725 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
726 ok(!device_window, "Unexpected device window found.\n");
728 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
729 if (broken(hr == DDERR_INVALIDPARAMS))
731 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
732 IDirectDraw7_Release(ddraw);
733 DestroyWindow(focus_window);
734 return;
737 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
738 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
739 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
740 ok(!device_window, "Unexpected device window found.\n");
741 hr = IDirectDraw7_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
742 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
743 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
744 ok(!device_window, "Unexpected device window found.\n");
746 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
747 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
748 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
749 ok(!device_window, "Unexpected device window found.\n");
750 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
751 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
752 ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
753 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
754 ok(!!device_window, "Device window not found.\n");
756 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
757 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
758 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
759 ok(!device_window, "Unexpected device window found.\n");
760 hr = IDirectDraw7_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
761 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
762 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
763 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
764 ok(!!device_window, "Device window not found.\n");
766 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
767 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
768 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
769 ok(!device_window, "Unexpected device window found.\n");
770 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
771 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
772 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
773 ok(!device_window, "Unexpected device window found.\n");
774 hr = IDirectDraw7_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
775 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
776 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
777 ok(!device_window, "Unexpected device window found.\n");
778 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
779 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
780 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
781 ok(!!device_window, "Device window not found.\n");
783 IDirectDraw7_Release(ddraw);
784 DestroyWindow(focus_window);
787 static void test_clipper_blt(void)
789 IDirectDrawSurface7 *src_surface, *dst_surface;
790 RECT client_rect, src_rect;
791 IDirectDrawClipper *clipper;
792 DDSURFACEDESC2 surface_desc;
793 unsigned int i, j, x, y;
794 IDirectDraw7 *ddraw;
795 RGNDATA *rgn_data;
796 D3DCOLOR color;
797 ULONG refcount;
798 HRGN r1, r2;
799 HWND window;
800 DDBLTFX fx;
801 HRESULT hr;
802 DWORD *ptr;
803 DWORD ret;
805 static const DWORD src_data[] =
807 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
808 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
809 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
811 static const D3DCOLOR expected1[] =
813 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
814 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
815 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
816 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
818 /* Nvidia on Windows seems to have an off-by-one error
819 * when processing source rectangles. Our left = 1 and
820 * right = 5 input reads from x = {1, 2, 3}. x = 4 is
821 * read as well, but only for the edge pixels on the
822 * output image. The bug happens on the y axis as well,
823 * but we only read one row there, and all source rows
824 * contain the same data. This bug is not dependent on
825 * the presence of a clipper. */
826 static const D3DCOLOR expected1_broken[] =
828 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
829 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
830 0x00000000, 0x00000000, 0x00ff0000, 0x00ff0000,
831 0x00000000, 0x00000000, 0x0000ff00, 0x00ff0000,
833 static const D3DCOLOR expected2[] =
835 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
836 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
837 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
838 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
841 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
842 10, 10, 640, 480, 0, 0, 0, 0);
843 ShowWindow(window, SW_SHOW);
844 ddraw = create_ddraw();
845 ok(!!ddraw, "Failed to create a ddraw object.\n");
847 ret = GetClientRect(window, &client_rect);
848 ok(ret, "Failed to get client rect.\n");
849 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
850 ok(ret, "Failed to map client rect.\n");
852 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
853 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
855 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
856 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
857 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
858 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
859 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
860 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
861 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
862 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
863 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
864 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
865 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
866 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
867 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
868 ok(rgn_data->rdh.nCount >= 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
869 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
870 "Got unexpected bounding rect %s, expected %s.\n",
871 wine_dbgstr_rect(&rgn_data->rdh.rcBound), wine_dbgstr_rect(&client_rect));
872 HeapFree(GetProcessHeap(), 0, rgn_data);
874 r1 = CreateRectRgn(0, 0, 320, 240);
875 ok(!!r1, "Failed to create region.\n");
876 r2 = CreateRectRgn(320, 240, 640, 480);
877 ok(!!r2, "Failed to create region.\n");
878 CombineRgn(r1, r1, r2, RGN_OR);
879 ret = GetRegionData(r1, 0, NULL);
880 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
881 ret = GetRegionData(r1, ret, rgn_data);
882 ok(!!ret, "Failed to get region data.\n");
884 DeleteObject(r2);
885 DeleteObject(r1);
887 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
888 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
889 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
890 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
891 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
892 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
894 HeapFree(GetProcessHeap(), 0, rgn_data);
896 memset(&surface_desc, 0, sizeof(surface_desc));
897 surface_desc.dwSize = sizeof(surface_desc);
898 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
899 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
900 surface_desc.dwWidth = 640;
901 surface_desc.dwHeight = 480;
902 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
903 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
904 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
905 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
906 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
907 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
909 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
910 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
911 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
912 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
914 memset(&fx, 0, sizeof(fx));
915 fx.dwSize = sizeof(fx);
916 hr = IDirectDrawSurface7_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
917 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
918 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
919 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
921 hr = IDirectDrawSurface7_Lock(src_surface, NULL, &surface_desc, 0, NULL);
922 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
923 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
924 ptr = surface_desc.lpSurface;
925 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
926 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
927 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
928 hr = IDirectDrawSurface7_Unlock(src_surface, NULL);
929 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
931 hr = IDirectDrawSurface7_SetClipper(dst_surface, clipper);
932 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
934 SetRect(&src_rect, 1, 1, 5, 2);
935 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
936 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
937 for (i = 0; i < 4; ++i)
939 for (j = 0; j < 4; ++j)
941 x = 80 * ((2 * j) + 1);
942 y = 60 * ((2 * i) + 1);
943 color = get_surface_color(dst_surface, x, y);
944 ok(compare_color(color, expected1[i * 4 + j], 1)
945 || broken(compare_color(color, expected1_broken[i * 4 + j], 1)),
946 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
950 U5(fx).dwFillColor = 0xff0000ff;
951 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
952 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
953 for (i = 0; i < 4; ++i)
955 for (j = 0; j < 4; ++j)
957 x = 80 * ((2 * j) + 1);
958 y = 60 * ((2 * i) + 1);
959 color = get_surface_color(dst_surface, x, y);
960 ok(compare_color(color, expected2[i * 4 + j], 1),
961 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
965 hr = IDirectDrawSurface7_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
966 ok(hr == DDERR_BLTFASTCANTCLIP, "Got unexpected hr %#x.\n", hr);
968 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
969 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
970 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
971 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
972 DestroyWindow(window);
973 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
974 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
975 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
976 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
977 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
978 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
979 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
980 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
981 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
982 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
983 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
984 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
986 IDirectDrawSurface7_Release(dst_surface);
987 IDirectDrawSurface7_Release(src_surface);
988 refcount = IDirectDrawClipper_Release(clipper);
989 ok(!refcount, "Clipper has %u references left.\n", refcount);
990 IDirectDraw7_Release(ddraw);
993 static void test_coop_level_d3d_state(void)
995 IDirectDrawSurface7 *rt, *surface;
996 IDirect3DDevice7 *device;
997 IDirectDraw7 *ddraw;
998 IDirect3D7 *d3d;
999 D3DCOLOR color;
1000 DWORD value;
1001 HWND window;
1002 HRESULT hr;
1004 window = create_window();
1005 if (!(device = create_device(window, DDSCL_NORMAL)))
1007 skip("Failed to create a 3D device, skipping test.\n");
1008 DestroyWindow(window);
1009 return;
1012 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1013 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1014 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
1015 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1016 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
1017 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
1018 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1019 ok(!value, "Got unexpected alpha blend enable state %#x.\n", value);
1020 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
1021 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
1022 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
1023 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1024 color = get_surface_color(rt, 320, 240);
1025 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1027 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1028 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1029 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1030 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1031 IDirect3D7_Release(d3d);
1032 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1033 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1034 hr = IDirectDrawSurface7_IsLost(rt);
1035 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
1036 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
1037 ok(SUCCEEDED(hr), "Failed to restore surfaces, hr %#x.\n", hr);
1038 IDirectDraw7_Release(ddraw);
1040 hr = IDirect3DDevice7_GetRenderTarget(device, &surface);
1041 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1042 ok(surface == rt, "Got unexpected surface %p.\n", surface);
1043 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
1044 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1045 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
1046 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
1047 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1048 ok(!!value, "Got unexpected alpha blend enable state %#x.\n", value);
1049 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
1050 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1051 color = get_surface_color(rt, 320, 240);
1052 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1054 IDirectDrawSurface7_Release(surface);
1055 IDirectDrawSurface7_Release(rt);
1056 IDirect3DDevice7_Release(device);
1057 DestroyWindow(window);
1060 static void test_surface_interface_mismatch(void)
1062 IDirectDraw7 *ddraw = NULL;
1063 IDirect3D7 *d3d = NULL;
1064 IDirectDrawSurface7 *surface = NULL, *ds;
1065 IDirectDrawSurface3 *surface3 = NULL;
1066 IDirect3DDevice7 *device = NULL;
1067 DDSURFACEDESC2 surface_desc;
1068 DDPIXELFORMAT z_fmt;
1069 ULONG refcount;
1070 HRESULT hr;
1071 D3DCOLOR color;
1072 HWND window;
1074 window = create_window();
1075 ddraw = create_ddraw();
1076 ok(!!ddraw, "Failed to create a ddraw object.\n");
1077 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1078 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1080 memset(&surface_desc, 0, sizeof(surface_desc));
1081 surface_desc.dwSize = sizeof(surface_desc);
1082 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1083 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
1084 surface_desc.dwWidth = 640;
1085 surface_desc.dwHeight = 480;
1087 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1088 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1090 hr = IDirectDrawSurface7_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
1091 ok(SUCCEEDED(hr), "Failed to QI IDirectDrawSurface3, hr %#x.\n", hr);
1093 if (FAILED(IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d)))
1095 skip("D3D interface is not available, skipping test.\n");
1096 goto cleanup;
1099 memset(&z_fmt, 0, sizeof(z_fmt));
1100 hr = IDirect3D7_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
1101 if (FAILED(hr) || !z_fmt.dwSize)
1103 skip("No depth buffer formats available, skipping test.\n");
1104 goto cleanup;
1107 memset(&surface_desc, 0, sizeof(surface_desc));
1108 surface_desc.dwSize = sizeof(surface_desc);
1109 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
1110 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1111 U4(surface_desc).ddpfPixelFormat = z_fmt;
1112 surface_desc.dwWidth = 640;
1113 surface_desc.dwHeight = 480;
1114 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL);
1115 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
1116 if (FAILED(hr))
1117 goto cleanup;
1119 /* Using a different surface interface version still works */
1120 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
1121 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
1122 refcount = IDirectDrawSurface7_Release(ds);
1123 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
1124 if (FAILED(hr))
1125 goto cleanup;
1127 /* Here too */
1128 hr = IDirect3D7_CreateDevice(d3d, &IID_IDirect3DHALDevice, (IDirectDrawSurface7 *)surface3, &device);
1129 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
1130 if (FAILED(hr))
1131 goto cleanup;
1133 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
1134 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1135 color = get_surface_color(surface, 320, 240);
1136 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1138 cleanup:
1139 if (surface3) IDirectDrawSurface3_Release(surface3);
1140 if (surface) IDirectDrawSurface7_Release(surface);
1141 if (device) IDirect3DDevice7_Release(device);
1142 if (d3d) IDirect3D7_Release(d3d);
1143 if (ddraw) IDirectDraw7_Release(ddraw);
1144 DestroyWindow(window);
1147 static void test_coop_level_threaded(void)
1149 struct create_window_thread_param p;
1150 IDirectDraw7 *ddraw;
1151 HRESULT hr;
1153 ddraw = create_ddraw();
1154 ok(!!ddraw, "Failed to create a ddraw object.\n");
1155 create_window_thread(&p);
1157 hr = IDirectDraw7_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1158 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1160 IDirectDraw7_Release(ddraw);
1161 destroy_window_thread(&p);
1164 static void test_depth_blit(void)
1166 IDirect3DDevice7 *device;
1167 static struct
1169 float x, y, z;
1170 DWORD color;
1172 quad1[] =
1174 { -1.0, 1.0, 0.50f, 0xff00ff00},
1175 { 1.0, 1.0, 0.50f, 0xff00ff00},
1176 { -1.0, -1.0, 0.50f, 0xff00ff00},
1177 { 1.0, -1.0, 0.50f, 0xff00ff00},
1179 static const D3DCOLOR expected_colors[4][4] =
1181 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1182 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1183 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1184 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1186 DDSURFACEDESC2 ddsd_new, ddsd_existing;
1188 IDirectDrawSurface7 *ds1, *ds2, *ds3, *rt;
1189 RECT src_rect, dst_rect;
1190 unsigned int i, j;
1191 D3DCOLOR color;
1192 HRESULT hr;
1193 IDirect3D7 *d3d;
1194 IDirectDraw7 *ddraw;
1195 DDBLTFX fx;
1196 HWND window;
1198 window = create_window();
1199 if (!(device = create_device(window, DDSCL_NORMAL)))
1201 skip("Failed to create a 3D device, skipping test.\n");
1202 DestroyWindow(window);
1203 return;
1206 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1207 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
1208 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1209 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
1210 IDirect3D7_Release(d3d);
1212 ds1 = get_depth_stencil(device);
1214 memset(&ddsd_new, 0, sizeof(ddsd_new));
1215 ddsd_new.dwSize = sizeof(ddsd_new);
1216 memset(&ddsd_existing, 0, sizeof(ddsd_existing));
1217 ddsd_existing.dwSize = sizeof(ddsd_existing);
1218 hr = IDirectDrawSurface7_GetSurfaceDesc(ds1, &ddsd_existing);
1219 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
1220 ddsd_new.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1221 ddsd_new.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1222 ddsd_new.dwWidth = ddsd_existing.dwWidth;
1223 ddsd_new.dwHeight = ddsd_existing.dwHeight;
1224 U4(ddsd_new).ddpfPixelFormat = U4(ddsd_existing).ddpfPixelFormat;
1225 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd_new, &ds2, NULL);
1226 ok(SUCCEEDED(hr), "Failed to create a z buffer, hr %#x.\n", hr);
1227 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd_new, &ds3, NULL);
1228 ok(SUCCEEDED(hr), "Failed to create a z buffer, hr %#x.\n", hr);
1229 IDirectDraw7_Release(ddraw);
1231 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
1232 ok(SUCCEEDED(hr), "Failed to enable z testing, hr %#x.\n", hr);
1233 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
1234 ok(SUCCEEDED(hr), "Failed to set the z function, hr %#x.\n", hr);
1235 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
1236 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
1238 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
1239 ok(SUCCEEDED(hr), "Failed to clear the z buffer, hr %#x.\n", hr);
1241 /* Partial blit. */
1242 SetRect(&src_rect, 0, 0, 320, 240);
1243 SetRect(&dst_rect, 0, 0, 320, 240);
1244 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1245 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1246 /* Different locations. */
1247 SetRect(&src_rect, 0, 0, 320, 240);
1248 SetRect(&dst_rect, 320, 240, 640, 480);
1249 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1250 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1251 /* Stretched. */
1252 SetRect(&src_rect, 0, 0, 320, 240);
1253 SetRect(&dst_rect, 0, 0, 640, 480);
1254 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1255 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1256 /* Flipped. */
1257 SetRect(&src_rect, 0, 480, 640, 0);
1258 SetRect(&dst_rect, 0, 0, 640, 480);
1259 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1260 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1261 SetRect(&src_rect, 0, 0, 640, 480);
1262 SetRect(&dst_rect, 0, 480, 640, 0);
1263 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1264 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1265 /* Full, explicit. */
1266 SetRect(&src_rect, 0, 0, 640, 480);
1267 SetRect(&dst_rect, 0, 0, 640, 480);
1268 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1269 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1270 /* Depth -> color blit: Succeeds on Win7 + Radeon HD 5700, fails on WinXP + Radeon X1600 */
1272 /* Depth blit inside a BeginScene / EndScene pair */
1273 hr = IDirect3DDevice7_BeginScene(device);
1274 ok(SUCCEEDED(hr), "Failed to start scene, hr %#x.\n", hr);
1275 /* From the current depth stencil */
1276 hr = IDirectDrawSurface7_Blt(ds2, NULL, ds1, NULL, DDBLT_WAIT, NULL);
1277 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1278 /* To the current depth stencil */
1279 hr = IDirectDrawSurface7_Blt(ds1, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1280 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1281 /* Between unbound surfaces */
1282 hr = IDirectDrawSurface7_Blt(ds3, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1283 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1284 hr = IDirect3DDevice7_EndScene(device);
1285 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1287 /* Avoid changing the depth stencil, it doesn't work properly on Windows.
1288 * Instead use DDBLT_DEPTHFILL to clear the depth stencil. Unfortunately
1289 * drivers disagree on the meaning of dwFillDepth. Only 0 seems to produce
1290 * a reliable result(z = 0.0) */
1291 memset(&fx, 0, sizeof(fx));
1292 fx.dwSize = sizeof(fx);
1293 hr = IDirectDrawSurface7_Blt(ds2, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
1294 ok(SUCCEEDED(hr), "Failed to clear the source z buffer, hr %#x.\n", hr);
1296 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET, 0xffff0000, 1.0f, 0);
1297 ok(SUCCEEDED(hr), "Failed to clear the color and z buffers, hr %#x.\n", hr);
1298 SetRect(&dst_rect, 0, 0, 320, 240);
1299 hr = IDirectDrawSurface7_Blt(ds1, &dst_rect, ds2, NULL, DDBLT_WAIT, NULL);
1300 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1301 IDirectDrawSurface7_Release(ds3);
1302 IDirectDrawSurface7_Release(ds2);
1303 IDirectDrawSurface7_Release(ds1);
1305 hr = IDirect3DDevice7_BeginScene(device);
1306 ok(SUCCEEDED(hr), "Failed to start scene, hr %#x.\n", hr);
1307 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
1308 quad1, 4, 0);
1309 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1310 hr = IDirect3DDevice7_EndScene(device);
1311 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1313 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1314 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1315 for (i = 0; i < 4; ++i)
1317 for (j = 0; j < 4; ++j)
1319 unsigned int x = 80 * ((2 * j) + 1);
1320 unsigned int y = 60 * ((2 * i) + 1);
1321 color = get_surface_color(rt, x, y);
1322 ok(compare_color(color, expected_colors[i][j], 1),
1323 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
1327 IDirectDrawSurface7_Release(rt);
1328 IDirect3DDevice7_Release(device);
1329 DestroyWindow(window);
1332 static void test_texture_load_ckey(void)
1334 HWND window;
1335 IDirect3DDevice7 *device;
1336 IDirectDraw7 *ddraw;
1337 IDirectDrawSurface7 *src;
1338 IDirectDrawSurface7 *dst;
1339 DDSURFACEDESC2 ddsd;
1340 HRESULT hr;
1341 DDCOLORKEY ckey;
1342 IDirect3D7 *d3d;
1344 window = create_window();
1345 if (!(device = create_device(window, DDSCL_NORMAL)))
1347 skip("Failed to create a 3D device, skipping test.\n");
1348 DestroyWindow(window);
1349 return;
1352 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1353 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
1354 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1355 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
1356 IDirect3D7_Release(d3d);
1358 memset(&ddsd, 0, sizeof(ddsd));
1359 ddsd.dwSize = sizeof(ddsd);
1360 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
1361 ddsd.dwHeight = 128;
1362 ddsd.dwWidth = 128;
1363 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
1364 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &src, NULL);
1365 ok(SUCCEEDED(hr), "Failed to create source texture, hr %#x.\n", hr);
1366 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1367 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &dst, NULL);
1368 ok(SUCCEEDED(hr), "Failed to create destination texture, hr %#x.\n", hr);
1370 /* No surface has a color key */
1371 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1372 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1373 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0xdeadbeef;
1374 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1375 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1376 ok(ckey.dwColorSpaceLowValue == 0xdeadbeef, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1377 ok(ckey.dwColorSpaceHighValue == 0xdeadbeef, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1379 /* Source surface has a color key */
1380 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
1381 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
1382 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1383 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1384 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1385 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1386 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1387 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1388 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1390 /* Both surfaces have a color key: Dest ckey is overwritten */
1391 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x000000ff;
1392 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1393 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1394 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1395 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1396 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1397 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1398 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1399 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1401 /* Only the destination has a color key: It is deleted. This behavior differs from
1402 * IDirect3DTexture(2)::Load */
1403 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, NULL);
1404 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1405 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
1406 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1407 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1408 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1409 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1410 todo_wine ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1412 IDirectDrawSurface7_Release(dst);
1413 IDirectDrawSurface7_Release(src);
1414 IDirectDraw7_Release(ddraw);
1415 IDirect3DDevice7_Release(device);
1416 DestroyWindow(window);
1419 static void test_zenable(void)
1421 static struct
1423 struct vec4 position;
1424 D3DCOLOR diffuse;
1426 tquad[] =
1428 {{ 0.0f, 480.0f, -0.5f, 1.0f}, 0xff00ff00},
1429 {{ 0.0f, 0.0f, -0.5f, 1.0f}, 0xff00ff00},
1430 {{640.0f, 480.0f, 1.5f, 1.0f}, 0xff00ff00},
1431 {{640.0f, 0.0f, 1.5f, 1.0f}, 0xff00ff00},
1433 IDirect3DDevice7 *device;
1434 IDirectDrawSurface7 *rt;
1435 D3DCOLOR color;
1436 HWND window;
1437 HRESULT hr;
1438 UINT x, y;
1439 UINT i, j;
1441 window = create_window();
1442 if (!(device = create_device(window, DDSCL_NORMAL)))
1444 skip("Failed to create a 3D device, skipping test.\n");
1445 DestroyWindow(window);
1446 return;
1449 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1450 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
1452 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 0.0f, 0);
1453 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1454 hr = IDirect3DDevice7_BeginScene(device);
1455 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1456 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_DIFFUSE, tquad, 4, 0);
1457 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1458 hr = IDirect3DDevice7_EndScene(device);
1459 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1461 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1462 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1463 for (i = 0; i < 4; ++i)
1465 for (j = 0; j < 4; ++j)
1467 x = 80 * ((2 * j) + 1);
1468 y = 60 * ((2 * i) + 1);
1469 color = get_surface_color(rt, x, y);
1470 ok(compare_color(color, 0x0000ff00, 1),
1471 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1474 IDirectDrawSurface7_Release(rt);
1476 IDirect3DDevice7_Release(device);
1477 DestroyWindow(window);
1480 static void test_ck_rgba(void)
1482 static struct
1484 struct vec4 position;
1485 struct vec2 texcoord;
1487 tquad[] =
1489 {{ 0.0f, 480.0f, 0.25f, 1.0f}, {0.0f, 0.0f}},
1490 {{ 0.0f, 0.0f, 0.25f, 1.0f}, {0.0f, 1.0f}},
1491 {{640.0f, 480.0f, 0.25f, 1.0f}, {1.0f, 0.0f}},
1492 {{640.0f, 0.0f, 0.25f, 1.0f}, {1.0f, 1.0f}},
1493 {{ 0.0f, 480.0f, 0.75f, 1.0f}, {0.0f, 0.0f}},
1494 {{ 0.0f, 0.0f, 0.75f, 1.0f}, {0.0f, 1.0f}},
1495 {{640.0f, 480.0f, 0.75f, 1.0f}, {1.0f, 0.0f}},
1496 {{640.0f, 0.0f, 0.75f, 1.0f}, {1.0f, 1.0f}},
1498 static const struct
1500 D3DCOLOR fill_color;
1501 BOOL color_key;
1502 BOOL blend;
1503 D3DCOLOR result1, result1_broken;
1504 D3DCOLOR result2, result2_broken;
1506 tests[] =
1508 /* r200 on Windows doesn't check the alpha component when applying the color
1509 * key, so the key matches on every texel. */
1510 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1511 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1512 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1513 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1514 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00ff0000, 0x00807f00, 0x000000ff},
1515 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x00ff0000, 0x0000ff00, 0x000000ff},
1516 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00, 0x00807f00, 0x00807f00},
1517 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1520 IDirectDrawSurface7 *texture;
1521 DDSURFACEDESC2 surface_desc;
1522 IDirect3DDevice7 *device;
1523 IDirectDrawSurface7 *rt;
1524 IDirectDraw7 *ddraw;
1525 IDirect3D7 *d3d;
1526 D3DCOLOR color;
1527 HWND window;
1528 DDBLTFX fx;
1529 HRESULT hr;
1530 UINT i;
1532 window = create_window();
1533 if (!(device = create_device(window, DDSCL_NORMAL)))
1535 skip("Failed to create a 3D device, skipping test.\n");
1536 DestroyWindow(window);
1537 return;
1540 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1541 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1542 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1543 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1544 IDirect3D7_Release(d3d);
1546 memset(&surface_desc, 0, sizeof(surface_desc));
1547 surface_desc.dwSize = sizeof(surface_desc);
1548 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1549 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1550 surface_desc.dwWidth = 256;
1551 surface_desc.dwHeight = 256;
1552 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1553 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1554 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1555 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1556 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1557 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1558 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1559 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1560 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1561 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
1562 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1564 hr = IDirect3DDevice7_SetTexture(device, 0, texture);
1565 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1566 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1567 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1568 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1569 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1571 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1572 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1574 for (i = 0; i < ARRAY_SIZE(tests); ++i)
1576 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1577 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1578 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1579 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1581 memset(&fx, 0, sizeof(fx));
1582 fx.dwSize = sizeof(fx);
1583 U5(fx).dwFillColor = tests[i].fill_color;
1584 hr = IDirectDrawSurface7_Blt(texture, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1585 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1587 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 1.0f, 0);
1588 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1589 hr = IDirect3DDevice7_BeginScene(device);
1590 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1591 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1592 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1593 hr = IDirect3DDevice7_EndScene(device);
1594 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1596 color = get_surface_color(rt, 320, 240);
1597 ok(compare_color(color, tests[i].result1, 1) || compare_color(color, tests[i].result1_broken, 1),
1598 "Expected color 0x%08x for test %u, got 0x%08x.\n",
1599 tests[i].result1, i, color);
1601 U5(fx).dwFillColor = 0xff0000ff;
1602 hr = IDirectDrawSurface7_Blt(texture, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1603 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1605 hr = IDirect3DDevice7_BeginScene(device);
1606 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1607 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[4], 4, 0);
1608 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1609 hr = IDirect3DDevice7_EndScene(device);
1610 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1612 /* This tests that fragments that are masked out by the color key are
1613 * discarded, instead of just fully transparent. */
1614 color = get_surface_color(rt, 320, 240);
1615 ok(compare_color(color, tests[i].result2, 1) || compare_color(color, tests[i].result2_broken, 1),
1616 "Expected color 0x%08x for test %u, got 0x%08x.\n",
1617 tests[i].result2, i, color);
1620 IDirectDrawSurface7_Release(rt);
1621 IDirectDrawSurface7_Release(texture);
1622 IDirectDraw7_Release(ddraw);
1623 IDirect3DDevice7_Release(device);
1624 DestroyWindow(window);
1627 static void test_ck_default(void)
1629 static struct
1631 struct vec4 position;
1632 struct vec2 texcoord;
1634 tquad[] =
1636 {{ 0.0f, 480.0f, 0.0f, 1.0f}, {0.0f, 0.0f}},
1637 {{ 0.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 1.0f}},
1638 {{640.0f, 480.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
1639 {{640.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
1641 IDirectDrawSurface7 *surface, *rt;
1642 DDSURFACEDESC2 surface_desc;
1643 IDirect3DDevice7 *device;
1644 IDirectDraw7 *ddraw;
1645 IDirect3D7 *d3d;
1646 D3DCOLOR color;
1647 DWORD value;
1648 HWND window;
1649 DDBLTFX fx;
1650 HRESULT hr;
1652 window = create_window();
1653 if (!(device = create_device(window, DDSCL_NORMAL)))
1655 skip("Failed to create a 3D device, skipping test.\n");
1656 DestroyWindow(window);
1657 return;
1660 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1661 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1662 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1663 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1664 IDirect3D7_Release(d3d);
1666 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1667 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1669 memset(&surface_desc, 0, sizeof(surface_desc));
1670 surface_desc.dwSize = sizeof(surface_desc);
1671 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1672 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1673 surface_desc.dwWidth = 256;
1674 surface_desc.dwHeight = 256;
1675 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1676 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
1677 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1678 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1679 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1680 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1681 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
1682 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
1683 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1684 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1685 hr = IDirect3DDevice7_SetTexture(device, 0, surface);
1686 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1688 memset(&fx, 0, sizeof(fx));
1689 fx.dwSize = sizeof(fx);
1690 U5(fx).dwFillColor = 0x000000ff;
1691 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1692 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
1694 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
1695 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1696 hr = IDirect3DDevice7_BeginScene(device);
1697 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1698 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1699 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1700 ok(!value, "Got unexpected color keying state %#x.\n", value);
1701 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1702 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1703 hr = IDirect3DDevice7_EndScene(device);
1704 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1705 color = get_surface_color(rt, 320, 240);
1706 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1708 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
1709 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1710 hr = IDirect3DDevice7_BeginScene(device);
1711 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1712 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
1713 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1714 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1715 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1716 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1717 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1718 ok(!!value, "Got unexpected color keying state %#x.\n", value);
1719 hr = IDirect3DDevice7_EndScene(device);
1720 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1721 color = get_surface_color(rt, 320, 240);
1722 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1724 IDirectDrawSurface7_Release(surface);
1725 IDirectDrawSurface7_Release(rt);
1726 IDirect3DDevice7_Release(device);
1727 IDirectDraw7_Release(ddraw);
1728 DestroyWindow(window);
1731 static void test_ck_complex(void)
1733 IDirectDrawSurface7 *surface, *mipmap, *tmp;
1734 D3DDEVICEDESC7 device_desc;
1735 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
1736 DDSURFACEDESC2 surface_desc;
1737 IDirect3DDevice7 *device;
1738 DDCOLORKEY color_key;
1739 IDirectDraw7 *ddraw;
1740 IDirect3D7 *d3d;
1741 unsigned int i;
1742 ULONG refcount;
1743 HWND window;
1744 HRESULT hr;
1746 window = create_window();
1747 if (!(device = create_device(window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
1749 skip("Failed to create a 3D device, skipping test.\n");
1750 DestroyWindow(window);
1751 return;
1753 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
1754 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
1755 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1756 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1757 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1758 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1759 IDirect3D7_Release(d3d);
1761 memset(&surface_desc, 0, sizeof(surface_desc));
1762 surface_desc.dwSize = sizeof(surface_desc);
1763 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1764 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1765 surface_desc.dwWidth = 128;
1766 surface_desc.dwHeight = 128;
1767 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1768 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1770 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1771 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1772 color_key.dwColorSpaceLowValue = 0x0000ff00;
1773 color_key.dwColorSpaceHighValue = 0x0000ff00;
1774 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1775 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1776 memset(&color_key, 0, sizeof(color_key));
1777 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1778 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1779 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1780 color_key.dwColorSpaceLowValue);
1781 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1782 color_key.dwColorSpaceHighValue);
1784 mipmap = surface;
1785 IDirectDrawSurface_AddRef(mipmap);
1786 for (i = 0; i < 7; ++i)
1788 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
1789 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
1790 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1791 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1793 color_key.dwColorSpaceLowValue = 0x000000ff;
1794 color_key.dwColorSpaceHighValue = 0x000000ff;
1795 hr = IDirectDrawSurface7_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1796 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x, i %u.\n", hr, i);
1798 IDirectDrawSurface_Release(mipmap);
1799 mipmap = tmp;
1802 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
1803 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
1804 IDirectDrawSurface_Release(mipmap);
1805 refcount = IDirectDrawSurface7_Release(surface);
1806 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1808 memset(&surface_desc, 0, sizeof(surface_desc));
1809 surface_desc.dwSize = sizeof(surface_desc);
1810 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
1811 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
1812 U5(surface_desc).dwBackBufferCount = 1;
1813 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1814 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1816 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1817 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1818 color_key.dwColorSpaceLowValue = 0x0000ff00;
1819 color_key.dwColorSpaceHighValue = 0x0000ff00;
1820 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1821 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1822 memset(&color_key, 0, sizeof(color_key));
1823 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1824 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1825 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1826 color_key.dwColorSpaceLowValue);
1827 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1828 color_key.dwColorSpaceHighValue);
1830 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &tmp);
1831 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
1833 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1834 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1835 color_key.dwColorSpaceLowValue = 0x0000ff00;
1836 color_key.dwColorSpaceHighValue = 0x0000ff00;
1837 hr = IDirectDrawSurface7_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1838 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1839 memset(&color_key, 0, sizeof(color_key));
1840 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1841 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1842 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1843 color_key.dwColorSpaceLowValue);
1844 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1845 color_key.dwColorSpaceHighValue);
1847 IDirectDrawSurface_Release(tmp);
1849 refcount = IDirectDrawSurface7_Release(surface);
1850 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1852 if (!(device_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP))
1854 skip("Device does not support cubemaps.\n");
1855 goto cleanup;
1857 memset(&surface_desc, 0, sizeof(surface_desc));
1858 surface_desc.dwSize = sizeof(surface_desc);
1859 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1860 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1861 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
1862 surface_desc.dwWidth = 128;
1863 surface_desc.dwHeight = 128;
1864 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1865 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1867 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1868 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1869 color_key.dwColorSpaceLowValue = 0x0000ff00;
1870 color_key.dwColorSpaceHighValue = 0x0000ff00;
1871 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1872 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1874 caps.dwCaps2 = DDSCAPS2_CUBEMAP_NEGATIVEZ;
1875 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
1876 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
1878 hr = IDirectDrawSurface7_GetColorKey(mipmap, DDCKEY_SRCBLT, &color_key);
1879 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1880 color_key.dwColorSpaceLowValue = 0x000000ff;
1881 color_key.dwColorSpaceHighValue = 0x000000ff;
1882 hr = IDirectDrawSurface7_SetColorKey(mipmap, DDCKEY_SRCBLT, &color_key);
1883 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1885 color_key.dwColorSpaceLowValue = 0;
1886 color_key.dwColorSpaceHighValue = 0;
1887 hr = IDirectDrawSurface7_GetColorKey(mipmap, DDCKEY_SRCBLT, &color_key);
1888 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1889 ok(color_key.dwColorSpaceLowValue == 0x000000ff, "Got unexpected value 0x%08x.\n",
1890 color_key.dwColorSpaceLowValue);
1891 ok(color_key.dwColorSpaceHighValue == 0x000000ff, "Got unexpected value 0x%08x.\n",
1892 color_key.dwColorSpaceHighValue);
1894 IDirectDrawSurface_AddRef(mipmap);
1895 for (i = 0; i < 7; ++i)
1897 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
1898 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
1899 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1900 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1902 color_key.dwColorSpaceLowValue = 0x000000ff;
1903 color_key.dwColorSpaceHighValue = 0x000000ff;
1904 hr = IDirectDrawSurface7_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1905 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x, i %u.\n", hr, i);
1907 IDirectDrawSurface_Release(mipmap);
1908 mipmap = tmp;
1911 IDirectDrawSurface7_Release(mipmap);
1913 refcount = IDirectDrawSurface7_Release(surface);
1914 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1916 cleanup:
1917 IDirectDraw7_Release(ddraw);
1918 refcount = IDirect3DDevice7_Release(device);
1919 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1920 DestroyWindow(window);
1923 struct qi_test
1925 REFIID iid;
1926 REFIID refcount_iid;
1927 HRESULT hr;
1930 static void test_qi(const char *test_name, IUnknown *base_iface,
1931 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
1933 ULONG refcount, expected_refcount;
1934 IUnknown *iface1, *iface2;
1935 HRESULT hr;
1936 UINT i, j;
1938 for (i = 0; i < entry_count; ++i)
1940 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
1941 ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
1942 if (SUCCEEDED(hr))
1944 for (j = 0; j < entry_count; ++j)
1946 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
1947 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
1948 if (SUCCEEDED(hr))
1950 expected_refcount = 0;
1951 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
1952 ++expected_refcount;
1953 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
1954 ++expected_refcount;
1955 refcount = IUnknown_Release(iface2);
1956 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
1957 refcount, test_name, i, j, expected_refcount);
1961 expected_refcount = 0;
1962 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
1963 ++expected_refcount;
1964 refcount = IUnknown_Release(iface1);
1965 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
1966 refcount, test_name, i, expected_refcount);
1971 static void test_surface_qi(void)
1973 static const struct qi_test tests[] =
1975 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
1976 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
1977 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
1978 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
1979 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
1980 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
1981 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
1982 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
1983 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
1984 {&IID_IDirect3DDevice7, NULL, E_NOINTERFACE},
1985 {&IID_IDirect3DDevice3, NULL, E_NOINTERFACE},
1986 {&IID_IDirect3DDevice2, NULL, E_NOINTERFACE},
1987 {&IID_IDirect3DDevice, NULL, E_NOINTERFACE},
1988 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
1989 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
1990 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
1991 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
1992 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
1993 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
1994 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
1995 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
1996 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
1997 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
1998 {&IID_IDirect3D, NULL, E_NOINTERFACE},
1999 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
2000 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
2001 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
2002 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
2003 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
2004 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
2005 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
2006 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
2007 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
2008 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
2009 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
2010 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
2011 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
2012 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
2013 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
2014 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
2015 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
2016 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
2017 {NULL, NULL, E_INVALIDARG },
2020 IDirectDrawSurface7 *surface;
2021 DDSURFACEDESC2 surface_desc;
2022 IDirect3DDevice7 *device;
2023 IDirectDraw7 *ddraw;
2024 HWND window;
2025 HRESULT hr;
2027 window = create_window();
2028 /* Try to create a D3D device to see if the ddraw implementation supports
2029 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
2030 * doesn't support e.g. the IDirect3DTexture interfaces. */
2031 if (!(device = create_device(window, DDSCL_NORMAL)))
2033 skip("Failed to create a 3D device, skipping test.\n");
2034 DestroyWindow(window);
2035 return;
2037 IDirect3DDevice_Release(device);
2038 ddraw = create_ddraw();
2039 ok(!!ddraw, "Failed to create a ddraw object.\n");
2040 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2041 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2043 memset(&surface_desc, 0, sizeof(surface_desc));
2044 surface_desc.dwSize = sizeof(surface_desc);
2045 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2046 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2047 surface_desc.dwWidth = 512;
2048 surface_desc.dwHeight = 512;
2049 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, (IDirectDrawSurface7 **)0xdeadbeef, NULL);
2050 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
2051 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2052 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
2054 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface7, tests, ARRAY_SIZE(tests));
2056 IDirectDrawSurface7_Release(surface);
2057 IDirectDraw7_Release(ddraw);
2058 DestroyWindow(window);
2061 static void test_device_qi(void)
2063 static const struct qi_test tests[] =
2065 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
2066 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
2067 {&IID_IDirectDrawGammaControl, NULL, E_NOINTERFACE},
2068 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2069 {&IID_IDirectDrawSurface7, NULL, E_NOINTERFACE},
2070 {&IID_IDirectDrawSurface4, NULL, E_NOINTERFACE},
2071 {&IID_IDirectDrawSurface3, NULL, E_NOINTERFACE},
2072 {&IID_IDirectDrawSurface2, NULL, E_NOINTERFACE},
2073 {&IID_IDirectDrawSurface, NULL, E_NOINTERFACE},
2074 {&IID_IDirect3DDevice7, &IID_IDirect3DDevice7, S_OK },
2075 {&IID_IDirect3DDevice3, NULL, E_NOINTERFACE},
2076 {&IID_IDirect3DDevice2, NULL, E_NOINTERFACE},
2077 {&IID_IDirect3DDevice, NULL, E_NOINTERFACE},
2078 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
2079 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
2080 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
2081 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
2082 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
2083 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
2084 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
2085 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
2086 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
2087 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
2088 {&IID_IDirect3D, NULL, E_NOINTERFACE},
2089 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
2090 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
2091 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
2092 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
2093 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
2094 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
2095 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
2096 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
2097 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
2098 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
2099 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
2100 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
2101 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
2102 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
2103 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
2104 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
2105 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
2106 {&IID_IUnknown, &IID_IDirect3DDevice7, S_OK },
2109 IDirect3DDevice7 *device;
2110 HWND window;
2112 window = create_window();
2113 if (!(device = create_device(window, DDSCL_NORMAL)))
2115 skip("Failed to create a 3D device, skipping test.\n");
2116 DestroyWindow(window);
2117 return;
2120 test_qi("device_qi", (IUnknown *)device, &IID_IDirect3DDevice7, tests, ARRAY_SIZE(tests));
2122 IDirect3DDevice7_Release(device);
2123 DestroyWindow(window);
2126 static void test_wndproc(void)
2128 LONG_PTR proc, ddraw_proc;
2129 IDirectDraw7 *ddraw;
2130 WNDCLASSA wc = {0};
2131 HWND window;
2132 HRESULT hr;
2133 ULONG ref;
2135 static struct message messages[] =
2137 {WM_WINDOWPOSCHANGING, FALSE, 0},
2138 {WM_MOVE, FALSE, 0},
2139 {WM_SIZE, FALSE, 0},
2140 {WM_WINDOWPOSCHANGING, FALSE, 0},
2141 {WM_ACTIVATE, FALSE, 0},
2142 {WM_SETFOCUS, FALSE, 0},
2143 {0, FALSE, 0},
2146 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
2147 ddraw = create_ddraw();
2148 ok(!!ddraw, "Failed to create a ddraw object.\n");
2150 wc.lpfnWndProc = test_proc;
2151 wc.lpszClassName = "ddraw_test_wndproc_wc";
2152 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2154 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
2155 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
2157 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2158 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2159 (LONG_PTR)test_proc, proc);
2160 expect_messages = messages;
2161 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2162 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2163 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2164 expect_messages = NULL;
2165 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2166 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2167 (LONG_PTR)test_proc, proc);
2168 ref = IDirectDraw7_Release(ddraw);
2169 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2170 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2171 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2172 (LONG_PTR)test_proc, proc);
2174 /* DDSCL_NORMAL doesn't. */
2175 ddraw = create_ddraw();
2176 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2177 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2178 (LONG_PTR)test_proc, proc);
2179 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2180 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2181 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2182 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2183 (LONG_PTR)test_proc, proc);
2184 ref = IDirectDraw7_Release(ddraw);
2185 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2186 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2187 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2188 (LONG_PTR)test_proc, proc);
2190 /* The original window proc is only restored by ddraw if the current
2191 * window proc matches the one ddraw set. This also affects switching
2192 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
2193 ddraw = create_ddraw();
2194 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2195 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2196 (LONG_PTR)test_proc, proc);
2197 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2198 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2199 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2200 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2201 (LONG_PTR)test_proc, proc);
2202 ddraw_proc = proc;
2203 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2204 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2205 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2206 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2207 (LONG_PTR)test_proc, proc);
2208 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2209 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2210 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2211 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2212 (LONG_PTR)test_proc, proc);
2213 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2214 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2215 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2216 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2217 (LONG_PTR)DefWindowProcA, proc);
2218 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2219 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2220 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, ddraw_proc);
2221 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2222 (LONG_PTR)DefWindowProcA, proc);
2223 ref = IDirectDraw7_Release(ddraw);
2224 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2225 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2226 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2227 (LONG_PTR)test_proc, proc);
2229 ddraw = create_ddraw();
2230 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2231 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2232 (LONG_PTR)test_proc, proc);
2233 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2234 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2235 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2236 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2237 (LONG_PTR)test_proc, proc);
2238 ref = IDirectDraw7_Release(ddraw);
2239 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2240 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2241 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2242 (LONG_PTR)DefWindowProcA, proc);
2244 fix_wndproc(window, (LONG_PTR)test_proc);
2245 expect_messages = NULL;
2246 DestroyWindow(window);
2247 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2250 static void test_window_style(void)
2252 LONG style, exstyle, tmp, expected_style;
2253 RECT fullscreen_rect, r;
2254 IDirectDraw7 *ddraw;
2255 HWND window;
2256 HRESULT hr;
2257 ULONG ref;
2258 BOOL ret;
2260 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2261 0, 0, 100, 100, 0, 0, 0, 0);
2262 ddraw = create_ddraw();
2263 ok(!!ddraw, "Failed to create a ddraw object.\n");
2265 style = GetWindowLongA(window, GWL_STYLE);
2266 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
2267 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2269 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2270 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2272 tmp = GetWindowLongA(window, GWL_STYLE);
2273 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2274 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2275 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2277 GetWindowRect(window, &r);
2278 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
2279 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
2280 GetClientRect(window, &r);
2281 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2283 ret = SetForegroundWindow(GetDesktopWindow());
2284 ok(ret, "Failed to set foreground window.\n");
2286 tmp = GetWindowLongA(window, GWL_STYLE);
2287 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2288 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2289 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2291 ret = SetForegroundWindow(window);
2292 ok(ret, "Failed to set foreground window.\n");
2293 /* Windows 7 (but not Vista and XP) shows the window when it receives focus. Hide it again,
2294 * the next tests expect this. */
2295 ShowWindow(window, SW_HIDE);
2297 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2298 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2300 tmp = GetWindowLongA(window, GWL_STYLE);
2301 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2302 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2303 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2305 ShowWindow(window, SW_SHOW);
2306 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2307 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2309 tmp = GetWindowLongA(window, GWL_STYLE);
2310 expected_style = style | WS_VISIBLE;
2311 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2312 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2313 expected_style = exstyle | WS_EX_TOPMOST;
2314 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2316 ret = SetForegroundWindow(GetDesktopWindow());
2317 ok(ret, "Failed to set foreground window.\n");
2318 tmp = GetWindowLongA(window, GWL_STYLE);
2319 expected_style = style | WS_VISIBLE | WS_MINIMIZE;
2320 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2321 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2322 expected_style = exstyle | WS_EX_TOPMOST;
2323 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2325 ref = IDirectDraw7_Release(ddraw);
2326 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2328 DestroyWindow(window);
2331 static void test_redundant_mode_set(void)
2333 DDSURFACEDESC2 surface_desc = {0};
2334 IDirectDraw7 *ddraw;
2335 RECT q, r, s;
2336 HWND window;
2337 HRESULT hr;
2338 ULONG ref;
2340 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2341 0, 0, 100, 100, 0, 0, 0, 0);
2342 ddraw = create_ddraw();
2343 ok(!!ddraw, "Failed to create a ddraw object.\n");
2344 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2345 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2347 surface_desc.dwSize = sizeof(surface_desc);
2348 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
2349 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
2351 hr = IDirectDraw7_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2352 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
2353 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2355 GetWindowRect(window, &q);
2356 r = q;
2357 r.right /= 2;
2358 r.bottom /= 2;
2359 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
2360 GetWindowRect(window, &s);
2361 ok(EqualRect(&r, &s), "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2363 hr = IDirectDraw7_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2364 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
2365 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2367 GetWindowRect(window, &s);
2368 ok(EqualRect(&r, &s) || broken(EqualRect(&q, &s) /* Windows 10 */),
2369 "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2371 ref = IDirectDraw7_Release(ddraw);
2372 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2374 DestroyWindow(window);
2377 static SIZE screen_size, screen_size2;
2379 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2381 if (message == WM_SIZE)
2383 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2384 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2387 return test_proc(hwnd, message, wparam, lparam);
2390 static LRESULT CALLBACK mode_set_proc2(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2392 if (message == WM_SIZE)
2394 screen_size2.cx = GetSystemMetrics(SM_CXSCREEN);
2395 screen_size2.cy = GetSystemMetrics(SM_CYSCREEN);
2398 return test_proc(hwnd, message, wparam, lparam);
2401 struct test_coop_level_mode_set_enum_param
2403 DWORD ddraw_width, ddraw_height, user32_width, user32_height;
2406 static HRESULT CALLBACK test_coop_level_mode_set_enum_cb(DDSURFACEDESC2 *surface_desc, void *context)
2408 struct test_coop_level_mode_set_enum_param *param = context;
2410 if (U1(U4(*surface_desc).ddpfPixelFormat).dwRGBBitCount != registry_mode.dmBitsPerPel)
2411 return DDENUMRET_OK;
2412 if (surface_desc->dwWidth == registry_mode.dmPelsWidth
2413 && surface_desc->dwHeight == registry_mode.dmPelsHeight)
2414 return DDENUMRET_OK;
2416 if (!param->ddraw_width)
2418 param->ddraw_width = surface_desc->dwWidth;
2419 param->ddraw_height = surface_desc->dwHeight;
2420 return DDENUMRET_OK;
2422 if (surface_desc->dwWidth == param->ddraw_width && surface_desc->dwHeight == param->ddraw_height)
2423 return DDENUMRET_OK;
2425 param->user32_width = surface_desc->dwWidth;
2426 param->user32_height = surface_desc->dwHeight;
2427 return DDENUMRET_CANCEL;
2430 static void test_coop_level_mode_set(void)
2432 IDirectDrawSurface7 *primary;
2433 RECT registry_rect, ddraw_rect, user32_rect, r;
2434 IDirectDraw7 *ddraw;
2435 DDSURFACEDESC2 ddsd;
2436 WNDCLASSA wc = {0};
2437 HWND window, window2;
2438 HRESULT hr;
2439 ULONG ref;
2440 MSG msg;
2441 struct test_coop_level_mode_set_enum_param param;
2442 DEVMODEW devmode;
2443 BOOL ret;
2444 LONG change_ret;
2446 static const struct message exclusive_messages[] =
2448 {WM_WINDOWPOSCHANGING, FALSE, 0},
2449 {WM_WINDOWPOSCHANGED, FALSE, 0},
2450 {WM_SIZE, FALSE, 0},
2451 {WM_DISPLAYCHANGE, FALSE, 0},
2452 {0, FALSE, 0},
2454 static const struct message exclusive_focus_loss_messages[] =
2456 {WM_ACTIVATE, TRUE, WA_INACTIVE, DD_OK},
2457 {WM_WINDOWPOSCHANGING, FALSE, 0, DD_OK}, /* Window resize due to mode change. */
2458 {WM_WINDOWPOSCHANGED, FALSE, 0, DD_OK},
2459 {WM_SIZE, TRUE, SIZE_RESTORED, DD_OK}, /* Generated by DefWindowProc. */
2460 {WM_DISPLAYCHANGE, FALSE, 0, DD_OK},
2461 {WM_KILLFOCUS, FALSE, 0, DDERR_NOEXCLUSIVEMODE},
2462 {WM_WINDOWPOSCHANGING, FALSE, 0, DDERR_NOEXCLUSIVEMODE}, /* Window minimized. */
2463 /* Like d3d8 and d3d9 ddraw seems to use SW_SHOWMINIMIZED instead of
2464 * SW_MINIMIZED, causing a recursive window activation that does not
2465 * produce the same result in Wine yet. Ignore the difference for now.
2466 * {WM_ACTIVATE, TRUE, 0x200000 | WA_ACTIVE}, */
2467 {WM_WINDOWPOSCHANGED, FALSE, 0, DDERR_NOEXCLUSIVEMODE},
2468 {WM_MOVE, FALSE, 0, DDERR_NOEXCLUSIVEMODE},
2469 {WM_SIZE, TRUE, SIZE_MINIMIZED, DDERR_NOEXCLUSIVEMODE},
2470 {WM_ACTIVATEAPP, TRUE, FALSE, DDERR_NOEXCLUSIVEMODE},
2471 {0, FALSE, 0, 0},
2473 static const struct message exclusive_focus_restore_messages[] =
2475 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* From the ShowWindow(SW_RESTORE). */
2476 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Generated by ddraw, matches d3d9 behavior. */
2477 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching previous message. */
2478 {WM_SIZE, FALSE, 0}, /* DefWindowProc. */
2479 {WM_DISPLAYCHANGE, FALSE, 0}, /* Ddraw restores mode. */
2480 /* Native redundantly sets the window size here. */
2481 {WM_ACTIVATEAPP, TRUE, TRUE}, /* End of ddraw's hooks. */
2482 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching the one from ShowWindow. */
2483 {WM_MOVE, FALSE, 0}, /* DefWindowProc. */
2484 {WM_SIZE, TRUE, SIZE_RESTORED}, /* DefWindowProc. */
2485 {0, FALSE, 0},
2487 static const struct message sc_restore_messages[] =
2489 {WM_SYSCOMMAND, TRUE, SC_RESTORE},
2490 {WM_WINDOWPOSCHANGING, FALSE, 0},
2491 {WM_WINDOWPOSCHANGED, FALSE, 0},
2492 {WM_SIZE, TRUE, SIZE_RESTORED},
2493 {0, FALSE, 0},
2495 static const struct message sc_minimize_messages[] =
2497 {WM_SYSCOMMAND, TRUE, SC_MINIMIZE},
2498 {WM_WINDOWPOSCHANGING, FALSE, 0},
2499 {WM_WINDOWPOSCHANGED, FALSE, 0},
2500 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2501 {0, FALSE, 0},
2503 static const struct message sc_maximize_messages[] =
2505 {WM_SYSCOMMAND, TRUE, SC_MAXIMIZE},
2506 {WM_WINDOWPOSCHANGING, FALSE, 0},
2507 {WM_WINDOWPOSCHANGED, FALSE, 0},
2508 {WM_SIZE, TRUE, SIZE_MAXIMIZED},
2509 {0, FALSE, 0},
2512 static const struct message normal_messages[] =
2514 {WM_DISPLAYCHANGE, FALSE, 0},
2515 {0, FALSE, 0},
2518 ddraw = create_ddraw();
2519 ok(!!ddraw, "Failed to create a ddraw object.\n");
2521 memset(&param, 0, sizeof(param));
2522 hr = IDirectDraw7_EnumDisplayModes(ddraw, 0, NULL, &param, test_coop_level_mode_set_enum_cb);
2523 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
2524 ref = IDirectDraw7_Release(ddraw);
2525 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2527 if (!param.user32_height)
2529 skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
2530 return;
2533 SetRect(&registry_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2534 SetRect(&ddraw_rect, 0, 0, param.ddraw_width, param.ddraw_height);
2535 SetRect(&user32_rect, 0, 0, param.user32_width, param.user32_height);
2537 memset(&devmode, 0, sizeof(devmode));
2538 devmode.dmSize = sizeof(devmode);
2539 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2540 devmode.dmPelsWidth = param.user32_width;
2541 devmode.dmPelsHeight = param.user32_height;
2542 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2543 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2545 ddraw = create_ddraw();
2546 ok(!!ddraw, "Failed to create a ddraw object.\n");
2548 wc.lpfnWndProc = mode_set_proc;
2549 wc.lpszClassName = "ddraw_test_wndproc_wc";
2550 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2551 wc.lpfnWndProc = mode_set_proc2;
2552 wc.lpszClassName = "ddraw_test_wndproc_wc2";
2553 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2555 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
2556 0, 0, 100, 100, 0, 0, 0, 0);
2557 window2 = CreateWindowA("ddraw_test_wndproc_wc2", "ddraw_test", WS_OVERLAPPEDWINDOW,
2558 0, 0, 100, 100, 0, 0, 0, 0);
2560 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2561 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2563 GetWindowRect(window, &r);
2564 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2565 wine_dbgstr_rect(&r));
2567 memset(&ddsd, 0, sizeof(ddsd));
2568 ddsd.dwSize = sizeof(ddsd);
2569 ddsd.dwFlags = DDSD_CAPS;
2570 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2572 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2573 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2574 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2575 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2576 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2577 param.user32_width, ddsd.dwWidth);
2578 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2579 param.user32_height, ddsd.dwHeight);
2581 GetWindowRect(window, &r);
2582 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2583 wine_dbgstr_rect(&r));
2585 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2586 expect_messages = exclusive_messages;
2587 screen_size.cx = 0;
2588 screen_size.cy = 0;
2590 hr = IDirectDrawSurface7_IsLost(primary);
2591 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2592 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2593 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2594 hr = IDirectDrawSurface7_IsLost(primary);
2595 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2597 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2598 expect_messages = NULL;
2599 ok(screen_size.cx == param.ddraw_width && screen_size.cy == param.ddraw_height,
2600 "Expected screen size %ux%u, got %ux%u.\n",
2601 param.ddraw_width, param.ddraw_height, screen_size.cx, screen_size.cy);
2603 GetWindowRect(window, &r);
2604 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2605 wine_dbgstr_rect(&r));
2607 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2608 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2609 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2610 param.user32_width, ddsd.dwWidth);
2611 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2612 param.user32_height, ddsd.dwHeight);
2613 IDirectDrawSurface7_Release(primary);
2615 memset(&ddsd, 0, sizeof(ddsd));
2616 ddsd.dwSize = sizeof(ddsd);
2617 ddsd.dwFlags = DDSD_CAPS;
2618 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2620 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2621 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2622 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2623 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2624 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2625 param.ddraw_width, ddsd.dwWidth);
2626 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2627 param.ddraw_height, ddsd.dwHeight);
2629 GetWindowRect(window, &r);
2630 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2631 wine_dbgstr_rect(&r));
2633 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2634 expect_messages = exclusive_messages;
2635 screen_size.cx = 0;
2636 screen_size.cy = 0;
2638 hr = IDirectDrawSurface7_IsLost(primary);
2639 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2640 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2641 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2642 hr = IDirectDrawSurface7_IsLost(primary);
2643 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2645 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2646 expect_messages = NULL;
2647 ok(screen_size.cx == param.user32_width && screen_size.cy == param.user32_height,
2648 "Expected screen size %ux%u, got %ux%u.\n",
2649 param.user32_width, param.user32_height, screen_size.cx, screen_size.cy);
2651 GetWindowRect(window, &r);
2652 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2653 wine_dbgstr_rect(&r));
2655 expect_messages = exclusive_focus_loss_messages;
2656 focus_test_ddraw = ddraw;
2657 ret = SetForegroundWindow(GetDesktopWindow());
2658 ok(ret, "Failed to set foreground window.\n");
2659 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2660 focus_test_ddraw = NULL;
2662 memset(&devmode, 0, sizeof(devmode));
2663 devmode.dmSize = sizeof(devmode);
2664 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2665 ok(ret, "Failed to get display mode.\n");
2666 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2667 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
2668 devmode.dmPelsWidth, devmode.dmPelsHeight);
2670 expect_messages = exclusive_focus_restore_messages;
2671 ShowWindow(window, SW_RESTORE);
2672 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2674 GetWindowRect(window, &r);
2675 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2676 wine_dbgstr_rect(&r));
2677 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2678 ok(ret, "Failed to get display mode.\n");
2679 ok(devmode.dmPelsWidth == param.ddraw_width
2680 && devmode.dmPelsHeight == param.ddraw_height, "Got unexpect screen size %ux%u.\n",
2681 devmode.dmPelsWidth, devmode.dmPelsHeight);
2683 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2684 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2685 /* Normally the primary should be restored here. Unfortunately this causes the
2686 * GetSurfaceDesc call after the next display mode change to crash on the Windows 8
2687 * testbot. Another Restore call would presumably avoid the crash, but it also moots
2688 * the point of the GetSurfaceDesc call. */
2690 expect_messages = sc_minimize_messages;
2691 SendMessageA(window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
2692 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2693 expect_messages = NULL;
2695 expect_messages = sc_restore_messages;
2696 SendMessageA(window, WM_SYSCOMMAND, SC_RESTORE, 0);
2697 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2698 expect_messages = NULL;
2700 expect_messages = sc_maximize_messages;
2701 SendMessageA(window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
2702 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2703 expect_messages = NULL;
2705 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2706 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2708 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2709 expect_messages = exclusive_messages;
2710 screen_size.cx = 0;
2711 screen_size.cy = 0;
2713 hr = IDirectDrawSurface7_IsLost(primary);
2714 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2715 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
2716 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2717 hr = IDirectDrawSurface7_IsLost(primary);
2718 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2720 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2721 expect_messages = NULL;
2722 ok(screen_size.cx == registry_mode.dmPelsWidth
2723 && screen_size.cy == registry_mode.dmPelsHeight,
2724 "Expected screen size %ux%u, got %ux%u.\n",
2725 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size.cx, screen_size.cy);
2727 GetWindowRect(window, &r);
2728 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2729 wine_dbgstr_rect(&r));
2731 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2732 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2733 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2734 param.ddraw_width, ddsd.dwWidth);
2735 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2736 param.ddraw_height, ddsd.dwHeight);
2737 IDirectDrawSurface7_Release(primary);
2739 /* For Wine. */
2740 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
2741 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2743 memset(&ddsd, 0, sizeof(ddsd));
2744 ddsd.dwSize = sizeof(ddsd);
2745 ddsd.dwFlags = DDSD_CAPS;
2746 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2748 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2749 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2750 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2751 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2752 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2753 registry_mode.dmPelsWidth, ddsd.dwWidth);
2754 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2755 registry_mode.dmPelsHeight, ddsd.dwHeight);
2757 GetWindowRect(window, &r);
2758 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2759 wine_dbgstr_rect(&r));
2761 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2762 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2764 GetWindowRect(window, &r);
2765 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2766 wine_dbgstr_rect(&r));
2768 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2769 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2770 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2771 registry_mode.dmPelsWidth, ddsd.dwWidth);
2772 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2773 registry_mode.dmPelsHeight, ddsd.dwHeight);
2774 IDirectDrawSurface7_Release(primary);
2776 memset(&ddsd, 0, sizeof(ddsd));
2777 ddsd.dwSize = sizeof(ddsd);
2778 ddsd.dwFlags = DDSD_CAPS;
2779 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2781 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2782 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2783 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2784 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2785 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2786 registry_mode.dmPelsWidth, ddsd.dwWidth);
2787 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2788 registry_mode.dmPelsHeight, ddsd.dwHeight);
2790 GetWindowRect(window, &r);
2791 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2792 wine_dbgstr_rect(&r));
2794 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2795 expect_messages = normal_messages;
2796 screen_size.cx = 0;
2797 screen_size.cy = 0;
2799 hr = IDirectDrawSurface7_IsLost(primary);
2800 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2801 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2802 devmode.dmPelsWidth = param.user32_width;
2803 devmode.dmPelsHeight = param.user32_height;
2804 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2805 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2806 hr = IDirectDrawSurface7_IsLost(primary);
2807 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2809 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2810 expect_messages = NULL;
2811 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2813 GetWindowRect(window, &r);
2814 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2815 wine_dbgstr_rect(&r));
2817 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2818 expect_messages = normal_messages;
2819 screen_size.cx = 0;
2820 screen_size.cy = 0;
2822 hr = IDirectDrawSurface7_Restore(primary);
2823 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2824 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2825 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2826 hr = IDirectDrawSurface7_Restore(primary);
2827 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2828 hr = IDirectDrawSurface7_IsLost(primary);
2829 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2831 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2832 expect_messages = NULL;
2833 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2835 GetWindowRect(window, &r);
2836 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2837 wine_dbgstr_rect(&r));
2839 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2840 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2841 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2842 registry_mode.dmPelsWidth, ddsd.dwWidth);
2843 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2844 registry_mode.dmPelsHeight, ddsd.dwHeight);
2845 IDirectDrawSurface7_Release(primary);
2847 memset(&ddsd, 0, sizeof(ddsd));
2848 ddsd.dwSize = sizeof(ddsd);
2849 ddsd.dwFlags = DDSD_CAPS;
2850 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2852 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2853 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2854 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2855 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2856 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2857 param.ddraw_width, ddsd.dwWidth);
2858 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2859 param.ddraw_height, ddsd.dwHeight);
2861 GetWindowRect(window, &r);
2862 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2863 wine_dbgstr_rect(&r));
2865 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2866 expect_messages = normal_messages;
2867 screen_size.cx = 0;
2868 screen_size.cy = 0;
2870 hr = IDirectDrawSurface7_IsLost(primary);
2871 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2872 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
2873 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2874 hr = IDirectDrawSurface7_IsLost(primary);
2875 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2877 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2878 expect_messages = NULL;
2879 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2881 GetWindowRect(window, &r);
2882 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2883 wine_dbgstr_rect(&r));
2885 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2886 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2887 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2888 param.ddraw_width, ddsd.dwWidth);
2889 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2890 param.ddraw_height, ddsd.dwHeight);
2891 IDirectDrawSurface7_Release(primary);
2893 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2894 ok(ret, "Failed to get display mode.\n");
2895 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2896 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
2897 "Expected resolution %ux%u, got %ux%u.\n",
2898 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
2899 devmode.dmPelsWidth, devmode.dmPelsHeight);
2900 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
2901 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2903 memset(&ddsd, 0, sizeof(ddsd));
2904 ddsd.dwSize = sizeof(ddsd);
2905 ddsd.dwFlags = DDSD_CAPS;
2906 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2908 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2909 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2910 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2911 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2912 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2913 registry_mode.dmPelsWidth, ddsd.dwWidth);
2914 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2915 registry_mode.dmPelsHeight, ddsd.dwHeight);
2917 GetWindowRect(window, &r);
2918 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2919 wine_dbgstr_rect(&r));
2921 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
2922 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
2923 * not DDSCL_FULLSCREEN. */
2924 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2925 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2927 GetWindowRect(window, &r);
2928 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2929 wine_dbgstr_rect(&r));
2931 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2932 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2933 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2934 registry_mode.dmPelsWidth, ddsd.dwWidth);
2935 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2936 registry_mode.dmPelsHeight, ddsd.dwHeight);
2937 IDirectDrawSurface7_Release(primary);
2939 memset(&ddsd, 0, sizeof(ddsd));
2940 ddsd.dwSize = sizeof(ddsd);
2941 ddsd.dwFlags = DDSD_CAPS;
2942 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2944 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2945 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2946 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2947 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2948 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2949 registry_mode.dmPelsWidth, ddsd.dwWidth);
2950 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2951 registry_mode.dmPelsHeight, ddsd.dwHeight);
2953 GetWindowRect(window, &r);
2954 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2955 wine_dbgstr_rect(&r));
2957 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2958 expect_messages = normal_messages;
2959 screen_size.cx = 0;
2960 screen_size.cy = 0;
2962 hr = IDirectDrawSurface7_IsLost(primary);
2963 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2964 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2965 devmode.dmPelsWidth = param.user32_width;
2966 devmode.dmPelsHeight = param.user32_height;
2967 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2968 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2969 hr = IDirectDrawSurface7_IsLost(primary);
2970 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2972 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2973 expect_messages = NULL;
2974 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2976 GetWindowRect(window, &r);
2977 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2978 wine_dbgstr_rect(&r));
2980 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2981 expect_messages = normal_messages;
2982 screen_size.cx = 0;
2983 screen_size.cy = 0;
2985 hr = IDirectDrawSurface7_Restore(primary);
2986 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2987 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2988 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2989 hr = IDirectDrawSurface7_Restore(primary);
2990 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2991 hr = IDirectDrawSurface7_IsLost(primary);
2992 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2994 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2995 expect_messages = NULL;
2996 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2998 GetWindowRect(window, &r);
2999 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3000 wine_dbgstr_rect(&r));
3002 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3003 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3004 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3005 registry_mode.dmPelsWidth, ddsd.dwWidth);
3006 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3007 registry_mode.dmPelsHeight, ddsd.dwHeight);
3008 IDirectDrawSurface7_Release(primary);
3010 memset(&ddsd, 0, sizeof(ddsd));
3011 ddsd.dwSize = sizeof(ddsd);
3012 ddsd.dwFlags = DDSD_CAPS;
3013 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3015 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3016 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3017 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3018 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3019 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3020 param.ddraw_width, ddsd.dwWidth);
3021 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3022 param.ddraw_height, ddsd.dwHeight);
3024 GetWindowRect(window, &r);
3025 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3026 wine_dbgstr_rect(&r));
3028 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3029 expect_messages = normal_messages;
3030 screen_size.cx = 0;
3031 screen_size.cy = 0;
3033 hr = IDirectDrawSurface7_IsLost(primary);
3034 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3035 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
3036 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3037 hr = IDirectDrawSurface7_IsLost(primary);
3038 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3040 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3041 expect_messages = NULL;
3042 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3044 GetWindowRect(window, &r);
3045 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3046 wine_dbgstr_rect(&r));
3048 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3049 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3050 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3051 param.ddraw_width, ddsd.dwWidth);
3052 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3053 param.ddraw_height, ddsd.dwHeight);
3054 IDirectDrawSurface7_Release(primary);
3056 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3057 ok(ret, "Failed to get display mode.\n");
3058 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3059 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3060 "Expected resolution %ux%u, got %ux%u.\n",
3061 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3062 devmode.dmPelsWidth, devmode.dmPelsHeight);
3063 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3064 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3066 memset(&ddsd, 0, sizeof(ddsd));
3067 ddsd.dwSize = sizeof(ddsd);
3068 ddsd.dwFlags = DDSD_CAPS;
3069 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3071 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3072 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3073 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3074 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3075 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3076 registry_mode.dmPelsWidth, ddsd.dwWidth);
3077 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3078 registry_mode.dmPelsHeight, ddsd.dwHeight);
3079 IDirectDrawSurface7_Release(primary);
3081 GetWindowRect(window, &r);
3082 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3083 wine_dbgstr_rect(&r));
3085 /* Changing the coop level from EXCLUSIVE to NORMAL restores the screen resolution */
3086 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3087 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3088 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3089 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3091 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3092 expect_messages = exclusive_messages;
3093 screen_size.cx = 0;
3094 screen_size.cy = 0;
3096 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3097 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3099 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3100 expect_messages = NULL;
3101 ok(screen_size.cx == registry_mode.dmPelsWidth
3102 && screen_size.cy == registry_mode.dmPelsHeight,
3103 "Expected screen size %ux%u, got %ux%u.\n",
3104 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3105 screen_size.cx, screen_size.cy);
3107 GetWindowRect(window, &r);
3108 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3109 wine_dbgstr_rect(&r));
3111 memset(&ddsd, 0, sizeof(ddsd));
3112 ddsd.dwSize = sizeof(ddsd);
3113 ddsd.dwFlags = DDSD_CAPS;
3114 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3116 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3117 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3118 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3119 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3120 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3121 registry_mode.dmPelsWidth, ddsd.dwWidth);
3122 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3123 registry_mode.dmPelsHeight, ddsd.dwHeight);
3124 IDirectDrawSurface7_Release(primary);
3126 /* The screen restore is a property of DDSCL_EXCLUSIVE */
3127 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3128 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3129 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3130 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3132 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3133 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3135 memset(&ddsd, 0, sizeof(ddsd));
3136 ddsd.dwSize = sizeof(ddsd);
3137 ddsd.dwFlags = DDSD_CAPS;
3138 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3140 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3141 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3142 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3143 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3144 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3145 param.ddraw_width, ddsd.dwWidth);
3146 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3147 param.ddraw_height, ddsd.dwHeight);
3148 IDirectDrawSurface7_Release(primary);
3150 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
3151 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3153 /* If the window is changed at the same time, messages are sent to the new window. */
3154 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3155 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3156 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3157 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3159 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3160 expect_messages = exclusive_messages;
3161 screen_size.cx = 0;
3162 screen_size.cy = 0;
3163 screen_size2.cx = 0;
3164 screen_size2.cy = 0;
3166 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3167 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3169 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3170 expect_messages = NULL;
3171 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n",
3172 screen_size.cx, screen_size.cy);
3173 ok(screen_size2.cx == registry_mode.dmPelsWidth && screen_size2.cy == registry_mode.dmPelsHeight,
3174 "Expected screen size 2 %ux%u, got %ux%u.\n",
3175 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size2.cx, screen_size2.cy);
3177 GetWindowRect(window, &r);
3178 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3179 wine_dbgstr_rect(&r));
3180 GetWindowRect(window2, &r);
3181 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3182 wine_dbgstr_rect(&r));
3184 memset(&ddsd, 0, sizeof(ddsd));
3185 ddsd.dwSize = sizeof(ddsd);
3186 ddsd.dwFlags = DDSD_CAPS;
3187 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3189 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3190 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3191 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3192 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3193 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3194 registry_mode.dmPelsWidth, ddsd.dwWidth);
3195 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3196 registry_mode.dmPelsHeight, ddsd.dwHeight);
3197 IDirectDrawSurface7_Release(primary);
3199 ref = IDirectDraw7_Release(ddraw);
3200 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3202 GetWindowRect(window, &r);
3203 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3204 wine_dbgstr_rect(&r));
3206 expect_messages = NULL;
3207 DestroyWindow(window);
3208 DestroyWindow(window2);
3209 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
3210 UnregisterClassA("ddraw_test_wndproc_wc2", GetModuleHandleA(NULL));
3213 static void test_coop_level_mode_set_multi(void)
3215 IDirectDraw7 *ddraw1, *ddraw2;
3216 UINT w, h;
3217 HWND window;
3218 HRESULT hr;
3219 ULONG ref;
3221 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3222 0, 0, 100, 100, 0, 0, 0, 0);
3223 ddraw1 = create_ddraw();
3224 ok(!!ddraw1, "Failed to create a ddraw object.\n");
3226 /* With just a single ddraw object, the display mode is restored on
3227 * release. */
3228 hr = set_display_mode(ddraw1, 800, 600);
3229 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3230 w = GetSystemMetrics(SM_CXSCREEN);
3231 ok(w == 800, "Got unexpected screen width %u.\n", w);
3232 h = GetSystemMetrics(SM_CYSCREEN);
3233 ok(h == 600, "Got unexpected screen height %u.\n", h);
3235 ref = IDirectDraw7_Release(ddraw1);
3236 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3237 w = GetSystemMetrics(SM_CXSCREEN);
3238 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3239 h = GetSystemMetrics(SM_CYSCREEN);
3240 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3242 /* When there are multiple ddraw objects, the display mode is restored to
3243 * the initial mode, before the first SetDisplayMode() call. */
3244 ddraw1 = create_ddraw();
3245 hr = set_display_mode(ddraw1, 800, 600);
3246 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3247 w = GetSystemMetrics(SM_CXSCREEN);
3248 ok(w == 800, "Got unexpected screen width %u.\n", w);
3249 h = GetSystemMetrics(SM_CYSCREEN);
3250 ok(h == 600, "Got unexpected screen height %u.\n", h);
3252 ddraw2 = create_ddraw();
3253 hr = set_display_mode(ddraw2, 640, 480);
3254 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3255 w = GetSystemMetrics(SM_CXSCREEN);
3256 ok(w == 640, "Got unexpected screen width %u.\n", w);
3257 h = GetSystemMetrics(SM_CYSCREEN);
3258 ok(h == 480, "Got unexpected screen height %u.\n", h);
3260 ref = IDirectDraw7_Release(ddraw2);
3261 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3262 w = GetSystemMetrics(SM_CXSCREEN);
3263 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3264 h = GetSystemMetrics(SM_CYSCREEN);
3265 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3267 ref = IDirectDraw7_Release(ddraw1);
3268 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3269 w = GetSystemMetrics(SM_CXSCREEN);
3270 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3271 h = GetSystemMetrics(SM_CYSCREEN);
3272 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3274 /* Regardless of release ordering. */
3275 ddraw1 = create_ddraw();
3276 hr = set_display_mode(ddraw1, 800, 600);
3277 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3278 w = GetSystemMetrics(SM_CXSCREEN);
3279 ok(w == 800, "Got unexpected screen width %u.\n", w);
3280 h = GetSystemMetrics(SM_CYSCREEN);
3281 ok(h == 600, "Got unexpected screen height %u.\n", h);
3283 ddraw2 = create_ddraw();
3284 hr = set_display_mode(ddraw2, 640, 480);
3285 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3286 w = GetSystemMetrics(SM_CXSCREEN);
3287 ok(w == 640, "Got unexpected screen width %u.\n", w);
3288 h = GetSystemMetrics(SM_CYSCREEN);
3289 ok(h == 480, "Got unexpected screen height %u.\n", h);
3291 ref = IDirectDraw7_Release(ddraw1);
3292 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3293 w = GetSystemMetrics(SM_CXSCREEN);
3294 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3295 h = GetSystemMetrics(SM_CYSCREEN);
3296 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3298 ref = IDirectDraw7_Release(ddraw2);
3299 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3300 w = GetSystemMetrics(SM_CXSCREEN);
3301 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3302 h = GetSystemMetrics(SM_CYSCREEN);
3303 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3305 /* But only for ddraw objects that called SetDisplayMode(). */
3306 ddraw1 = create_ddraw();
3307 ddraw2 = create_ddraw();
3308 hr = set_display_mode(ddraw2, 640, 480);
3309 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3310 w = GetSystemMetrics(SM_CXSCREEN);
3311 ok(w == 640, "Got unexpected screen width %u.\n", w);
3312 h = GetSystemMetrics(SM_CYSCREEN);
3313 ok(h == 480, "Got unexpected screen height %u.\n", h);
3315 ref = IDirectDraw7_Release(ddraw1);
3316 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3317 w = GetSystemMetrics(SM_CXSCREEN);
3318 ok(w == 640, "Got unexpected screen width %u.\n", w);
3319 h = GetSystemMetrics(SM_CYSCREEN);
3320 ok(h == 480, "Got unexpected screen height %u.\n", h);
3322 ref = IDirectDraw7_Release(ddraw2);
3323 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3324 w = GetSystemMetrics(SM_CXSCREEN);
3325 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3326 h = GetSystemMetrics(SM_CYSCREEN);
3327 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3329 /* If there's a ddraw object that's currently in exclusive mode, it blocks
3330 * restoring the display mode. */
3331 ddraw1 = create_ddraw();
3332 hr = set_display_mode(ddraw1, 800, 600);
3333 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3334 w = GetSystemMetrics(SM_CXSCREEN);
3335 ok(w == 800, "Got unexpected screen width %u.\n", w);
3336 h = GetSystemMetrics(SM_CYSCREEN);
3337 ok(h == 600, "Got unexpected screen height %u.\n", h);
3339 ddraw2 = create_ddraw();
3340 hr = set_display_mode(ddraw2, 640, 480);
3341 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3342 w = GetSystemMetrics(SM_CXSCREEN);
3343 ok(w == 640, "Got unexpected screen width %u.\n", w);
3344 h = GetSystemMetrics(SM_CYSCREEN);
3345 ok(h == 480, "Got unexpected screen height %u.\n", h);
3347 hr = IDirectDraw7_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3348 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3350 ref = IDirectDraw7_Release(ddraw1);
3351 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3352 w = GetSystemMetrics(SM_CXSCREEN);
3353 ok(w == 640, "Got unexpected screen width %u.\n", w);
3354 h = GetSystemMetrics(SM_CYSCREEN);
3355 ok(h == 480, "Got unexpected screen height %u.\n", h);
3357 ref = IDirectDraw7_Release(ddraw2);
3358 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3359 w = GetSystemMetrics(SM_CXSCREEN);
3360 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3361 h = GetSystemMetrics(SM_CYSCREEN);
3362 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3364 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
3365 ddraw1 = create_ddraw();
3366 hr = set_display_mode(ddraw1, 800, 600);
3367 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3368 w = GetSystemMetrics(SM_CXSCREEN);
3369 ok(w == 800, "Got unexpected screen width %u.\n", w);
3370 h = GetSystemMetrics(SM_CYSCREEN);
3371 ok(h == 600, "Got unexpected screen height %u.\n", h);
3373 hr = IDirectDraw7_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3374 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3376 ddraw2 = create_ddraw();
3377 hr = set_display_mode(ddraw2, 640, 480);
3378 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
3380 ref = IDirectDraw7_Release(ddraw1);
3381 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3382 w = GetSystemMetrics(SM_CXSCREEN);
3383 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3384 h = GetSystemMetrics(SM_CYSCREEN);
3385 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3387 ref = IDirectDraw7_Release(ddraw2);
3388 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3389 w = GetSystemMetrics(SM_CXSCREEN);
3390 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3391 h = GetSystemMetrics(SM_CYSCREEN);
3392 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3394 DestroyWindow(window);
3397 static void test_initialize(void)
3399 IDirectDraw7 *ddraw;
3400 HRESULT hr;
3402 ddraw = create_ddraw();
3403 ok(!!ddraw, "Failed to create a ddraw object.\n");
3405 hr = IDirectDraw7_Initialize(ddraw, NULL);
3406 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
3407 IDirectDraw7_Release(ddraw);
3409 CoInitialize(NULL);
3410 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw7, (void **)&ddraw);
3411 ok(SUCCEEDED(hr), "Failed to create IDirectDraw7 instance, hr %#x.\n", hr);
3412 hr = IDirectDraw7_Initialize(ddraw, NULL);
3413 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
3414 hr = IDirectDraw7_Initialize(ddraw, NULL);
3415 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
3416 IDirectDraw7_Release(ddraw);
3417 CoUninitialize();
3420 static void test_coop_level_surf_create(void)
3422 IDirectDrawSurface7 *surface;
3423 IDirectDraw7 *ddraw;
3424 DDSURFACEDESC2 ddsd;
3425 HRESULT hr;
3427 ddraw = create_ddraw();
3428 ok(!!ddraw, "Failed to create a ddraw object.\n");
3430 memset(&ddsd, 0, sizeof(ddsd));
3431 ddsd.dwSize = sizeof(ddsd);
3432 ddsd.dwFlags = DDSD_CAPS;
3433 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3434 surface = (void *)0xdeadbeef;
3435 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
3436 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
3437 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
3439 surface = (void *)0xdeadbeef;
3440 hr = IDirectDraw7_CreateSurface(ddraw, NULL, &surface, NULL);
3441 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
3442 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
3444 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3445 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3447 surface = (void *)0xdeadbeef;
3448 hr = IDirectDraw7_CreateSurface(ddraw, NULL, &surface, NULL);
3449 ok(hr == DDERR_INVALIDPARAMS, "Unexpected hr %#x.\n", hr);
3450 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
3452 IDirectDraw7_Release(ddraw);
3455 static void test_vb_discard(void)
3457 static const struct vec4 quad[] =
3459 { 0.0f, 480.0f, 0.0f, 1.0f},
3460 { 0.0f, 0.0f, 0.0f, 1.0f},
3461 {640.0f, 480.0f, 0.0f, 1.0f},
3462 {640.0f, 0.0f, 0.0f, 1.0f},
3465 IDirect3DDevice7 *device;
3466 IDirect3D7 *d3d;
3467 IDirect3DVertexBuffer7 *buffer;
3468 HWND window;
3469 HRESULT hr;
3470 D3DVERTEXBUFFERDESC desc;
3471 BYTE *data;
3472 static const unsigned int vbsize = 16;
3473 unsigned int i;
3475 window = create_window();
3476 if (!(device = create_device(window, DDSCL_NORMAL)))
3478 skip("Failed to create a 3D device, skipping test.\n");
3479 DestroyWindow(window);
3480 return;
3483 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
3484 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
3486 memset(&desc, 0, sizeof(desc));
3487 desc.dwSize = sizeof(desc);
3488 desc.dwCaps = D3DVBCAPS_WRITEONLY;
3489 desc.dwFVF = D3DFVF_XYZRHW;
3490 desc.dwNumVertices = vbsize;
3491 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &buffer, 0);
3492 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
3494 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3495 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3496 memcpy(data, quad, sizeof(quad));
3497 hr = IDirect3DVertexBuffer7_Unlock(buffer);
3498 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3500 hr = IDirect3DDevice7_BeginScene(device);
3501 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3502 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
3503 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3504 hr = IDirect3DDevice7_EndScene(device);
3505 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3507 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3508 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3509 memset(data, 0xaa, sizeof(struct vec4) * vbsize);
3510 hr = IDirect3DVertexBuffer7_Unlock(buffer);
3511 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3513 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3514 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3515 for (i = 0; i < sizeof(struct vec4) * vbsize; i++)
3517 if (data[i] != 0xaa)
3519 ok(FALSE, "Vertex buffer data byte %u is 0x%02x, expected 0xaa\n", i, data[i]);
3520 break;
3523 hr = IDirect3DVertexBuffer7_Unlock(buffer);
3524 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3526 IDirect3DVertexBuffer7_Release(buffer);
3527 IDirect3D7_Release(d3d);
3528 IDirect3DDevice7_Release(device);
3529 DestroyWindow(window);
3532 static void test_coop_level_multi_window(void)
3534 HWND window1, window2;
3535 IDirectDraw7 *ddraw;
3536 HRESULT hr;
3538 window1 = create_window();
3539 window2 = create_window();
3540 ddraw = create_ddraw();
3541 ok(!!ddraw, "Failed to create a ddraw object.\n");
3543 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
3544 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3545 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3546 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3547 ok(IsWindow(window1), "Window 1 was destroyed.\n");
3548 ok(IsWindow(window2), "Window 2 was destroyed.\n");
3550 IDirectDraw7_Release(ddraw);
3551 DestroyWindow(window2);
3552 DestroyWindow(window1);
3555 static void test_draw_strided(void)
3557 static struct vec3 position[] =
3559 {-1.0, -1.0, 0.0},
3560 {-1.0, 1.0, 0.0},
3561 { 1.0, 1.0, 0.0},
3562 { 1.0, -1.0, 0.0},
3564 static DWORD diffuse[] =
3566 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
3568 static WORD indices[] =
3570 0, 1, 2, 2, 3, 0
3573 IDirectDrawSurface7 *rt;
3574 IDirect3DDevice7 *device;
3575 D3DCOLOR color;
3576 HWND window;
3577 HRESULT hr;
3578 D3DDRAWPRIMITIVESTRIDEDDATA strided;
3580 window = create_window();
3581 if (!(device = create_device(window, DDSCL_NORMAL)))
3583 skip("Failed to create a 3D device, skipping test.\n");
3584 DestroyWindow(window);
3585 return;
3588 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
3589 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3591 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
3592 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
3593 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 1.0f, 0);
3594 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
3595 hr = IDirect3DDevice7_BeginScene(device);
3596 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3598 memset(&strided, 0x55, sizeof(strided));
3599 strided.position.lpvData = position;
3600 strided.position.dwStride = sizeof(*position);
3601 strided.diffuse.lpvData = diffuse;
3602 strided.diffuse.dwStride = sizeof(*diffuse);
3603 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device, D3DPT_TRIANGLELIST, D3DFVF_XYZ | D3DFVF_DIFFUSE,
3604 &strided, 4, indices, 6, 0);
3605 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3607 hr = IDirect3DDevice7_EndScene(device);
3608 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3610 color = get_surface_color(rt, 320, 240);
3611 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
3613 IDirectDrawSurface7_Release(rt);
3614 IDirect3DDevice7_Release(device);
3615 DestroyWindow(window);
3618 static void test_lighting(void)
3620 static D3DMATRIX mat =
3622 1.0f, 0.0f, 0.0f, 0.0f,
3623 0.0f, 1.0f, 0.0f, 0.0f,
3624 0.0f, 0.0f, 1.0f, 0.0f,
3625 0.0f, 0.0f, 0.0f, 1.0f,
3627 mat_singular =
3629 1.0f, 0.0f, 1.0f, 0.0f,
3630 0.0f, 1.0f, 0.0f, 0.0f,
3631 1.0f, 0.0f, 1.0f, 0.0f,
3632 0.0f, 0.0f, 0.5f, 1.0f,
3634 mat_transf =
3636 0.0f, 0.0f, 1.0f, 0.0f,
3637 0.0f, 1.0f, 0.0f, 0.0f,
3638 -1.0f, 0.0f, 0.0f, 0.0f,
3639 10.f, 10.0f, 10.0f, 1.0f,
3641 mat_nonaffine =
3643 1.0f, 0.0f, 0.0f, 0.0f,
3644 0.0f, 1.0f, 0.0f, 0.0f,
3645 0.0f, 0.0f, 1.0f, -1.0f,
3646 10.f, 10.0f, 10.0f, 0.0f,
3648 static struct vertex
3650 struct vec3 position;
3651 DWORD diffuse;
3653 unlitquad[] =
3655 {{-1.0f, -1.0f, 0.1f}, 0xffff0000},
3656 {{-1.0f, 0.0f, 0.1f}, 0xffff0000},
3657 {{ 0.0f, 0.0f, 0.1f}, 0xffff0000},
3658 {{ 0.0f, -1.0f, 0.1f}, 0xffff0000},
3660 litquad[] =
3662 {{-1.0f, 0.0f, 0.1f}, 0xff00ff00},
3663 {{-1.0f, 1.0f, 0.1f}, 0xff00ff00},
3664 {{ 0.0f, 1.0f, 0.1f}, 0xff00ff00},
3665 {{ 0.0f, 0.0f, 0.1f}, 0xff00ff00},
3667 static struct vertex_normal
3669 struct vec3 position;
3670 struct vec3 normal;
3671 DWORD diffuse;
3673 unlitnquad[] =
3675 {{0.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3676 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3677 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3678 {{1.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3680 litnquad[] =
3682 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3683 {{0.0f, 1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3684 {{1.0f, 1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3685 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3687 nquad[] =
3689 {{-1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3690 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3691 {{ 1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3692 {{ 1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3694 rotatedquad[] =
3696 {{-10.0f, -11.0f, 11.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3697 {{-10.0f, -9.0f, 11.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3698 {{-10.0f, -9.0f, 9.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3699 {{-10.0f, -11.0f, 9.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3701 translatedquad[] =
3703 {{-11.0f, -11.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3704 {{-11.0f, -9.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3705 {{ -9.0f, -9.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3706 {{ -9.0f, -11.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3708 static WORD indices[] = {0, 1, 2, 2, 3, 0};
3709 static const struct
3711 D3DMATRIX *world_matrix;
3712 void *quad;
3713 DWORD expected, expected_process_vertices;
3714 const char *message;
3715 BOOL process_vertices_todo;
3717 tests[] =
3719 {&mat, nquad, 0x000000ff, 0xff0000ff, "Lit quad with light"},
3720 {&mat_singular, nquad, 0x000000ff, 0xff000000, "Lit quad with singular world matrix", TRUE},
3721 {&mat_transf, rotatedquad, 0x000000ff, 0xff0000ff, "Lit quad with transformation matrix"},
3722 {&mat_nonaffine, translatedquad, 0x00000000, 0xff000000, "Lit quad with non-affine matrix"},
3725 DWORD nfvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL;
3726 IDirect3DVertexBuffer7 *src_vb1, *src_vb2, *dst_vb;
3727 DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
3728 struct vertex_normal *src_data2;
3729 D3DVERTEXBUFFERDESC vb_desc;
3730 struct vertex *src_data1;
3731 IDirect3DDevice7 *device;
3732 IDirectDrawSurface7 *rt;
3733 IDirectDraw7 *ddraw;
3734 IDirect3D7 *d3d;
3735 D3DCOLOR color;
3736 ULONG refcount;
3737 unsigned int i;
3738 BOOL is_warp;
3739 HWND window;
3740 HRESULT hr;
3741 struct
3743 struct vec4 position;
3744 DWORD diffuse;
3745 DWORD specular;
3747 *dst_data;
3749 window = create_window();
3750 if (!(device = create_device(window, DDSCL_NORMAL)))
3752 skip("Failed to create a 3D device, skipping test.\n");
3753 DestroyWindow(window);
3754 return;
3756 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
3757 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3758 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
3759 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3761 is_warp = ddraw_is_warp(ddraw);
3763 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
3764 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3766 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
3767 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3769 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
3770 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3771 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
3772 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3773 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
3774 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3775 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
3776 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3777 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
3778 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3779 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
3780 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3781 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
3782 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3783 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
3784 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3786 hr = IDirect3DDevice7_BeginScene(device);
3787 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3789 memset(&vb_desc, 0, sizeof(vb_desc));
3790 vb_desc.dwSize = sizeof(vb_desc);
3791 vb_desc.dwFVF = fvf;
3792 vb_desc.dwNumVertices = 2;
3793 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &src_vb1, 0);
3794 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3795 vb_desc.dwSize = sizeof(vb_desc);
3796 vb_desc.dwFVF = nfvf;
3797 vb_desc.dwNumVertices = 2;
3798 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &src_vb2, 0);
3799 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3801 memset(&vb_desc, 0, sizeof(vb_desc));
3802 vb_desc.dwSize = sizeof(vb_desc);
3803 vb_desc.dwFVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR;
3804 vb_desc.dwNumVertices = 4;
3805 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &dst_vb, 0);
3806 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3808 hr = IDirect3DVertexBuffer7_Lock(src_vb1, 0, (void **)&src_data1, NULL);
3809 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3810 memcpy(src_data1, unlitquad, sizeof(*src_data1));
3811 memcpy(&src_data1[1], litquad, sizeof(*src_data1));
3812 hr = IDirect3DVertexBuffer7_Unlock(src_vb1);
3813 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3815 hr = IDirect3DVertexBuffer7_Lock(src_vb2, 0, (void **)&src_data2, NULL);
3816 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3817 memcpy(src_data2, unlitnquad, sizeof(*src_data2));
3818 memcpy(&src_data2[1], litnquad, sizeof(*src_data2));
3819 hr = IDirect3DVertexBuffer7_Unlock(src_vb2);
3820 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3822 /* No lights are defined... That means, lit vertices should be entirely black. */
3823 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
3824 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3825 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0,
3826 1, src_vb1, 0, device, 0);
3827 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3828 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, unlitquad, 4,
3829 indices, 6, 0);
3830 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3832 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
3833 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3834 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 1,
3835 1, src_vb1, 1, device, 0);
3836 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3837 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, litquad, 4,
3838 indices, 6, 0);
3839 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3841 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
3842 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3843 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 2,
3844 1, src_vb2, 0, device, 0);
3845 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, unlitnquad, 4,
3846 indices, 6, 0);
3847 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3849 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
3850 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3851 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 3,
3852 1, src_vb2, 1, device, 0);
3853 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, litnquad, 4,
3854 indices, 6, 0);
3855 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3857 hr = IDirect3DDevice7_EndScene(device);
3858 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3860 hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL);
3861 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3863 color = get_surface_color(rt, 160, 360);
3864 ok(color == 0x00ff0000, "Unlit quad without normals has color 0x%08x, expected 0x00ff0000.\n", color);
3865 ok(dst_data[0].diffuse == 0xffff0000,
3866 "Unlit quad without normals has color 0x%08x, expected 0xffff0000.\n", dst_data[0].diffuse);
3867 ok(!dst_data[0].specular,
3868 "Unexpected specular color 0x%08x.\n", dst_data[0].specular);
3869 color = get_surface_color(rt, 160, 120);
3870 /* Broken on some of WARP drivers. */
3871 ok(color == 0x00000000 || broken(is_warp && color == 0x000000ff),
3872 "Lit quad without normals has color 0x%08x, expected 0x00000000.\n", color);
3873 ok(dst_data[1].diffuse == 0xff000000,
3874 "Lit quad without normals has color 0x%08x, expected 0xff000000.\n", dst_data[1].diffuse);
3875 ok(!dst_data[1].specular,
3876 "Unexpected specular color 0x%08x.\n", dst_data[1].specular);
3877 color = get_surface_color(rt, 480, 360);
3878 ok(color == 0x000000ff, "Unlit quad with normals has color 0x%08x, expected 0x000000ff.\n", color);
3879 ok(dst_data[2].diffuse == 0xff0000ff,
3880 "Unlit quad with normals has color 0x%08x, expected 0xff0000ff.\n", dst_data[2].diffuse);
3881 ok(!dst_data[2].specular,
3882 "Unexpected specular color 0x%08x.\n", dst_data[2].specular);
3883 color = get_surface_color(rt, 480, 120);
3884 ok(color == 0x00000000 || broken(is_warp && color == 0x000000ff),
3885 "Lit quad with normals has color 0x%08x, expected 0x00000000.\n", color);
3886 ok(dst_data[3].diffuse == 0xff000000,
3887 "Lit quad with normals has color 0x%08x, expected 0xff000000.\n", dst_data[3].diffuse);
3888 ok(!dst_data[3].specular,
3889 "Unexpected specular color 0x%08x.\n", dst_data[3].specular);
3891 hr = IDirect3DVertexBuffer7_Unlock(dst_vb);
3892 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3894 hr = IDirect3DDevice7_LightEnable(device, 0, TRUE);
3895 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3897 for (i = 0; i < ARRAY_SIZE(tests); ++i)
3899 hr = IDirect3DVertexBuffer7_Lock(src_vb2, 0, (void **)&src_data2, NULL);
3900 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3901 memcpy(src_data2, tests[i].quad, sizeof(*src_data2));
3902 hr = IDirect3DVertexBuffer7_Unlock(src_vb2);
3903 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3905 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, tests[i].world_matrix);
3906 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3908 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
3909 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3911 hr = IDirect3DDevice7_BeginScene(device);
3912 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3914 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 0,
3915 1, src_vb2, 0, device, 0);
3916 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3918 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, tests[i].quad,
3919 4, indices, 6, 0);
3920 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3922 hr = IDirect3DDevice7_EndScene(device);
3923 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3925 hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL);
3926 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3928 color = get_surface_color(rt, 320, 240);
3929 ok(color == tests[i].expected || broken(is_warp && color == 0x000000ff),
3930 "%s has color 0x%08x.\n", tests[i].message, color);
3931 todo_wine_if(tests[i].process_vertices_todo)
3932 ok(dst_data[0].diffuse == tests[i].expected_process_vertices,
3933 "%s has color 0x%08x.\n", tests[i].message, dst_data[0].diffuse);
3934 ok(!dst_data[0].specular,
3935 "%s has specular color 0x%08x.\n", tests[i].message, dst_data[0].specular);
3937 hr = IDirect3DVertexBuffer7_Unlock(dst_vb);
3938 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3941 IDirect3DVertexBuffer7_Release(src_vb1);
3942 IDirect3DVertexBuffer7_Release(src_vb2);
3943 IDirect3DVertexBuffer7_Release(dst_vb);
3945 IDirectDrawSurface7_Release(rt);
3947 IDirectDraw7_Release(ddraw);
3948 IDirect3D7_Release(d3d);
3949 refcount = IDirect3DDevice7_Release(device);
3950 ok(!refcount, "Device has %u references left.\n", refcount);
3951 DestroyWindow(window);
3954 static void test_specular_lighting(void)
3956 static const unsigned int vertices_side = 5;
3957 const unsigned int indices_count = (vertices_side - 1) * (vertices_side - 1) * 2 * 3;
3958 static const DWORD fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
3959 static D3DMATRIX mat =
3961 1.0f, 0.0f, 0.0f, 0.0f,
3962 0.0f, 1.0f, 0.0f, 0.0f,
3963 0.0f, 0.0f, 1.0f, 0.0f,
3964 0.0f, 0.0f, 0.0f, 1.0f,
3966 static const struct vertex
3968 struct vec3 position;
3969 struct vec3 normal;
3971 vertices[] =
3973 {{-0.5f, -0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
3974 {{ 0.0f, -0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
3975 {{ 0.5f, -0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
3976 {{-0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}},
3977 {{ 0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}},
3978 {{ 0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}},
3979 {{-0.5f, 0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
3980 {{ 0.0f, 0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
3981 {{ 0.5f, 0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
3984 static D3DLIGHT7 directional =
3986 D3DLIGHT_DIRECTIONAL,
3987 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3988 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
3989 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3990 {{0.0f}, {0.0f}, {0.0f}},
3991 {{0.0f}, {0.0f}, {1.0f}},
3993 point =
3995 D3DLIGHT_POINT,
3996 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3997 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
3998 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
3999 {{0.0f}, {0.0f}, {0.0f}},
4000 {{0.0f}, {0.0f}, {0.0f}},
4001 100.0f,
4002 0.0f,
4003 0.0f, 0.0f, 1.0f,
4005 spot =
4007 D3DLIGHT_SPOT,
4008 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4009 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4010 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4011 {{0.0f}, {0.0f}, {0.0f}},
4012 {{0.0f}, {0.0f}, {1.0f}},
4013 100.0f,
4014 1.0f,
4015 0.0f, 0.0f, 1.0f,
4016 M_PI / 12.0f, M_PI / 3.0f
4018 /* The chosen range value makes the test fail when using a manhattan
4019 * distance metric vs the correct euclidean distance. */
4020 point_range =
4022 D3DLIGHT_POINT,
4023 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4024 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4025 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4026 {{0.0f}, {0.0f}, {0.0f}},
4027 {{0.0f}, {0.0f}, {0.0f}},
4028 1.2f,
4029 0.0f,
4030 0.0f, 0.0f, 1.0f,
4032 point_side =
4034 D3DLIGHT_POINT,
4035 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4036 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4037 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4038 {{-1.1f}, {0.0f}, {1.1f}},
4039 {{0.0f}, {0.0f}, {0.0f}},
4040 100.0f,
4041 0.0f,
4042 1.0f, 0.0f, 0.0f,
4044 static const struct expected_color
4046 unsigned int x, y;
4047 D3DCOLOR color;
4049 expected_directional[] =
4051 {160, 120, 0x00ffffff},
4052 {320, 120, 0x00ffffff},
4053 {480, 120, 0x00ffffff},
4054 {160, 240, 0x00ffffff},
4055 {320, 240, 0x00ffffff},
4056 {480, 240, 0x00ffffff},
4057 {160, 360, 0x00ffffff},
4058 {320, 360, 0x00ffffff},
4059 {480, 360, 0x00ffffff},
4061 expected_directional_local[] =
4063 {160, 120, 0x003c3c3c},
4064 {320, 120, 0x00717171},
4065 {480, 120, 0x003c3c3c},
4066 {160, 240, 0x00717171},
4067 {320, 240, 0x00ffffff},
4068 {480, 240, 0x00717171},
4069 {160, 360, 0x003c3c3c},
4070 {320, 360, 0x00717171},
4071 {480, 360, 0x003c3c3c},
4073 expected_point[] =
4075 {160, 120, 0x00282828},
4076 {320, 120, 0x005a5a5a},
4077 {480, 120, 0x00282828},
4078 {160, 240, 0x005a5a5a},
4079 {320, 240, 0x00ffffff},
4080 {480, 240, 0x005a5a5a},
4081 {160, 360, 0x00282828},
4082 {320, 360, 0x005a5a5a},
4083 {480, 360, 0x00282828},
4085 expected_point_local[] =
4087 {160, 120, 0x00000000},
4088 {320, 120, 0x00070707},
4089 {480, 120, 0x00000000},
4090 {160, 240, 0x00070707},
4091 {320, 240, 0x00ffffff},
4092 {480, 240, 0x00070707},
4093 {160, 360, 0x00000000},
4094 {320, 360, 0x00070707},
4095 {480, 360, 0x00000000},
4097 expected_spot[] =
4099 {160, 120, 0x00000000},
4100 {320, 120, 0x00141414},
4101 {480, 120, 0x00000000},
4102 {160, 240, 0x00141414},
4103 {320, 240, 0x00ffffff},
4104 {480, 240, 0x00141414},
4105 {160, 360, 0x00000000},
4106 {320, 360, 0x00141414},
4107 {480, 360, 0x00000000},
4109 expected_spot_local[] =
4111 {160, 120, 0x00000000},
4112 {320, 120, 0x00020202},
4113 {480, 120, 0x00000000},
4114 {160, 240, 0x00020202},
4115 {320, 240, 0x00ffffff},
4116 {480, 240, 0x00020202},
4117 {160, 360, 0x00000000},
4118 {320, 360, 0x00020202},
4119 {480, 360, 0x00000000},
4121 expected_point_range[] =
4123 {160, 120, 0x00000000},
4124 {320, 120, 0x005a5a5a},
4125 {480, 120, 0x00000000},
4126 {160, 240, 0x005a5a5a},
4127 {320, 240, 0x00ffffff},
4128 {480, 240, 0x005a5a5a},
4129 {160, 360, 0x00000000},
4130 {320, 360, 0x005a5a5a},
4131 {480, 360, 0x00000000},
4133 expected_point_side[] =
4135 {160, 120, 0x00000000},
4136 {320, 120, 0x00000000},
4137 {480, 120, 0x00000000},
4138 {160, 240, 0x00000000},
4139 {320, 240, 0x00000000},
4140 {480, 240, 0x00000000},
4141 {160, 360, 0x00000000},
4142 {320, 360, 0x00000000},
4143 {480, 360, 0x00000000},
4145 expected_directional_local_0[] =
4147 {160, 120, 0x00ffffff},
4148 {320, 120, 0x00ffffff},
4149 {480, 120, 0x00ffffff},
4150 {160, 240, 0x00ffffff},
4151 {320, 240, 0x00ffffff},
4152 {480, 240, 0x00ffffff},
4153 {160, 360, 0x00ffffff},
4154 {320, 360, 0x00ffffff},
4155 {480, 360, 0x00ffffff},
4157 expected_point_0[] =
4159 {160, 120, 0x00aaaaaa},
4160 {320, 120, 0x00cccccc},
4161 {480, 120, 0x00aaaaaa},
4162 {160, 240, 0x00cccccc},
4163 {320, 240, 0x00ffffff},
4164 {480, 240, 0x00cccccc},
4165 {160, 360, 0x00aaaaaa},
4166 {320, 360, 0x00cccccc},
4167 {480, 360, 0x00aaaaaa},
4169 expected_spot_0[] =
4171 {160, 120, 0x00000000},
4172 {320, 120, 0x002e2e2e},
4173 {480, 120, 0x00000000},
4174 {160, 240, 0x002e2e2e},
4175 {320, 240, 0x00ffffff},
4176 {480, 240, 0x002e2e2e},
4177 {160, 360, 0x00000000},
4178 {320, 360, 0x002e2e2e},
4179 {480, 360, 0x00000000},
4181 expected_point_range_0[] =
4183 {160, 120, 0x00000000},
4184 {320, 120, 0x00cccccc},
4185 {480, 120, 0x00000000},
4186 {160, 240, 0x00cccccc},
4187 {320, 240, 0x00ffffff},
4188 {480, 240, 0x00cccccc},
4189 {160, 360, 0x00000000},
4190 {320, 360, 0x00cccccc},
4191 {480, 360, 0x00000000},
4193 static const struct
4195 D3DLIGHT7 *light;
4196 BOOL local_viewer;
4197 float specular_power;
4198 const struct expected_color *expected, *expected_process_vertices;
4199 unsigned int expected_count;
4200 BOOL todo_process_vertices;
4202 tests[] =
4204 {&directional, FALSE, 30.0f, expected_directional, expected_directional,
4205 ARRAY_SIZE(expected_directional)},
4206 {&directional, TRUE, 30.0f, expected_directional_local, expected_directional_local,
4207 ARRAY_SIZE(expected_directional_local)},
4208 {&point, FALSE, 30.0f, expected_point, expected_point, ARRAY_SIZE(expected_point)},
4209 {&point, TRUE, 30.0f, expected_point_local, expected_point_local, ARRAY_SIZE(expected_point_local)},
4210 {&spot, FALSE, 30.0f, expected_spot, expected_spot, ARRAY_SIZE(expected_spot)},
4211 {&spot, TRUE, 30.0f, expected_spot_local, expected_spot_local, ARRAY_SIZE(expected_spot_local)},
4212 {&point_range, FALSE, 30.0f, expected_point_range, expected_point_range,
4213 ARRAY_SIZE(expected_point_range)},
4215 /* For zero material shininess _ProcessVertices() seem to keep non-zero material shininess set previously. */
4216 {&point_side, TRUE, 0.0f, expected_point_side, expected_point_side, ARRAY_SIZE(expected_point_side), TRUE},
4217 {&directional, FALSE, 0.0f, expected_directional, expected_directional,
4218 ARRAY_SIZE(expected_directional), TRUE},
4219 {&directional, TRUE, 0.0f, expected_directional_local_0, expected_directional_local,
4220 ARRAY_SIZE(expected_directional_local_0), TRUE},
4221 {&point, FALSE, 0.0f, expected_point_0, expected_point, ARRAY_SIZE(expected_point_0), TRUE},
4222 {&point, TRUE, 0.0f, expected_point_0, expected_point_local, ARRAY_SIZE(expected_point_0), TRUE},
4223 {&spot, FALSE, 0.0f, expected_spot_0, expected_spot, ARRAY_SIZE(expected_spot_0), TRUE},
4224 {&spot, TRUE, 0.0f, expected_spot_0, expected_spot_local, ARRAY_SIZE(expected_spot_0), TRUE},
4225 {&point_range, FALSE, 0.0f, expected_point_range_0, expected_point_range, ARRAY_SIZE(expected_point_range_0), TRUE},
4228 IDirect3DVertexBuffer7 *src_vb, *dst_vb;
4229 D3DCOLOR color, expected_color;
4230 D3DVERTEXBUFFERDESC vb_desc;
4231 IDirect3DDevice7 *device;
4232 unsigned int i, j, x, y;
4233 IDirectDrawSurface7 *rt;
4234 D3DMATERIAL7 material;
4235 struct vec3 *src_data;
4236 struct vertex *quad;
4237 IDirect3D7 *d3d;
4238 ULONG refcount;
4239 WORD *indices;
4240 HWND window;
4241 HRESULT hr;
4242 struct
4244 struct vec4 position;
4245 DWORD diffuse;
4246 DWORD specular;
4247 } *dst_data;
4249 window = create_window();
4250 if (!(device = create_device(window, DDSCL_NORMAL)))
4252 skip("Failed to create a 3D device, skipping test.\n");
4253 DestroyWindow(window);
4254 return;
4256 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
4257 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4259 quad = heap_alloc(vertices_side * vertices_side * sizeof(*quad));
4260 indices = heap_alloc(indices_count * sizeof(*indices));
4261 for (i = 0, y = 0; y < vertices_side; ++y)
4263 for (x = 0; x < vertices_side; ++x)
4265 quad[i].position.x = x * 2.0f / (vertices_side - 1) - 1.0f;
4266 quad[i].position.y = y * 2.0f / (vertices_side - 1) - 1.0f;
4267 quad[i].position.z = 1.0f;
4268 quad[i].normal.x = 0.0f;
4269 quad[i].normal.y = 0.0f;
4270 quad[i++].normal.z = -1.0f;
4273 for (i = 0, y = 0; y < (vertices_side - 1); ++y)
4275 for (x = 0; x < (vertices_side - 1); ++x)
4277 indices[i++] = y * vertices_side + x + 1;
4278 indices[i++] = y * vertices_side + x;
4279 indices[i++] = (y + 1) * vertices_side + x;
4280 indices[i++] = y * vertices_side + x + 1;
4281 indices[i++] = (y + 1) * vertices_side + x;
4282 indices[i++] = (y + 1) * vertices_side + x + 1;
4286 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
4287 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4289 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
4290 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4291 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
4292 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4293 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
4294 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4295 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
4296 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4297 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
4298 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4299 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
4300 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4302 hr = IDirect3DDevice7_LightEnable(device, 0, TRUE);
4303 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4304 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, TRUE);
4305 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4307 memset(&vb_desc, 0, sizeof(vb_desc));
4308 vb_desc.dwSize = sizeof(vb_desc);
4309 vb_desc.dwFVF = fvf;
4310 vb_desc.dwNumVertices = ARRAY_SIZE(vertices);
4311 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &src_vb, 0);
4312 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4313 hr = IDirect3DVertexBuffer7_Lock(src_vb, 0, (void **)&src_data, NULL);
4314 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4315 memcpy(src_data, vertices, sizeof(vertices));
4316 hr = IDirect3DVertexBuffer7_Unlock(src_vb);
4317 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4319 memset(&vb_desc, 0, sizeof(vb_desc));
4320 vb_desc.dwSize = sizeof(vb_desc);
4321 vb_desc.dwFVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR;
4322 vb_desc.dwNumVertices = ARRAY_SIZE(vertices);
4323 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &dst_vb, 0);
4324 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4326 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4328 hr = IDirect3DDevice7_SetLight(device, 0, tests[i].light);
4329 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4331 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LOCALVIEWER, tests[i].local_viewer);
4332 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4334 memset(&material, 0, sizeof(material));
4335 U1(U2(material).specular).r = 1.0f;
4336 U2(U2(material).specular).g = 1.0f;
4337 U3(U2(material).specular).b = 1.0f;
4338 U4(U2(material).specular).a = 0.5f;
4339 U4(material).power = tests[i].specular_power;
4340 hr = IDirect3DDevice7_SetMaterial(device, &material);
4341 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4343 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
4344 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4346 hr = IDirect3DDevice7_BeginScene(device);
4347 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4349 hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL);
4350 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4351 memset(dst_data, 0, sizeof(*dst_data) * ARRAY_SIZE(vertices));
4352 hr = IDirect3DVertexBuffer7_Unlock(dst_vb);
4353 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4355 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 0,
4356 ARRAY_SIZE(vertices), src_vb, 0, device, 0);
4357 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4359 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, quad,
4360 vertices_side * vertices_side, indices, indices_count, 0);
4361 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4363 hr = IDirect3DDevice7_EndScene(device);
4364 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4366 hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL);
4367 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4369 ok(tests[i].expected_count == ARRAY_SIZE(vertices), "Array size mismatch.\n");
4370 for (j = 0; j < tests[i].expected_count; ++j)
4372 color = get_surface_color(rt, tests[i].expected[j].x, tests[i].expected[j].y);
4373 ok(compare_color(color, tests[i].expected[j].color, 1),
4374 "Expected color 0x%08x at location (%u, %u), got 0x%08x, case %u.\n",
4375 tests[i].expected[j].color, tests[i].expected[j].x,
4376 tests[i].expected[j].y, color, i);
4377 ok(!dst_data[j].diffuse, "Expected color 0x00000000 for vertex %u, got 0x%08x, case %u.\n",
4378 j, dst_data[j].diffuse, i);
4379 expected_color = tests[i].expected_process_vertices[j].color | 0x80000000;
4380 todo_wine_if(tests[i].todo_process_vertices && dst_data[j].specular != expected_color)
4381 ok(compare_color(dst_data[j].specular, expected_color, 1),
4382 "Expected color 0x%08x for vertex %u, got 0x%08x, case %u.\n",
4383 expected_color, j, dst_data[j].specular, i);
4385 hr = IDirect3DVertexBuffer7_Unlock(dst_vb);
4386 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4389 IDirect3DVertexBuffer7_Release(dst_vb);
4390 IDirect3DVertexBuffer7_Release(src_vb);
4391 IDirectDrawSurface7_Release(rt);
4393 IDirect3D7_Release(d3d);
4394 refcount = IDirect3DDevice7_Release(device);
4395 ok(!refcount, "Device has %u references left.\n", refcount);
4396 DestroyWindow(window);
4397 heap_free(indices);
4398 heap_free(quad);
4401 static void test_clear_rect_count(void)
4403 IDirectDrawSurface7 *rt;
4404 IDirect3DDevice7 *device;
4405 D3DCOLOR color;
4406 HWND window;
4407 HRESULT hr;
4408 D3DRECT rect = {{0}, {0}, {640}, {480}};
4410 window = create_window();
4411 if (!(device = create_device(window, DDSCL_NORMAL)))
4413 skip("Failed to create a 3D device, skipping test.\n");
4414 DestroyWindow(window);
4415 return;
4418 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
4419 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4421 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ffffff, 1.0f, 0);
4422 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4423 hr = IDirect3DDevice7_Clear(device, 0, &rect, D3DCLEAR_TARGET, 0x00ff0000, 1.0f, 0);
4424 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4426 color = get_surface_color(rt, 320, 240);
4427 ok(compare_color(color, 0x00ffffff, 1) || broken(compare_color(color, 0x00ff0000, 1)),
4428 "Clear with count = 0, rect != NULL has color %#08x.\n", color);
4430 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ffffff, 1.0f, 0);
4431 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4432 hr = IDirect3DDevice7_Clear(device, 1, NULL, D3DCLEAR_TARGET, 0x0000ff00, 1.0f, 0);
4433 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4435 color = get_surface_color(rt, 320, 240);
4436 ok(compare_color(color, 0x0000ff00, 1),
4437 "Clear with count = 1, rect = NULL has color %#08x.\n", color);
4439 IDirectDrawSurface7_Release(rt);
4440 IDirect3DDevice7_Release(device);
4441 DestroyWindow(window);
4444 static BOOL test_mode_restored(IDirectDraw7 *ddraw, HWND window)
4446 DDSURFACEDESC2 ddsd1, ddsd2;
4447 HRESULT hr;
4449 memset(&ddsd1, 0, sizeof(ddsd1));
4450 ddsd1.dwSize = sizeof(ddsd1);
4451 hr = IDirectDraw7_GetDisplayMode(ddraw, &ddsd1);
4452 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
4454 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4455 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4456 hr = set_display_mode(ddraw, 640, 480);
4457 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
4458 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4459 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4461 memset(&ddsd2, 0, sizeof(ddsd2));
4462 ddsd2.dwSize = sizeof(ddsd2);
4463 hr = IDirectDraw7_GetDisplayMode(ddraw, &ddsd2);
4464 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
4465 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
4466 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
4468 return ddsd1.dwWidth == ddsd2.dwWidth && ddsd1.dwHeight == ddsd2.dwHeight;
4471 static void test_coop_level_versions(void)
4473 HWND window;
4474 IDirectDraw *ddraw;
4475 HRESULT hr;
4476 BOOL restored;
4477 IDirectDrawSurface *surface;
4478 IDirectDraw7 *ddraw7;
4479 DDSURFACEDESC ddsd;
4481 window = create_window();
4482 ddraw7 = create_ddraw();
4483 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4484 /* Newly created ddraw objects restore the mode on ddraw2+::SetCooperativeLevel(NORMAL) */
4485 restored = test_mode_restored(ddraw7, window);
4486 ok(restored, "Display mode not restored in new ddraw object\n");
4488 /* A failing ddraw1::SetCooperativeLevel call does not have an effect */
4489 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4490 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4492 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4493 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
4494 restored = test_mode_restored(ddraw7, window);
4495 ok(restored, "Display mode not restored after bad ddraw1::SetCooperativeLevel call\n");
4497 /* A successful one does */
4498 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4499 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4500 restored = test_mode_restored(ddraw7, window);
4501 ok(!restored, "Display mode restored after good ddraw1::SetCooperativeLevel call\n");
4503 IDirectDraw_Release(ddraw);
4504 IDirectDraw7_Release(ddraw7);
4506 ddraw7 = create_ddraw();
4507 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4508 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4509 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4511 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_SETFOCUSWINDOW);
4512 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4513 restored = test_mode_restored(ddraw7, window);
4514 ok(!restored, "Display mode restored after ddraw1::SetCooperativeLevel(SETFOCUSWINDOW) call\n");
4516 IDirectDraw_Release(ddraw);
4517 IDirectDraw7_Release(ddraw7);
4519 /* A failing call does not restore the ddraw2+ behavior */
4520 ddraw7 = create_ddraw();
4521 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4522 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4523 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4525 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4526 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4527 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4528 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
4529 restored = test_mode_restored(ddraw7, window);
4530 ok(!restored, "Display mode restored after good-bad ddraw1::SetCooperativeLevel() call sequence\n");
4532 IDirectDraw_Release(ddraw);
4533 IDirectDraw7_Release(ddraw7);
4535 /* Neither does a sequence of successful calls with the new interface */
4536 ddraw7 = create_ddraw();
4537 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4538 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4539 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4541 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4542 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4543 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4544 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4545 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
4546 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4548 restored = test_mode_restored(ddraw7, window);
4549 ok(!restored, "Display mode restored after ddraw1-ddraw7 SetCooperativeLevel() call sequence\n");
4550 IDirectDraw_Release(ddraw);
4551 IDirectDraw7_Release(ddraw7);
4553 /* ddraw1::CreateSurface does not triger the ddraw1 behavior */
4554 ddraw7 = create_ddraw();
4555 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4556 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4557 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4559 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
4560 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4562 memset(&ddsd, 0, sizeof(ddsd));
4563 ddsd.dwSize = sizeof(ddsd);
4564 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
4565 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4566 ddsd.dwWidth = ddsd.dwHeight = 8;
4567 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
4568 ok(SUCCEEDED(hr), "CreateSurface failed, hr %#x.\n", hr);
4569 IDirectDrawSurface_Release(surface);
4570 restored = test_mode_restored(ddraw7, window);
4571 ok(restored, "Display mode not restored after ddraw1::CreateSurface() call\n");
4573 IDirectDraw_Release(ddraw);
4574 IDirectDraw7_Release(ddraw7);
4575 DestroyWindow(window);
4578 static void test_fog_special(void)
4580 static struct
4582 struct vec3 position;
4583 D3DCOLOR diffuse;
4585 quad[] =
4587 {{ -1.0f, 1.0f, 0.0f}, 0xff00ff00},
4588 {{ 1.0f, 1.0f, 1.0f}, 0xff00ff00},
4589 {{ -1.0f, -1.0f, 0.0f}, 0xff00ff00},
4590 {{ 1.0f, -1.0f, 1.0f}, 0xff00ff00},
4592 static const struct
4594 DWORD vertexmode, tablemode;
4595 D3DCOLOR color_left, color_right;
4597 tests[] =
4599 {D3DFOG_LINEAR, D3DFOG_NONE, 0x00ff0000, 0x00ff0000},
4600 {D3DFOG_NONE, D3DFOG_LINEAR, 0x0000ff00, 0x00ff0000},
4602 union
4604 float f;
4605 DWORD d;
4606 } conv;
4607 D3DCOLOR color;
4608 HRESULT hr;
4609 unsigned int i;
4610 HWND window;
4611 IDirect3DDevice7 *device;
4612 IDirectDrawSurface7 *rt;
4614 window = create_window();
4615 if (!(device = create_device(window, DDSCL_NORMAL)))
4617 skip("Failed to create a 3D device, skipping test.\n");
4618 DestroyWindow(window);
4619 return;
4622 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
4623 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4625 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
4626 ok(SUCCEEDED(hr), "Failed to enable fog, hr %#x.\n", hr);
4627 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0xffff0000);
4628 ok(SUCCEEDED(hr), "Failed to set fog color, hr %#x.\n", hr);
4629 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
4630 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
4631 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
4632 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
4634 conv.f = 0.5f;
4635 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGSTART, conv.d);
4636 ok(SUCCEEDED(hr), "Failed to set fog start, hr %#x.\n", hr);
4637 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGEND, conv.d);
4638 ok(SUCCEEDED(hr), "Failed to set fog end, hr %#x.\n", hr);
4640 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4642 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x000000ff, 1.0f, 0);
4643 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4645 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, tests[i].vertexmode);
4646 ok(SUCCEEDED(hr), "Failed to set fogvertexmode, hr %#x.\n", hr);
4647 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, tests[i].tablemode);
4648 ok(SUCCEEDED(hr), "Failed to set fogtablemode, hr %#x.\n", hr);
4650 hr = IDirect3DDevice7_BeginScene(device);
4651 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4652 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, 4, 0);
4653 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4654 hr = IDirect3DDevice7_EndScene(device);
4655 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4657 color = get_surface_color(rt, 310, 240);
4658 ok(compare_color(color, tests[i].color_left, 1),
4659 "Expected left color 0x%08x, got 0x%08x, case %u.\n", tests[i].color_left, color, i);
4660 color = get_surface_color(rt, 330, 240);
4661 ok(compare_color(color, tests[i].color_right, 1),
4662 "Expected right color 0x%08x, got 0x%08x, case %u.\n", tests[i].color_right, color, i);
4665 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
4666 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
4668 IDirectDrawSurface7_Release(rt);
4669 IDirect3DDevice7_Release(device);
4670 DestroyWindow(window);
4673 static void test_lighting_interface_versions(void)
4675 IDirect3DDevice7 *device;
4676 IDirectDrawSurface7 *rt;
4677 D3DCOLOR color;
4678 HWND window;
4679 HRESULT hr;
4680 DWORD rs;
4681 unsigned int i;
4682 ULONG ref;
4683 D3DMATERIAL7 material;
4684 static D3DVERTEX quad[] =
4686 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4687 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4688 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4689 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4692 #define FVF_COLORVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_SPECULAR)
4693 static struct
4695 struct vec3 position;
4696 struct vec3 normal;
4697 DWORD diffuse, specular;
4699 quad2[] =
4701 {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4702 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4703 {{-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4704 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4707 static D3DLVERTEX lquad[] =
4709 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4710 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4711 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4712 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4715 #define FVF_LVERTEX2 (D3DFVF_LVERTEX & ~D3DFVF_RESERVED1)
4716 static struct
4718 struct vec3 position;
4719 DWORD diffuse, specular;
4720 struct vec2 texcoord;
4722 lquad2[] =
4724 {{-1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
4725 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
4726 {{-1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
4727 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
4730 static D3DTLVERTEX tlquad[] =
4732 {{ 0.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4733 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4734 {{ 640.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4735 {{ 640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4738 static const struct
4740 DWORD vertextype;
4741 void *data;
4742 DWORD d3drs_lighting, d3drs_specular;
4743 DWORD draw_flags;
4744 D3DCOLOR color;
4746 tests[] =
4748 /* Lighting is enabled when D3DFVF_XYZ is used and D3DRENDERSTATE_LIGHTING is
4749 * enabled. D3DDP_DONOTLIGHT is ignored. Lighting is also enabled when normals
4750 * are not available
4752 * Note that the specular result is 0x00000000 when lighting is on even if the
4753 * input vertex has specular color because D3DRENDERSTATE_COLORVERTEX is not
4754 * enabled */
4756 /* 0 */
4757 { D3DFVF_VERTEX, quad, FALSE, FALSE, 0, 0x00ffffff},
4758 { D3DFVF_VERTEX, quad, TRUE, FALSE, 0, 0x0000ff00},
4759 { D3DFVF_VERTEX, quad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
4760 { D3DFVF_VERTEX, quad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
4761 { D3DFVF_VERTEX, quad, FALSE, TRUE, 0, 0x00ffffff},
4762 { D3DFVF_VERTEX, quad, TRUE, TRUE, 0, 0x0000ff00},
4763 { D3DFVF_VERTEX, quad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
4764 { D3DFVF_VERTEX, quad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
4766 /* 8 */
4767 { FVF_COLORVERTEX, quad2, FALSE, FALSE, 0, 0x00ff0000},
4768 { FVF_COLORVERTEX, quad2, TRUE, FALSE, 0, 0x0000ff00},
4769 { FVF_COLORVERTEX, quad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4770 { FVF_COLORVERTEX, quad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
4771 { FVF_COLORVERTEX, quad2, FALSE, TRUE, 0, 0x00ff8080},
4772 { FVF_COLORVERTEX, quad2, TRUE, TRUE, 0, 0x0000ff00},
4773 { FVF_COLORVERTEX, quad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4774 { FVF_COLORVERTEX, quad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
4776 /* 16 */
4777 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, 0, 0x00ff0000},
4778 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, 0, 0x0000ff00},
4779 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4780 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
4781 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, 0, 0x00ff8080},
4782 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, 0, 0x0000ff00},
4783 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4784 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
4786 /* 24 */
4787 { FVF_LVERTEX2, lquad2, FALSE, FALSE, 0, 0x00ff0000},
4788 { FVF_LVERTEX2, lquad2, TRUE, FALSE, 0, 0x0000ff00},
4789 { FVF_LVERTEX2, lquad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4790 { FVF_LVERTEX2, lquad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
4791 { FVF_LVERTEX2, lquad2, FALSE, TRUE, 0, 0x00ff8080},
4792 { FVF_LVERTEX2, lquad2, TRUE, TRUE, 0, 0x0000ff00},
4793 { FVF_LVERTEX2, lquad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4794 { FVF_LVERTEX2, lquad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
4796 /* 32 */
4797 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, 0, 0x000000ff},
4798 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, 0, 0x000000ff},
4799 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
4800 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
4801 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, 0, 0x008080ff},
4802 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, 0, 0x008080ff},
4803 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
4804 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
4807 window = create_window();
4808 if (!(device = create_device(window, DDSCL_NORMAL)))
4810 skip("Failed to create a 3D device, skipping test.\n");
4811 DestroyWindow(window);
4812 return;
4815 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
4816 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4818 memset(&material, 0, sizeof(material));
4819 U2(U3(material).emissive).g = 1.0f;
4820 hr = IDirect3DDevice7_SetMaterial(device, &material);
4821 ok(SUCCEEDED(hr), "Failed set material, hr %#x.\n", hr);
4822 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
4823 ok(SUCCEEDED(hr), "Failed to disable z test, hr %#x.\n", hr);
4825 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &rs);
4826 ok(SUCCEEDED(hr), "Failed to get lighting render state, hr %#x.\n", hr);
4827 ok(rs == TRUE, "Initial D3DRENDERSTATE_LIGHTING is %#x, expected TRUE.\n", rs);
4828 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, &rs);
4829 ok(SUCCEEDED(hr), "Failed to get specularenable render state, hr %#x.\n", hr);
4830 ok(rs == FALSE, "Initial D3DRENDERSTATE_SPECULARENABLE is %#x, expected FALSE.\n", rs);
4832 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4834 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff202020, 0.0f, 0);
4835 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
4837 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, tests[i].d3drs_lighting);
4838 ok(SUCCEEDED(hr), "Failed to set lighting render state, hr %#x.\n", hr);
4839 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE,
4840 tests[i].d3drs_specular);
4841 ok(SUCCEEDED(hr), "Failed to set specularenable render state, hr %#x.\n", hr);
4843 hr = IDirect3DDevice7_BeginScene(device);
4844 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4845 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
4846 tests[i].vertextype, tests[i].data, 4, tests[i].draw_flags | D3DDP_WAIT);
4847 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4848 hr = IDirect3DDevice7_EndScene(device);
4849 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4851 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &rs);
4852 ok(SUCCEEDED(hr), "Failed to get lighting render state, hr %#x.\n", hr);
4853 ok(rs == tests[i].d3drs_lighting, "D3DRENDERSTATE_LIGHTING is %#x, expected %#x.\n",
4854 rs, tests[i].d3drs_lighting);
4856 color = get_surface_color(rt, 320, 240);
4857 ok(compare_color(color, tests[i].color, 1),
4858 "Got unexpected color 0x%08x, expected 0x%08x, test %u.\n",
4859 color, tests[i].color, i);
4862 IDirectDrawSurface7_Release(rt);
4863 ref = IDirect3DDevice7_Release(device);
4864 ok(ref == 0, "Device not properly released, refcount %u.\n", ref);
4865 DestroyWindow(window);
4868 static struct
4870 BOOL received;
4871 IDirectDraw7 *ddraw;
4872 HWND window;
4873 DWORD coop_level;
4874 } activateapp_testdata;
4876 static LRESULT CALLBACK activateapp_test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
4878 if (message == WM_ACTIVATEAPP)
4880 if (activateapp_testdata.ddraw)
4882 HRESULT hr;
4883 activateapp_testdata.received = FALSE;
4884 hr = IDirectDraw7_SetCooperativeLevel(activateapp_testdata.ddraw,
4885 activateapp_testdata.window, activateapp_testdata.coop_level);
4886 ok(SUCCEEDED(hr), "Recursive SetCooperativeLevel call failed, hr %#x.\n", hr);
4887 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP during recursive SetCooperativeLevel call.\n");
4889 activateapp_testdata.received = TRUE;
4892 return DefWindowProcA(hwnd, message, wparam, lparam);
4895 static void test_coop_level_activateapp(void)
4897 IDirectDraw7 *ddraw;
4898 HRESULT hr;
4899 HWND window;
4900 WNDCLASSA wc = {0};
4901 DDSURFACEDESC2 ddsd;
4902 IDirectDrawSurface7 *surface;
4904 ddraw = create_ddraw();
4905 ok(!!ddraw, "Failed to create a ddraw object.\n");
4907 wc.lpfnWndProc = activateapp_test_proc;
4908 wc.lpszClassName = "ddraw_test_wndproc_wc";
4909 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4911 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
4912 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
4914 /* Exclusive with window already active. */
4915 SetForegroundWindow(window);
4916 activateapp_testdata.received = FALSE;
4917 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4918 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4919 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP although window was already active.\n");
4920 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4921 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4923 /* Exclusive with window not active. */
4924 SetForegroundWindow(GetDesktopWindow());
4925 activateapp_testdata.received = FALSE;
4926 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4927 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4928 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4929 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4930 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4932 /* Normal with window not active, then exclusive with the same window. */
4933 SetForegroundWindow(GetDesktopWindow());
4934 activateapp_testdata.received = FALSE;
4935 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4936 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4937 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP when setting DDSCL_NORMAL.\n");
4938 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4939 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4940 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4941 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4942 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4944 /* Recursive set of DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. */
4945 SetForegroundWindow(GetDesktopWindow());
4946 activateapp_testdata.received = FALSE;
4947 activateapp_testdata.ddraw = ddraw;
4948 activateapp_testdata.window = window;
4949 activateapp_testdata.coop_level = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
4950 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4951 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4952 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4953 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4954 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4956 /* The recursive call seems to have some bad effect on native ddraw, despite (apparently)
4957 * succeeding. Another switch to exclusive and back to normal is needed to release the
4958 * window properly. Without doing this, SetCooperativeLevel(EXCLUSIVE) will not send
4959 * WM_ACTIVATEAPP messages. */
4960 activateapp_testdata.ddraw = NULL;
4961 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4962 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4963 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4964 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4966 /* Setting DDSCL_NORMAL with recursive invocation. */
4967 SetForegroundWindow(GetDesktopWindow());
4968 activateapp_testdata.received = FALSE;
4969 activateapp_testdata.ddraw = ddraw;
4970 activateapp_testdata.window = window;
4971 activateapp_testdata.coop_level = DDSCL_NORMAL;
4972 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4973 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4974 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
4976 /* DDraw is in exclusive mode now. */
4977 memset(&ddsd, 0, sizeof(ddsd));
4978 ddsd.dwSize = sizeof(ddsd);
4979 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
4980 U5(ddsd).dwBackBufferCount = 1;
4981 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
4982 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
4983 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4984 IDirectDrawSurface7_Release(surface);
4986 /* Recover again, just to be sure. */
4987 activateapp_testdata.ddraw = NULL;
4988 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4989 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4990 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4991 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4993 DestroyWindow(window);
4994 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
4995 IDirectDraw7_Release(ddraw);
4998 static void test_texturemanage(void)
5000 IDirectDraw7 *ddraw;
5001 HRESULT hr;
5002 DDSURFACEDESC2 ddsd;
5003 IDirectDrawSurface7 *surface;
5004 unsigned int i;
5005 DDCAPS hal_caps, hel_caps;
5006 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
5007 static const struct
5009 DWORD caps_in, caps2_in;
5010 HRESULT hr;
5011 DWORD caps_out, caps2_out;
5013 tests[] =
5015 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
5016 ~0U, ~0U},
5017 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
5018 ~0U, ~0U},
5019 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
5020 ~0U, ~0U},
5021 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
5022 ~0U, ~0U},
5023 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DD_OK,
5024 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE},
5025 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DD_OK,
5026 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE},
5027 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
5028 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_LOCALVIDMEM, 0},
5029 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
5030 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0},
5032 {0, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
5033 ~0U, ~0U},
5034 {0, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
5035 ~0U, ~0U},
5036 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
5037 ~0U, ~0U},
5038 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
5039 ~0U, ~0U},
5040 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
5041 ~0U, ~0U},
5042 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
5043 ~0U, ~0U},
5044 {DDSCAPS_VIDEOMEMORY, 0, DD_OK,
5045 DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY, 0},
5046 {DDSCAPS_SYSTEMMEMORY, 0, DD_OK,
5047 DDSCAPS_SYSTEMMEMORY, 0},
5050 ddraw = create_ddraw();
5051 ok(!!ddraw, "Failed to create a ddraw object.\n");
5052 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5053 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5055 memset(&hal_caps, 0, sizeof(hal_caps));
5056 hal_caps.dwSize = sizeof(hal_caps);
5057 memset(&hel_caps, 0, sizeof(hel_caps));
5058 hel_caps.dwSize = sizeof(hel_caps);
5059 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, &hel_caps);
5060 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
5061 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps)
5063 skip("Managed textures not supported, skipping managed texture test.\n");
5064 IDirectDraw7_Release(ddraw);
5065 return;
5068 for (i = 0; i < ARRAY_SIZE(tests); ++i)
5070 memset(&ddsd, 0, sizeof(ddsd));
5071 ddsd.dwSize = sizeof(ddsd);
5072 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
5073 ddsd.ddsCaps.dwCaps = tests[i].caps_in;
5074 ddsd.ddsCaps.dwCaps2 = tests[i].caps2_in;
5075 ddsd.dwWidth = 4;
5076 ddsd.dwHeight = 4;
5078 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5079 if (tests[i].hr == DD_OK && is_ddraw64 && (tests[i].caps_in & DDSCAPS_TEXTURE))
5080 todo_wine ok(hr == E_NOINTERFACE, "Test %u: Got unexpected hr %#x.\n", i, hr);
5081 else
5082 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, tests[i].hr);
5083 if (FAILED(hr))
5084 continue;
5086 memset(&ddsd, 0, sizeof(ddsd));
5087 ddsd.dwSize = sizeof(ddsd);
5088 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
5089 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5091 ok(ddsd.ddsCaps.dwCaps == tests[i].caps_out,
5092 "Input caps %#x, %#x, expected output caps %#x, got %#x, case %u.\n",
5093 tests[i].caps_in, tests[i].caps2_in, tests[i].caps_out, ddsd.ddsCaps.dwCaps, i);
5094 ok(ddsd.ddsCaps.dwCaps2 == tests[i].caps2_out,
5095 "Input caps %#x, %#x, expected output caps %#x, got %#x, case %u.\n",
5096 tests[i].caps_in, tests[i].caps2_in, tests[i].caps2_out, ddsd.ddsCaps.dwCaps2, i);
5098 IDirectDrawSurface7_Release(surface);
5101 IDirectDraw7_Release(ddraw);
5104 #define SUPPORT_DXT1 0x01
5105 #define SUPPORT_DXT2 0x02
5106 #define SUPPORT_DXT3 0x04
5107 #define SUPPORT_DXT4 0x08
5108 #define SUPPORT_DXT5 0x10
5109 #define SUPPORT_YUY2 0x20
5110 #define SUPPORT_UYVY 0x40
5112 static HRESULT WINAPI test_block_formats_creation_cb(DDPIXELFORMAT *fmt, void *ctx)
5114 DWORD *supported_fmts = ctx;
5116 if (!(fmt->dwFlags & DDPF_FOURCC))
5117 return DDENUMRET_OK;
5119 switch (fmt->dwFourCC)
5121 case MAKEFOURCC('D','X','T','1'):
5122 *supported_fmts |= SUPPORT_DXT1;
5123 break;
5124 case MAKEFOURCC('D','X','T','2'):
5125 *supported_fmts |= SUPPORT_DXT2;
5126 break;
5127 case MAKEFOURCC('D','X','T','3'):
5128 *supported_fmts |= SUPPORT_DXT3;
5129 break;
5130 case MAKEFOURCC('D','X','T','4'):
5131 *supported_fmts |= SUPPORT_DXT4;
5132 break;
5133 case MAKEFOURCC('D','X','T','5'):
5134 *supported_fmts |= SUPPORT_DXT5;
5135 break;
5136 case MAKEFOURCC('Y','U','Y','2'):
5137 *supported_fmts |= SUPPORT_YUY2;
5138 break;
5139 case MAKEFOURCC('U','Y','V','Y'):
5140 *supported_fmts |= SUPPORT_UYVY;
5141 break;
5142 default:
5143 break;
5146 return DDENUMRET_OK;
5149 static void test_block_formats_creation(void)
5151 HRESULT hr, expect_hr;
5152 unsigned int i, j, w, h;
5153 HWND window;
5154 IDirectDraw7 *ddraw;
5155 IDirect3D7 *d3d;
5156 IDirect3DDevice7 *device;
5157 IDirectDrawSurface7 *surface;
5158 DWORD supported_fmts = 0, supported_overlay_fmts = 0;
5159 DWORD num_fourcc_codes = 0, *fourcc_codes;
5160 DDSURFACEDESC2 ddsd;
5161 DDCAPS hal_caps;
5162 void *mem;
5164 static const struct
5166 DWORD fourcc;
5167 const char *name;
5168 DWORD support_flag;
5169 unsigned int block_width;
5170 unsigned int block_height;
5171 unsigned int block_size;
5172 BOOL create_size_checked, overlay;
5174 formats[] =
5176 {MAKEFOURCC('D','X','T','1'), "D3DFMT_DXT1", SUPPORT_DXT1, 4, 4, 8, TRUE, FALSE},
5177 {MAKEFOURCC('D','X','T','2'), "D3DFMT_DXT2", SUPPORT_DXT2, 4, 4, 16, TRUE, FALSE},
5178 {MAKEFOURCC('D','X','T','3'), "D3DFMT_DXT3", SUPPORT_DXT3, 4, 4, 16, TRUE, FALSE},
5179 {MAKEFOURCC('D','X','T','4'), "D3DFMT_DXT4", SUPPORT_DXT4, 4, 4, 16, TRUE, FALSE},
5180 {MAKEFOURCC('D','X','T','5'), "D3DFMT_DXT5", SUPPORT_DXT5, 4, 4, 16, TRUE, FALSE},
5181 {MAKEFOURCC('Y','U','Y','2'), "D3DFMT_YUY2", SUPPORT_YUY2, 2, 1, 4, FALSE, TRUE },
5182 {MAKEFOURCC('U','Y','V','Y'), "D3DFMT_UYVY", SUPPORT_UYVY, 2, 1, 4, FALSE, TRUE },
5184 static const struct
5186 DWORD caps, caps2;
5187 const char *name;
5188 BOOL overlay;
5190 types[] =
5192 /* DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY fails to create any fourcc
5193 * surface with DDERR_INVALIDPIXELFORMAT. Don't care about it for now.
5195 * Nvidia returns E_FAIL on DXTN DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY.
5196 * Other hw / drivers successfully create those surfaces. Ignore them, this
5197 * suggests that no game uses this, otherwise Nvidia would support it. */
5199 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0,
5200 "videomemory texture", FALSE
5203 DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY, 0,
5204 "videomemory overlay", TRUE
5207 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0,
5208 "systemmemory texture", FALSE
5211 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
5212 "managed texture", FALSE
5215 enum size_type
5217 SIZE_TYPE_ZERO,
5218 SIZE_TYPE_PITCH,
5219 SIZE_TYPE_SIZE,
5221 static const struct
5223 DWORD flags;
5224 enum size_type size_type;
5225 int rel_size;
5226 HRESULT hr;
5228 user_mem_tests[] =
5230 {DDSD_LINEARSIZE, SIZE_TYPE_ZERO, 0, DD_OK},
5231 {DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
5232 {DDSD_PITCH, SIZE_TYPE_ZERO, 0, DD_OK},
5233 {DDSD_PITCH, SIZE_TYPE_PITCH, 0, DD_OK},
5234 {DDSD_LPSURFACE, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
5235 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
5236 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_PITCH, 0, DDERR_INVALIDPARAMS},
5237 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
5238 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 1, DD_OK},
5239 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, -1, DDERR_INVALIDPARAMS},
5240 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
5241 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_PITCH, 0, DDERR_INVALIDPARAMS},
5242 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_SIZE, 0, DDERR_INVALIDPARAMS},
5243 {DDSD_LPSURFACE | DDSD_PITCH | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DDERR_INVALIDPARAMS},
5246 window = create_window();
5247 if (!(device = create_device(window, DDSCL_NORMAL)))
5249 skip("Failed to create a 3D device, skipping test.\n");
5250 DestroyWindow(window);
5251 return;
5254 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
5255 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
5256 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **) &ddraw);
5257 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
5258 IDirect3D7_Release(d3d);
5260 hr = IDirect3DDevice7_EnumTextureFormats(device, test_block_formats_creation_cb,
5261 &supported_fmts);
5262 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
5264 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
5265 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
5266 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5267 num_fourcc_codes * sizeof(*fourcc_codes));
5268 if (!fourcc_codes)
5269 goto cleanup;
5270 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
5271 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
5272 for (i = 0; i < num_fourcc_codes; i++)
5274 for (j = 0; j < ARRAY_SIZE(formats); ++j)
5276 if (fourcc_codes[i] == formats[j].fourcc)
5277 supported_overlay_fmts |= formats[j].support_flag;
5280 HeapFree(GetProcessHeap(), 0, fourcc_codes);
5282 memset(&hal_caps, 0, sizeof(hal_caps));
5283 hal_caps.dwSize = sizeof(hal_caps);
5284 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
5285 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
5287 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 2 * 2 * 16 + 1);
5289 for (i = 0; i < ARRAY_SIZE(formats); ++i)
5291 for (j = 0; j < ARRAY_SIZE(types); ++j)
5293 BOOL support;
5295 if (formats[i].overlay != types[j].overlay
5296 || (types[j].overlay && !(hal_caps.dwCaps & DDCAPS_OVERLAY)))
5297 continue;
5299 if (formats[i].overlay)
5300 support = supported_overlay_fmts & formats[i].support_flag;
5301 else
5302 support = supported_fmts & formats[i].support_flag;
5304 for (w = 1; w <= 8; w++)
5306 for (h = 1; h <= 8; h++)
5308 BOOL block_aligned = TRUE;
5309 BOOL todo = FALSE;
5311 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
5312 block_aligned = FALSE;
5314 memset(&ddsd, 0, sizeof(ddsd));
5315 ddsd.dwSize = sizeof(ddsd);
5316 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
5317 ddsd.ddsCaps.dwCaps = types[j].caps;
5318 ddsd.ddsCaps.dwCaps2 = types[j].caps2;
5319 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
5320 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
5321 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
5322 ddsd.dwWidth = w;
5323 ddsd.dwHeight = h;
5325 /* TODO: Handle power of two limitations. I cannot test the pow2
5326 * behavior on windows because I have no hardware that doesn't at
5327 * least support np2_conditional. There's probably no HW that
5328 * supports DXTN textures but no conditional np2 textures. */
5329 if (!support && !(types[j].caps & DDSCAPS_SYSTEMMEMORY))
5330 expect_hr = DDERR_INVALIDPARAMS;
5331 else if (formats[i].create_size_checked && !block_aligned)
5333 expect_hr = DDERR_INVALIDPARAMS;
5334 if (!(types[j].caps & DDSCAPS_TEXTURE))
5335 todo = TRUE;
5337 else
5338 expect_hr = D3D_OK;
5340 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5341 todo_wine_if (todo)
5342 ok(hr == expect_hr,
5343 "Got unexpected hr %#x for format %s, resource type %s, size %ux%u, expected %#x.\n",
5344 hr, formats[i].name, types[j].name, w, h, expect_hr);
5346 if (SUCCEEDED(hr))
5347 IDirectDrawSurface7_Release(surface);
5352 if (formats[i].overlay)
5353 continue;
5355 for (j = 0; j < ARRAY_SIZE(user_mem_tests); ++j)
5357 memset(&ddsd, 0, sizeof(ddsd));
5358 ddsd.dwSize = sizeof(ddsd);
5359 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | user_mem_tests[j].flags;
5360 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE;
5362 switch (user_mem_tests[j].size_type)
5364 case SIZE_TYPE_ZERO:
5365 U1(ddsd).dwLinearSize = 0;
5366 break;
5368 case SIZE_TYPE_PITCH:
5369 U1(ddsd).dwLinearSize = 2 * formats[i].block_size;
5370 break;
5372 case SIZE_TYPE_SIZE:
5373 U1(ddsd).dwLinearSize = 2 * 2 * formats[i].block_size;
5374 break;
5376 U1(ddsd).dwLinearSize += user_mem_tests[j].rel_size;
5378 ddsd.lpSurface = mem;
5379 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
5380 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
5381 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
5382 ddsd.dwWidth = 8;
5383 ddsd.dwHeight = 8;
5385 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5386 ok(hr == user_mem_tests[j].hr, "Test %u: Got unexpected hr %#x, format %s.\n", j, hr, formats[i].name);
5388 if (FAILED(hr))
5389 continue;
5391 memset(&ddsd, 0, sizeof(ddsd));
5392 ddsd.dwSize = sizeof(ddsd);
5393 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
5394 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", j, hr);
5395 ok(ddsd.dwFlags == (DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_LINEARSIZE),
5396 "Test %u: Got unexpected flags %#x.\n", j, ddsd.dwFlags);
5397 if (user_mem_tests[j].flags & DDSD_LPSURFACE)
5398 ok(U1(ddsd).dwLinearSize == ~0u, "Test %u: Got unexpected linear size %#x.\n",
5399 j, U1(ddsd).dwLinearSize);
5400 else
5401 ok(U1(ddsd).dwLinearSize == 2 * 2 * formats[i].block_size,
5402 "Test %u: Got unexpected linear size %#x, expected %#x.\n",
5403 j, U1(ddsd).dwLinearSize, 2 * 2 * formats[i].block_size);
5404 IDirectDrawSurface7_Release(surface);
5408 HeapFree(GetProcessHeap(), 0, mem);
5409 cleanup:
5410 IDirectDraw7_Release(ddraw);
5411 IDirect3DDevice7_Release(device);
5412 DestroyWindow(window);
5415 struct format_support_check
5417 const DDPIXELFORMAT *format;
5418 BOOL supported;
5421 static HRESULT WINAPI test_unsupported_formats_cb(DDPIXELFORMAT *fmt, void *ctx)
5423 struct format_support_check *format = ctx;
5425 if (!memcmp(format->format, fmt, sizeof(*fmt)))
5427 format->supported = TRUE;
5428 return DDENUMRET_CANCEL;
5431 return DDENUMRET_OK;
5434 static void test_unsupported_formats(void)
5436 HRESULT hr;
5437 BOOL expect_success;
5438 HWND window;
5439 IDirectDraw7 *ddraw;
5440 IDirect3D7 *d3d;
5441 IDirect3DDevice7 *device;
5442 IDirectDrawSurface7 *surface;
5443 DDSURFACEDESC2 ddsd;
5444 unsigned int i, j;
5445 DWORD expected_caps;
5446 static const struct
5448 const char *name;
5449 DDPIXELFORMAT fmt;
5451 formats[] =
5454 "D3DFMT_A8R8G8B8",
5456 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
5457 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
5461 "D3DFMT_P8",
5463 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
5464 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
5468 static const DWORD caps[] = {0, DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY};
5470 window = create_window();
5471 if (!(device = create_device(window, DDSCL_NORMAL)))
5473 skip("Failed to create a 3D device, skipping test.\n");
5474 DestroyWindow(window);
5475 return;
5478 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
5479 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
5480 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **) &ddraw);
5481 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
5482 IDirect3D7_Release(d3d);
5484 for (i = 0; i < ARRAY_SIZE(formats); ++i)
5486 struct format_support_check check = {&formats[i].fmt, FALSE};
5487 hr = IDirect3DDevice7_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
5488 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
5490 for (j = 0; j < ARRAY_SIZE(caps); ++j)
5492 memset(&ddsd, 0, sizeof(ddsd));
5493 ddsd.dwSize = sizeof(ddsd);
5494 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
5495 U4(ddsd).ddpfPixelFormat = formats[i].fmt;
5496 ddsd.dwWidth = 4;
5497 ddsd.dwHeight = 4;
5498 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | caps[j];
5500 if (caps[j] & DDSCAPS_VIDEOMEMORY && !check.supported)
5501 expect_success = FALSE;
5502 else
5503 expect_success = TRUE;
5505 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5506 ok(SUCCEEDED(hr) == expect_success,
5507 "Got unexpected hr %#x for format %s, caps %#x, expected %s.\n",
5508 hr, formats[i].name, caps[j], expect_success ? "success" : "failure");
5509 if (FAILED(hr))
5510 continue;
5512 memset(&ddsd, 0, sizeof(ddsd));
5513 ddsd.dwSize = sizeof(ddsd);
5514 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
5515 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5517 if (caps[j] & DDSCAPS_VIDEOMEMORY)
5518 expected_caps = DDSCAPS_VIDEOMEMORY;
5519 else if (caps[j] & DDSCAPS_SYSTEMMEMORY)
5520 expected_caps = DDSCAPS_SYSTEMMEMORY;
5521 else if (check.supported)
5522 expected_caps = DDSCAPS_VIDEOMEMORY;
5523 else
5524 expected_caps = DDSCAPS_SYSTEMMEMORY;
5526 ok(ddsd.ddsCaps.dwCaps & expected_caps,
5527 "Expected capability %#x, format %s, input cap %#x.\n",
5528 expected_caps, formats[i].name, caps[j]);
5530 IDirectDrawSurface7_Release(surface);
5534 IDirectDraw7_Release(ddraw);
5535 IDirect3DDevice7_Release(device);
5536 DestroyWindow(window);
5539 static void test_rt_caps(void)
5541 const GUID *devtype = &IID_IDirect3DHALDevice;
5542 PALETTEENTRY palette_entries[256];
5543 IDirectDrawPalette *palette;
5544 IDirectDraw7 *ddraw;
5545 BOOL hal_ok = FALSE;
5546 DDPIXELFORMAT z_fmt;
5547 IDirect3D7 *d3d;
5548 unsigned int i;
5549 ULONG refcount;
5550 HWND window;
5551 HRESULT hr;
5553 static const DDPIXELFORMAT p8_fmt =
5555 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
5556 {8}, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000},
5559 const struct
5561 const DDPIXELFORMAT *pf;
5562 DWORD caps_in;
5563 DWORD caps_out;
5564 HRESULT create_device_hr;
5565 HRESULT set_rt_hr, alternative_set_rt_hr;
5567 test_data[] =
5570 NULL,
5571 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
5572 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5573 D3D_OK,
5574 D3D_OK,
5575 D3D_OK,
5578 NULL,
5579 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5580 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5581 D3D_OK,
5582 D3D_OK,
5583 D3D_OK,
5586 NULL,
5587 DDSCAPS_OFFSCREENPLAIN,
5588 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5589 DDERR_INVALIDCAPS,
5590 DDERR_INVALIDCAPS,
5591 DDERR_INVALIDCAPS,
5594 NULL,
5595 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5596 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5597 D3DERR_SURFACENOTINVIDMEM,
5598 DDERR_INVALIDPARAMS,
5599 D3D_OK,
5602 NULL,
5603 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5604 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5605 DDERR_INVALIDCAPS,
5606 DDERR_INVALIDCAPS,
5607 DDERR_INVALIDCAPS,
5610 NULL,
5611 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
5612 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5613 D3D_OK,
5614 D3D_OK,
5615 D3D_OK,
5618 NULL,
5619 DDSCAPS_3DDEVICE,
5620 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5621 D3D_OK,
5622 D3D_OK,
5623 D3D_OK,
5626 NULL,
5628 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5629 DDERR_INVALIDCAPS,
5630 DDERR_INVALIDCAPS,
5631 DDERR_INVALIDCAPS,
5634 NULL,
5635 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5636 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5637 D3DERR_SURFACENOTINVIDMEM,
5638 DDERR_INVALIDPARAMS,
5639 D3D_OK,
5642 NULL,
5643 DDSCAPS_SYSTEMMEMORY,
5644 DDSCAPS_SYSTEMMEMORY,
5645 DDERR_INVALIDCAPS,
5646 DDERR_INVALIDCAPS,
5647 DDERR_INVALIDCAPS,
5650 &p8_fmt,
5652 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5653 DDERR_INVALIDCAPS,
5654 DDERR_INVALIDCAPS,
5655 DDERR_INVALIDCAPS,
5658 &p8_fmt,
5659 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5660 ~0U /* AMD r200 */,
5661 DDERR_NOPALETTEATTACHED,
5662 DDERR_INVALIDCAPS,
5663 DDERR_INVALIDCAPS,
5666 &p8_fmt,
5667 DDSCAPS_OFFSCREENPLAIN,
5668 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5669 DDERR_INVALIDCAPS,
5670 DDERR_INVALIDCAPS,
5671 DDERR_INVALIDCAPS,
5674 &p8_fmt,
5675 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5676 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5677 DDERR_NOPALETTEATTACHED,
5678 DDERR_INVALIDCAPS,
5679 DDERR_INVALIDCAPS,
5682 &p8_fmt,
5683 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5684 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5685 DDERR_INVALIDCAPS,
5686 DDERR_INVALIDCAPS,
5687 DDERR_INVALIDCAPS,
5690 &z_fmt,
5691 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
5692 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5693 DDERR_INVALIDCAPS,
5694 DDERR_INVALIDPIXELFORMAT,
5695 DDERR_INVALIDPIXELFORMAT,
5698 &z_fmt,
5699 DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5700 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5701 DDERR_INVALIDCAPS,
5702 DDERR_INVALIDPIXELFORMAT,
5703 DDERR_INVALIDPIXELFORMAT,
5706 &z_fmt,
5707 DDSCAPS_ZBUFFER,
5708 DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5709 DDERR_INVALIDCAPS,
5710 DDERR_INVALIDCAPS,
5711 DDERR_INVALIDCAPS,
5714 &z_fmt,
5715 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5716 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5717 DDERR_INVALIDCAPS,
5718 DDERR_INVALIDPARAMS,
5719 DDERR_INVALIDPIXELFORMAT,
5722 &z_fmt,
5723 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
5724 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
5725 DDERR_INVALIDCAPS,
5726 DDERR_INVALIDCAPS,
5727 DDERR_INVALIDCAPS,
5731 window = create_window();
5732 ddraw = create_ddraw();
5733 ok(!!ddraw, "Failed to create a ddraw object.\n");
5734 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5735 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5737 if (FAILED(IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d)))
5739 skip("D3D interface is not available, skipping test.\n");
5740 goto done;
5743 hr = IDirect3D7_EnumDevices(d3d, enum_devtype_cb, &hal_ok);
5744 ok(SUCCEEDED(hr), "Failed to enumerate devices, hr %#x.\n", hr);
5745 if (hal_ok)
5746 devtype = &IID_IDirect3DTnLHalDevice;
5748 memset(&z_fmt, 0, sizeof(z_fmt));
5749 hr = IDirect3D7_EnumZBufferFormats(d3d, devtype, enum_z_fmt, &z_fmt);
5750 if (FAILED(hr) || !z_fmt.dwSize)
5752 skip("No depth buffer formats available, skipping test.\n");
5753 IDirect3D7_Release(d3d);
5754 goto done;
5757 memset(palette_entries, 0, sizeof(palette_entries));
5758 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
5759 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
5761 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
5763 IDirectDrawSurface7 *surface, *rt, *expected_rt, *tmp;
5764 DDSURFACEDESC2 surface_desc;
5765 IDirect3DDevice7 *device;
5767 memset(&surface_desc, 0, sizeof(surface_desc));
5768 surface_desc.dwSize = sizeof(surface_desc);
5769 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5770 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5771 if (test_data[i].pf)
5773 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
5774 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
5776 surface_desc.dwWidth = 640;
5777 surface_desc.dwHeight = 480;
5778 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5779 ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
5780 i, test_data[i].caps_in, hr);
5782 memset(&surface_desc, 0, sizeof(surface_desc));
5783 surface_desc.dwSize = sizeof(surface_desc);
5784 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
5785 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
5786 ok(test_data[i].caps_out == ~0U || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out,
5787 "Test %u: Got unexpected caps %#x, expected %#x.\n",
5788 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
5790 hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
5791 ok(hr == test_data[i].create_device_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n",
5792 i, hr, test_data[i].create_device_hr);
5793 if (FAILED(hr))
5795 if (hr == DDERR_NOPALETTEATTACHED)
5797 hr = IDirectDrawSurface7_SetPalette(surface, palette);
5798 ok(SUCCEEDED(hr), "Test %u: Failed to set palette, hr %#x.\n", i, hr);
5799 hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
5800 if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
5801 ok(hr == DDERR_INVALIDPIXELFORMAT, "Test %u: Got unexpected hr %#x.\n", i, hr);
5802 else
5803 ok(hr == D3DERR_SURFACENOTINVIDMEM, "Test %u: Got unexpected hr %#x.\n", i, hr);
5805 IDirectDrawSurface7_Release(surface);
5807 memset(&surface_desc, 0, sizeof(surface_desc));
5808 surface_desc.dwSize = sizeof(surface_desc);
5809 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5810 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
5811 surface_desc.dwWidth = 640;
5812 surface_desc.dwHeight = 480;
5813 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5814 ok(SUCCEEDED(hr), "Test %u: Failed to create surface, hr %#x.\n", i, hr);
5816 hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
5817 ok(SUCCEEDED(hr), "Test %u: Failed to create device, hr %#x.\n", i, hr);
5820 memset(&surface_desc, 0, sizeof(surface_desc));
5821 surface_desc.dwSize = sizeof(surface_desc);
5822 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5823 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5824 if (test_data[i].pf)
5826 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
5827 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
5829 surface_desc.dwWidth = 640;
5830 surface_desc.dwHeight = 480;
5831 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &rt, NULL);
5832 ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
5833 i, test_data[i].caps_in, hr);
5835 hr = IDirect3DDevice7_SetRenderTarget(device, rt, 0);
5836 ok(hr == test_data[i].set_rt_hr || broken(hr == test_data[i].alternative_set_rt_hr),
5837 "Test %u: Got unexpected hr %#x, expected %#x.\n",
5838 i, hr, test_data[i].set_rt_hr);
5839 if (SUCCEEDED(hr) || hr == DDERR_INVALIDPIXELFORMAT)
5840 expected_rt = rt;
5841 else
5842 expected_rt = surface;
5844 hr = IDirect3DDevice7_GetRenderTarget(device, &tmp);
5845 ok(SUCCEEDED(hr), "Test %u: Failed to get render target, hr %#x.\n", i, hr);
5846 ok(tmp == expected_rt, "Test %u: Got unexpected rt %p.\n", i, tmp);
5848 IDirectDrawSurface7_Release(tmp);
5849 IDirectDrawSurface7_Release(rt);
5850 refcount = IDirect3DDevice7_Release(device);
5851 ok(refcount == 0, "Test %u: The device was not properly freed, refcount %u.\n", i, refcount);
5852 refcount = IDirectDrawSurface7_Release(surface);
5853 ok(refcount == 0, "Test %u: The surface was not properly freed, refcount %u.\n", i, refcount);
5856 IDirectDrawPalette_Release(palette);
5857 IDirect3D7_Release(d3d);
5859 done:
5860 refcount = IDirectDraw7_Release(ddraw);
5861 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5862 DestroyWindow(window);
5865 static void test_primary_caps(void)
5867 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
5868 IDirectDrawSurface7 *surface;
5869 DDSURFACEDESC2 surface_desc;
5870 IDirectDraw7 *ddraw;
5871 unsigned int i;
5872 ULONG refcount;
5873 HWND window;
5874 HRESULT hr;
5876 static const struct
5878 DWORD coop_level;
5879 DWORD caps_in;
5880 DWORD back_buffer_count;
5881 HRESULT hr;
5882 DWORD caps_out;
5884 test_data[] =
5887 DDSCL_NORMAL,
5888 DDSCAPS_PRIMARYSURFACE,
5889 ~0u,
5890 DD_OK,
5891 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE,
5894 DDSCL_NORMAL,
5895 DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE,
5896 ~0u,
5897 DDERR_INVALIDCAPS,
5898 ~0u,
5901 DDSCL_NORMAL,
5902 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
5903 ~0u,
5904 DDERR_INVALIDCAPS,
5905 ~0u,
5908 DDSCL_NORMAL,
5909 DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER,
5910 ~0u,
5911 DDERR_INVALIDCAPS,
5912 ~0u,
5915 DDSCL_NORMAL,
5916 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP,
5917 ~0u,
5918 DDERR_INVALIDCAPS,
5919 ~0u,
5922 DDSCL_NORMAL,
5923 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX,
5924 ~0u,
5925 DDERR_INVALIDCAPS,
5926 ~0u,
5929 DDSCL_NORMAL,
5930 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5931 ~0u,
5932 DDERR_INVALIDCAPS,
5933 ~0u,
5936 DDSCL_NORMAL,
5937 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5939 DDERR_INVALIDCAPS,
5940 ~0u,
5943 DDSCL_NORMAL,
5944 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5946 DDERR_NOEXCLUSIVEMODE,
5947 ~0u,
5950 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5951 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5953 DDERR_INVALIDCAPS,
5954 ~0u,
5957 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5958 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
5960 DD_OK,
5961 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX,
5964 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5965 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER,
5967 DDERR_INVALIDCAPS,
5968 ~0u,
5971 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
5972 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_BACKBUFFER,
5974 DDERR_INVALIDCAPS,
5975 ~0u,
5979 window = create_window();
5980 ddraw = create_ddraw();
5981 ok(!!ddraw, "Failed to create a ddraw object.\n");
5983 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
5985 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, test_data[i].coop_level);
5986 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5988 memset(&surface_desc, 0, sizeof(surface_desc));
5989 surface_desc.dwSize = sizeof(surface_desc);
5990 surface_desc.dwFlags = DDSD_CAPS;
5991 if (test_data[i].back_buffer_count != ~0u)
5992 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
5993 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5994 U5(surface_desc).dwBackBufferCount = test_data[i].back_buffer_count;
5995 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5996 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
5997 if (FAILED(hr))
5998 continue;
6000 memset(&surface_desc, 0, sizeof(surface_desc));
6001 surface_desc.dwSize = sizeof(surface_desc);
6002 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
6003 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
6004 ok((surface_desc.ddsCaps.dwCaps & ~placement) == test_data[i].caps_out,
6005 "Test %u: Got unexpected caps %#x, expected %#x.\n",
6006 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
6008 IDirectDrawSurface7_Release(surface);
6011 refcount = IDirectDraw7_Release(ddraw);
6012 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
6013 DestroyWindow(window);
6016 static void test_surface_lock(void)
6018 IDirectDraw7 *ddraw;
6019 IDirect3D7 *d3d = NULL;
6020 IDirectDrawSurface7 *surface;
6021 IDirect3DDevice7 *device;
6022 HRESULT hr, expected_hr;
6023 HWND window;
6024 unsigned int i;
6025 DDSURFACEDESC2 ddsd;
6026 ULONG refcount;
6027 DDPIXELFORMAT z_fmt;
6028 BOOL hal_ok = FALSE;
6029 const GUID *devtype = &IID_IDirect3DHALDevice;
6030 D3DDEVICEDESC7 device_desc;
6031 BOOL cubemap_supported;
6032 static const struct
6034 DWORD caps;
6035 DWORD caps2;
6036 const char *name;
6038 tests[] =
6041 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
6043 "videomemory offscreenplain"
6046 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
6048 "systemmemory offscreenplain"
6051 DDSCAPS_PRIMARYSURFACE,
6053 "primary"
6056 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
6058 "videomemory texture"
6061 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
6062 DDSCAPS2_OPAQUE,
6063 "opaque videomemory texture"
6066 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
6068 "systemmemory texture"
6071 DDSCAPS_TEXTURE,
6072 DDSCAPS2_TEXTUREMANAGE,
6073 "managed texture"
6076 DDSCAPS_TEXTURE,
6077 DDSCAPS2_D3DTEXTUREMANAGE,
6078 "managed texture"
6081 DDSCAPS_TEXTURE,
6082 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_OPAQUE,
6083 "opaque managed texture"
6086 DDSCAPS_TEXTURE,
6087 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_OPAQUE,
6088 "opaque managed texture"
6091 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
6093 "render target"
6096 DDSCAPS_ZBUFFER,
6098 "Z buffer"
6101 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY,
6102 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
6103 "videomemory cube"
6106 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY,
6107 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_OPAQUE,
6108 "opaque videomemory cube"
6111 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_SYSTEMMEMORY,
6112 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
6113 "systemmemory cube"
6116 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
6117 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
6118 "managed cube"
6121 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
6122 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
6123 "managed cube"
6126 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
6127 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_OPAQUE,
6128 "opaque managed cube"
6131 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
6132 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_OPAQUE,
6133 "opaque managed cube"
6137 window = create_window();
6138 ddraw = create_ddraw();
6139 ok(!!ddraw, "Failed to create a ddraw object.\n");
6140 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6141 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6143 if (FAILED(IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d)))
6145 skip("D3D interface is not available, skipping test.\n");
6146 goto done;
6149 hr = IDirect3D7_EnumDevices(d3d, enum_devtype_cb, &hal_ok);
6150 ok(SUCCEEDED(hr), "Failed to enumerate devices, hr %#x.\n", hr);
6151 if (hal_ok)
6152 devtype = &IID_IDirect3DTnLHalDevice;
6154 memset(&z_fmt, 0, sizeof(z_fmt));
6155 hr = IDirect3D7_EnumZBufferFormats(d3d, devtype, enum_z_fmt, &z_fmt);
6156 if (FAILED(hr) || !z_fmt.dwSize)
6158 skip("No depth buffer formats available, skipping test.\n");
6159 goto done;
6162 memset(&ddsd, 0, sizeof(ddsd));
6163 ddsd.dwSize = sizeof(ddsd);
6164 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6165 ddsd.dwWidth = 64;
6166 ddsd.dwHeight = 64;
6167 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
6168 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6169 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6171 hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
6172 ok(SUCCEEDED(hr), "Failed to create device, hr %#x.\n", hr);
6173 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
6174 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6175 cubemap_supported = !!(device_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP);
6176 IDirect3DDevice7_Release(device);
6178 IDirectDrawSurface7_Release(surface);
6180 for (i = 0; i < ARRAY_SIZE(tests); ++i)
6182 if (!cubemap_supported && tests[i].caps2 & DDSCAPS2_CUBEMAP)
6183 continue;
6185 memset(&ddsd, 0, sizeof(ddsd));
6186 ddsd.dwSize = sizeof(ddsd);
6187 ddsd.dwFlags = DDSD_CAPS;
6188 if (!(tests[i].caps & DDSCAPS_PRIMARYSURFACE))
6190 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
6191 ddsd.dwWidth = 64;
6192 ddsd.dwHeight = 64;
6194 if (tests[i].caps & DDSCAPS_ZBUFFER)
6196 ddsd.dwFlags |= DDSD_PIXELFORMAT;
6197 U4(ddsd).ddpfPixelFormat = z_fmt;
6199 ddsd.ddsCaps.dwCaps = tests[i].caps;
6200 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
6202 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6203 ok(SUCCEEDED(hr), "Failed to create surface, type %s, hr %#x.\n", tests[i].name, hr);
6205 memset(&ddsd, 0, sizeof(ddsd));
6206 ddsd.dwSize = sizeof(ddsd);
6207 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
6208 ok(SUCCEEDED(hr), "Failed to lock surface, type %s, hr %#x.\n", tests[i].name, hr);
6209 if (SUCCEEDED(hr))
6211 ok(ddsd.dwSize == sizeof(ddsd), "Got unexpected dwSize %u, type %s.\n", ddsd.dwSize, tests[i].name);
6212 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6213 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
6216 memset(&ddsd, 0, sizeof(ddsd));
6217 expected_hr = tests[i].caps & DDSCAPS_TEXTURE && !(tests[i].caps & DDSCAPS_VIDEOMEMORY)
6218 ? DD_OK : DDERR_INVALIDPARAMS;
6219 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
6220 ok(hr == expected_hr, "Got hr %#x, expected %#x, type %s.\n", hr, expected_hr, tests[i].name);
6221 if (SUCCEEDED(hr))
6223 ok(!ddsd.dwSize, "Got unexpected dwSize %u, type %s.\n", ddsd.dwSize, tests[i].name);
6224 ok(!!ddsd.lpSurface, "Got NULL lpSurface, type %s.\n", tests[i].name);
6225 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6226 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
6229 IDirectDrawSurface7_Release(surface);
6232 done:
6233 if (d3d)
6234 IDirect3D7_Release(d3d);
6235 refcount = IDirectDraw7_Release(ddraw);
6236 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
6237 DestroyWindow(window);
6240 static void test_surface_discard(void)
6242 IDirect3DDevice7 *device;
6243 IDirect3D7 *d3d;
6244 IDirectDraw7 *ddraw;
6245 HRESULT hr;
6246 HWND window;
6247 DDSURFACEDESC2 ddsd;
6248 IDirectDrawSurface7 *surface, *target;
6249 void *addr;
6250 static const struct
6252 DWORD caps, caps2;
6253 BOOL discard;
6255 tests[] =
6257 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, TRUE},
6258 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
6259 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, TRUE},
6260 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
6261 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE},
6262 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
6263 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE},
6264 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
6266 unsigned int i;
6268 window = create_window();
6269 if (!(device = create_device(window, DDSCL_NORMAL)))
6271 skip("Failed to create a 3D device, skipping test.\n");
6272 DestroyWindow(window);
6273 return;
6275 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
6276 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
6277 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
6278 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
6279 hr = IDirect3DDevice7_GetRenderTarget(device, &target);
6280 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
6282 for (i = 0; i < ARRAY_SIZE(tests); ++i)
6284 BOOL discarded;
6286 memset(&ddsd, 0, sizeof(ddsd));
6287 ddsd.dwSize = sizeof(ddsd);
6288 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6289 ddsd.ddsCaps.dwCaps = tests[i].caps;
6290 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
6291 ddsd.dwWidth = 64;
6292 ddsd.dwHeight = 64;
6293 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6294 ok(SUCCEEDED(hr), "Failed to create offscreen surface, hr %#x, case %u.\n", hr, i);
6296 memset(&ddsd, 0, sizeof(ddsd));
6297 ddsd.dwSize = sizeof(ddsd);
6298 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, 0, NULL);
6299 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6300 addr = ddsd.lpSurface;
6301 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6302 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6304 memset(&ddsd, 0, sizeof(ddsd));
6305 ddsd.dwSize = sizeof(ddsd);
6306 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
6307 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6308 discarded = ddsd.lpSurface != addr;
6309 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6310 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6312 hr = IDirectDrawSurface7_Blt(target, NULL, surface, NULL, DDBLT_WAIT, NULL);
6313 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
6315 memset(&ddsd, 0, sizeof(ddsd));
6316 ddsd.dwSize = sizeof(ddsd);
6317 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
6318 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6319 discarded |= ddsd.lpSurface != addr;
6320 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6321 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6323 IDirectDrawSurface7_Release(surface);
6325 /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler,
6326 * AMD r500, evergreen). Windows XP, at least on AMD r200, does not. */
6327 ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i);
6330 IDirectDrawSurface7_Release(target);
6331 IDirectDraw7_Release(ddraw);
6332 IDirect3D7_Release(d3d);
6333 IDirect3DDevice7_Release(device);
6334 DestroyWindow(window);
6337 static void fill_surface(IDirectDrawSurface7 *surface, D3DCOLOR color)
6339 DDSURFACEDESC2 surface_desc = {sizeof(surface_desc)};
6340 HRESULT hr;
6341 unsigned int x, y;
6342 DWORD *ptr;
6344 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
6345 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6347 for (y = 0; y < surface_desc.dwHeight; ++y)
6349 ptr = (DWORD *)((BYTE *)surface_desc.lpSurface + y * U1(surface_desc).lPitch);
6350 for (x = 0; x < surface_desc.dwWidth; ++x)
6352 ptr[x] = color;
6356 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6357 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6360 static void test_flip(void)
6362 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
6363 IDirectDrawSurface7 *frontbuffer, *backbuffer1, *backbuffer2, *backbuffer3, *surface;
6364 DDSCAPS2 caps = {DDSCAPS_FLIP, 0, 0, {0}};
6365 DDSURFACEDESC2 surface_desc;
6366 D3DDEVICEDESC7 device_desc;
6367 IDirect3DDevice7 *device;
6368 BOOL sysmem_primary;
6369 IDirectDraw7 *ddraw;
6370 DWORD expected_caps;
6371 unsigned int i;
6372 D3DCOLOR color;
6373 ULONG refcount;
6374 HWND window;
6375 HRESULT hr;
6377 static const struct
6379 const char *name;
6380 DWORD caps;
6382 test_data[] =
6384 {"PRIMARYSURFACE", DDSCAPS_PRIMARYSURFACE},
6385 {"OFFSCREENPLAIN", DDSCAPS_OFFSCREENPLAIN},
6386 {"TEXTURE", DDSCAPS_TEXTURE},
6389 window = create_window();
6390 ddraw = create_ddraw();
6391 ok(!!ddraw, "Failed to create a ddraw object.\n");
6393 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6394 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6396 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
6398 /* Creating a flippable texture induces a BSoD on some versions of the
6399 * Intel graphics driver. At least Intel GMA 950 with driver version
6400 * 6.14.10.4926 on Windows XP SP3 is affected. */
6401 if ((test_data[i].caps & DDSCAPS_TEXTURE) && ddraw_is_intel(ddraw))
6403 win_skip("Skipping flippable texture test.\n");
6404 continue;
6407 memset(&surface_desc, 0, sizeof(surface_desc));
6408 surface_desc.dwSize = sizeof(surface_desc);
6409 surface_desc.dwFlags = DDSD_CAPS;
6410 if (!(test_data[i].caps & DDSCAPS_PRIMARYSURFACE))
6411 surface_desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
6412 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
6413 surface_desc.dwWidth = 512;
6414 surface_desc.dwHeight = 512;
6415 U5(surface_desc).dwBackBufferCount = 3;
6416 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6417 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6419 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_FLIP;
6420 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
6421 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6422 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6424 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_COMPLEX;
6425 surface_desc.ddsCaps.dwCaps |= DDSCAPS_FLIP;
6426 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6427 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6429 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
6430 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6431 if (is_ddraw64 && test_data[i].caps & DDSCAPS_TEXTURE)
6432 todo_wine ok(hr == E_NOINTERFACE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6433 else todo_wine_if(test_data[i].caps & DDSCAPS_TEXTURE)
6434 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
6435 if (FAILED(hr))
6436 continue;
6438 memset(&surface_desc, 0, sizeof(surface_desc));
6439 surface_desc.dwSize = sizeof(surface_desc);
6440 hr = IDirectDrawSurface7_GetSurfaceDesc(frontbuffer, &surface_desc);
6441 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6442 expected_caps = DDSCAPS_FRONTBUFFER | DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
6443 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
6444 expected_caps |= DDSCAPS_VISIBLE;
6445 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6446 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6447 sysmem_primary = surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
6449 hr = IDirectDrawSurface7_GetAttachedSurface(frontbuffer, &caps, &backbuffer1);
6450 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6451 memset(&surface_desc, 0, sizeof(surface_desc));
6452 surface_desc.dwSize = sizeof(surface_desc);
6453 hr = IDirectDrawSurface7_GetSurfaceDesc(backbuffer1, &surface_desc);
6454 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6455 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
6456 test_data[i].name, U5(surface_desc).dwBackBufferCount);
6457 expected_caps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER);
6458 expected_caps |= DDSCAPS_BACKBUFFER;
6459 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6460 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6462 hr = IDirectDrawSurface7_GetAttachedSurface(backbuffer1, &caps, &backbuffer2);
6463 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6464 memset(&surface_desc, 0, sizeof(surface_desc));
6465 surface_desc.dwSize = sizeof(surface_desc);
6466 hr = IDirectDrawSurface7_GetSurfaceDesc(backbuffer2, &surface_desc);
6467 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6468 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
6469 test_data[i].name, U5(surface_desc).dwBackBufferCount);
6470 expected_caps &= ~DDSCAPS_BACKBUFFER;
6471 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6472 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6474 hr = IDirectDrawSurface7_GetAttachedSurface(backbuffer2, &caps, &backbuffer3);
6475 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6476 memset(&surface_desc, 0, sizeof(surface_desc));
6477 surface_desc.dwSize = sizeof(surface_desc);
6478 hr = IDirectDrawSurface7_GetSurfaceDesc(backbuffer3, &surface_desc);
6479 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6480 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
6481 test_data[i].name, U5(surface_desc).dwBackBufferCount);
6482 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6483 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6485 hr = IDirectDrawSurface7_GetAttachedSurface(backbuffer3, &caps, &surface);
6486 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6487 ok(surface == frontbuffer, "%s: Got unexpected surface %p, expected %p.\n",
6488 test_data[i].name, surface, frontbuffer);
6489 IDirectDrawSurface7_Release(surface);
6491 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
6492 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
6493 hr = IDirectDrawSurface7_IsLost(frontbuffer);
6494 ok(hr == DD_OK, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6495 hr = IDirectDrawSurface7_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6496 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
6497 ok(hr == DDERR_NOEXCLUSIVEMODE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6498 else
6499 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6500 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6501 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
6502 hr = IDirectDrawSurface7_IsLost(frontbuffer);
6503 todo_wine ok(hr == DDERR_SURFACELOST, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6504 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
6505 ok(SUCCEEDED(hr), "%s: Failed to restore surfaces, hr %#x.\n", test_data[i].name, hr);
6507 memset(&surface_desc, 0, sizeof(surface_desc));
6508 surface_desc.dwSize = sizeof(surface_desc);
6509 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6510 surface_desc.ddsCaps.dwCaps = 0;
6511 surface_desc.dwWidth = 640;
6512 surface_desc.dwHeight = 480;
6513 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6514 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
6515 hr = IDirectDrawSurface7_Flip(frontbuffer, surface, DDFLIP_WAIT);
6516 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6517 IDirectDrawSurface7_Release(surface);
6519 hr = IDirectDrawSurface7_Flip(frontbuffer, frontbuffer, DDFLIP_WAIT);
6520 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6521 hr = IDirectDrawSurface7_Flip(backbuffer1, NULL, DDFLIP_WAIT);
6522 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6523 hr = IDirectDrawSurface7_Flip(backbuffer2, NULL, DDFLIP_WAIT);
6524 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6525 hr = IDirectDrawSurface7_Flip(backbuffer3, NULL, DDFLIP_WAIT);
6526 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6528 /* The Nvidia Geforce 7 driver cannot do a color fill on a texture backbuffer after
6529 * the backbuffer has been locked. Do it ourselves as a workaround. Unlike ddraw1
6530 * and 2 GetSurfaceDesc does not cause issues in ddraw4 and ddraw7. */
6531 fill_surface(backbuffer1, 0xffff0000);
6532 fill_surface(backbuffer2, 0xff00ff00);
6533 fill_surface(backbuffer3, 0xff0000ff);
6535 hr = IDirectDrawSurface7_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6536 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6537 color = get_surface_color(backbuffer1, 320, 240);
6538 /* The testbot seems to just copy the contents of one surface to all the
6539 * others, instead of properly flipping. */
6540 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
6541 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6542 color = get_surface_color(backbuffer2, 320, 240);
6543 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6544 fill_surface(backbuffer3, 0xffff0000);
6546 hr = IDirectDrawSurface7_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6547 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6548 color = get_surface_color(backbuffer1, 320, 240);
6549 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
6550 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6551 color = get_surface_color(backbuffer2, 320, 240);
6552 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6553 fill_surface(backbuffer3, 0xff00ff00);
6555 hr = IDirectDrawSurface7_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6556 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6557 color = get_surface_color(backbuffer1, 320, 240);
6558 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
6559 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6560 color = get_surface_color(backbuffer2, 320, 240);
6561 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6562 fill_surface(backbuffer3, 0xff0000ff);
6564 hr = IDirectDrawSurface7_Flip(frontbuffer, backbuffer1, DDFLIP_WAIT);
6565 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6566 color = get_surface_color(backbuffer2, 320, 240);
6567 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
6568 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6569 color = get_surface_color(backbuffer3, 320, 240);
6570 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6571 fill_surface(backbuffer1, 0xffff0000);
6573 hr = IDirectDrawSurface7_Flip(frontbuffer, backbuffer2, DDFLIP_WAIT);
6574 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6575 color = get_surface_color(backbuffer1, 320, 240);
6576 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6577 color = get_surface_color(backbuffer3, 320, 240);
6578 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
6579 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6580 fill_surface(backbuffer2, 0xff00ff00);
6582 hr = IDirectDrawSurface7_Flip(frontbuffer, backbuffer3, DDFLIP_WAIT);
6583 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6584 color = get_surface_color(backbuffer1, 320, 240);
6585 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
6586 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6587 color = get_surface_color(backbuffer2, 320, 240);
6588 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6590 IDirectDrawSurface7_Release(backbuffer3);
6591 IDirectDrawSurface7_Release(backbuffer2);
6592 IDirectDrawSurface7_Release(backbuffer1);
6593 IDirectDrawSurface7_Release(frontbuffer);
6596 if (!(device = create_device(window, DDSCL_NORMAL)))
6598 skip("Failed to create 3D device.\n");
6599 goto done;
6601 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
6602 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6603 IDirect3DDevice7_Release(device);
6604 if (!(device_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP))
6606 skip("Cubemaps are not supported.\n");
6607 goto done;
6610 memset(&surface_desc, 0, sizeof(surface_desc));
6611 surface_desc.dwSize = sizeof(surface_desc);
6612 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6613 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_TEXTURE;
6614 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
6615 surface_desc.dwWidth = 128;
6616 surface_desc.dwHeight = 128;
6617 U5(surface_desc).dwBackBufferCount = 3;
6618 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6619 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x.\n", hr);
6621 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_FLIP;
6622 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
6623 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6624 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6626 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_COMPLEX;
6627 surface_desc.ddsCaps.dwCaps |= DDSCAPS_FLIP;
6628 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6629 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x.\n", hr);
6631 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
6632 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6633 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6635 U5(surface_desc).dwBackBufferCount = 1;
6636 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6637 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6639 U5(surface_desc).dwBackBufferCount = 0;
6640 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6641 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x.\n", hr);
6643 done:
6644 refcount = IDirectDraw7_Release(ddraw);
6645 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
6646 DestroyWindow(window);
6649 static void reset_ddsd(DDSURFACEDESC2 *ddsd)
6651 memset(ddsd, 0, sizeof(*ddsd));
6652 ddsd->dwSize = sizeof(*ddsd);
6655 static void test_set_surface_desc(void)
6657 IDirectDraw7 *ddraw;
6658 HWND window;
6659 HRESULT hr;
6660 DDSURFACEDESC2 ddsd;
6661 IDirectDrawSurface7 *surface;
6662 BYTE data[16*16*4];
6663 ULONG ref;
6664 unsigned int i;
6665 static const struct
6667 DWORD caps, caps2;
6668 BOOL supported;
6669 const char *name;
6671 invalid_caps_tests[] =
6673 {DDSCAPS_VIDEOMEMORY, 0, FALSE, "videomemory plain"},
6674 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, TRUE, "systemmemory texture"},
6675 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE, "managed texture"},
6676 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE, "managed texture"},
6677 {DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY, 0, FALSE, "systemmemory primary"},
6680 window = create_window();
6681 ddraw = create_ddraw();
6682 ok(!!ddraw, "Failed to create a ddraw object.\n");
6683 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6684 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6686 reset_ddsd(&ddsd);
6687 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
6688 ddsd.dwWidth = 8;
6689 ddsd.dwHeight = 8;
6690 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6691 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6692 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6693 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6694 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6695 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6696 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6698 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6699 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6701 reset_ddsd(&ddsd);
6702 ddsd.dwFlags = DDSD_LPSURFACE;
6703 ddsd.lpSurface = data;
6704 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6705 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6707 /* Redundantly setting the same lpSurface is not an error. */
6708 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6709 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6711 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6712 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6713 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
6714 ok(ddsd.lpSurface == NULL, "lpSurface is %p, expected NULL.\n", ddsd.lpSurface);
6716 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, 0, NULL);
6717 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6718 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
6719 ok(ddsd.lpSurface == data, "lpSurface is %p, expected %p.\n", data, data);
6720 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6721 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6723 reset_ddsd(&ddsd);
6724 ddsd.dwFlags = DDSD_LPSURFACE;
6725 ddsd.lpSurface = data;
6726 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 1);
6727 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with flags=1 returned %#x.\n", hr);
6729 ddsd.lpSurface = NULL;
6730 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6731 ok(hr == DDERR_INVALIDPARAMS, "Setting lpSurface=NULL returned %#x.\n", hr);
6733 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, NULL, 0);
6734 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with NULL desc returned %#x.\n", hr);
6736 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6737 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6738 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
6739 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
6740 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#x.\n", 0);
6742 /* Setting the caps is an error. This also means the original description cannot be reapplied. */
6743 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6744 ok(hr == DDERR_INVALIDPARAMS, "Setting the original desc returned %#x.\n", hr);
6746 ddsd.dwFlags = DDSD_CAPS;
6747 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6748 ok(hr == DDERR_INVALIDPARAMS, "Setting DDSD_CAPS returned %#x.\n", hr);
6750 /* dwCaps = 0 is allowed, but ignored. Caps2 can be anything and is ignored too. */
6751 ddsd.dwFlags = DDSD_CAPS | DDSD_LPSURFACE;
6752 ddsd.lpSurface = data;
6753 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6754 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
6755 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6756 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6757 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
6758 ddsd.ddsCaps.dwCaps = 0;
6759 ddsd.ddsCaps.dwCaps2 = 0xdeadbeef;
6760 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6761 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6763 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6764 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6765 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
6766 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
6767 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#x.\n", 0);
6769 /* Setting the height is allowed, but it cannot be set to 0, and only if LPSURFACE is set too. */
6770 reset_ddsd(&ddsd);
6771 ddsd.dwFlags = DDSD_HEIGHT;
6772 ddsd.dwHeight = 16;
6773 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6774 ok(hr == DDERR_INVALIDPARAMS, "Setting height without lpSurface returned %#x.\n", hr);
6776 ddsd.lpSurface = data;
6777 ddsd.dwFlags = DDSD_HEIGHT | DDSD_LPSURFACE;
6778 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6779 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6781 ddsd.dwHeight = 0;
6782 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6783 ok(hr == DDERR_INVALIDPARAMS, "Setting height=0 returned %#x.\n", hr);
6785 reset_ddsd(&ddsd);
6786 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6787 ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr);
6788 ok(ddsd.dwWidth == 8, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
6789 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
6791 /* Pitch and width can be set, but only together, and only with LPSURFACE. They must not be 0. */
6792 reset_ddsd(&ddsd);
6793 ddsd.dwFlags = DDSD_PITCH;
6794 U1(ddsd).lPitch = 8 * 4;
6795 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6796 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch without lpSurface or width returned %#x.\n", hr);
6798 ddsd.dwFlags = DDSD_WIDTH;
6799 ddsd.dwWidth = 16;
6800 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6801 ok(hr == DDERR_INVALIDPARAMS, "Setting width without lpSurface or pitch returned %#x.\n", hr);
6803 ddsd.dwFlags = DDSD_PITCH | DDSD_LPSURFACE;
6804 ddsd.lpSurface = data;
6805 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6806 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch and lpSurface without width returned %#x.\n", hr);
6808 ddsd.dwFlags = DDSD_WIDTH | DDSD_LPSURFACE;
6809 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6810 ok(hr == DDERR_INVALIDPARAMS, "Setting width and lpSurface without pitch returned %#x.\n", hr);
6812 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6813 U1(ddsd).lPitch = 16 * 4;
6814 ddsd.dwWidth = 16;
6815 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6816 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6818 reset_ddsd(&ddsd);
6819 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6820 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6821 ok(ddsd.dwWidth == 16, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
6822 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
6823 ok(U1(ddsd).lPitch == 16 * 4, "SetSurfaceDesc: Expected pitch 64, got %u.\n", U1(ddsd).lPitch);
6825 /* The pitch must be 32 bit aligned and > 0, but is not verified for sanity otherwise.
6827 * VMware rejects those calls, but all real drivers accept it. Mark the VMware behavior broken. */
6828 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6829 U1(ddsd).lPitch = 4 * 4;
6830 ddsd.lpSurface = data;
6831 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6832 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
6834 U1(ddsd).lPitch = 4;
6835 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6836 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
6838 U1(ddsd).lPitch = 16 * 4 + 1;
6839 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6840 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
6842 U1(ddsd).lPitch = 16 * 4 + 3;
6843 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6844 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
6846 U1(ddsd).lPitch = -4;
6847 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6848 ok(hr == DDERR_INVALIDPARAMS, "Setting negative pitch returned %#x.\n", hr);
6850 U1(ddsd).lPitch = 16 * 4;
6851 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6852 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6854 reset_ddsd(&ddsd);
6855 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6856 U1(ddsd).lPitch = 0;
6857 ddsd.dwWidth = 16;
6858 ddsd.lpSurface = data;
6859 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6860 ok(hr == DDERR_INVALIDPARAMS, "Setting zero pitch returned %#x.\n", hr);
6862 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6863 U1(ddsd).lPitch = 16 * 4;
6864 ddsd.dwWidth = 0;
6865 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6866 ok(hr == DDERR_INVALIDPARAMS, "Setting zero width returned %#x.\n", hr);
6868 /* Setting the pixelformat without LPSURFACE is an error, but with LPSURFACE it works. */
6869 ddsd.dwFlags = DDSD_PIXELFORMAT;
6870 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6871 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6872 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6873 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6874 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6875 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6876 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6877 ok(hr == DDERR_INVALIDPARAMS, "Setting the pixel format returned %#x.\n", hr);
6879 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_LPSURFACE;
6880 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6881 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6883 /* Can't set color keys. */
6884 reset_ddsd(&ddsd);
6885 ddsd.dwFlags = DDSD_CKSRCBLT;
6886 ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff0000;
6887 ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff0000;
6888 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6889 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
6891 ddsd.dwFlags = DDSD_CKSRCBLT | DDSD_LPSURFACE;
6892 ddsd.lpSurface = data;
6893 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6894 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
6896 IDirectDrawSurface7_Release(surface);
6898 /* SetSurfaceDesc needs systemmemory surfaces.
6900 * As a sidenote, fourcc surfaces aren't allowed in sysmem, thus testing
6901 * DDSD_LINEARSIZE is moot. */
6902 for (i = 0; i < ARRAY_SIZE(invalid_caps_tests); ++i)
6904 reset_ddsd(&ddsd);
6905 ddsd.dwFlags = DDSD_CAPS;
6906 ddsd.ddsCaps.dwCaps = invalid_caps_tests[i].caps;
6907 ddsd.ddsCaps.dwCaps2 = invalid_caps_tests[i].caps2;
6908 if (!(invalid_caps_tests[i].caps & DDSCAPS_PRIMARYSURFACE))
6910 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6911 ddsd.dwWidth = 8;
6912 ddsd.dwHeight = 8;
6913 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6914 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6915 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6916 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6917 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6918 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6921 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6922 if (is_ddraw64 && (invalid_caps_tests[i].caps & DDSCAPS_TEXTURE))
6923 todo_wine ok(hr == E_NOINTERFACE, "Test %u: Got unexpected hr %#x.\n", i, hr);
6924 else
6925 ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWHW, "Test %u: Got unexpected hr %#x.\n", i, hr);
6926 if (FAILED(hr))
6927 continue;
6929 reset_ddsd(&ddsd);
6930 ddsd.dwFlags = DDSD_LPSURFACE;
6931 ddsd.lpSurface = data;
6932 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6933 if (invalid_caps_tests[i].supported)
6935 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6937 else
6939 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
6940 invalid_caps_tests[i].name, hr);
6942 /* Check priority of error conditions. */
6943 ddsd.dwFlags = DDSD_WIDTH;
6944 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6945 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
6946 invalid_caps_tests[i].name, hr);
6949 IDirectDrawSurface7_Release(surface);
6952 ref = IDirectDraw7_Release(ddraw);
6953 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
6954 DestroyWindow(window);
6957 static void test_user_memory_getdc(void)
6959 IDirectDraw7 *ddraw;
6960 HWND window;
6961 HRESULT hr;
6962 DDSURFACEDESC2 ddsd;
6963 IDirectDrawSurface7 *surface;
6964 DWORD data[16][16];
6965 HGDIOBJ *bitmap;
6966 DIBSECTION dib;
6967 ULONG ref;
6968 int size;
6969 HDC dc;
6970 unsigned int x, y;
6972 window = create_window();
6973 ddraw = create_ddraw();
6974 ok(!!ddraw, "Failed to create a ddraw object.\n");
6975 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6976 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6978 reset_ddsd(&ddsd);
6979 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
6980 ddsd.dwWidth = 16;
6981 ddsd.dwHeight = 16;
6982 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6983 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6984 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6985 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6986 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6987 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6988 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6989 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6990 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6992 memset(data, 0xaa, sizeof(data));
6993 reset_ddsd(&ddsd);
6994 ddsd.dwFlags = DDSD_LPSURFACE;
6995 ddsd.lpSurface = data;
6996 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6997 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6999 hr = IDirectDrawSurface7_GetDC(surface, &dc);
7000 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7001 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
7002 ok(!!bitmap, "Failed to get bitmap.\n");
7003 size = GetObjectA(bitmap, sizeof(dib), &dib);
7004 ok(size == sizeof(dib), "Got unexpected size %d.\n", size);
7005 ok(dib.dsBm.bmBits == data, "Got unexpected bits %p, expected %p.\n", dib.dsBm.bmBits, data);
7006 BitBlt(dc, 0, 0, 16, 8, NULL, 0, 0, WHITENESS);
7007 BitBlt(dc, 0, 8, 16, 8, NULL, 0, 0, BLACKNESS);
7008 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
7009 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7011 ok(data[0][0] == 0xffffffff, "Expected color 0xffffffff, got %#x.\n", data[0][0]);
7012 ok(data[15][15] == 0x00000000, "Expected color 0x00000000, got %#x.\n", data[15][15]);
7014 ddsd.dwFlags = DDSD_LPSURFACE | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH;
7015 ddsd.lpSurface = data;
7016 ddsd.dwWidth = 4;
7017 ddsd.dwHeight = 8;
7018 U1(ddsd).lPitch = sizeof(*data);
7019 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7020 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7022 memset(data, 0xaa, sizeof(data));
7023 hr = IDirectDrawSurface7_GetDC(surface, &dc);
7024 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7025 BitBlt(dc, 0, 0, 4, 8, NULL, 0, 0, BLACKNESS);
7026 BitBlt(dc, 1, 1, 2, 2, NULL, 0, 0, WHITENESS);
7027 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
7028 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7030 for (y = 0; y < 4; y++)
7032 for (x = 0; x < 4; x++)
7034 if ((x == 1 || x == 2) && (y == 1 || y == 2))
7035 ok(data[y][x] == 0xffffffff, "Expected color 0xffffffff on position %ux%u, got %#x.\n",
7036 x, y, data[y][x]);
7037 else
7038 ok(data[y][x] == 0x00000000, "Expected color 0x00000000 on position %ux%u, got %#x.\n",
7039 x, y, data[y][x]);
7042 ok(data[0][5] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 5x0, got %#x.\n",
7043 data[0][5]);
7044 ok(data[7][3] == 0x00000000, "Expected color 0x00000000 on position 3x7, got %#x.\n",
7045 data[7][3]);
7046 ok(data[7][4] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 4x7, got %#x.\n",
7047 data[7][4]);
7048 ok(data[8][0] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 0x8, got %#x.\n",
7049 data[8][0]);
7051 IDirectDrawSurface7_Release(surface);
7052 ref = IDirectDraw7_Release(ddraw);
7053 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
7054 DestroyWindow(window);
7057 static void test_sysmem_overlay(void)
7059 IDirectDraw7 *ddraw;
7060 HWND window;
7061 HRESULT hr;
7062 DDSURFACEDESC2 ddsd;
7063 IDirectDrawSurface7 *surface;
7064 ULONG ref;
7066 window = create_window();
7067 ddraw = create_ddraw();
7068 ok(!!ddraw, "Failed to create a ddraw object.\n");
7069 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7070 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7072 reset_ddsd(&ddsd);
7073 ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
7074 ddsd.dwWidth = 16;
7075 ddsd.dwHeight = 16;
7076 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OVERLAY;
7077 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
7078 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
7079 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
7080 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7081 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7082 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7083 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
7084 ok(hr == DDERR_NOOVERLAYHW, "Got unexpected hr %#x.\n", hr);
7086 ref = IDirectDraw7_Release(ddraw);
7087 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
7088 DestroyWindow(window);
7091 static void test_primary_palette(void)
7093 DDSCAPS2 surface_caps = {DDSCAPS_FLIP, 0, 0, {0}};
7094 IDirectDrawSurface7 *primary, *backbuffer;
7095 PALETTEENTRY palette_entries[256];
7096 IDirectDrawPalette *palette, *tmp;
7097 DDSURFACEDESC2 surface_desc;
7098 IDirectDraw7 *ddraw;
7099 DWORD palette_caps;
7100 ULONG refcount;
7101 HWND window;
7102 HRESULT hr;
7104 window = create_window();
7105 ddraw = create_ddraw();
7106 ok(!!ddraw, "Failed to create a ddraw object.\n");
7107 if (FAILED(IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
7109 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
7110 IDirectDraw7_Release(ddraw);
7111 DestroyWindow(window);
7112 return;
7114 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7115 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7117 memset(&surface_desc, 0, sizeof(surface_desc));
7118 surface_desc.dwSize = sizeof(surface_desc);
7119 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
7120 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
7121 U5(surface_desc).dwBackBufferCount = 1;
7122 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
7123 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7124 hr = IDirectDrawSurface7_GetAttachedSurface(primary, &surface_caps, &backbuffer);
7125 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
7127 memset(palette_entries, 0, sizeof(palette_entries));
7128 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_entries, &palette, NULL);
7129 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7130 refcount = get_refcount((IUnknown *)palette);
7131 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7133 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
7134 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
7135 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
7137 hr = IDirectDrawSurface7_SetPalette(primary, palette);
7138 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7140 /* The Windows 8 testbot attaches the palette to the backbuffer as well,
7141 * and is generally somewhat broken with respect to 8 bpp / palette
7142 * handling. */
7143 if (SUCCEEDED(IDirectDrawSurface7_GetPalette(backbuffer, &tmp)))
7145 win_skip("Broken palette handling detected, skipping tests.\n");
7146 IDirectDrawPalette_Release(tmp);
7147 IDirectDrawPalette_Release(palette);
7148 /* The Windows 8 testbot keeps extra references to the primary and
7149 * backbuffer while in 8 bpp mode. */
7150 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
7151 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
7152 goto done;
7155 refcount = get_refcount((IUnknown *)palette);
7156 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
7158 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
7159 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
7160 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE | DDPCAPS_ALLOW256),
7161 "Got unexpected palette caps %#x.\n", palette_caps);
7163 hr = IDirectDrawSurface7_SetPalette(primary, NULL);
7164 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7165 refcount = get_refcount((IUnknown *)palette);
7166 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7168 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
7169 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
7170 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
7172 hr = IDirectDrawSurface7_SetPalette(primary, palette);
7173 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7174 refcount = get_refcount((IUnknown *)palette);
7175 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
7177 hr = IDirectDrawSurface7_GetPalette(primary, &tmp);
7178 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
7179 ok(tmp == palette, "Got unexpected palette %p, expected %p.\n", tmp, palette);
7180 IDirectDrawPalette_Release(tmp);
7181 hr = IDirectDrawSurface7_GetPalette(backbuffer, &tmp);
7182 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
7184 refcount = IDirectDrawPalette_Release(palette);
7185 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7186 refcount = IDirectDrawPalette_Release(palette);
7187 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7189 /* Note that this only seems to work when the palette is attached to the
7190 * primary surface. When attached to a regular surface, attempting to get
7191 * the palette here will cause an access violation. */
7192 hr = IDirectDrawSurface7_GetPalette(primary, &tmp);
7193 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
7195 hr = IDirectDrawSurface7_IsLost(primary);
7196 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7198 memset(&surface_desc, 0, sizeof(surface_desc));
7199 surface_desc.dwSize = sizeof(surface_desc);
7200 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &surface_desc);
7201 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7202 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
7203 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
7204 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 8, "Got unexpected bit count %u.\n",
7205 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
7207 hr = set_display_mode(ddraw, 640, 480);
7208 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
7210 memset(&surface_desc, 0, sizeof(surface_desc));
7211 surface_desc.dwSize = sizeof(surface_desc);
7212 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &surface_desc);
7213 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7214 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
7215 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
7216 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 32
7217 || U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 24,
7218 "Got unexpected bit count %u.\n", U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
7220 hr = IDirectDrawSurface7_IsLost(primary);
7221 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7222 hr = IDirectDrawSurface7_Restore(primary);
7223 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
7224 hr = IDirectDrawSurface7_IsLost(primary);
7225 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7227 memset(&surface_desc, 0, sizeof(surface_desc));
7228 surface_desc.dwSize = sizeof(surface_desc);
7229 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &surface_desc);
7230 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7231 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
7232 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
7233 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 32
7234 || U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 24,
7235 "Got unexpected bit count %u.\n", U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
7237 done:
7238 refcount = IDirectDrawSurface7_Release(backbuffer);
7239 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7240 refcount = IDirectDrawSurface7_Release(primary);
7241 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7242 refcount = IDirectDraw7_Release(ddraw);
7243 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7244 DestroyWindow(window);
7247 static HRESULT WINAPI surface_counter(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
7249 UINT *surface_count = context;
7251 ++(*surface_count);
7252 IDirectDrawSurface_Release(surface);
7254 return DDENUMRET_OK;
7257 static void test_surface_attachment(void)
7259 IDirectDrawSurface7 *surface1, *surface2, *surface3, *surface4;
7260 IDirectDrawSurface *surface1v1, *surface2v1;
7261 DDSCAPS2 caps = {DDSCAPS_TEXTURE, 0, 0, {0}};
7262 DDSURFACEDESC2 surface_desc;
7263 IDirectDraw7 *ddraw;
7264 UINT surface_count;
7265 ULONG refcount;
7266 HWND window;
7267 HRESULT hr;
7269 window = create_window();
7270 ddraw = create_ddraw();
7271 ok(!!ddraw, "Failed to create a ddraw object.\n");
7272 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7273 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7275 memset(&surface_desc, 0, sizeof(surface_desc));
7276 surface_desc.dwSize = sizeof(surface_desc);
7277 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
7278 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7279 U2(surface_desc).dwMipMapCount = 3;
7280 surface_desc.dwWidth = 128;
7281 surface_desc.dwHeight = 128;
7282 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL)))
7284 skip("Failed to create a texture, skipping tests.\n");
7285 IDirectDraw7_Release(ddraw);
7286 DestroyWindow(window);
7287 return;
7290 hr = IDirectDrawSurface7_GetAttachedSurface(surface1, &caps, &surface2);
7291 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
7292 hr = IDirectDrawSurface7_GetAttachedSurface(surface2, &caps, &surface3);
7293 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
7294 hr = IDirectDrawSurface7_GetAttachedSurface(surface3, &caps, &surface4);
7295 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7297 surface_count = 0;
7298 IDirectDrawSurface7_EnumAttachedSurfaces(surface1, &surface_count, surface_counter);
7299 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
7300 surface_count = 0;
7301 IDirectDrawSurface7_EnumAttachedSurfaces(surface2, &surface_count, surface_counter);
7302 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
7303 surface_count = 0;
7304 IDirectDrawSurface7_EnumAttachedSurfaces(surface3, &surface_count, surface_counter);
7305 ok(!surface_count, "Got unexpected surface_count %u.\n", surface_count);
7307 memset(&surface_desc, 0, sizeof(surface_desc));
7308 surface_desc.dwSize = sizeof(surface_desc);
7309 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7310 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
7311 surface_desc.dwWidth = 16;
7312 surface_desc.dwHeight = 16;
7313 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
7314 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7316 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
7317 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7318 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
7319 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7320 hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface4);
7321 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7322 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface3);
7323 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7324 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface4);
7325 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7326 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface2);
7327 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7329 IDirectDrawSurface7_Release(surface4);
7331 memset(&surface_desc, 0, sizeof(surface_desc));
7332 surface_desc.dwSize = sizeof(surface_desc);
7333 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7334 surface_desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
7335 surface_desc.dwWidth = 16;
7336 surface_desc.dwHeight = 16;
7337 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
7338 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7340 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
7341 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7342 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
7343 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7344 hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface4);
7345 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7346 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface3);
7347 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7348 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface4);
7349 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7350 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface2);
7351 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7353 IDirectDrawSurface7_Release(surface4);
7354 IDirectDrawSurface7_Release(surface3);
7355 IDirectDrawSurface7_Release(surface2);
7356 IDirectDrawSurface7_Release(surface1);
7358 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7359 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7361 /* Try a single primary and two offscreen plain surfaces. */
7362 memset(&surface_desc, 0, sizeof(surface_desc));
7363 surface_desc.dwSize = sizeof(surface_desc);
7364 surface_desc.dwFlags = DDSD_CAPS;
7365 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7366 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7367 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7369 memset(&surface_desc, 0, sizeof(surface_desc));
7370 surface_desc.dwSize = sizeof(surface_desc);
7371 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7372 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7373 surface_desc.dwWidth = registry_mode.dmPelsWidth;
7374 surface_desc.dwHeight = registry_mode.dmPelsHeight;
7375 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
7376 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7378 memset(&surface_desc, 0, sizeof(surface_desc));
7379 surface_desc.dwSize = sizeof(surface_desc);
7380 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7381 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7382 surface_desc.dwWidth = registry_mode.dmPelsWidth;
7383 surface_desc.dwHeight = registry_mode.dmPelsHeight;
7384 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
7385 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7387 /* This one has a different size. */
7388 memset(&surface_desc, 0, sizeof(surface_desc));
7389 surface_desc.dwSize = sizeof(surface_desc);
7390 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7391 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7392 surface_desc.dwWidth = 128;
7393 surface_desc.dwHeight = 128;
7394 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
7395 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7397 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
7398 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7399 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface1);
7400 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7401 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface3);
7402 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7403 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
7404 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7405 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
7406 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7408 IDirectDrawSurface7_Release(surface4);
7409 IDirectDrawSurface7_Release(surface3);
7410 IDirectDrawSurface7_Release(surface2);
7411 IDirectDrawSurface7_Release(surface1);
7413 /* Test depth surfaces of different sizes. */
7414 memset(&surface_desc, 0, sizeof(surface_desc));
7415 surface_desc.dwSize = sizeof(surface_desc);
7416 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7417 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
7418 surface_desc.dwWidth = 64;
7419 surface_desc.dwHeight = 64;
7420 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7421 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
7423 memset(&surface_desc, 0, sizeof(surface_desc));
7424 surface_desc.dwSize = sizeof(surface_desc);
7425 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
7426 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
7427 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7428 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
7429 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = 16;
7430 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = 0x0000ffff;
7431 surface_desc.dwWidth = 32;
7432 surface_desc.dwHeight = 32;
7433 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
7434 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
7435 surface_desc.dwWidth = 64;
7436 surface_desc.dwHeight = 64;
7437 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
7438 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
7439 surface_desc.dwWidth = 128;
7440 surface_desc.dwHeight = 128;
7441 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
7442 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
7444 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
7445 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7446 if (SUCCEEDED(hr))
7447 IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface3);
7448 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface3);
7449 ok(hr == D3D_OK, "Failed to attach depth buffer, hr %#x.\n", hr);
7450 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface3);
7451 ok(hr == D3D_OK, "Failed to detach depth buffer, hr %#x.\n", hr);
7452 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
7453 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7455 IDirectDrawSurface7_Release(surface4);
7456 IDirectDrawSurface7_Release(surface3);
7457 IDirectDrawSurface7_Release(surface2);
7458 IDirectDrawSurface7_Release(surface1);
7460 /* Test DeleteAttachedSurface() and automatic detachment of attached surfaces on release. */
7461 memset(&surface_desc, 0, sizeof(surface_desc));
7462 surface_desc.dwSize = sizeof(surface_desc);
7463 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7464 surface_desc.dwWidth = 64;
7465 surface_desc.dwHeight = 64;
7466 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
7467 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7468 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
7469 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
7470 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
7471 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
7472 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
7473 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7474 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7475 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
7476 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7478 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
7479 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
7480 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = 16;
7481 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = 0x0000ffff;
7482 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
7483 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7485 hr = IDirectDrawSurface7_QueryInterface(surface1, &IID_IDirectDrawSurface, (void **)&surface1v1);
7486 ok(SUCCEEDED(hr), "Failed to get interface, hr %#x.\n", hr);
7487 hr = IDirectDrawSurface7_QueryInterface(surface2, &IID_IDirectDrawSurface, (void **)&surface2v1);
7488 ok(SUCCEEDED(hr), "Failed to get interface, hr %#x.\n", hr);
7490 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
7491 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7492 refcount = get_refcount((IUnknown *)surface2);
7493 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
7494 refcount = get_refcount((IUnknown *)surface2v1);
7495 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7496 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
7497 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
7498 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
7499 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7500 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
7501 ok(hr == DDERR_SURFACENOTATTACHED, "Got unexpected hr %#x.\n", hr);
7503 /* Attaching while already attached to other surface. */
7504 hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface2);
7505 todo_wine ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7506 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface3, 0, surface2);
7507 todo_wine ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7508 IDirectDrawSurface7_Release(surface3);
7510 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface2);
7511 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7512 refcount = get_refcount((IUnknown *)surface2);
7513 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7514 refcount = get_refcount((IUnknown *)surface2v1);
7515 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7517 /* DeleteAttachedSurface() when attaching via IDirectDrawSurface. */
7518 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
7519 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7520 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface2);
7521 ok(hr == DDERR_SURFACENOTATTACHED, "Got unexpected hr %#x.\n", hr);
7522 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
7523 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7524 refcount = IDirectDrawSurface7_Release(surface2);
7525 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7526 refcount = IDirectDrawSurface7_Release(surface1);
7527 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7529 /* Automatic detachment on release. */
7530 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
7531 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7532 refcount = get_refcount((IUnknown *)surface2v1);
7533 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
7534 refcount = IDirectDrawSurface_Release(surface1v1);
7535 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7536 refcount = IDirectDrawSurface_Release(surface2v1);
7537 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7538 refcount = IDirectDraw7_Release(ddraw);
7539 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7540 DestroyWindow(window);
7543 static void test_private_data(void)
7545 IDirectDraw7 *ddraw;
7546 IDirectDrawSurface7 *surface, *surface2;
7547 DDSURFACEDESC2 surface_desc;
7548 ULONG refcount, refcount2, refcount3;
7549 IUnknown *ptr;
7550 DWORD size = sizeof(ptr);
7551 HRESULT hr;
7552 HWND window;
7553 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
7554 DWORD data[] = {1, 2, 3, 4};
7555 DDCAPS hal_caps;
7556 static const GUID ddraw_private_data_test_guid =
7558 0xfdb37466,
7559 0x428f,
7560 0x4edf,
7561 {0xa3,0x7f,0x9b,0x1d,0xf4,0x88,0xc5,0xfc}
7563 static const GUID ddraw_private_data_test_guid2 =
7565 0x2e5afac2,
7566 0x87b5,
7567 0x4c10,
7568 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
7571 window = create_window();
7572 ddraw = create_ddraw();
7573 ok(!!ddraw, "Failed to create a ddraw object.\n");
7574 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7575 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7577 reset_ddsd(&surface_desc);
7578 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
7579 surface_desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
7580 surface_desc.dwHeight = 4;
7581 surface_desc.dwWidth = 4;
7582 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7583 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7585 /* NULL pointers are not valid, but don't cause a crash. */
7586 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL,
7587 sizeof(IUnknown *), DDSPD_IUNKNOWNPOINTER);
7588 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7589 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL, 0, 0);
7590 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7591 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL, 1, 0);
7592 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7594 /* DDSPD_IUNKNOWNPOINTER needs sizeof(IUnknown *) bytes of data. */
7595 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7596 0, DDSPD_IUNKNOWNPOINTER);
7597 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7598 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7599 5, DDSPD_IUNKNOWNPOINTER);
7600 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7601 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7602 sizeof(ddraw) * 2, DDSPD_IUNKNOWNPOINTER);
7603 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7605 /* Note that with a size != 0 and size != sizeof(IUnknown *) and
7606 * DDSPD_IUNKNOWNPOINTER set SetPrivateData in ddraw4 and ddraw7
7607 * erases the old content and returns an error. This behavior has
7608 * been fixed in d3d8 and d3d9. Unless an application is found
7609 * that depends on this we don't care about this behavior. */
7610 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7611 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7612 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7613 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7614 0, DDSPD_IUNKNOWNPOINTER);
7615 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7616 size = sizeof(ptr);
7617 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
7618 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7619 hr = IDirectDrawSurface7_FreePrivateData(surface, &ddraw_private_data_test_guid);
7620 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7622 refcount = get_refcount((IUnknown *)ddraw);
7623 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7624 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7625 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7626 refcount2 = get_refcount((IUnknown *)ddraw);
7627 ok(refcount2 == refcount + 1, "Got unexpected refcount %u.\n", refcount2);
7629 hr = IDirectDrawSurface7_FreePrivateData(surface, &ddraw_private_data_test_guid);
7630 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7631 refcount2 = get_refcount((IUnknown *)ddraw);
7632 ok(refcount2 == refcount, "Got unexpected refcount %u.\n", refcount2);
7634 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7635 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7636 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7637 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, surface,
7638 sizeof(surface), DDSPD_IUNKNOWNPOINTER);
7639 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7640 refcount2 = get_refcount((IUnknown *)ddraw);
7641 ok(refcount2 == refcount, "Got unexpected refcount %u.\n", refcount2);
7643 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7644 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7645 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7646 size = 2 * sizeof(ptr);
7647 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
7648 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7649 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
7650 refcount2 = get_refcount(ptr);
7651 /* Object is NOT addref'ed by the getter. */
7652 ok(ptr == (IUnknown *)ddraw, "Returned interface pointer is %p, expected %p.\n", ptr, ddraw);
7653 ok(refcount2 == refcount + 1, "Got unexpected refcount %u.\n", refcount2);
7655 ptr = (IUnknown *)0xdeadbeef;
7656 size = 1;
7657 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, &size);
7658 ok(hr == DDERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
7659 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
7660 size = 2 * sizeof(ptr);
7661 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, &size);
7662 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7663 ok(size == 2 * sizeof(ptr), "Got unexpected size %u.\n", size);
7664 size = 1;
7665 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
7666 ok(hr == DDERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
7667 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
7668 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7669 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid2, NULL, NULL);
7670 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7671 size = 0xdeadbabe;
7672 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid2, &ptr, &size);
7673 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7674 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7675 ok(size == 0xdeadbabe, "Got unexpected size %u.\n", size);
7676 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, NULL);
7677 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7679 refcount3 = IDirectDrawSurface7_Release(surface);
7680 ok(!refcount3, "Got unexpected refcount %u.\n", refcount3);
7682 /* Destroying the surface frees the reference held on the private data. It also frees
7683 * the reference the surface is holding on its creating object. */
7684 refcount2 = get_refcount((IUnknown *)ddraw);
7685 ok(refcount2 == refcount - 1, "Got unexpected refcount %u.\n", refcount2);
7687 memset(&hal_caps, 0, sizeof(hal_caps));
7688 hal_caps.dwSize = sizeof(hal_caps);
7689 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
7690 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7691 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) == (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)
7692 && !is_ddraw64)
7694 reset_ddsd(&surface_desc);
7695 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_MIPMAPCOUNT;
7696 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7697 surface_desc.dwHeight = 4;
7698 surface_desc.dwWidth = 4;
7699 U2(surface_desc).dwMipMapCount = 2;
7700 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7701 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7702 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &surface2);
7703 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
7705 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, data, sizeof(data), 0);
7706 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7707 hr = IDirectDrawSurface7_GetPrivateData(surface2, &ddraw_private_data_test_guid, NULL, NULL);
7708 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7710 IDirectDrawSurface7_Release(surface2);
7711 IDirectDrawSurface7_Release(surface);
7713 else
7714 skip("Mipmapped textures not supported, skipping mipmap private data test.\n");
7716 refcount = IDirectDraw7_Release(ddraw);
7717 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7718 DestroyWindow(window);
7721 static void test_pixel_format(void)
7723 HWND window, window2 = NULL;
7724 HDC hdc, hdc2 = NULL;
7725 HMODULE gl = NULL;
7726 int format, test_format;
7727 PIXELFORMATDESCRIPTOR pfd;
7728 IDirectDraw7 *ddraw = NULL;
7729 IDirectDrawClipper *clipper = NULL;
7730 DDSURFACEDESC2 ddsd;
7731 IDirectDrawSurface7 *primary = NULL;
7732 DDBLTFX fx;
7733 HRESULT hr;
7735 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
7736 100, 100, 160, 160, NULL, NULL, NULL, NULL);
7737 if (!window)
7739 skip("Failed to create window\n");
7740 return;
7743 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
7744 100, 100, 160, 160, NULL, NULL, NULL, NULL);
7746 hdc = GetDC(window);
7747 if (!hdc)
7749 skip("Failed to get DC\n");
7750 goto cleanup;
7753 if (window2)
7754 hdc2 = GetDC(window2);
7756 gl = LoadLibraryA("opengl32.dll");
7757 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
7759 format = GetPixelFormat(hdc);
7760 ok(format == 0, "new window has pixel format %d\n", format);
7762 ZeroMemory(&pfd, sizeof(pfd));
7763 pfd.nSize = sizeof(pfd);
7764 pfd.nVersion = 1;
7765 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
7766 pfd.iPixelType = PFD_TYPE_RGBA;
7767 pfd.iLayerType = PFD_MAIN_PLANE;
7768 format = ChoosePixelFormat(hdc, &pfd);
7769 if (format <= 0)
7771 skip("no pixel format available\n");
7772 goto cleanup;
7775 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
7777 skip("failed to set pixel format\n");
7778 goto cleanup;
7781 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
7783 skip("failed to set pixel format on second window\n");
7784 if (hdc2)
7786 ReleaseDC(window2, hdc2);
7787 hdc2 = NULL;
7791 ddraw = create_ddraw();
7792 ok(!!ddraw, "Failed to create a ddraw object.\n");
7794 test_format = GetPixelFormat(hdc);
7795 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7797 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7798 if (FAILED(hr))
7800 skip("Failed to set cooperative level, hr %#x.\n", hr);
7801 goto cleanup;
7804 test_format = GetPixelFormat(hdc);
7805 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7807 if (hdc2)
7809 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
7810 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
7811 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window2);
7812 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
7814 test_format = GetPixelFormat(hdc);
7815 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7817 test_format = GetPixelFormat(hdc2);
7818 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7821 memset(&ddsd, 0, sizeof(ddsd));
7822 ddsd.dwSize = sizeof(ddsd);
7823 ddsd.dwFlags = DDSD_CAPS;
7824 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7826 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
7827 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
7829 test_format = GetPixelFormat(hdc);
7830 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7832 if (hdc2)
7834 test_format = GetPixelFormat(hdc2);
7835 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7838 if (clipper)
7840 hr = IDirectDrawSurface7_SetClipper(primary, clipper);
7841 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
7843 test_format = GetPixelFormat(hdc);
7844 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7846 test_format = GetPixelFormat(hdc2);
7847 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7850 memset(&fx, 0, sizeof(fx));
7851 fx.dwSize = sizeof(fx);
7852 hr = IDirectDrawSurface7_Blt(primary, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
7853 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
7855 test_format = GetPixelFormat(hdc);
7856 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7858 if (hdc2)
7860 test_format = GetPixelFormat(hdc2);
7861 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7864 cleanup:
7865 if (primary) IDirectDrawSurface7_Release(primary);
7866 if (clipper) IDirectDrawClipper_Release(clipper);
7867 if (ddraw) IDirectDraw7_Release(ddraw);
7868 if (gl) FreeLibrary(gl);
7869 if (hdc) ReleaseDC(window, hdc);
7870 if (hdc2) ReleaseDC(window2, hdc2);
7871 DestroyWindow(window);
7872 if (window2) DestroyWindow(window2);
7875 static void test_create_surface_pitch(void)
7877 IDirectDrawSurface7 *surface;
7878 DDSURFACEDESC2 surface_desc;
7879 IDirectDraw7 *ddraw;
7880 unsigned int i;
7881 ULONG refcount;
7882 HWND window;
7883 HRESULT hr;
7884 void *mem;
7886 static const struct
7888 DWORD caps;
7889 DWORD flags_in;
7890 DWORD pitch_in;
7891 HRESULT hr;
7892 DWORD flags_out;
7893 DWORD pitch_out32;
7894 DWORD pitch_out64;
7896 test_data[] =
7898 /* 0 */
7899 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7900 0, 0, DD_OK,
7901 DDSD_PITCH, 0x100, 0x100},
7902 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7903 DDSD_PITCH, 0x104, DD_OK,
7904 DDSD_PITCH, 0x100, 0x100},
7905 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7906 DDSD_PITCH, 0x0f8, DD_OK,
7907 DDSD_PITCH, 0x100, 0x100},
7908 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
7909 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
7910 0, 0, 0 },
7911 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7912 0, 0, DD_OK,
7913 DDSD_PITCH, 0x100, 0x0fc},
7914 /* 5 */
7915 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7916 DDSD_PITCH, 0x104, DD_OK,
7917 DDSD_PITCH, 0x100, 0x0fc},
7918 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7919 DDSD_PITCH, 0x0f8, DD_OK,
7920 DDSD_PITCH, 0x100, 0x0fc},
7921 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7922 DDSD_PITCH | DDSD_LINEARSIZE, 0, DD_OK,
7923 DDSD_PITCH, 0x100, 0x0fc},
7924 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7925 DDSD_LPSURFACE, 0, DDERR_INVALIDPARAMS,
7926 0, 0, 0 },
7927 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7928 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DD_OK,
7929 DDSD_PITCH, 0x100, 0x100},
7930 /* 10 */
7931 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7932 DDSD_LPSURFACE | DDSD_PITCH, 0x0fe, DDERR_INVALIDPARAMS,
7933 0, 0, 0 },
7934 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7935 DDSD_LPSURFACE | DDSD_PITCH, 0x0fc, DD_OK,
7936 DDSD_PITCH, 0x0fc, 0x0fc},
7937 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7938 DDSD_LPSURFACE | DDSD_PITCH, 0x0f8, DDERR_INVALIDPARAMS,
7939 0, 0, 0 },
7940 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7941 DDSD_LPSURFACE | DDSD_LINEARSIZE, 0x100, DDERR_INVALIDPARAMS,
7942 0, 0, 0 },
7943 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7944 DDSD_LPSURFACE | DDSD_LINEARSIZE, 0x3f00, DDERR_INVALIDPARAMS,
7945 0, 0, 0 },
7946 /* 15 */
7947 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
7948 DDSD_LPSURFACE | DDSD_PITCH | DDSD_LINEARSIZE, 0x100, DD_OK,
7949 DDSD_PITCH, 0x100, 0x100},
7950 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
7951 0, 0, DDERR_INVALIDCAPS,
7952 0, 0, 0 },
7953 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7954 0, 0, DD_OK,
7955 DDSD_PITCH, 0x100, 0 },
7956 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7957 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
7958 0, 0, 0 },
7959 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
7960 0, 0, DDERR_INVALIDCAPS,
7961 0, 0, 0 },
7962 /* 20 */
7963 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7964 0, 0, DD_OK,
7965 DDSD_PITCH, 0x100, 0 },
7966 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
7967 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DD_OK,
7968 DDSD_PITCH, 0x100, 0 },
7970 DWORD flags_mask = DDSD_PITCH | DDSD_LPSURFACE | DDSD_LINEARSIZE;
7972 window = create_window();
7973 ddraw = create_ddraw();
7974 ok(!!ddraw, "Failed to create a ddraw object.\n");
7975 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7976 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7978 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((63 * 4) + 8) * 63);
7980 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
7982 memset(&surface_desc, 0, sizeof(surface_desc));
7983 surface_desc.dwSize = sizeof(surface_desc);
7984 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | test_data[i].flags_in;
7985 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
7986 surface_desc.dwWidth = 63;
7987 surface_desc.dwHeight = 63;
7988 U1(surface_desc).lPitch = test_data[i].pitch_in;
7989 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7990 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
7991 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
7992 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7993 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7994 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7995 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7996 if (test_data[i].flags_in & DDSD_LPSURFACE)
7998 HRESULT expected_hr = SUCCEEDED(test_data[i].hr) ? DDERR_INVALIDPARAMS : test_data[i].hr;
7999 ok(hr == expected_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, expected_hr);
8000 surface_desc.lpSurface = mem;
8001 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8003 if ((test_data[i].caps & DDSCAPS_VIDEOMEMORY) && hr == DDERR_NODIRECTDRAWHW)
8004 continue;
8005 if (is_ddraw64 && (test_data[i].caps & DDSCAPS_TEXTURE) && SUCCEEDED(test_data[i].hr))
8006 todo_wine ok(hr == E_NOINTERFACE, "Test %u: Got unexpected hr %#x.\n", i, hr);
8007 else
8008 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
8009 if (FAILED(hr))
8010 continue;
8012 memset(&surface_desc, 0, sizeof(surface_desc));
8013 surface_desc.dwSize = sizeof(surface_desc);
8014 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
8015 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
8016 ok((surface_desc.dwFlags & flags_mask) == test_data[i].flags_out,
8017 "Test %u: Got unexpected flags %#x, expected %#x.\n",
8018 i, surface_desc.dwFlags & flags_mask, test_data[i].flags_out);
8019 /* The pitch for textures seems to be implementation specific. */
8020 if (!(test_data[i].caps & DDSCAPS_TEXTURE))
8022 if (is_ddraw64 && test_data[i].pitch_out32 != test_data[i].pitch_out64)
8023 todo_wine ok(U1(surface_desc).lPitch == test_data[i].pitch_out64,
8024 "Test %u: Got unexpected pitch %u, expected %u.\n",
8025 i, U1(surface_desc).lPitch, test_data[i].pitch_out64);
8026 else
8027 ok(U1(surface_desc).lPitch == test_data[i].pitch_out32,
8028 "Test %u: Got unexpected pitch %u, expected %u.\n",
8029 i, U1(surface_desc).lPitch, test_data[i].pitch_out32);
8031 ok(!surface_desc.lpSurface, "Test %u: Got unexpected lpSurface %p.\n", i, surface_desc.lpSurface);
8033 IDirectDrawSurface7_Release(surface);
8036 HeapFree(GetProcessHeap(), 0, mem);
8037 refcount = IDirectDraw7_Release(ddraw);
8038 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8039 DestroyWindow(window);
8042 static void test_mipmap(void)
8044 IDirectDrawSurface7 *surface, *surface_base, *surface_mip;
8045 unsigned int i, mipmap_count;
8046 DDSURFACEDESC2 surface_desc;
8047 IDirectDraw7 *ddraw;
8048 ULONG refcount;
8049 HWND window;
8050 HRESULT hr;
8051 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
8052 DDCAPS hal_caps;
8054 static const struct
8056 DWORD flags;
8057 DWORD caps;
8058 DWORD width;
8059 DWORD height;
8060 DWORD mipmap_count_in;
8061 HRESULT hr;
8062 DWORD mipmap_count_out;
8064 tests[] =
8066 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 3, DD_OK, 3},
8067 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDPARAMS, 0},
8068 {0, DDSCAPS_TEXTURE | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 1},
8069 {0, DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDCAPS, 0},
8070 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 8},
8071 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 32, 64, 0, DD_OK, 7},
8074 window = create_window();
8075 ddraw = create_ddraw();
8076 ok(!!ddraw, "Failed to create a ddraw object.\n");
8077 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8078 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8080 memset(&hal_caps, 0, sizeof(hal_caps));
8081 hal_caps.dwSize = sizeof(hal_caps);
8082 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
8083 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8084 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)
8085 || is_ddraw64)
8087 skip("Mipmapped textures not supported, skipping tests.\n");
8088 IDirectDraw7_Release(ddraw);
8089 DestroyWindow(window);
8090 return;
8093 for (i = 0; i < ARRAY_SIZE(tests); ++i)
8095 memset(&surface_desc, 0, sizeof(surface_desc));
8096 surface_desc.dwSize = sizeof(surface_desc);
8097 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | tests[i].flags;
8098 surface_desc.ddsCaps.dwCaps = tests[i].caps;
8099 surface_desc.dwWidth = tests[i].width;
8100 surface_desc.dwHeight = tests[i].height;
8101 if (tests[i].flags & DDSD_MIPMAPCOUNT)
8102 U2(surface_desc).dwMipMapCount = tests[i].mipmap_count_in;
8103 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8104 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x.\n", i, hr);
8105 if (FAILED(hr))
8106 continue;
8108 memset(&surface_desc, 0, sizeof(surface_desc));
8109 surface_desc.dwSize = sizeof(surface_desc);
8110 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
8111 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
8112 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
8113 "Test %u: Got unexpected flags %#x.\n", i, surface_desc.dwFlags);
8114 ok(U2(surface_desc).dwMipMapCount == tests[i].mipmap_count_out,
8115 "Test %u: Got unexpected mipmap count %u.\n", i, U2(surface_desc).dwMipMapCount);
8117 surface_base = surface;
8118 IDirectDrawSurface7_AddRef(surface_base);
8119 mipmap_count = U2(surface_desc).dwMipMapCount;
8120 while (mipmap_count > 1)
8122 hr = IDirectDrawSurface7_GetAttachedSurface(surface_base, &caps, &surface_mip);
8123 ok(SUCCEEDED(hr), "Test %u, %u: Failed to get attached surface, hr %#x.\n", i, mipmap_count, hr);
8125 memset(&surface_desc, 0, sizeof(surface_desc));
8126 surface_desc.dwSize = sizeof(surface_desc);
8127 hr = IDirectDrawSurface7_GetSurfaceDesc(surface_base, &surface_desc);
8128 ok(SUCCEEDED(hr), "Test %u, %u: Failed to get surface desc, hr %#x.\n", i, mipmap_count, hr);
8129 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
8130 "Test %u, %u: Got unexpected flags %#x.\n", i, mipmap_count, surface_desc.dwFlags);
8131 ok(U2(surface_desc).dwMipMapCount == mipmap_count,
8132 "Test %u, %u: Got unexpected mipmap count %u.\n",
8133 i, mipmap_count, U2(surface_desc).dwMipMapCount);
8135 memset(&surface_desc, 0, sizeof(surface_desc));
8136 surface_desc.dwSize = sizeof(surface_desc);
8137 hr = IDirectDrawSurface7_Lock(surface_base, NULL, &surface_desc, 0, NULL);
8138 ok(SUCCEEDED(hr), "Test %u, %u: Failed to lock surface, hr %#x.\n", i, mipmap_count, hr);
8139 ok(surface_desc.dwMipMapCount == mipmap_count,
8140 "Test %u, %u: unexpected change of mipmap count %u.\n",
8141 i, mipmap_count, surface_desc.dwMipMapCount);
8142 memset(&surface_desc, 0, sizeof(surface_desc));
8143 surface_desc.dwSize = sizeof(surface_desc);
8144 hr = IDirectDrawSurface7_Lock(surface_mip, NULL, &surface_desc, 0, NULL);
8145 ok(SUCCEEDED(hr), "Test %u, %u: Failed to lock surface, hr %#x.\n", i, mipmap_count, hr);
8146 ok(surface_desc.dwMipMapCount == mipmap_count - 1,
8147 "Test %u, %u: Child mipmap count unexpected %u\n", i, mipmap_count, surface_desc.dwMipMapCount);
8148 IDirectDrawSurface7_Unlock(surface_mip, NULL);
8149 IDirectDrawSurface7_Unlock(surface_base, NULL);
8151 IDirectDrawSurface7_Release(surface_base);
8152 surface_base = surface_mip;
8153 --mipmap_count;
8155 IDirectDrawSurface7_Release(surface_base);
8157 IDirectDrawSurface7_Release(surface);
8160 refcount = IDirectDraw7_Release(ddraw);
8161 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8162 DestroyWindow(window);
8165 static void test_palette_complex(void)
8167 IDirectDrawSurface7 *surface, *mipmap, *tmp;
8168 DDSURFACEDESC2 surface_desc;
8169 IDirectDraw7 *ddraw;
8170 IDirectDrawPalette *palette, *palette2;
8171 ULONG refcount;
8172 HWND window;
8173 HRESULT hr;
8174 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
8175 DDCAPS hal_caps;
8176 PALETTEENTRY palette_entries[256];
8177 unsigned int i;
8179 window = create_window();
8180 ddraw = create_ddraw();
8181 ok(!!ddraw, "Failed to create a ddraw object.\n");
8182 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8183 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8185 memset(&hal_caps, 0, sizeof(hal_caps));
8186 hal_caps.dwSize = sizeof(hal_caps);
8187 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
8188 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8189 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)
8190 || is_ddraw64)
8192 skip("Mipmapped textures not supported, skipping mipmap palette test.\n");
8193 IDirectDraw7_Release(ddraw);
8194 DestroyWindow(window);
8195 return;
8198 memset(&surface_desc, 0, sizeof(surface_desc));
8199 surface_desc.dwSize = sizeof(surface_desc);
8200 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8201 surface_desc.dwWidth = 128;
8202 surface_desc.dwHeight = 128;
8203 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
8204 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8205 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
8206 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
8207 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8208 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8210 memset(palette_entries, 0, sizeof(palette_entries));
8211 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8212 palette_entries, &palette, NULL);
8213 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8215 palette2 = (void *)0xdeadbeef;
8216 hr = IDirectDrawSurface7_GetPalette(surface, &palette2);
8217 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
8218 ok(!palette2, "Got unexpected palette %p.\n", palette2);
8219 hr = IDirectDrawSurface7_SetPalette(surface, palette);
8220 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8221 hr = IDirectDrawSurface7_GetPalette(surface, &palette2);
8222 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
8223 ok(palette == palette2, "Got unexpected palette %p.\n", palette2);
8224 IDirectDrawPalette_Release(palette2);
8226 mipmap = surface;
8227 IDirectDrawSurface7_AddRef(mipmap);
8228 for (i = 0; i < 7; ++i)
8230 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
8231 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
8232 palette2 = (void *)0xdeadbeef;
8233 hr = IDirectDrawSurface7_GetPalette(tmp, &palette2);
8234 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x, i %u.\n", hr, i);
8235 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
8237 hr = IDirectDrawSurface7_SetPalette(tmp, palette);
8238 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x, i %u.\n", hr, i);
8240 hr = IDirectDrawSurface7_GetPalette(tmp, &palette2);
8241 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x, i %u.\n", hr, i);
8242 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
8244 /* Ddraw7 uses the palette of the mipmap for GetDC, just like previous
8245 * ddraw versions. Combined with the test results above this means no
8246 * palette is available. So depending on the driver either GetDC fails
8247 * or the DIB color table contains random data. */
8249 IDirectDrawSurface7_Release(mipmap);
8250 mipmap = tmp;
8253 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
8254 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
8255 IDirectDrawSurface7_Release(mipmap);
8256 refcount = IDirectDrawSurface7_Release(surface);
8257 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8259 /* Test DDERR_INVALIDPIXELFORMAT vs DDERR_NOTONMIPMAPSUBLEVEL. */
8260 memset(&surface_desc, 0, sizeof(surface_desc));
8261 surface_desc.dwSize = sizeof(surface_desc);
8262 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8263 surface_desc.dwWidth = 128;
8264 surface_desc.dwHeight = 128;
8265 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
8266 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8267 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
8268 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
8269 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8270 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8271 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
8272 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8273 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8275 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
8276 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
8277 hr = IDirectDrawSurface7_SetPalette(mipmap, palette);
8278 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x.\n", hr);
8280 IDirectDrawSurface7_Release(mipmap);
8281 refcount = IDirectDrawSurface7_Release(surface);
8282 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8283 refcount = IDirectDrawPalette_Release(palette);
8284 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8286 refcount = IDirectDraw7_Release(ddraw);
8287 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8288 DestroyWindow(window);
8291 static void test_p8_blit(void)
8293 IDirectDrawSurface7 *src, *dst, *dst_p8;
8294 DDSURFACEDESC2 surface_desc;
8295 IDirectDraw7 *ddraw;
8296 IDirectDrawPalette *palette, *palette2;
8297 ULONG refcount;
8298 HWND window;
8299 HRESULT hr;
8300 PALETTEENTRY palette_entries[256];
8301 unsigned int x;
8302 DDBLTFX fx;
8303 BOOL is_warp;
8304 static const BYTE src_data[] = {0x10, 0x1, 0x2, 0x3, 0x4, 0x5, 0xff, 0x80};
8305 static const BYTE src_data2[] = {0x10, 0x5, 0x4, 0x3, 0x2, 0x1, 0xff, 0x80};
8306 static const BYTE expected_p8[] = {0x10, 0x1, 0x4, 0x3, 0x4, 0x5, 0xff, 0x80};
8307 static const D3DCOLOR expected[] =
8309 0x00101010, 0x00010101, 0x00020202, 0x00030303,
8310 0x00040404, 0x00050505, 0x00ffffff, 0x00808080,
8312 D3DCOLOR color;
8314 window = create_window();
8315 ddraw = create_ddraw();
8316 ok(!!ddraw, "Failed to create a ddraw object.\n");
8317 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8318 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8319 is_warp = ddraw_is_warp(ddraw);
8321 memset(palette_entries, 0, sizeof(palette_entries));
8322 palette_entries[1].peGreen = 0xff;
8323 palette_entries[2].peBlue = 0xff;
8324 palette_entries[3].peFlags = 0xff;
8325 palette_entries[4].peRed = 0xff;
8326 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8327 palette_entries, &palette, NULL);
8328 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8329 palette_entries[1].peBlue = 0xff;
8330 palette_entries[2].peGreen = 0xff;
8331 palette_entries[3].peRed = 0xff;
8332 palette_entries[4].peFlags = 0x0;
8333 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8334 palette_entries, &palette2, NULL);
8335 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8337 memset(&surface_desc, 0, sizeof(surface_desc));
8338 surface_desc.dwSize = sizeof(surface_desc);
8339 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8340 surface_desc.dwWidth = 8;
8341 surface_desc.dwHeight = 1;
8342 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8343 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8344 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
8345 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
8346 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
8347 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8348 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_p8, NULL);
8349 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8350 hr = IDirectDrawSurface7_SetPalette(dst_p8, palette2);
8351 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8353 memset(&surface_desc, 0, sizeof(surface_desc));
8354 surface_desc.dwSize = sizeof(surface_desc);
8355 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8356 surface_desc.dwWidth = 8;
8357 surface_desc.dwHeight = 1;
8358 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8359 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8360 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
8361 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
8362 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8363 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8364 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
8365 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
8366 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
8367 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8369 memset(&surface_desc, 0, sizeof(surface_desc));
8370 surface_desc.dwSize = sizeof(surface_desc);
8371 hr = IDirectDrawSurface7_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
8372 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
8373 memcpy(surface_desc.lpSurface, src_data, sizeof(src_data));
8374 hr = IDirectDrawSurface7_Unlock(src, NULL);
8375 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
8377 hr = IDirectDrawSurface7_Lock(dst_p8, NULL, &surface_desc, DDLOCK_WAIT, NULL);
8378 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#x.\n", hr);
8379 memcpy(surface_desc.lpSurface, src_data2, sizeof(src_data2));
8380 hr = IDirectDrawSurface7_Unlock(dst_p8, NULL);
8381 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#x.\n", hr);
8383 hr = IDirectDrawSurface7_SetPalette(src, palette);
8384 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8385 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_WAIT, NULL);
8386 /* The r500 Windows 7 driver returns E_NOTIMPL. r200 on Windows XP works.
8387 * The Geforce 7 driver on Windows Vista returns E_FAIL. Newer Nvidia GPUs work. */
8388 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL) || broken(hr == E_FAIL),
8389 "Failed to blit, hr %#x.\n", hr);
8391 if (SUCCEEDED(hr))
8393 for (x = 0; x < ARRAY_SIZE(expected); ++x)
8395 color = get_surface_color(dst, x, 0);
8396 todo_wine ok(compare_color(color, expected[x], 0),
8397 "Pixel %u: Got color %#x, expected %#x.\n",
8398 x, color, expected[x]);
8402 memset(&fx, 0, sizeof(fx));
8403 fx.dwSize = sizeof(fx);
8404 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x2;
8405 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x2;
8406 hr = IDirectDrawSurface7_Blt(dst_p8, NULL, src, NULL, DDBLT_WAIT | DDBLT_KEYSRCOVERRIDE, &fx);
8407 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
8409 hr = IDirectDrawSurface7_Lock(dst_p8, NULL, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
8410 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#x.\n", hr);
8411 /* A color keyed P8 blit doesn't do anything on WARP - it just leaves the data in the destination
8412 * surface untouched. P8 blits without color keys work. Error checking (DDBLT_KEYSRC without a key
8413 * for example) also works as expected.
8415 * Using DDBLT_KEYSRC instead of DDBLT_KEYSRCOVERRIDE doesn't change this. Doing this blit with
8416 * the display mode set to P8 doesn't help either. */
8417 ok(!memcmp(surface_desc.lpSurface, expected_p8, sizeof(expected_p8))
8418 || broken(is_warp && !memcmp(surface_desc.lpSurface, src_data2, sizeof(src_data2))),
8419 "Got unexpected P8 color key blit result.\n");
8420 hr = IDirectDrawSurface7_Unlock(dst_p8, NULL);
8421 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#x.\n", hr);
8423 IDirectDrawSurface7_Release(src);
8424 IDirectDrawSurface7_Release(dst);
8425 IDirectDrawSurface7_Release(dst_p8);
8426 IDirectDrawPalette_Release(palette);
8427 IDirectDrawPalette_Release(palette2);
8429 refcount = IDirectDraw7_Release(ddraw);
8430 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8431 DestroyWindow(window);
8434 static void test_material(void)
8436 static const D3DCOLORVALUE null_color;
8437 IDirect3DDevice7 *device;
8438 D3DMATERIAL7 material;
8439 ULONG refcount;
8440 HWND window;
8441 HRESULT hr;
8443 window = create_window();
8444 if (!(device = create_device(window, DDSCL_NORMAL)))
8446 skip("Failed to create a 3D device, skipping test.\n");
8447 DestroyWindow(window);
8448 return;
8451 hr = IDirect3DDevice7_GetMaterial(device, &material);
8452 ok(SUCCEEDED(hr), "Failed to get material, hr %#x.\n", hr);
8453 ok(!memcmp(&U(material).diffuse, &null_color, sizeof(null_color)),
8454 "Got unexpected diffuse color {%.8e, %.8e, %.8e, %.8e}.\n",
8455 U1(U(material).diffuse).r, U2(U(material).diffuse).g,
8456 U3(U(material).diffuse).b, U4(U(material).diffuse).a);
8457 ok(!memcmp(&U1(material).ambient, &null_color, sizeof(null_color)),
8458 "Got unexpected ambient color {%.8e, %.8e, %.8e, %.8e}.\n",
8459 U1(U1(material).ambient).r, U2(U1(material).ambient).g,
8460 U3(U1(material).ambient).b, U4(U1(material).ambient).a);
8461 ok(!memcmp(&U2(material).specular, &null_color, sizeof(null_color)),
8462 "Got unexpected specular color {%.8e, %.8e, %.8e, %.8e}.\n",
8463 U1(U2(material).specular).r, U2(U2(material).specular).g,
8464 U3(U2(material).specular).b, U4(U2(material).specular).a);
8465 ok(!memcmp(&U3(material).emissive, &null_color, sizeof(null_color)),
8466 "Got unexpected emissive color {%.8e, %.8e, %.8e, %.8e}.\n",
8467 U1(U3(material).emissive).r, U2(U3(material).emissive).g,
8468 U3(U3(material).emissive).b, U4(U3(material).emissive).a);
8469 ok(U4(material).power == 0.0f, "Got unexpected power %.8e.\n", U4(material).power);
8471 refcount = IDirect3DDevice7_Release(device);
8472 ok(!refcount, "Device has %u references left.\n", refcount);
8473 DestroyWindow(window);
8476 static void test_palette_gdi(void)
8478 IDirectDrawSurface7 *surface, *primary;
8479 DDSURFACEDESC2 surface_desc;
8480 IDirectDraw7 *ddraw;
8481 IDirectDrawPalette *palette, *palette2;
8482 ULONG refcount;
8483 HWND window;
8484 HRESULT hr;
8485 PALETTEENTRY palette_entries[256];
8486 UINT i;
8487 HDC dc;
8488 DDBLTFX fx;
8489 RECT r;
8490 COLORREF color;
8491 /* On the Windows 8 testbot palette index 0 of the onscreen palette is forced to
8492 * r = 0, g = 0, b = 0. Do not attempt to set it to something else as this is
8493 * not the point of this test. */
8494 static const RGBQUAD expected1[] =
8496 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
8497 {0x03, 0x00, 0x00, 0x00}, {0x15, 0x14, 0x13, 0x00},
8499 static const RGBQUAD expected2[] =
8501 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
8502 {0x03, 0x00, 0x00, 0x00}, {0x25, 0x24, 0x23, 0x00},
8504 static const RGBQUAD expected3[] =
8506 {0x00, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x40, 0x00},
8507 {0x00, 0x40, 0x00, 0x00}, {0x56, 0x34, 0x12, 0x00},
8509 HPALETTE ddraw_palette_handle;
8510 /* Similar to index 0, index 255 is r = 0xff, g = 0xff, b = 0xff on the Win8 VMs. */
8511 RGBQUAD rgbquad[255];
8512 static const RGBQUAD rgb_zero = {0, 0, 0, 0};
8514 window = create_window();
8515 ddraw = create_ddraw();
8516 ok(!!ddraw, "Failed to create a ddraw object.\n");
8517 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8518 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8520 memset(&surface_desc, 0, sizeof(surface_desc));
8521 surface_desc.dwSize = sizeof(surface_desc);
8522 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8523 surface_desc.dwWidth = 16;
8524 surface_desc.dwHeight = 16;
8525 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8526 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8527 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
8528 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
8529 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8530 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8532 /* Avoid colors from the Windows default palette. */
8533 memset(palette_entries, 0, sizeof(palette_entries));
8534 palette_entries[1].peRed = 0x01;
8535 palette_entries[2].peGreen = 0x02;
8536 palette_entries[3].peBlue = 0x03;
8537 palette_entries[4].peRed = 0x13;
8538 palette_entries[4].peGreen = 0x14;
8539 palette_entries[4].peBlue = 0x15;
8540 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8541 palette_entries, &palette, NULL);
8542 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8544 /* If there is no palette assigned and the display mode is not 8 bpp, some
8545 * drivers refuse to create a DC while others allow it. If a DC is created,
8546 * the DIB color table is uninitialized and contains random colors. No error
8547 * is generated when trying to read pixels and random garbage is returned.
8549 * The most likely explanation is that if the driver creates a DC, it (or
8550 * the higher-level runtime) uses GetSystemPaletteEntries to find the
8551 * palette, but GetSystemPaletteEntries fails when bpp > 8 and the palette
8552 * contains uninitialized garbage. See comments below for the P8 case. */
8554 hr = IDirectDrawSurface7_SetPalette(surface, palette);
8555 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8556 hr = IDirectDrawSurface7_GetDC(surface, &dc);
8557 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8558 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
8559 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
8560 "Got unexpected palette %p, expected %p.\n",
8561 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
8563 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8564 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8565 for (i = 0; i < ARRAY_SIZE(expected1); ++i)
8567 ok(!memcmp(&rgbquad[i], &expected1[i], sizeof(rgbquad[i])),
8568 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8569 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8570 expected1[i].rgbRed, expected1[i].rgbGreen, expected1[i].rgbBlue);
8572 for (; i < ARRAY_SIZE(rgbquad); ++i)
8574 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8575 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8576 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8579 /* Update the palette while the DC is in use. This does not modify the DC. */
8580 palette_entries[4].peRed = 0x23;
8581 palette_entries[4].peGreen = 0x24;
8582 palette_entries[4].peBlue = 0x25;
8583 hr = IDirectDrawPalette_SetEntries(palette, 0, 4, 1, &palette_entries[4]);
8584 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
8586 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
8587 ok(i == 1, "Expected count 1, got %u.\n", i);
8588 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
8589 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8590 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
8591 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
8593 /* Neither does re-setting the palette. */
8594 hr = IDirectDrawSurface7_SetPalette(surface, NULL);
8595 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8596 hr = IDirectDrawSurface7_SetPalette(surface, palette);
8597 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8599 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
8600 ok(i == 1, "Expected count 1, got %u.\n", i);
8601 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
8602 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8603 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
8604 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
8606 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
8607 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8609 /* Refresh the DC. This updates the palette. */
8610 hr = IDirectDrawSurface7_GetDC(surface, &dc);
8611 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8612 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8613 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8614 for (i = 0; i < ARRAY_SIZE(expected2); ++i)
8616 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8617 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8618 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8619 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8621 for (; i < ARRAY_SIZE(rgbquad); ++i)
8623 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8624 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8625 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8627 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
8628 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8630 refcount = IDirectDrawSurface7_Release(surface);
8631 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8633 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
8634 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8635 if (FAILED(IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
8637 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
8638 IDirectDrawPalette_Release(palette);
8639 IDirectDraw7_Release(ddraw);
8640 DestroyWindow(window);
8641 return;
8643 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
8645 memset(&surface_desc, 0, sizeof(surface_desc));
8646 surface_desc.dwSize = sizeof(surface_desc);
8647 surface_desc.dwFlags = DDSD_CAPS;
8648 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8649 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
8650 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8652 memset(&fx, 0, sizeof(fx));
8653 fx.dwSize = sizeof(fx);
8654 U5(fx).dwFillColor = 3;
8655 SetRect(&r, 0, 0, 319, 479);
8656 hr = IDirectDrawSurface7_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8657 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#x.\n", hr);
8658 SetRect(&r, 320, 0, 639, 479);
8659 U5(fx).dwFillColor = 4;
8660 hr = IDirectDrawSurface7_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8661 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#x.\n", hr);
8663 hr = IDirectDrawSurface7_SetPalette(primary, palette);
8664 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8665 hr = IDirectDrawSurface7_GetDC(primary, &dc);
8666 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8668 color = GetPixel(dc, 160, 240);
8669 ok(color == 0x00030000, "Clear index 3: Got unexpected color 0x%08x.\n", color);
8670 color = GetPixel(dc, 480, 240);
8671 ok(color == 0x00252423, "Clear index 4: Got unexpected color 0x%08x.\n", color);
8673 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
8674 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
8675 "Got unexpected palette %p, expected %p.\n",
8676 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
8677 SelectPalette(dc, ddraw_palette_handle, FALSE);
8679 /* The primary uses the system palette. In exclusive mode, the system palette matches
8680 * the ddraw palette attached to the primary, so the result is what you would expect
8681 * from a regular surface. Tests for the interaction between the ddraw palette and
8682 * the system palette are not included pending an application that depends on this.
8683 * The relation between those causes problems on Windows Vista and newer for games
8684 * like Age of Empires or StarcCaft. Don't emulate it without a real need. */
8685 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8686 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8687 for (i = 0; i < ARRAY_SIZE(expected2); ++i)
8689 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8690 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8691 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8692 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8694 for (; i < ARRAY_SIZE(rgbquad); ++i)
8696 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8697 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8698 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8700 hr = IDirectDrawSurface7_ReleaseDC(primary, dc);
8701 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8703 memset(&surface_desc, 0, sizeof(surface_desc));
8704 surface_desc.dwSize = sizeof(surface_desc);
8705 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8706 surface_desc.dwWidth = 16;
8707 surface_desc.dwHeight = 16;
8708 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8709 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8710 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8712 /* Here the offscreen surface appears to use the primary's palette,
8713 * but in all likelihood it is actually the system palette. */
8714 hr = IDirectDrawSurface7_GetDC(surface, &dc);
8715 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8716 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8717 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8718 for (i = 0; i < ARRAY_SIZE(expected2); ++i)
8720 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8721 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8722 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8723 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8725 for (; i < ARRAY_SIZE(rgbquad); ++i)
8727 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8728 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8729 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8731 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
8732 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8734 /* On real hardware a change to the primary surface's palette applies immediately,
8735 * even on device contexts from offscreen surfaces that do not have their own
8736 * palette. On the testbot VMs this is not the case. Don't test this until we
8737 * know of an application that depends on this. */
8739 memset(palette_entries, 0, sizeof(palette_entries));
8740 palette_entries[1].peBlue = 0x40;
8741 palette_entries[2].peRed = 0x40;
8742 palette_entries[3].peGreen = 0x40;
8743 palette_entries[4].peRed = 0x12;
8744 palette_entries[4].peGreen = 0x34;
8745 palette_entries[4].peBlue = 0x56;
8746 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8747 palette_entries, &palette2, NULL);
8748 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8749 hr = IDirectDrawSurface7_SetPalette(surface, palette2);
8750 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8752 /* A palette assigned to the offscreen surface overrides the primary / system
8753 * palette. */
8754 hr = IDirectDrawSurface7_GetDC(surface, &dc);
8755 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8756 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8757 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8758 for (i = 0; i < ARRAY_SIZE(expected3); ++i)
8760 ok(!memcmp(&rgbquad[i], &expected3[i], sizeof(rgbquad[i])),
8761 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8762 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8763 expected3[i].rgbRed, expected3[i].rgbGreen, expected3[i].rgbBlue);
8765 for (; i < ARRAY_SIZE(rgbquad); ++i)
8767 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8768 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8769 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8771 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
8772 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8774 refcount = IDirectDrawSurface7_Release(surface);
8775 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8777 /* The Windows 8 testbot keeps extra references to the primary and
8778 * backbuffer while in 8 bpp mode. */
8779 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
8780 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
8782 refcount = IDirectDrawSurface7_Release(primary);
8783 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8784 refcount = IDirectDrawPalette_Release(palette2);
8785 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8786 refcount = IDirectDrawPalette_Release(palette);
8787 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8788 refcount = IDirectDraw7_Release(ddraw);
8789 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8790 DestroyWindow(window);
8793 static void test_palette_alpha(void)
8795 IDirectDrawSurface7 *surface;
8796 DDSURFACEDESC2 surface_desc;
8797 IDirectDraw7 *ddraw;
8798 IDirectDrawPalette *palette;
8799 ULONG refcount;
8800 HWND window;
8801 HRESULT hr;
8802 PALETTEENTRY palette_entries[256];
8803 unsigned int i;
8804 static const struct
8806 DWORD caps, flags;
8807 BOOL attach_allowed;
8808 const char *name;
8810 test_data[] =
8812 {DDSCAPS_OFFSCREENPLAIN, DDSD_WIDTH | DDSD_HEIGHT, FALSE, "offscreenplain"},
8813 {DDSCAPS_TEXTURE, DDSD_WIDTH | DDSD_HEIGHT, TRUE, "texture"},
8814 {DDSCAPS_PRIMARYSURFACE, 0, FALSE, "primary"}
8817 window = create_window();
8818 ddraw = create_ddraw();
8819 ok(!!ddraw, "Failed to create a ddraw object.\n");
8820 if (FAILED(IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
8822 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
8823 IDirectDraw7_Release(ddraw);
8824 DestroyWindow(window);
8825 return;
8827 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8828 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8830 memset(palette_entries, 0, sizeof(palette_entries));
8831 palette_entries[1].peFlags = 0x42;
8832 palette_entries[2].peFlags = 0xff;
8833 palette_entries[3].peFlags = 0x80;
8834 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
8835 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8837 memset(palette_entries, 0x66, sizeof(palette_entries));
8838 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
8839 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
8840 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8841 palette_entries[0].peFlags);
8842 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8843 palette_entries[1].peFlags);
8844 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
8845 palette_entries[2].peFlags);
8846 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
8847 palette_entries[3].peFlags);
8849 IDirectDrawPalette_Release(palette);
8851 memset(palette_entries, 0, sizeof(palette_entries));
8852 palette_entries[1].peFlags = 0x42;
8853 palette_entries[1].peRed = 0xff;
8854 palette_entries[2].peFlags = 0xff;
8855 palette_entries[3].peFlags = 0x80;
8856 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT | DDPCAPS_ALPHA,
8857 palette_entries, &palette, NULL);
8858 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8860 memset(palette_entries, 0x66, sizeof(palette_entries));
8861 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
8862 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
8863 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8864 palette_entries[0].peFlags);
8865 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8866 palette_entries[1].peFlags);
8867 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
8868 palette_entries[2].peFlags);
8869 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
8870 palette_entries[3].peFlags);
8872 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
8874 memset(&surface_desc, 0, sizeof(surface_desc));
8875 surface_desc.dwSize = sizeof(surface_desc);
8876 surface_desc.dwFlags = DDSD_CAPS | test_data[i].flags;
8877 surface_desc.dwWidth = 128;
8878 surface_desc.dwHeight = 128;
8879 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
8880 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8881 ok(SUCCEEDED(hr), "Failed to create %s surface, hr %#x.\n", test_data[i].name, hr);
8883 hr = IDirectDrawSurface7_SetPalette(surface, palette);
8884 if (test_data[i].attach_allowed)
8885 ok(SUCCEEDED(hr), "Failed to attach palette to %s surface, hr %#x.\n", test_data[i].name, hr);
8886 else
8887 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x, %s surface.\n", hr, test_data[i].name);
8889 if (SUCCEEDED(hr))
8891 HDC dc;
8892 RGBQUAD rgbquad;
8893 UINT retval;
8895 hr = IDirectDrawSurface7_GetDC(surface, &dc);
8896 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x, %s surface.\n", hr, test_data[i].name);
8897 retval = GetDIBColorTable(dc, 1, 1, &rgbquad);
8898 ok(retval == 1, "GetDIBColorTable returned unexpected result %u.\n", retval);
8899 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x, %s surface.\n",
8900 rgbquad.rgbRed, test_data[i].name);
8901 ok(rgbquad.rgbGreen == 0, "Expected rgbGreen = 0, got %#x, %s surface.\n",
8902 rgbquad.rgbGreen, test_data[i].name);
8903 ok(rgbquad.rgbBlue == 0, "Expected rgbBlue = 0, got %#x, %s surface.\n",
8904 rgbquad.rgbBlue, test_data[i].name);
8905 ok(rgbquad.rgbReserved == 0, "Expected rgbReserved = 0, got %u, %s surface.\n",
8906 rgbquad.rgbReserved, test_data[i].name);
8907 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
8908 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8910 IDirectDrawSurface7_Release(surface);
8913 /* Test INVALIDSURFACETYPE vs INVALIDPIXELFORMAT. */
8914 memset(&surface_desc, 0, sizeof(surface_desc));
8915 surface_desc.dwSize = sizeof(surface_desc);
8916 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8917 surface_desc.dwWidth = 128;
8918 surface_desc.dwHeight = 128;
8919 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8920 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8921 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
8922 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
8923 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8924 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8925 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
8926 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8927 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8928 hr = IDirectDrawSurface7_SetPalette(surface, palette);
8929 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x.\n", hr);
8930 IDirectDrawSurface7_Release(surface);
8932 /* The Windows 8 testbot keeps extra references to the primary
8933 * while in 8 bpp mode. */
8934 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
8935 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
8937 refcount = IDirectDrawPalette_Release(palette);
8938 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8939 refcount = IDirectDraw7_Release(ddraw);
8940 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8941 DestroyWindow(window);
8944 static void test_vb_writeonly(void)
8946 IDirect3DDevice7 *device;
8947 IDirect3D7 *d3d;
8948 IDirect3DVertexBuffer7 *buffer;
8949 HWND window;
8950 HRESULT hr;
8951 D3DVERTEXBUFFERDESC desc;
8952 void *ptr;
8953 static const struct vec4 quad[] =
8955 { 0.0f, 480.0f, 0.0f, 1.0f},
8956 { 0.0f, 0.0f, 0.0f, 1.0f},
8957 {640.0f, 480.0f, 0.0f, 1.0f},
8958 {640.0f, 0.0f, 0.0f, 1.0f},
8961 window = create_window();
8962 if (!(device = create_device(window, DDSCL_NORMAL)))
8964 skip("Failed to create a 3D device, skipping test.\n");
8965 DestroyWindow(window);
8966 return;
8969 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
8970 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
8972 memset(&desc, 0, sizeof(desc));
8973 desc.dwSize = sizeof(desc);
8974 desc.dwCaps = D3DVBCAPS_WRITEONLY;
8975 desc.dwFVF = D3DFVF_XYZRHW;
8976 desc.dwNumVertices = ARRAY_SIZE(quad);
8977 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &buffer, 0);
8978 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
8980 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, &ptr, NULL);
8981 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
8982 memcpy(ptr, quad, sizeof(quad));
8983 hr = IDirect3DVertexBuffer7_Unlock(buffer);
8984 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
8986 hr = IDirect3DDevice7_BeginScene(device);
8987 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8988 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
8989 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8990 hr = IDirect3DDevice7_EndScene(device);
8991 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8993 hr = IDirect3DVertexBuffer7_Lock(buffer, 0, &ptr, NULL);
8994 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
8995 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
8996 hr = IDirect3DVertexBuffer7_Unlock(buffer);
8997 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
8999 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_READONLY, &ptr, NULL);
9000 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
9001 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
9002 hr = IDirect3DVertexBuffer7_Unlock(buffer);
9003 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
9005 IDirect3DVertexBuffer7_Release(buffer);
9006 IDirect3D7_Release(d3d);
9007 IDirect3DDevice7_Release(device);
9008 DestroyWindow(window);
9011 static void test_lost_device(void)
9013 IDirectDrawSurface7 *surface;
9014 DDSURFACEDESC2 surface_desc;
9015 HWND window1, window2;
9016 IDirectDraw7 *ddraw;
9017 ULONG refcount;
9018 HRESULT hr;
9019 BOOL ret;
9021 window1 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9022 0, 0, 640, 480, 0, 0, 0, 0);
9023 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9024 0, 0, 640, 480, 0, 0, 0, 0);
9025 ddraw = create_ddraw();
9026 ok(!!ddraw, "Failed to create a ddraw object.\n");
9027 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
9028 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9030 memset(&surface_desc, 0, sizeof(surface_desc));
9031 surface_desc.dwSize = sizeof(surface_desc);
9032 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
9033 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
9034 U5(surface_desc).dwBackBufferCount = 1;
9035 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9036 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9038 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9039 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9040 hr = IDirectDrawSurface7_IsLost(surface);
9041 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9042 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9043 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9045 ret = SetForegroundWindow(GetDesktopWindow());
9046 ok(ret, "Failed to set foreground window.\n");
9047 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9048 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
9049 hr = IDirectDrawSurface7_IsLost(surface);
9050 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9051 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9052 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9054 ret = SetForegroundWindow(window1);
9055 ok(ret, "Failed to set foreground window.\n");
9056 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9057 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9058 hr = IDirectDrawSurface7_IsLost(surface);
9059 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9060 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9061 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9063 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
9064 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9065 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9066 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9067 hr = IDirectDrawSurface7_IsLost(surface);
9068 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9069 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9070 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9072 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
9073 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9074 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9075 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9076 hr = IDirectDrawSurface7_IsLost(surface);
9077 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9078 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9079 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9081 /* Trying to restore the primary will crash, probably because flippable
9082 * surfaces can't exist in DDSCL_NORMAL. */
9083 IDirectDrawSurface7_Release(surface);
9084 memset(&surface_desc, 0, sizeof(surface_desc));
9085 surface_desc.dwSize = sizeof(surface_desc);
9086 surface_desc.dwFlags = DDSD_CAPS;
9087 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
9088 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9089 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9091 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9092 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9093 hr = IDirectDrawSurface7_IsLost(surface);
9094 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9096 ret = SetForegroundWindow(GetDesktopWindow());
9097 ok(ret, "Failed to set foreground window.\n");
9098 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9099 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9100 hr = IDirectDrawSurface7_IsLost(surface);
9101 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9103 ret = SetForegroundWindow(window1);
9104 ok(ret, "Failed to set foreground window.\n");
9105 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9106 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9107 hr = IDirectDrawSurface7_IsLost(surface);
9108 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9110 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
9111 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9112 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9113 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9114 hr = IDirectDrawSurface7_IsLost(surface);
9115 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9117 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
9118 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9119 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9120 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9121 hr = IDirectDrawSurface7_IsLost(surface);
9122 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9124 IDirectDrawSurface7_Release(surface);
9125 memset(&surface_desc, 0, sizeof(surface_desc));
9126 surface_desc.dwSize = sizeof(surface_desc);
9127 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
9128 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
9129 U5(surface_desc).dwBackBufferCount = 1;
9130 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9131 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9133 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
9134 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9135 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9136 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9137 hr = IDirectDrawSurface7_IsLost(surface);
9138 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9139 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9140 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9142 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL | DDSCL_FULLSCREEN);
9143 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9144 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9145 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9146 hr = IDirectDrawSurface7_IsLost(surface);
9147 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9148 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9149 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
9151 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
9152 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9153 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9154 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9155 hr = IDirectDrawSurface7_IsLost(surface);
9156 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9157 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9158 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
9160 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
9161 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9162 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9163 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9164 hr = IDirectDrawSurface7_IsLost(surface);
9165 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9166 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9167 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
9169 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL | DDSCL_FULLSCREEN);
9170 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9171 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9172 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9173 hr = IDirectDrawSurface7_IsLost(surface);
9174 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9175 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9176 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
9178 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
9179 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9180 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9181 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9182 hr = IDirectDrawSurface7_IsLost(surface);
9183 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9184 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9185 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9187 IDirectDrawSurface7_Release(surface);
9188 refcount = IDirectDraw7_Release(ddraw);
9189 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9190 DestroyWindow(window2);
9191 DestroyWindow(window1);
9194 static void test_resource_priority(void)
9196 IDirectDrawSurface7 *surface, *mipmap;
9197 DDSURFACEDESC2 surface_desc;
9198 IDirectDraw7 *ddraw;
9199 ULONG refcount;
9200 HWND window;
9201 HRESULT hr;
9202 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
9203 DDCAPS hal_caps;
9204 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_MIPMAP;
9205 unsigned int i;
9206 DWORD priority;
9207 static const struct
9209 DWORD caps, caps2;
9210 const char *name;
9211 HRESULT hr;
9212 /* SetPriority on offscreenplain surfaces crashes on AMD GPUs on Win7. */
9213 BOOL crash;
9215 test_data[] =
9217 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, "vidmem texture", DDERR_INVALIDPARAMS, FALSE},
9218 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, "sysmem texture", DDERR_INVALIDPARAMS, FALSE},
9219 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, "managed texture", DD_OK, FALSE},
9220 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, "managed texture", DD_OK, FALSE},
9221 {DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP,
9222 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_TEXTUREMANAGE,
9223 "cubemap", DD_OK, FALSE},
9224 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, "vidmem offscreenplain", DDERR_INVALIDOBJECT, TRUE},
9225 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, "sysmem offscreenplain", DDERR_INVALIDOBJECT, TRUE},
9228 window = create_window();
9229 ddraw = create_ddraw();
9230 ok(!!ddraw, "Failed to create a ddraw object.\n");
9231 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9232 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9234 memset(&hal_caps, 0, sizeof(hal_caps));
9235 hal_caps.dwSize = sizeof(hal_caps);
9236 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
9237 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9238 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps
9239 || !(hal_caps.ddsCaps.dwCaps & DDSCAPS2_TEXTUREMANAGE))
9241 skip("Required surface types not supported, skipping test.\n");
9242 goto done;
9245 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
9247 memset(&surface_desc, 0, sizeof(surface_desc));
9248 surface_desc.dwSize = sizeof(surface_desc);
9249 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
9250 surface_desc.dwWidth = 32;
9251 surface_desc.dwHeight = 32;
9252 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
9253 surface_desc.ddsCaps.dwCaps2 = test_data[i].caps2;
9254 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9255 if (is_ddraw64 && (test_data[i].caps & DDSCAPS_TEXTURE))
9257 todo_wine ok(hr == E_NOINTERFACE, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
9258 if (SUCCEEDED(hr))
9259 IDirectDrawSurface7_Release(surface);
9260 continue;
9262 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n", hr, test_data[i].name);
9264 /* Priority == NULL segfaults. */
9265 priority = 0xdeadbeef;
9266 hr = IDirectDrawSurface7_GetPriority(surface, &priority);
9267 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
9268 if (SUCCEEDED(test_data[i].hr))
9269 ok(priority == 0, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
9270 else
9271 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
9273 if (!test_data[i].crash)
9275 hr = IDirectDrawSurface7_SetPriority(surface, 1);
9276 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
9277 hr = IDirectDrawSurface7_GetPriority(surface, &priority);
9278 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
9279 if (SUCCEEDED(test_data[i].hr))
9281 ok(priority == 1, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
9282 hr = IDirectDrawSurface7_SetPriority(surface, 2);
9283 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
9285 else
9286 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
9289 if (test_data[i].caps2 & DDSCAPS2_CUBEMAP)
9291 caps.dwCaps2 = DDSCAPS2_CUBEMAP_NEGATIVEZ;
9292 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
9293 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
9294 /* IDirectDrawSurface7_SetPriority crashes when called on non-positive X surfaces on Windows */
9295 priority = 0xdeadbeef;
9296 hr = IDirectDrawSurface7_GetPriority(mipmap, &priority);
9297 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
9298 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
9300 IDirectDrawSurface7_Release(mipmap);
9303 IDirectDrawSurface7_Release(surface);
9306 if (is_ddraw64)
9307 goto done;
9309 memset(&surface_desc, 0, sizeof(surface_desc));
9310 surface_desc.dwSize = sizeof(surface_desc);
9311 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_MIPMAPCOUNT;
9312 surface_desc.dwWidth = 32;
9313 surface_desc.dwHeight = 32;
9314 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
9315 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
9316 U2(surface_desc).dwMipMapCount = 2;
9317 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9318 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9319 caps.dwCaps2 = 0;
9320 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
9321 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
9323 priority = 0xdeadbeef;
9324 hr = IDirectDrawSurface7_GetPriority(mipmap, &priority);
9325 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type managed mipmap.\n", hr);
9326 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type managed mipmap.\n", priority);
9327 /* SetPriority on the mipmap surface crashes. */
9328 hr = IDirectDrawSurface7_GetPriority(surface, &priority);
9329 ok(SUCCEEDED(hr), "Failed to get priority, hr %#x.\n", hr);
9330 ok(priority == 0, "Got unexpected priority %u, type managed mipmap.\n", priority);
9332 IDirectDrawSurface7_Release(mipmap);
9333 refcount = IDirectDrawSurface7_Release(surface);
9334 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9336 done:
9337 refcount = IDirectDraw7_Release(ddraw);
9338 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9339 DestroyWindow(window);
9342 static void test_surface_desc_lock(void)
9344 IDirectDrawSurface7 *surface;
9345 DDSURFACEDESC2 surface_desc;
9346 IDirectDraw7 *ddraw;
9347 ULONG refcount;
9348 HWND window;
9349 HRESULT hr;
9351 window = create_window();
9352 ddraw = create_ddraw();
9353 ok(!!ddraw, "Failed to create a ddraw object.\n");
9354 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9355 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9357 memset(&surface_desc, 0, sizeof(surface_desc));
9358 surface_desc.dwSize = sizeof(surface_desc);
9359 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
9360 surface_desc.dwWidth = 16;
9361 surface_desc.dwHeight = 16;
9362 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9363 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9364 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9366 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9367 surface_desc.dwSize = sizeof(surface_desc);
9368 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
9369 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
9370 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9372 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9373 surface_desc.dwSize = sizeof(surface_desc);
9374 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, 0, NULL);
9375 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
9376 ok(surface_desc.lpSurface != NULL, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9377 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9378 surface_desc.dwSize = sizeof(surface_desc);
9379 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
9380 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
9381 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9382 hr = IDirectDrawSurface7_Unlock(surface, NULL);
9383 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9385 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9386 surface_desc.dwSize = sizeof(surface_desc);
9387 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
9388 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
9389 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9391 IDirectDrawSurface7_Release(surface);
9392 refcount = IDirectDraw7_Release(ddraw);
9393 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9394 DestroyWindow(window);
9397 static void test_fog_interpolation(void)
9399 HRESULT hr;
9400 IDirect3DDevice7 *device;
9401 IDirectDrawSurface7 *rt;
9402 ULONG refcount;
9403 HWND window;
9404 D3DCOLOR color;
9405 static struct
9407 struct vec3 position;
9408 D3DCOLOR diffuse;
9409 D3DCOLOR specular;
9411 quad[] =
9413 {{-1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff000000},
9414 {{-1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff000000},
9415 {{ 1.0f, -1.0f, 1.0f}, 0xffff0000, 0x00000000},
9416 {{ 1.0f, 1.0f, 1.0f}, 0xffff0000, 0x00000000},
9418 union
9420 DWORD d;
9421 float f;
9422 } conv;
9423 unsigned int i;
9424 static const struct
9426 D3DFOGMODE vfog, tfog;
9427 D3DSHADEMODE shade;
9428 D3DCOLOR middle_color;
9429 BOOL todo;
9431 tests[] =
9433 {D3DFOG_NONE, D3DFOG_NONE, D3DSHADE_FLAT, 0x00007f80, FALSE},
9434 {D3DFOG_NONE, D3DFOG_NONE, D3DSHADE_GOURAUD, 0x00007f80, FALSE},
9435 {D3DFOG_EXP, D3DFOG_NONE, D3DSHADE_FLAT, 0x00007f80, TRUE},
9436 {D3DFOG_EXP, D3DFOG_NONE, D3DSHADE_GOURAUD, 0x00007f80, TRUE},
9437 {D3DFOG_NONE, D3DFOG_EXP, D3DSHADE_FLAT, 0x0000ea15, FALSE},
9438 {D3DFOG_NONE, D3DFOG_EXP, D3DSHADE_GOURAUD, 0x0000ea15, FALSE},
9439 {D3DFOG_EXP, D3DFOG_EXP, D3DSHADE_FLAT, 0x0000ea15, FALSE},
9440 {D3DFOG_EXP, D3DFOG_EXP, D3DSHADE_GOURAUD, 0x0000ea15, FALSE},
9442 D3DDEVICEDESC7 caps;
9444 window = create_window();
9445 if (!(device = create_device(window, DDSCL_NORMAL)))
9447 skip("Failed to create a 3D device, skipping test.\n");
9448 DestroyWindow(window);
9449 return;
9452 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
9453 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9454 hr = IDirect3DDevice7_GetCaps(device, &caps);
9455 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
9456 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE))
9457 skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping some fog tests\n");
9459 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
9460 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9461 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
9462 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9463 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
9464 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9465 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x0000ff00);
9466 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9467 conv.f = 5.0;
9468 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGDENSITY, conv.d);
9469 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9471 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
9472 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
9473 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
9474 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
9475 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x000000ff);
9476 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9478 for (i = 0; i < ARRAY_SIZE(tests); ++i)
9480 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE) && tests[i].tfog)
9481 continue;
9483 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00808080, 0.0f, 0);
9484 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
9486 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SHADEMODE, tests[i].shade);
9487 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9488 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, tests[i].vfog);
9489 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9490 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, tests[i].tfog);
9491 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9492 hr = IDirect3DDevice7_BeginScene(device);
9493 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9494 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9495 D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR, quad, 4, 0);
9496 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9497 hr = IDirect3DDevice7_EndScene(device);
9498 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9500 color = get_surface_color(rt, 0, 240);
9501 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x, case %u.\n", color, i);
9502 color = get_surface_color(rt, 320, 240);
9503 todo_wine_if (tests[i].todo)
9504 ok(compare_color(color, tests[i].middle_color, 2),
9505 "Got unexpected color 0x%08x, case %u.\n", color, i);
9506 color = get_surface_color(rt, 639, 240);
9507 ok(compare_color(color, 0x0000fd02, 2), "Got unexpected color 0x%08x, case %u.\n", color, i);
9510 IDirectDrawSurface7_Release(rt);
9511 refcount = IDirect3DDevice7_Release(device);
9512 ok(!refcount, "Device has %u references left.\n", refcount);
9513 DestroyWindow(window);
9516 static void test_fog_process_vertices(void)
9518 static D3DMATRIX view_matrix =
9520 1.0f, 0.0f, 0.0f, 0.0f,
9521 0.0f, 1.0f, 0.0f, 0.0f,
9522 0.0f, 0.0f, 0.5f, 0.0f,
9523 0.0f, 0.0f, 0.0f, 1.0f
9525 static D3DMATRIX model_matrix =
9527 1.0f, 0.0f, 0.0f, 0.0f,
9528 0.0f, 1.0f, 0.0f, 0.0f,
9529 0.0f, 0.0f, 0.75f, 0.0f,
9530 0.0f, 0.0f, 0.0f, 1.0f
9532 static D3DMATRIX identity_matrix =
9534 1.0f, 0.0f, 0.0f, 0.0f,
9535 0.0f, 1.0f, 0.0f, 0.0f,
9536 0.0f, 0.0f, 1.0f, 0.0f,
9537 0.0f, 0.0f, 0.0f, 1.0f
9540 static D3DLIGHT7 directional_light =
9542 D3DLIGHT_DIRECTIONAL,
9543 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
9544 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
9545 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
9546 {{0.0f}, {0.0f}, {0.0f}},
9547 {{0.0f}, {0.0f}, {1.0f}},
9550 struct vertex
9552 struct vec3 position;
9553 struct vec3 normal;
9555 static const struct
9557 struct vertex vertex;
9558 D3DFOGMODE fog_vertex_mode, fog_table_mode;
9559 BOOL range_fog;
9560 D3DCOLOR expected_color, expected_broken;
9562 tests[] =
9564 /* Some drivers ignore ranged fog state without an obvious reason, even with D3DPRASTERCAPS_FOGRANGE
9565 * set, while some others (including WARP driver on Windows 10) favour it.
9566 * Vertex fog result does not depend on table fog settings. */
9567 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_NONE, D3DFOG_NONE, FALSE, 0x8000ff00},
9568 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_NONE, D3DFOG_LINEAR, FALSE, 0x8000ff00},
9569 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_EXP, D3DFOG_NONE, FALSE, 0xaf00ff00},
9570 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_EXP2, D3DFOG_NONE, FALSE, 0xde00ff00},
9571 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_LINEAR, D3DFOG_NONE, FALSE, 0x9f00ff00},
9572 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_LINEAR, D3DFOG_LINEAR, FALSE, 0x9f00ff00},
9573 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_NONE, D3DFOG_NONE, TRUE, 0x8000ff00},
9574 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_EXP, D3DFOG_NONE, TRUE, 0x8800ff00, 0xaf00ff00},
9575 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_EXP2, D3DFOG_NONE, TRUE, 0xad00ff00, 0xde00ff00},
9576 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_LINEAR, D3DFOG_NONE, TRUE, 0x6000ff00, 0x9f00ff00},
9577 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_LINEAR, D3DFOG_EXP, TRUE, 0x6000ff00, 0x9f00ff00},
9578 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_EXP, D3DFOG_LINEAR, TRUE, 0x8800ff00, 0xaf00ff00},
9581 struct
9583 struct vec4 position;
9584 D3DCOLOR diffuse, specular;
9586 *dst_data;
9588 IDirect3DVertexBuffer7 *src_vb, *dst_vb;
9589 D3DVERTEXBUFFERDESC vb_desc;
9590 IDirect3DDevice7 *device;
9591 struct vertex *src_data;
9592 D3DMATERIAL7 material;
9593 IDirect3D7 *d3d;
9594 ULONG refcount;
9595 unsigned int i;
9596 HWND window;
9597 HRESULT hr;
9599 window = create_window();
9600 if (!(device = create_device(window, DDSCL_NORMAL)))
9602 skip("Failed to create a 3D device, skipping test.\n");
9603 DestroyWindow(window);
9604 return;
9606 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
9607 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9609 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &model_matrix);
9610 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9611 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &view_matrix);
9612 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9613 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &identity_matrix);
9614 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9616 memset(&vb_desc, 0, sizeof(vb_desc));
9617 vb_desc.dwSize = sizeof(vb_desc);
9618 vb_desc.dwFVF = D3DFVF_XYZ | D3DFVF_NORMAL;
9619 vb_desc.dwNumVertices = 1;
9620 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &src_vb, 0);
9621 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9623 memset(&vb_desc, 0, sizeof(vb_desc));
9624 vb_desc.dwSize = sizeof(vb_desc);
9625 vb_desc.dwFVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR;
9626 vb_desc.dwNumVertices = 1;
9627 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &dst_vb, 0);
9628 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9630 hr = IDirect3DDevice7_LightEnable(device, 0, TRUE);
9631 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9632 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, TRUE);
9633 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9634 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
9635 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9636 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
9637 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9638 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
9639 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9641 hr = IDirect3DDevice7_SetLight(device, 0, &directional_light);
9642 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9644 memset(&material, 0, sizeof(material));
9645 U1(U2(material).specular).r = 0.0f;
9646 U2(U2(material).specular).g = 1.0f;
9647 U3(U2(material).specular).b = 0.0f;
9648 U4(U2(material).specular).a = 0.5f;
9649 U4(material).power = 5.0f;
9650 hr = IDirect3DDevice7_SetMaterial(device, &material);
9651 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9653 for (i = 0; i < ARRAY_SIZE(tests); ++i)
9655 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE,
9656 tests[i].fog_vertex_mode);
9657 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE,
9658 tests[i].fog_table_mode);
9659 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9660 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_RANGEFOGENABLE, tests[i].range_fog);
9661 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9663 hr = IDirect3DVertexBuffer7_Lock(src_vb, 0, (void **)&src_data, NULL);
9664 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9665 *src_data = tests[i].vertex;
9666 hr = IDirect3DVertexBuffer7_Unlock(src_vb);
9667 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9669 hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL);
9670 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9671 memset(dst_data, 0, sizeof(*dst_data));
9672 hr = IDirect3DVertexBuffer7_Unlock(dst_vb);
9673 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9674 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 0,
9675 1, src_vb, 0, device, 0);
9676 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9678 hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL);
9679 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9681 ok(compare_color(dst_data->specular, tests[i].expected_color, 1)
9682 || broken(tests[i].expected_broken
9683 && compare_color(dst_data->specular, tests[i].expected_broken, 1)),
9684 "Expected color 0x%08x, got 0x%08x, test %u.\n",
9685 tests[i].expected_color, dst_data->specular, i);
9687 hr = IDirect3DVertexBuffer7_Unlock(dst_vb);
9688 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9691 IDirect3DVertexBuffer7_Release(dst_vb);
9692 IDirect3DVertexBuffer7_Release(src_vb);
9693 IDirect3D7_Release(d3d);
9694 refcount = IDirect3DDevice7_Release(device);
9695 ok(!refcount, "Device has %u references left.\n", refcount);
9696 DestroyWindow(window);
9699 static void test_negative_fixedfunction_fog(void)
9701 HRESULT hr;
9702 IDirect3DDevice7 *device;
9703 IDirectDrawSurface7 *rt;
9704 ULONG refcount;
9705 HWND window;
9706 D3DCOLOR color;
9707 static struct
9709 struct vec3 position;
9710 D3DCOLOR diffuse;
9712 quad[] =
9714 {{-1.0f, -1.0f, -0.5f}, 0xffff0000},
9715 {{-1.0f, 1.0f, -0.5f}, 0xffff0000},
9716 {{ 1.0f, -1.0f, -0.5f}, 0xffff0000},
9717 {{ 1.0f, 1.0f, -0.5f}, 0xffff0000},
9719 static struct
9721 struct vec4 position;
9722 D3DCOLOR diffuse;
9724 tquad[] =
9726 {{ 0.0f, 0.0f, -0.5f, 1.0f}, 0xffff0000},
9727 {{640.0f, 0.0f, -0.5f, 1.0f}, 0xffff0000},
9728 {{ 0.0f, 480.0f, -0.5f, 1.0f}, 0xffff0000},
9729 {{640.0f, 480.0f, -0.5f, 1.0f}, 0xffff0000},
9731 unsigned int i;
9732 static D3DMATRIX zero =
9734 1.0f, 0.0f, 0.0f, 0.0f,
9735 0.0f, 1.0f, 0.0f, 0.0f,
9736 0.0f, 0.0f, 0.0f, 0.0f,
9737 0.0f, 0.0f, 0.0f, 1.0f
9739 static D3DMATRIX identity =
9741 1.0f, 0.0f, 0.0f, 0.0f,
9742 0.0f, 1.0f, 0.0f, 0.0f,
9743 0.0f, 0.0f, 1.0f, 0.0f,
9744 0.0f, 0.0f, 0.0f, 1.0f
9746 static const struct
9748 DWORD pos_type;
9749 void *quad;
9750 D3DMATRIX *matrix;
9751 union
9753 float f;
9754 DWORD d;
9755 } start, end;
9756 D3DFOGMODE vfog, tfog;
9757 DWORD color, color_broken, color_broken2;
9759 tests[] =
9761 /* Run the XYZRHW tests first. Depth clamping is broken after RHW draws on the testbot.
9763 * Geforce8+ GPUs on Windows abs() table fog, everything else does not. */
9764 {D3DFVF_XYZRHW, tquad, &identity, { 0.0f}, {1.0f}, D3DFOG_NONE, D3DFOG_LINEAR,
9765 0x00ff0000, 0x00808000, 0x00808000},
9766 /* r200 GPUs and presumably all d3d8 and older HW clamp the fog
9767 * parameters to 0.0 and 1.0 in the table fog case. */
9768 {D3DFVF_XYZRHW, tquad, &identity, {-1.0f}, {0.0f}, D3DFOG_NONE, D3DFOG_LINEAR,
9769 0x00808000, 0x00ff0000, 0x0000ff00},
9770 /* test_fog_interpolation shows that vertex fog evaluates the fog
9771 * equation in the vertex pipeline. Start = -1.0 && end = 0.0 shows
9772 * that the abs happens before the fog equation is evaluated.
9774 * Vertex fog abs() behavior is the same on all GPUs. */
9775 {D3DFVF_XYZ, quad, &zero, { 0.0f}, {1.0f}, D3DFOG_LINEAR, D3DFOG_NONE,
9776 0x00808000, 0x00808000, 0x00808000},
9777 {D3DFVF_XYZ, quad, &zero, {-1.0f}, {0.0f}, D3DFOG_LINEAR, D3DFOG_NONE,
9778 0x0000ff00, 0x0000ff00, 0x0000ff00},
9779 {D3DFVF_XYZ, quad, &zero, { 0.0f}, {1.0f}, D3DFOG_EXP, D3DFOG_NONE,
9780 0x009b6400, 0x009b6400, 0x009b6400},
9782 D3DDEVICEDESC7 caps;
9784 window = create_window();
9785 if (!(device = create_device(window, DDSCL_NORMAL)))
9787 skip("Failed to create a 3D device, skipping test.\n");
9788 DestroyWindow(window);
9789 return;
9792 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
9793 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9794 hr = IDirect3DDevice7_GetCaps(device, &caps);
9795 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
9796 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE))
9797 skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping some fog tests.\n");
9799 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
9800 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9801 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
9802 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9803 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
9804 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9805 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x0000ff00);
9806 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9807 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
9808 ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
9810 for (i = 0; i < ARRAY_SIZE(tests); ++i)
9812 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE) && tests[i].tfog)
9813 continue;
9815 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0);
9816 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
9818 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, tests[i].matrix);
9819 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
9820 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGSTART, tests[i].start.d);
9821 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9822 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGEND, tests[i].end.d);
9823 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9824 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, tests[i].vfog);
9825 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9826 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, tests[i].tfog);
9827 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9829 hr = IDirect3DDevice7_BeginScene(device);
9830 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9831 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9832 tests[i].pos_type | D3DFVF_DIFFUSE, tests[i].quad, 4, 0);
9833 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9834 hr = IDirect3DDevice7_EndScene(device);
9835 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9837 color = get_surface_color(rt, 0, 240);
9838 ok(compare_color(color, tests[i].color, 2) || broken(compare_color(color, tests[i].color_broken, 2))
9839 || broken(compare_color(color, tests[i].color_broken2, 2)),
9840 "Got unexpected color 0x%08x, case %u.\n", color, i);
9843 IDirectDrawSurface7_Release(rt);
9844 refcount = IDirect3DDevice7_Release(device);
9845 ok(!refcount, "Device has %u references left.\n", refcount);
9846 DestroyWindow(window);
9849 static void test_table_fog_zw(void)
9851 HRESULT hr;
9852 IDirect3DDevice7 *device;
9853 IDirectDrawSurface7 *rt;
9854 ULONG refcount;
9855 HWND window;
9856 D3DCOLOR color;
9857 static struct
9859 struct vec4 position;
9860 D3DCOLOR diffuse;
9862 quad[] =
9864 {{ 0.0f, 0.0f, 0.0f, 0.0f}, 0xffff0000},
9865 {{640.0f, 0.0f, 0.0f, 0.0f}, 0xffff0000},
9866 {{ 0.0f, 480.0f, 0.0f, 0.0f}, 0xffff0000},
9867 {{640.0f, 480.0f, 0.0f, 0.0f}, 0xffff0000},
9869 static D3DMATRIX identity =
9871 1.0f, 0.0f, 0.0f, 0.0f,
9872 0.0f, 1.0f, 0.0f, 0.0f,
9873 0.0f, 0.0f, 1.0f, 0.0f,
9874 0.0f, 0.0f, 0.0f, 1.0f
9876 D3DDEVICEDESC7 caps;
9877 static const struct
9879 float z, w;
9880 D3DZBUFFERTYPE z_test;
9881 D3DCOLOR color;
9883 tests[] =
9885 {0.7f, 0.0f, D3DZB_TRUE, 0x004cb200},
9886 {0.7f, 0.0f, D3DZB_FALSE, 0x004cb200},
9887 {0.7f, 0.3f, D3DZB_TRUE, 0x004cb200},
9888 {0.7f, 0.3f, D3DZB_FALSE, 0x004cb200},
9889 {0.7f, 3.0f, D3DZB_TRUE, 0x004cb200},
9890 {0.7f, 3.0f, D3DZB_FALSE, 0x004cb200},
9891 {0.3f, 0.0f, D3DZB_TRUE, 0x00b24c00},
9892 {0.3f, 0.0f, D3DZB_FALSE, 0x00b24c00},
9894 unsigned int i;
9896 window = create_window();
9897 if (!(device = create_device(window, DDSCL_NORMAL)))
9899 skip("Failed to create a 3D device, skipping test.\n");
9900 DestroyWindow(window);
9901 return;
9904 hr = IDirect3DDevice7_GetCaps(device, &caps);
9905 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
9906 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE))
9908 skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping POSITIONT table fog test.\n");
9909 goto done;
9911 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
9912 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9914 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
9915 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9916 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
9917 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9918 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x0000ff00);
9919 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9920 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
9921 ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
9922 /* Work around an AMD Windows driver bug. Needs a proj matrix applied redundantly. */
9923 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &identity);
9924 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
9925 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_LINEAR);
9926 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9928 for (i = 0; i < ARRAY_SIZE(tests); ++i)
9930 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x000000ff, 1.0f, 0);
9931 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
9933 quad[0].position.z = tests[i].z;
9934 quad[1].position.z = tests[i].z;
9935 quad[2].position.z = tests[i].z;
9936 quad[3].position.z = tests[i].z;
9937 quad[0].position.w = tests[i].w;
9938 quad[1].position.w = tests[i].w;
9939 quad[2].position.w = tests[i].w;
9940 quad[3].position.w = tests[i].w;
9941 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, tests[i].z_test);
9942 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9944 hr = IDirect3DDevice7_BeginScene(device);
9945 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9946 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9947 D3DFVF_XYZRHW | D3DFVF_DIFFUSE, quad, 4, 0);
9948 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9949 hr = IDirect3DDevice7_EndScene(device);
9950 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9952 color = get_surface_color(rt, 0, 240);
9953 ok(compare_color(color, tests[i].color, 2),
9954 "Got unexpected color 0x%08x, expected 0x%8x, case %u.\n", color, tests[i].color, i);
9957 IDirectDrawSurface7_Release(rt);
9958 done:
9959 refcount = IDirect3DDevice7_Release(device);
9960 ok(!refcount, "Device has %u references left.\n", refcount);
9961 DestroyWindow(window);
9964 static void test_signed_formats(void)
9966 HRESULT hr;
9967 IDirect3DDevice7 *device;
9968 IDirect3D7 *d3d;
9969 IDirectDraw7 *ddraw;
9970 IDirectDrawSurface7 *surface, *rt;
9971 DDSURFACEDESC2 surface_desc;
9972 ULONG refcount;
9973 HWND window;
9974 D3DCOLOR color, expected_color;
9975 static struct
9977 struct vec3 position;
9978 struct vec2 texcoord;
9980 quad[] =
9982 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
9983 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
9984 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
9985 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
9987 /* See test_signed_formats() in dlls/d3d9/tests/visual.c for an explanation
9988 * of these values. */
9989 static const USHORT content_v8u8[4][4] =
9991 {0x0000, 0x7f7f, 0x8880, 0x0000},
9992 {0x0080, 0x8000, 0x7f00, 0x007f},
9993 {0x193b, 0xe8c8, 0x0808, 0xf8f8},
9994 {0x4444, 0xc0c0, 0xa066, 0x22e0},
9996 static const DWORD content_x8l8v8u8[4][4] =
9998 {0x00000000, 0x00ff7f7f, 0x00008880, 0x00ff0000},
9999 {0x00000080, 0x00008000, 0x00007f00, 0x0000007f},
10000 {0x0041193b, 0x0051e8c8, 0x00040808, 0x00fff8f8},
10001 {0x00824444, 0x0000c0c0, 0x00c2a066, 0x009222e0},
10003 static const USHORT content_l6v5u5[4][4] =
10005 {0x0000, 0xfdef, 0x0230, 0xfc00},
10006 {0x0010, 0x0200, 0x01e0, 0x000f},
10007 {0x4067, 0x53b9, 0x0421, 0xffff},
10008 {0x8108, 0x0318, 0xc28c, 0x909c},
10010 static const struct
10012 const char *name;
10013 const void *content;
10014 SIZE_T pixel_size;
10015 BOOL blue;
10016 unsigned int slop, slop_broken;
10017 DDPIXELFORMAT format;
10019 formats[] =
10022 "D3DFMT_V8U8", content_v8u8, sizeof(WORD), FALSE, 1, 0,
10024 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV, 0,
10025 {16}, {0x000000ff}, {0x0000ff00}, {0x00000000}, {0x00000000}
10029 "D3DFMT_X8L8V8U8", content_x8l8v8u8, sizeof(DWORD), TRUE, 1, 0,
10031 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE, 0,
10032 {32}, {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}
10036 "D3DFMT_L6V5U5", content_l6v5u5, sizeof(WORD), TRUE, 4, 7,
10038 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE, 0,
10039 {16}, {0x0000001f}, {0x000003e0}, {0x0000fc00}, {0x00000000}
10043 /* No V16U16 or Q8W8V8U8 support in ddraw. */
10045 static const D3DCOLOR expected_colors[4][4] =
10047 {0x00808080, 0x00fefeff, 0x00010780, 0x008080ff},
10048 {0x00018080, 0x00800180, 0x0080fe80, 0x00fe8080},
10049 {0x00ba98a0, 0x004767a8, 0x00888881, 0x007878ff},
10050 {0x00c3c3c0, 0x003f3f80, 0x00e51fe1, 0x005fa2c8},
10052 unsigned int i, width, x, y;
10053 D3DDEVICEDESC7 device_desc;
10055 window = create_window();
10056 if (!(device = create_device(window, DDSCL_NORMAL)))
10058 skip("Failed to create a 3D device, skipping test.\n");
10059 DestroyWindow(window);
10060 return;
10063 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
10064 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10065 if (!(device_desc.dwTextureOpCaps & D3DTEXOPCAPS_BLENDFACTORALPHA))
10067 skip("D3DTOP_BLENDFACTORALPHA not supported, skipping bumpmap format tests.\n");
10068 goto done;
10071 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
10072 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
10073 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
10074 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
10075 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
10076 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10078 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
10079 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10081 /* dst = tex * 0.5 + 1.0 * (1.0 - 0.5) = tex * 0.5 + 0.5 */
10082 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x80ffffff);
10083 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10084 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_BLENDFACTORALPHA);
10085 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
10086 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
10087 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
10088 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
10089 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
10091 for (i = 0; i < ARRAY_SIZE(formats); ++i)
10093 for (width = 1; width < 5; width += 3)
10095 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
10096 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
10098 memset(&surface_desc, 0, sizeof(surface_desc));
10099 surface_desc.dwSize = sizeof(surface_desc);
10100 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
10101 surface_desc.dwWidth = width;
10102 surface_desc.dwHeight = 4;
10103 U4(surface_desc).ddpfPixelFormat = formats[i].format;
10104 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
10105 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10106 if (FAILED(hr))
10108 skip("%s textures not supported, skipping.\n", formats[i].name);
10109 continue;
10111 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, format %s.\n", hr, formats[i].name);
10112 hr = IDirect3DDevice7_SetTexture(device, 0, surface);
10113 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x, format %s.\n", hr, formats[i].name);
10115 memset(&surface_desc, 0, sizeof(surface_desc));
10116 surface_desc.dwSize = sizeof(surface_desc);
10117 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, 0, NULL);
10118 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, format %s.\n", hr, formats[i].name);
10119 for (y = 0; y < 4; y++)
10121 memcpy((char *)surface_desc.lpSurface + y * U1(surface_desc).lPitch,
10122 (char *)formats[i].content + y * 4 * formats[i].pixel_size,
10123 width * formats[i].pixel_size);
10125 hr = IDirectDrawSurface7_Unlock(surface, NULL);
10126 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, format %s.\n", hr, formats[i].name);
10128 hr = IDirect3DDevice7_BeginScene(device);
10129 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10130 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
10131 D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
10132 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10133 hr = IDirect3DDevice7_EndScene(device);
10134 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10136 for (y = 0; y < 4; y++)
10138 for (x = 0; x < width; x++)
10140 expected_color = expected_colors[y][x];
10141 if (!formats[i].blue)
10142 expected_color |= 0x000000ff;
10144 color = get_surface_color(rt, 80 + 160 * x, 60 + 120 * y);
10145 ok(compare_color(color, expected_color, formats[i].slop)
10146 || broken(compare_color(color, expected_color, formats[i].slop_broken)),
10147 "Expected color 0x%08x, got 0x%08x, format %s, location %ux%u.\n",
10148 expected_color, color, formats[i].name, x, y);
10152 IDirectDrawSurface7_Release(surface);
10157 IDirectDrawSurface7_Release(rt);
10158 IDirectDraw7_Release(ddraw);
10159 IDirect3D7_Release(d3d);
10161 done:
10162 refcount = IDirect3DDevice7_Release(device);
10163 ok(!refcount, "Device has %u references left.\n", refcount);
10164 DestroyWindow(window);
10167 static void test_color_fill(void)
10169 HRESULT hr;
10170 IDirect3DDevice7 *device;
10171 IDirect3D7 *d3d;
10172 IDirectDraw7 *ddraw;
10173 IDirectDrawSurface7 *surface, *surface2;
10174 DDSURFACEDESC2 surface_desc;
10175 DDPIXELFORMAT z_fmt;
10176 ULONG refcount;
10177 HWND window;
10178 unsigned int i;
10179 DDBLTFX fx;
10180 RECT rect = {5, 5, 7, 7};
10181 DWORD *color;
10182 DWORD supported_fmts = 0, num_fourcc_codes, *fourcc_codes;
10183 DDCAPS hal_caps;
10184 static const struct
10186 DWORD caps, caps2;
10187 HRESULT colorfill_hr, depthfill_hr;
10188 BOOL rop_success;
10189 const char *name;
10190 DWORD result;
10191 BOOL check_result;
10192 DDPIXELFORMAT format;
10194 tests[] =
10197 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
10198 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain RGB", 0xdeadbeef, TRUE,
10200 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
10201 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
10205 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0,
10206 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain RGB", 0xdeadbeef, TRUE,
10208 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
10209 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
10213 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0,
10214 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem texture RGB", 0xdeadbeef, TRUE,
10216 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
10217 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
10221 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0,
10222 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem texture RGB", 0xdeadbeef, TRUE,
10224 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
10225 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
10229 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
10230 DD_OK, DDERR_INVALIDPARAMS, TRUE, "managed texture RGB", 0xdeadbeef, TRUE,
10232 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
10233 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
10237 DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY, 0,
10238 DDERR_INVALIDPARAMS, DD_OK, TRUE, "vidmem zbuffer", 0xdeadbeef, TRUE,
10239 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
10242 DDSCAPS_ZBUFFER | DDSCAPS_SYSTEMMEMORY, 0,
10243 DDERR_INVALIDPARAMS, DD_OK, TRUE, "sysmem zbuffer", 0xdeadbeef, TRUE,
10244 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
10247 /* Colorfill on YUV surfaces always returns DD_OK, but the content is
10248 * different afterwards. DX9+ GPUs set one of the two luminance values
10249 * in each block, but AMD and Nvidia GPUs disagree on which luminance
10250 * value they set. r200 (dx8) just sets the entire block to the clear
10251 * value. */
10252 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
10253 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain YUY2", 0, FALSE,
10255 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
10256 {0}, {0}, {0}, {0}, {0}
10260 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
10261 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain UYVY", 0, FALSE,
10263 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
10264 {0}, {0}, {0}, {0}, {0}
10268 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY, 0,
10269 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay YUY2", 0, FALSE,
10271 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
10272 {0}, {0}, {0}, {0}, {0}
10276 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY, 0,
10277 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay UYVY", 0, FALSE,
10279 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
10280 {0}, {0}, {0}, {0}, {0}
10284 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0,
10285 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "vidmem texture DXT1", 0, FALSE,
10287 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
10288 {0}, {0}, {0}, {0}, {0}
10292 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0,
10293 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "sysmem texture DXT1", 0, FALSE,
10295 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
10296 {0}, {0}, {0}, {0}, {0}
10300 /* The testbot fills this with 0x00 instead of the blue channel. The sysmem
10301 * surface works, presumably because it is handled by the runtime instead of
10302 * the driver. */
10303 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
10304 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain P8", 0xefefefef, FALSE,
10306 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
10307 {8}, {0}, {0}, {0}, {0}
10311 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0,
10312 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain P8", 0xefefefef, TRUE,
10314 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
10315 {8}, {0}, {0}, {0}, {0}
10319 static const struct
10321 DWORD rop;
10322 const char *name;
10323 HRESULT hr;
10325 rops[] =
10327 {SRCCOPY, "SRCCOPY", DD_OK},
10328 {SRCPAINT, "SRCPAINT", DDERR_NORASTEROPHW},
10329 {SRCAND, "SRCAND", DDERR_NORASTEROPHW},
10330 {SRCINVERT, "SRCINVERT", DDERR_NORASTEROPHW},
10331 {SRCERASE, "SRCERASE", DDERR_NORASTEROPHW},
10332 {NOTSRCCOPY, "NOTSRCCOPY", DDERR_NORASTEROPHW},
10333 {NOTSRCERASE, "NOTSRCERASE", DDERR_NORASTEROPHW},
10334 {MERGECOPY, "MERGECOPY", DDERR_NORASTEROPHW},
10335 {MERGEPAINT, "MERGEPAINT", DDERR_NORASTEROPHW},
10336 {PATCOPY, "PATCOPY", DDERR_NORASTEROPHW},
10337 {PATPAINT, "PATPAINT", DDERR_NORASTEROPHW},
10338 {PATINVERT, "PATINVERT", DDERR_NORASTEROPHW},
10339 {DSTINVERT, "DSTINVERT", DDERR_NORASTEROPHW},
10340 {BLACKNESS, "BLACKNESS", DD_OK},
10341 {WHITENESS, "WHITENESS", DD_OK},
10342 {0xaa0029, "0xaa0029", DDERR_NORASTEROPHW} /* noop */
10345 window = create_window();
10346 if (!(device = create_device(window, DDSCL_NORMAL)))
10348 skip("Failed to create a 3D device, skipping test.\n");
10349 DestroyWindow(window);
10350 return;
10353 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
10354 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
10355 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
10356 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
10358 memset(&z_fmt, 0, sizeof(z_fmt));
10359 IDirect3D7_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
10360 if (!z_fmt.dwSize)
10361 skip("No Z buffer formats supported, skipping Z buffer colorfill test.\n");
10363 IDirect3DDevice7_EnumTextureFormats(device, test_block_formats_creation_cb, &supported_fmts);
10364 if (!(supported_fmts & SUPPORT_DXT1))
10365 skip("DXT1 textures not supported, skipping DXT1 colorfill test.\n");
10367 IDirect3D7_Release(d3d);
10369 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
10370 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
10371 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
10372 num_fourcc_codes * sizeof(*fourcc_codes));
10373 if (!fourcc_codes)
10374 goto done;
10375 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
10376 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
10377 for (i = 0; i < num_fourcc_codes; i++)
10379 if (fourcc_codes[i] == MAKEFOURCC('Y', 'U', 'Y', '2'))
10380 supported_fmts |= SUPPORT_YUY2;
10381 else if (fourcc_codes[i] == MAKEFOURCC('U', 'Y', 'V', 'Y'))
10382 supported_fmts |= SUPPORT_UYVY;
10384 HeapFree(GetProcessHeap(), 0, fourcc_codes);
10386 memset(&hal_caps, 0, sizeof(hal_caps));
10387 hal_caps.dwSize = sizeof(hal_caps);
10388 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
10389 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
10391 if (!(supported_fmts & (SUPPORT_YUY2 | SUPPORT_UYVY)) || !(hal_caps.dwCaps & DDCAPS_OVERLAY))
10392 skip("Overlays or some YUV formats not supported, skipping YUV colorfill tests.\n");
10394 for (i = 0; i < ARRAY_SIZE(tests); ++i)
10396 DWORD expected_broken = tests[i].result;
10398 /* Some Windows drivers modify dwFillColor when it is used on P8 or FourCC formats. */
10399 memset(&fx, 0, sizeof(fx));
10400 fx.dwSize = sizeof(fx);
10401 U5(fx).dwFillColor = 0xdeadbeef;
10403 memset(&surface_desc, 0, sizeof(surface_desc));
10404 surface_desc.dwSize = sizeof(surface_desc);
10405 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10406 surface_desc.dwWidth = 64;
10407 surface_desc.dwHeight = 64;
10408 U4(surface_desc).ddpfPixelFormat = tests[i].format;
10409 surface_desc.ddsCaps.dwCaps = tests[i].caps;
10410 surface_desc.ddsCaps.dwCaps2 = tests[i].caps2;
10412 if (tests[i].format.dwFourCC == MAKEFOURCC('D','X','T','1') && !(supported_fmts & SUPPORT_DXT1))
10413 continue;
10414 if (tests[i].format.dwFourCC == MAKEFOURCC('Y','U','Y','2') && !(supported_fmts & SUPPORT_YUY2))
10415 continue;
10416 if (tests[i].format.dwFourCC == MAKEFOURCC('U','Y','V','Y') && !(supported_fmts & SUPPORT_UYVY))
10417 continue;
10418 if (tests[i].caps & DDSCAPS_OVERLAY && !(hal_caps.dwCaps & DDCAPS_OVERLAY))
10419 continue;
10421 if (tests[i].caps & DDSCAPS_ZBUFFER)
10423 if (!z_fmt.dwSize)
10424 continue;
10426 U4(surface_desc).ddpfPixelFormat = z_fmt;
10427 /* Some drivers seem to convert depth values incorrectly or not at
10428 * all. Affects at least AMD PALM, 8.17.10.1247. */
10429 if (tests[i].caps & DDSCAPS_VIDEOMEMORY)
10431 DWORD expected;
10432 float f, g;
10434 expected = tests[i].result & U3(z_fmt).dwZBitMask;
10435 f = ceilf(log2f(expected + 1.0f));
10436 g = (f + 1.0f) / 2.0f;
10437 g -= (int)g;
10438 expected_broken = (expected / exp2f(f) - g) * 256;
10439 expected_broken *= 0x01010101;
10443 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10444 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, surface %s.\n", hr, tests[i].name);
10446 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10447 todo_wine_if (tests[i].format.dwFourCC)
10448 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
10449 hr, tests[i].colorfill_hr, tests[i].name);
10451 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10452 todo_wine_if (tests[i].format.dwFourCC)
10453 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
10454 hr, tests[i].colorfill_hr, tests[i].name);
10456 if (SUCCEEDED(hr) && tests[i].check_result)
10458 memset(&surface_desc, 0, sizeof(surface_desc));
10459 surface_desc.dwSize = sizeof(surface_desc);
10460 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
10461 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10462 color = surface_desc.lpSurface;
10463 ok(*color == tests[i].result, "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
10464 *color, tests[i].result, tests[i].name);
10465 hr = IDirectDrawSurface7_Unlock(surface, NULL);
10466 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10469 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10470 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
10471 hr, tests[i].depthfill_hr, tests[i].name);
10472 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10473 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
10474 hr, tests[i].depthfill_hr, tests[i].name);
10476 if (SUCCEEDED(hr) && tests[i].check_result)
10478 memset(&surface_desc, 0, sizeof(surface_desc));
10479 surface_desc.dwSize = sizeof(surface_desc);
10480 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
10481 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10482 color = surface_desc.lpSurface;
10483 ok((*color & U3(z_fmt).dwZBitMask) == (tests[i].result & U3(z_fmt).dwZBitMask)
10484 || broken((*color & U3(z_fmt).dwZBitMask) == (expected_broken & U3(z_fmt).dwZBitMask)),
10485 "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
10486 *color & U3(z_fmt).dwZBitMask, tests[i].result & U3(z_fmt).dwZBitMask, tests[i].name);
10487 hr = IDirectDrawSurface7_Unlock(surface, NULL);
10488 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10491 U5(fx).dwFillColor = 0xdeadbeef;
10492 fx.dwROP = BLACKNESS;
10493 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
10494 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
10495 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
10496 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
10497 U5(fx).dwFillColor, tests[i].name);
10499 if (SUCCEEDED(hr) && tests[i].check_result)
10501 memset(&surface_desc, 0, sizeof(surface_desc));
10502 surface_desc.dwSize = sizeof(surface_desc);
10503 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
10504 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10505 color = surface_desc.lpSurface;
10506 ok(*color == 0, "Got clear result 0x%08x, expected 0x00000000, surface %s.\n",
10507 *color, tests[i].name);
10508 hr = IDirectDrawSurface7_Unlock(surface, NULL);
10509 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10512 fx.dwROP = WHITENESS;
10513 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
10514 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
10515 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
10516 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
10517 U5(fx).dwFillColor, tests[i].name);
10519 if (SUCCEEDED(hr) && tests[i].check_result)
10521 memset(&surface_desc, 0, sizeof(surface_desc));
10522 surface_desc.dwSize = sizeof(surface_desc);
10523 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
10524 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10525 color = surface_desc.lpSurface;
10526 /* WHITENESS sets the alpha channel to 0x00. Ignore this for now. */
10527 ok((*color & 0x00ffffff) == 0x00ffffff, "Got clear result 0x%08x, expected 0xffffffff, surface %s.\n",
10528 *color, tests[i].name);
10529 hr = IDirectDrawSurface7_Unlock(surface, NULL);
10530 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10533 IDirectDrawSurface7_Release(surface);
10536 memset(&fx, 0, sizeof(fx));
10537 fx.dwSize = sizeof(fx);
10538 U5(fx).dwFillColor = 0xdeadbeef;
10539 fx.dwROP = WHITENESS;
10541 memset(&surface_desc, 0, sizeof(surface_desc));
10542 surface_desc.dwSize = sizeof(surface_desc);
10543 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10544 surface_desc.dwWidth = 64;
10545 surface_desc.dwHeight = 64;
10546 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
10547 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
10548 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
10549 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
10550 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
10551 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
10552 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
10553 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10554 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10555 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
10556 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10558 /* No DDBLTFX. */
10559 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, NULL);
10560 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10561 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, NULL);
10562 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10564 /* Unused source rectangle. */
10565 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10566 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10567 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10568 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10570 /* Unused source surface. */
10571 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10572 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10573 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
10574 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10575 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10576 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10577 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10578 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10580 /* Inverted destination or source rectangle. */
10581 SetRect(&rect, 5, 7, 7, 5);
10582 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10583 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10584 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10585 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10586 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10587 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10588 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10589 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10590 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10591 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10593 /* Negative rectangle. */
10594 SetRect(&rect, -1, -1, 5, 5);
10595 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10596 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10597 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10598 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10599 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10600 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10601 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10602 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10603 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10604 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10606 /* Out of bounds rectangle. */
10607 SetRect(&rect, 0, 0, 65, 65);
10608 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10609 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10610 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10611 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10613 /* Combine multiple flags. */
10614 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10615 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10616 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
10617 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10618 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
10619 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10621 for (i = 0; i < ARRAY_SIZE(rops); ++i)
10623 fx.dwROP = rops[i].rop;
10624 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
10625 ok(hr == rops[i].hr, "Got unexpected hr %#x for rop %s.\n", hr, rops[i].name);
10628 IDirectDrawSurface7_Release(surface2);
10629 IDirectDrawSurface7_Release(surface);
10631 if (!z_fmt.dwSize)
10632 goto done;
10634 memset(&surface_desc, 0, sizeof(surface_desc));
10635 surface_desc.dwSize = sizeof(surface_desc);
10636 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10637 surface_desc.dwWidth = 64;
10638 surface_desc.dwHeight = 64;
10639 U4(surface_desc).ddpfPixelFormat = z_fmt;
10640 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
10641 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10642 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10643 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
10644 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10646 /* No DDBLTFX. */
10647 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, NULL);
10648 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10650 /* Unused source rectangle. */
10651 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10652 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10654 /* Unused source surface. */
10655 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10656 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10657 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10658 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10660 /* Inverted destination or source rectangle. */
10661 SetRect(&rect, 5, 7, 7, 5);
10662 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10663 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10664 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10665 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10666 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10667 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10668 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10669 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10671 /* Negative rectangle. */
10672 SetRect(&rect, -1, -1, 5, 5);
10673 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10674 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10675 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10676 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10677 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10678 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10679 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10680 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10682 /* Out of bounds rectangle. */
10683 SetRect(&rect, 0, 0, 65, 65);
10684 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10685 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10687 /* Combine multiple flags. */
10688 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10689 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10691 IDirectDrawSurface7_Release(surface2);
10692 IDirectDrawSurface7_Release(surface);
10694 done:
10695 IDirectDraw7_Release(ddraw);
10696 refcount = IDirect3DDevice7_Release(device);
10697 ok(!refcount, "Device has %u references left.\n", refcount);
10698 DestroyWindow(window);
10701 static void test_texcoordindex(void)
10703 static D3DMATRIX mat =
10705 1.0f, 0.0f, 0.0f, 0.0f,
10706 0.0f, 0.0f, 0.0f, 0.0f,
10707 0.0f, 0.0f, 0.0f, 0.0f,
10708 0.0f, 0.0f, 0.0f, 0.0f,
10710 static struct
10712 struct vec3 pos;
10713 struct vec2 texcoord1;
10714 struct vec2 texcoord2;
10715 struct vec2 texcoord3;
10717 quad[] =
10719 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f}},
10720 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 0.0f}},
10721 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}},
10722 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}},
10724 static const DWORD fvf = D3DFVF_XYZ | D3DFVF_TEX3;
10725 IDirect3DDevice7 *device;
10726 IDirect3D7 *d3d;
10727 IDirectDraw7 *ddraw;
10728 IDirectDrawSurface7 *rt;
10729 HWND window;
10730 HRESULT hr;
10731 IDirectDrawSurface7 *texture1, *texture2;
10732 DDSURFACEDESC2 surface_desc;
10733 ULONG refcount;
10734 D3DCOLOR color;
10735 DWORD *ptr;
10737 window = create_window();
10738 if (!(device = create_device(window, DDSCL_NORMAL)))
10740 skip("Failed to create a 3D device, skipping test.\n");
10741 DestroyWindow(window);
10742 return;
10745 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
10746 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
10747 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
10748 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
10749 IDirect3D7_Release(d3d);
10751 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
10752 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10754 memset(&surface_desc, 0, sizeof(surface_desc));
10755 surface_desc.dwSize = sizeof(surface_desc);
10756 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10757 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
10758 surface_desc.dwWidth = 2;
10759 surface_desc.dwHeight = 2;
10760 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
10761 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
10762 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
10763 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
10764 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
10765 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
10766 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
10767 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture1, NULL);
10768 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10769 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture2, NULL);
10770 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10772 memset(&surface_desc, 0, sizeof(surface_desc));
10773 surface_desc.dwSize = sizeof(surface_desc);
10774 hr = IDirectDrawSurface7_Lock(texture1, 0, &surface_desc, 0, NULL);
10775 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10776 ptr = surface_desc.lpSurface;
10777 ptr[0] = 0xff000000;
10778 ptr[1] = 0xff00ff00;
10779 ptr += U1(surface_desc).lPitch / sizeof(*ptr);
10780 ptr[0] = 0xff0000ff;
10781 ptr[1] = 0xff00ffff;
10782 hr = IDirectDrawSurface7_Unlock(texture1, NULL);
10783 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10785 memset(&surface_desc, 0, sizeof(surface_desc));
10786 surface_desc.dwSize = sizeof(surface_desc);
10787 hr = IDirectDrawSurface7_Lock(texture2, 0, &surface_desc, 0, NULL);
10788 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10789 ptr = surface_desc.lpSurface;
10790 ptr[0] = 0xff000000;
10791 ptr[1] = 0xff0000ff;
10792 ptr += U1(surface_desc).lPitch / sizeof(*ptr);
10793 ptr[0] = 0xffff0000;
10794 ptr[1] = 0xffff00ff;
10795 hr = IDirectDrawSurface7_Unlock(texture2, 0);
10796 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10798 hr = IDirect3DDevice7_SetTexture(device, 0, texture1);
10799 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
10800 hr = IDirect3DDevice7_SetTexture(device, 1, texture2);
10801 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
10802 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
10803 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
10804 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
10805 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
10806 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
10807 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10808 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_ADD);
10809 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
10810 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
10811 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10812 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
10813 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10814 hr = IDirect3DDevice7_SetTextureStageState(device, 2, D3DTSS_COLOROP, D3DTOP_DISABLE);
10815 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
10817 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_TEXCOORDINDEX, 1);
10818 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
10819 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXCOORDINDEX, 0);
10820 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
10822 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
10823 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
10825 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
10826 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10828 hr = IDirect3DDevice7_BeginScene(device);
10829 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10830 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
10831 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10832 hr = IDirect3DDevice7_EndScene(device);
10833 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10835 color = get_surface_color(rt, 160, 120);
10836 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
10837 color = get_surface_color(rt, 480, 120);
10838 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
10839 color = get_surface_color(rt, 160, 360);
10840 ok(compare_color(color, 0x00ff0000, 2), "Got unexpected color 0x%08x.\n", color);
10841 color = get_surface_color(rt, 480, 360);
10842 ok(compare_color(color, 0x00ffffff, 2), "Got unexpected color 0x%08x.\n", color);
10844 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
10845 ok(SUCCEEDED(hr), "Failed to set texture transform flags, hr %#x.\n", hr);
10846 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_TEXTURE1, &mat);
10847 ok(SUCCEEDED(hr), "Failed to set transformation matrix, hr %#x.\n", hr);
10849 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
10850 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10852 hr = IDirect3DDevice7_BeginScene(device);
10853 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10854 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
10855 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10856 hr = IDirect3DDevice7_EndScene(device);
10857 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10859 color = get_surface_color(rt, 160, 120);
10860 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
10861 color = get_surface_color(rt, 480, 120);
10862 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
10863 color = get_surface_color(rt, 160, 360);
10864 ok(compare_color(color, 0x00000000, 2), "Got unexpected color 0x%08x.\n", color);
10865 color = get_surface_color(rt, 480, 360);
10866 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
10868 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
10869 ok(SUCCEEDED(hr), "Failed to set texture transform flags, hr %#x.\n", hr);
10870 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXCOORDINDEX, 2);
10871 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
10873 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
10874 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10876 hr = IDirect3DDevice7_BeginScene(device);
10877 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10878 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
10879 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10880 hr = IDirect3DDevice7_EndScene(device);
10881 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10883 color = get_surface_color(rt, 160, 120);
10884 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
10885 color = get_surface_color(rt, 480, 120);
10886 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
10887 color = get_surface_color(rt, 160, 360);
10888 ok(compare_color(color, 0x00ff00ff, 2), "Got unexpected color 0x%08x.\n", color);
10889 color = get_surface_color(rt, 480, 360);
10890 ok(compare_color(color, 0x00ffff00, 2), "Got unexpected color 0x%08x.\n", color);
10892 IDirectDrawSurface7_Release(texture1);
10893 IDirectDrawSurface7_Release(texture2);
10895 IDirectDrawSurface7_Release(rt);
10896 IDirectDraw_Release(ddraw);
10897 refcount = IDirect3DDevice7_Release(device);
10898 ok(!refcount, "Device has %u references left.\n", refcount);
10899 DestroyWindow(window);
10902 static void test_colorkey_precision(void)
10904 static struct
10906 struct vec3 pos;
10907 struct vec2 texcoord;
10909 quad[] =
10911 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
10912 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
10913 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
10914 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
10916 IDirect3DDevice7 *device;
10917 IDirect3D7 *d3d;
10918 IDirectDraw7 *ddraw;
10919 IDirectDrawSurface7 *rt;
10920 HWND window;
10921 HRESULT hr;
10922 IDirectDrawSurface7 *src, *dst, *texture;
10923 DDSURFACEDESC2 surface_desc, lock_desc;
10924 ULONG refcount;
10925 D3DCOLOR color;
10926 unsigned int t, c;
10927 DDCOLORKEY ckey;
10928 DDBLTFX fx;
10929 DWORD data[4] = {0}, color_mask;
10930 BOOL is_nvidia, is_warp;
10931 static const struct
10933 unsigned int max, shift, bpp, clear;
10934 const char *name;
10935 BOOL skip_nv;
10936 DDPIXELFORMAT fmt;
10938 tests[] =
10941 255, 0, 4, 0x00345678, "D3DFMT_X8R8G8B8", FALSE,
10943 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
10944 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
10949 63, 5, 2, 0x5678, "D3DFMT_R5G6B5, G channel", FALSE,
10951 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
10952 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
10957 31, 0, 2, 0x5678, "D3DFMT_R5G6B5, B channel", FALSE,
10959 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
10960 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
10965 15, 0, 2, 0x0678, "D3DFMT_A4R4G4B4", TRUE,
10967 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
10968 {16}, {0x0f00}, {0x00f0}, {0x000f}, {0xf000}
10973 window = create_window();
10974 if (!(device = create_device(window, DDSCL_NORMAL)))
10976 skip("Failed to create a 3D device, skipping test.\n");
10977 DestroyWindow(window);
10978 return;
10981 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
10982 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
10983 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
10984 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
10985 IDirect3D7_Release(d3d);
10986 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
10987 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10989 is_nvidia = ddraw_is_nvidia(ddraw);
10990 /* The Windows 8 WARP driver has plenty of false negatives in X8R8G8B8
10991 * (color key doesn't match although the values are equal), and a false
10992 * positive when the color key is 0 and the texture contains the value 1.
10993 * I don't want to mark this broken unconditionally since this would
10994 * essentially disable the test on Windows. Also on random occasions
10995 * 254 == 255 and 255 != 255.*/
10996 is_warp = ddraw_is_warp(ddraw);
10998 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
10999 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
11000 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
11001 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
11002 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
11003 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
11004 /* Multiply the texture read result with 0, that way the result color if the key doesn't
11005 * match is constant. In theory color keying works without reading the texture result
11006 * (meaning we could just op=arg1, arg1=tfactor), but the Geforce7 Windows driver begs
11007 * to differ. */
11008 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
11009 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
11010 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
11011 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11012 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
11013 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11014 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x00000000);
11015 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
11017 memset(&fx, 0, sizeof(fx));
11018 fx.dwSize = sizeof(fx);
11019 memset(&lock_desc, 0, sizeof(lock_desc));
11020 lock_desc.dwSize = sizeof(lock_desc);
11022 for (t = 0; t < ARRAY_SIZE(tests); ++t)
11024 if (is_nvidia && tests[t].skip_nv)
11026 win_skip("Skipping test %s on Nvidia Windows drivers.\n", tests[t].name);
11027 continue;
11030 memset(&surface_desc, 0, sizeof(surface_desc));
11031 surface_desc.dwSize = sizeof(surface_desc);
11032 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
11033 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11034 surface_desc.dwWidth = 4;
11035 surface_desc.dwHeight = 1;
11036 U4(surface_desc).ddpfPixelFormat = tests[t].fmt;
11037 /* Windows XP (at least with the r200 driver, other drivers untested) produces
11038 * garbage when doing color keyed texture->texture blits. */
11039 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
11040 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11041 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
11042 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11044 U5(fx).dwFillColor = tests[t].clear;
11045 /* On the w8 testbot (WARP driver) the blit result has different values in the
11046 * X channel. */
11047 color_mask = U2(tests[t].fmt).dwRBitMask
11048 | U3(tests[t].fmt).dwGBitMask
11049 | U4(tests[t].fmt).dwBBitMask;
11051 for (c = 0; c <= tests[t].max; ++c)
11053 /* The idiotic Nvidia Windows driver can't change the color key on a d3d
11054 * texture after it has been set once... */
11055 surface_desc.dwFlags |= DDSD_CKSRCBLT;
11056 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
11057 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = c << tests[t].shift;
11058 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = c << tests[t].shift;
11059 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
11060 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11061 hr = IDirect3DDevice7_SetTexture(device, 0, texture);
11062 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
11064 hr = IDirectDrawSurface7_Blt(dst, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11065 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
11067 hr = IDirectDrawSurface7_Lock(src, NULL, &lock_desc, DDLOCK_WAIT, NULL);
11068 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11069 switch (tests[t].bpp)
11071 case 4:
11072 ((DWORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
11073 ((DWORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
11074 ((DWORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
11075 ((DWORD *)lock_desc.lpSurface)[3] = 0xffffffff;
11076 break;
11078 case 2:
11079 ((WORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
11080 ((WORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
11081 ((WORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
11082 ((WORD *)lock_desc.lpSurface)[3] = 0xffff;
11083 break;
11085 hr = IDirectDrawSurface7_Unlock(src, 0);
11086 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11087 hr = IDirectDrawSurface7_Blt(texture, NULL, src, NULL, DDBLT_WAIT, NULL);
11088 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
11090 ckey.dwColorSpaceLowValue = c << tests[t].shift;
11091 ckey.dwColorSpaceHighValue = c << tests[t].shift;
11092 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
11093 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
11095 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_WAIT, NULL);
11096 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
11098 /* Don't make this read only, it somehow breaks the detection of the Nvidia bug below. */
11099 hr = IDirectDrawSurface7_Lock(dst, NULL, &lock_desc, DDLOCK_WAIT, NULL);
11100 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11101 switch (tests[t].bpp)
11103 case 4:
11104 data[0] = ((DWORD *)lock_desc.lpSurface)[0] & color_mask;
11105 data[1] = ((DWORD *)lock_desc.lpSurface)[1] & color_mask;
11106 data[2] = ((DWORD *)lock_desc.lpSurface)[2] & color_mask;
11107 data[3] = ((DWORD *)lock_desc.lpSurface)[3] & color_mask;
11108 break;
11110 case 2:
11111 data[0] = ((WORD *)lock_desc.lpSurface)[0] & color_mask;
11112 data[1] = ((WORD *)lock_desc.lpSurface)[1] & color_mask;
11113 data[2] = ((WORD *)lock_desc.lpSurface)[2] & color_mask;
11114 data[3] = ((WORD *)lock_desc.lpSurface)[3] & color_mask;
11115 break;
11117 hr = IDirectDrawSurface7_Unlock(dst, 0);
11118 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11120 if (!c)
11122 ok(data[0] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
11123 tests[t].clear, data[0], tests[t].name, c);
11125 if (data[3] == tests[t].clear)
11127 /* My Geforce GTX 460 on Windows 7 misbehaves when A4R4G4B4 is blitted with color
11128 * keying: The blit takes ~0.5 seconds, and subsequent color keying draws are broken,
11129 * even when a different surface is used. The blit itself doesn't draw anything,
11130 * so we can detect the bug by looking at the otherwise unused 4th texel. It should
11131 * never be masked out by the key.
11133 * On Windows 10 the problem is worse, Blt just hangs. For this reason the ARGB4444
11134 * test is disabled on Nvidia.
11136 * Also appears to affect the testbot in some way with R5G6B5. Color keying is
11137 * terrible on WARP. */
11138 skip("Nvidia A4R4G4B4 color keying blit bug detected, skipping.\n");
11139 IDirectDrawSurface7_Release(texture);
11140 IDirectDrawSurface7_Release(src);
11141 IDirectDrawSurface7_Release(dst);
11142 goto done;
11145 else
11146 ok(data[0] == (c - 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
11147 (c - 1) << tests[t].shift, data[0], tests[t].name, c);
11149 ok(data[1] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
11150 tests[t].clear, data[1], tests[t].name, c);
11152 if (c == tests[t].max)
11153 ok(data[2] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
11154 tests[t].clear, data[2], tests[t].name, c);
11155 else
11156 ok(data[2] == (c + 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
11157 (c + 1) << tests[t].shift, data[2], tests[t].name, c);
11159 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x0000ff00, 1.0f, 0);
11160 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
11162 hr = IDirect3DDevice7_BeginScene(device);
11163 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11164 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
11165 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11166 hr = IDirect3DDevice7_EndScene(device);
11167 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11169 color = get_surface_color(rt, 80, 240);
11170 if (!c)
11171 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
11172 "Got unexpected color 0x%08x, format %s, c=%u.\n",
11173 color, tests[t].name, c);
11174 else
11175 ok(compare_color(color, 0x00000000, 1) || broken(is_warp && compare_color(color, 0x0000ff00, 1)),
11176 "Got unexpected color 0x%08x, format %s, c=%u.\n",
11177 color, tests[t].name, c);
11179 color = get_surface_color(rt, 240, 240);
11180 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
11181 "Got unexpected color 0x%08x, format %s, c=%u.\n",
11182 color, tests[t].name, c);
11184 color = get_surface_color(rt, 400, 240);
11185 if (c == tests[t].max)
11186 ok(compare_color(color, 0x0000ff00, 1) || broken(is_warp && compare_color(color, 0x00000000, 1)),
11187 "Got unexpected color 0x%08x, format %s, c=%u.\n",
11188 color, tests[t].name, c);
11189 else
11190 ok(compare_color(color, 0x00000000, 1) || broken(is_warp && compare_color(color, 0x0000ff00, 1)),
11191 "Got unexpected color 0x%08x, format %s, c=%u.\n",
11192 color, tests[t].name, c);
11194 IDirectDrawSurface7_Release(texture);
11196 IDirectDrawSurface7_Release(src);
11197 IDirectDrawSurface7_Release(dst);
11199 done:
11201 IDirectDrawSurface7_Release(rt);
11202 IDirectDraw7_Release(ddraw);
11203 refcount = IDirect3DDevice7_Release(device);
11204 ok(!refcount, "Device has %u references left.\n", refcount);
11205 DestroyWindow(window);
11208 static void test_range_colorkey(void)
11210 IDirectDraw7 *ddraw;
11211 HWND window;
11212 HRESULT hr;
11213 IDirectDrawSurface7 *surface;
11214 DDSURFACEDESC2 surface_desc;
11215 ULONG refcount;
11216 DDCOLORKEY ckey;
11218 window = create_window();
11219 ddraw = create_ddraw();
11220 ok(!!ddraw, "Failed to create a ddraw object.\n");
11221 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11222 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11224 memset(&surface_desc, 0, sizeof(surface_desc));
11225 surface_desc.dwSize = sizeof(surface_desc);
11226 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
11227 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
11228 surface_desc.dwWidth = 1;
11229 surface_desc.dwHeight = 1;
11230 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
11231 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
11232 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
11233 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
11234 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
11235 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0x00000000;
11237 /* Creating a surface with a range color key fails with DDERR_NOCOLORKEY. */
11238 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
11239 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
11240 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11241 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11243 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
11244 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
11245 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11246 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11248 /* Same for DDSCAPS_OFFSCREENPLAIN. */
11249 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11250 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
11251 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
11252 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11253 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11255 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
11256 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
11257 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11258 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11260 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
11261 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
11262 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11263 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11265 /* Setting a range color key without DDCKEY_COLORSPACE collapses the key. */
11266 ckey.dwColorSpaceLowValue = 0x00000000;
11267 ckey.dwColorSpaceHighValue = 0x00000001;
11268 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
11269 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
11271 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
11272 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
11273 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
11274 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
11276 ckey.dwColorSpaceLowValue = 0x00000001;
11277 ckey.dwColorSpaceHighValue = 0x00000000;
11278 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
11279 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
11281 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
11282 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
11283 ok(ckey.dwColorSpaceLowValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
11284 ok(ckey.dwColorSpaceHighValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
11286 /* DDCKEY_COLORSPACE is ignored if the key is a single value. */
11287 ckey.dwColorSpaceLowValue = 0x00000000;
11288 ckey.dwColorSpaceHighValue = 0x00000000;
11289 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
11290 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
11292 /* Using it with a range key results in DDERR_NOCOLORKEYHW. */
11293 ckey.dwColorSpaceLowValue = 0x00000001;
11294 ckey.dwColorSpaceHighValue = 0x00000000;
11295 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
11296 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11297 ckey.dwColorSpaceLowValue = 0x00000000;
11298 ckey.dwColorSpaceHighValue = 0x00000001;
11299 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
11300 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11301 /* Range destination keys don't work either. */
11302 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_DESTBLT | DDCKEY_COLORSPACE, &ckey);
11303 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11305 /* Just to show it's not because of A, R, and G having equal values. */
11306 ckey.dwColorSpaceLowValue = 0x00000000;
11307 ckey.dwColorSpaceHighValue = 0x01010101;
11308 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
11309 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11311 /* None of these operations modified the key. */
11312 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
11313 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
11314 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
11315 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
11317 IDirectDrawSurface7_Release(surface);
11318 refcount = IDirectDraw7_Release(ddraw);
11319 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
11320 DestroyWindow(window);
11323 static void test_shademode(void)
11325 IDirect3DVertexBuffer7 *vb_strip, *vb_list, *buffer;
11326 IDirect3DDevice7 *device;
11327 D3DVERTEXBUFFERDESC desc;
11328 IDirectDrawSurface7 *rt;
11329 DWORD color0, color1;
11330 void *data = NULL;
11331 IDirect3D7 *d3d;
11332 ULONG refcount;
11333 UINT i, count;
11334 HWND window;
11335 HRESULT hr;
11336 static const struct
11338 struct vec3 position;
11339 DWORD diffuse;
11341 quad_strip[] =
11343 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
11344 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
11345 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
11346 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
11348 quad_list[] =
11350 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
11351 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
11352 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
11354 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
11355 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
11356 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
11358 static const struct
11360 DWORD primtype;
11361 DWORD shademode;
11362 DWORD color0, color1;
11364 tests[] =
11366 {D3DPT_TRIANGLESTRIP, D3DSHADE_FLAT, 0x00ff0000, 0x0000ff00},
11367 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
11368 {D3DPT_TRIANGLESTRIP, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
11369 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
11370 {D3DPT_TRIANGLELIST, D3DSHADE_FLAT, 0x00ff0000, 0x000000ff},
11371 {D3DPT_TRIANGLELIST, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
11374 window = create_window();
11375 if (!(device = create_device(window, DDSCL_NORMAL)))
11377 skip("Failed to create a 3D device, skipping test.\n");
11378 DestroyWindow(window);
11379 return;
11382 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
11383 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
11384 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
11385 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11387 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
11388 ok(hr == D3D_OK, "Failed to disable lighting, hr %#x.\n", hr);
11389 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
11390 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
11392 memset(&desc, 0, sizeof(desc));
11393 desc.dwSize = sizeof(desc);
11394 desc.dwCaps = D3DVBCAPS_WRITEONLY;
11395 desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
11396 desc.dwNumVertices = ARRAY_SIZE(quad_strip);
11397 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &vb_strip, 0);
11398 ok(hr == D3D_OK, "Failed to create vertex buffer, hr %#x.\n", hr);
11399 hr = IDirect3DVertexBuffer7_Lock(vb_strip, 0, &data, NULL);
11400 ok(hr == D3D_OK, "Failed to lock vertex buffer, hr %#x.\n", hr);
11401 memcpy(data, quad_strip, sizeof(quad_strip));
11402 hr = IDirect3DVertexBuffer7_Unlock(vb_strip);
11403 ok(hr == D3D_OK, "Failed to unlock vertex buffer, hr %#x.\n", hr);
11405 desc.dwNumVertices = ARRAY_SIZE(quad_list);
11406 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &vb_list, 0);
11407 ok(hr == D3D_OK, "Failed to create vertex buffer, hr %#x.\n", hr);
11408 hr = IDirect3DVertexBuffer7_Lock(vb_list, 0, &data, NULL);
11409 ok(hr == D3D_OK, "Failed to lock vertex buffer, hr %#x.\n", hr);
11410 memcpy(data, quad_list, sizeof(quad_list));
11411 hr = IDirect3DVertexBuffer7_Unlock(vb_list);
11412 ok(hr == D3D_OK, "Failed to unlock vertex buffer, hr %#x.\n", hr);
11414 /* Try it first with a TRIANGLESTRIP. Do it with different geometry because
11415 * the color fixups we have to do for FLAT shading will be dependent on that. */
11417 for (i = 0; i < ARRAY_SIZE(tests); ++i)
11419 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
11420 ok(hr == D3D_OK, "Failed to clear, hr %#x.\n", hr);
11422 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SHADEMODE, tests[i].shademode);
11423 ok(hr == D3D_OK, "Failed to set shade mode, hr %#x.\n", hr);
11425 hr = IDirect3DDevice7_BeginScene(device);
11426 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11427 buffer = tests[i].primtype == D3DPT_TRIANGLESTRIP ? vb_strip : vb_list;
11428 count = tests[i].primtype == D3DPT_TRIANGLESTRIP ? 4 : 6;
11429 hr = IDirect3DDevice7_DrawPrimitiveVB(device, tests[i].primtype, buffer, 0, count, 0);
11430 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11431 hr = IDirect3DDevice7_EndScene(device);
11432 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11434 color0 = get_surface_color(rt, 100, 100); /* Inside first triangle */
11435 color1 = get_surface_color(rt, 500, 350); /* Inside second triangle */
11437 /* For D3DSHADE_FLAT it should take the color of the first vertex of
11438 * each triangle. This requires EXT_provoking_vertex or similar
11439 * functionality being available. */
11440 /* PHONG should be the same as GOURAUD, since no hardware implements
11441 * this. */
11442 ok(compare_color(color0, tests[i].color0, 1), "Test %u shading has color0 %08x, expected %08x.\n",
11443 i, color0, tests[i].color0);
11444 ok(compare_color(color1, tests[i].color1, 1), "Test %u shading has color1 %08x, expected %08x.\n",
11445 i, color1, tests[i].color1);
11448 IDirect3DVertexBuffer7_Release(vb_strip);
11449 IDirect3DVertexBuffer7_Release(vb_list);
11450 IDirectDrawSurface7_Release(rt);
11451 IDirect3D7_Release(d3d);
11452 refcount = IDirect3DDevice7_Release(device);
11453 ok(!refcount, "Device has %u references left.\n", refcount);
11454 DestroyWindow(window);
11457 static void test_lockrect_invalid(void)
11459 unsigned int i, r;
11460 IDirectDraw7 *ddraw;
11461 IDirectDrawSurface7 *surface;
11462 HWND window;
11463 HRESULT hr;
11464 DDSURFACEDESC2 surface_desc;
11465 DDSURFACEDESC2 locked_desc;
11466 DDCAPS hal_caps;
11467 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
11468 static RECT valid[] =
11470 {60, 60, 68, 68},
11471 {60, 60, 60, 68},
11472 {60, 60, 68, 60},
11473 {120, 60, 128, 68},
11474 {60, 120, 68, 128},
11476 static RECT invalid[] =
11478 {68, 60, 60, 68}, /* left > right */
11479 {60, 68, 68, 60}, /* top > bottom */
11480 {-8, 60, 0, 68}, /* left < surface */
11481 {60, -8, 68, 0}, /* top < surface */
11482 {-16, 60, -8, 68}, /* right < surface */
11483 {60, -16, 68, -8}, /* bottom < surface */
11484 {60, 60, 136, 68}, /* right > surface */
11485 {60, 60, 68, 136}, /* bottom > surface */
11486 {136, 60, 144, 68}, /* left > surface */
11487 {60, 136, 68, 144}, /* top > surface */
11489 static const struct
11491 DWORD caps, caps2;
11492 const char *name;
11493 BOOL allowed;
11494 HRESULT hr;
11496 resources[] =
11498 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, "sysmem offscreenplain", TRUE, DDERR_INVALIDPARAMS},
11499 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, "vidmem offscreenplain", TRUE, DDERR_INVALIDPARAMS},
11500 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, "sysmem texture", TRUE, DD_OK},
11501 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, "vidmem texture", TRUE, DDERR_INVALIDPARAMS},
11502 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, "managed texture", TRUE, DD_OK},
11504 /* FWIW the SDK header mentions DDSCAPS_WRITEONLY as being a "READ
11505 * ONLY" flag. */
11506 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_WRITEONLY, 0, "sysmem offscreenplain writeonly", FALSE, DDERR_INVALIDPARAMS},
11507 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_WRITEONLY, 0, "vidmem offscreenplain writeonly", FALSE, DDERR_INVALIDPARAMS},
11508 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_WRITEONLY, 0, "sysmem texture writeonly", FALSE, DD_OK},
11509 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_WRITEONLY, 0, "vidmem texture writeonly", FALSE, DDERR_INVALIDPARAMS},
11510 {DDSCAPS_TEXTURE | DDSCAPS_WRITEONLY, DDSCAPS2_TEXTUREMANAGE, "managed texture writeonly", TRUE, DD_OK},
11513 window = create_window();
11514 ddraw = create_ddraw();
11515 ok(!!ddraw, "Failed to create a ddraw object.\n");
11516 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11517 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11519 memset(&hal_caps, 0, sizeof(hal_caps));
11520 hal_caps.dwSize = sizeof(hal_caps);
11521 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
11522 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
11523 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps
11524 || !(hal_caps.ddsCaps.dwCaps & DDSCAPS2_TEXTUREMANAGE))
11526 skip("Required surface types not supported, skipping test.\n");
11527 goto done;
11530 for (r = 0; r < ARRAY_SIZE(resources); ++r)
11532 memset(&surface_desc, 0, sizeof(surface_desc));
11533 surface_desc.dwSize = sizeof(surface_desc);
11534 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
11535 surface_desc.ddsCaps.dwCaps = resources[r].caps;
11536 surface_desc.ddsCaps.dwCaps2 = resources[r].caps2;
11537 surface_desc.dwWidth = 128;
11538 surface_desc.dwHeight = 128;
11539 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
11540 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
11541 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
11542 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xff0000;
11543 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x00ff00;
11544 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x0000ff;
11546 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11547 if (!resources[r].allowed)
11549 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
11550 continue;
11552 if (is_ddraw64 && (resources[r].caps & DDSCAPS_TEXTURE))
11554 todo_wine ok(hr == E_NOINTERFACE, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
11555 if (SUCCEEDED(hr))
11556 IDirectDrawSurface7_Release(surface);
11557 continue;
11559 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n", hr, resources[r].name);
11561 /* Crashes in ddraw7
11562 hr = IDirectDrawSurface7_Lock(surface, NULL, NULL, DDLOCK_WAIT, NULL);
11563 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
11566 for (i = 0; i < ARRAY_SIZE(valid); ++i)
11568 RECT *rect = &valid[i];
11570 memset(&locked_desc, 0, sizeof(locked_desc));
11571 locked_desc.dwSize = sizeof(locked_desc);
11573 hr = IDirectDrawSurface7_Lock(surface, rect, &locked_desc, DDLOCK_WAIT, NULL);
11574 ok(SUCCEEDED(hr), "Lock failed (%#x) for rect %s, type %s.\n",
11575 hr, wine_dbgstr_rect(rect), resources[r].name);
11577 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11578 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11581 for (i = 0; i < ARRAY_SIZE(invalid); ++i)
11583 RECT *rect = &invalid[i];
11585 memset(&locked_desc, 1, sizeof(locked_desc));
11586 locked_desc.dwSize = sizeof(locked_desc);
11588 hr = IDirectDrawSurface7_Lock(surface, rect, &locked_desc, DDLOCK_WAIT, NULL);
11589 todo_wine_if (SUCCEEDED(resources[r].hr))
11590 ok(hr == resources[r].hr, "Lock returned %#x for rect %s, type %s.\n",
11591 hr, wine_dbgstr_rect(rect), resources[r].name);
11592 if (SUCCEEDED(hr))
11594 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11595 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11597 else
11598 ok(!locked_desc.lpSurface, "Got unexpected lpSurface %p.\n", locked_desc.lpSurface);
11601 hr = IDirectDrawSurface7_Lock(surface, NULL, &locked_desc, DDLOCK_WAIT, NULL);
11602 ok(SUCCEEDED(hr), "Lock(rect = NULL) failed, hr %#x, type %s.\n",
11603 hr, resources[r].name);
11604 hr = IDirectDrawSurface7_Lock(surface, NULL, &locked_desc, DDLOCK_WAIT, NULL);
11605 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = NULL) returned %#x, type %s.\n",
11606 hr, resources[r].name);
11607 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11608 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11610 hr = IDirectDrawSurface7_Lock(surface, &valid[0], &locked_desc, DDLOCK_WAIT, NULL);
11611 ok(SUCCEEDED(hr), "Lock(rect = %s) failed (%#x).\n", wine_dbgstr_rect(&valid[0]), hr);
11612 hr = IDirectDrawSurface7_Lock(surface, &valid[0], &locked_desc, DDLOCK_WAIT, NULL);
11613 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = %s) failed (%#x).\n",
11614 wine_dbgstr_rect(&valid[0]), hr);
11616 /* Locking a different rectangle returns DD_OK, but it seems to break the surface.
11617 * Afterwards unlocking the surface fails(NULL rectangle or both locked rectangles) */
11619 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11620 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11622 IDirectDrawSurface7_Release(surface);
11625 done:
11626 IDirectDraw7_Release(ddraw);
11627 DestroyWindow(window);
11630 static void test_yv12_overlay(void)
11632 IDirectDrawSurface7 *src_surface, *dst_surface;
11633 RECT rect = {13, 17, 14, 18};
11634 unsigned int offset, y;
11635 DDSURFACEDESC2 desc;
11636 unsigned char *base;
11637 IDirectDraw7 *ddraw;
11638 HWND window;
11639 HRESULT hr;
11641 window = create_window();
11642 ddraw = create_ddraw();
11643 ok(!!ddraw, "Failed to create a ddraw object.\n");
11644 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11645 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11647 if (!(src_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
11649 skip("Failed to create a YV12 overlay, skipping test.\n");
11650 goto done;
11653 memset(&desc, 0, sizeof(desc));
11654 desc.dwSize = sizeof(desc);
11655 hr = IDirectDrawSurface7_Lock(src_surface, NULL, &desc, DDLOCK_WAIT, NULL);
11656 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11658 ok(desc.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH),
11659 "Got unexpected flags %#x.\n", desc.dwFlags);
11660 ok(desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_HWCODEC)
11661 || desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
11662 "Got unexpected caps %#x.\n", desc.ddsCaps.dwCaps);
11663 ok(desc.dwWidth == 256, "Got unexpected width %u.\n", desc.dwWidth);
11664 ok(desc.dwHeight == 256, "Got unexpected height %u.\n", desc.dwHeight);
11665 /* The overlay pitch seems to have 256 byte alignment. */
11666 ok(!(U1(desc).lPitch & 0xff), "Got unexpected pitch %u.\n", U1(desc).lPitch);
11668 /* Fill the surface with some data for the blit test. */
11669 base = desc.lpSurface;
11670 /* Luminance */
11671 for (y = 0; y < desc.dwHeight; ++y)
11673 memset(base + U1(desc).lPitch * y, 0x10, desc.dwWidth);
11675 /* V */
11676 for (; y < desc.dwHeight + desc.dwHeight / 4; ++y)
11678 memset(base + U1(desc).lPitch * y, 0x20, desc.dwWidth);
11680 /* U */
11681 for (; y < desc.dwHeight + desc.dwHeight / 2; ++y)
11683 memset(base + U1(desc).lPitch * y, 0x30, desc.dwWidth);
11686 hr = IDirectDrawSurface7_Unlock(src_surface, NULL);
11687 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11689 /* YV12 uses 2x2 blocks with 6 bytes per block (4*Y, 1*U, 1*V). Unlike
11690 * other block-based formats like DXT the entire Y channel is stored in
11691 * one big chunk of memory, followed by the chroma channels. So partial
11692 * locks do not really make sense. Show that they are allowed nevertheless
11693 * and the offset points into the luminance data. */
11694 hr = IDirectDrawSurface7_Lock(src_surface, &rect, &desc, DDLOCK_WAIT, NULL);
11695 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11696 offset = ((const unsigned char *)desc.lpSurface - base);
11697 ok(offset == rect.top * U1(desc).lPitch + rect.left, "Got unexpected offset %u, expected %u.\n",
11698 offset, rect.top * U1(desc).lPitch + rect.left);
11699 hr = IDirectDrawSurface7_Unlock(src_surface, NULL);
11700 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11702 if (!(dst_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
11704 /* Windows XP with a Radeon X1600 GPU refuses to create a second
11705 * overlay surface, DDERR_NOOVERLAYHW, making the blit tests moot. */
11706 skip("Failed to create a second YV12 surface, skipping blit test.\n");
11707 IDirectDrawSurface7_Release(src_surface);
11708 goto done;
11711 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, src_surface, NULL, DDBLT_WAIT, NULL);
11712 /* VMware rejects YV12 blits. This behavior has not been seen on real
11713 * hardware yet, so mark it broken. */
11714 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL), "Failed to blit, hr %#x.\n", hr);
11716 if (SUCCEEDED(hr))
11718 memset(&desc, 0, sizeof(desc));
11719 desc.dwSize = sizeof(desc);
11720 hr = IDirectDrawSurface7_Lock(dst_surface, NULL, &desc, DDLOCK_WAIT, NULL);
11721 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11723 base = desc.lpSurface;
11724 ok(base[0] == 0x10, "Got unexpected Y data 0x%02x.\n", base[0]);
11725 base += desc.dwHeight * U1(desc).lPitch;
11726 todo_wine ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]);
11727 base += desc.dwHeight / 4 * U1(desc).lPitch;
11728 todo_wine ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]);
11730 hr = IDirectDrawSurface7_Unlock(dst_surface, NULL);
11731 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11734 IDirectDrawSurface7_Release(dst_surface);
11735 IDirectDrawSurface7_Release(src_surface);
11736 done:
11737 IDirectDraw7_Release(ddraw);
11738 DestroyWindow(window);
11741 static BOOL dwm_enabled(void)
11743 BOOL ret = FALSE;
11745 if (!strcmp(winetest_platform, "wine"))
11746 return FALSE;
11747 if (!pDwmIsCompositionEnabled)
11748 return FALSE;
11749 if (FAILED(pDwmIsCompositionEnabled(&ret)))
11750 return FALSE;
11751 return ret;
11754 static void test_offscreen_overlay(void)
11756 IDirectDrawSurface7 *overlay, *offscreen, *primary;
11757 DDSURFACEDESC2 surface_desc;
11758 IDirectDraw7 *ddraw;
11759 HWND window;
11760 HRESULT hr;
11761 HDC dc;
11763 window = create_window();
11764 ddraw = create_ddraw();
11765 ok(!!ddraw, "Failed to create a ddraw object.\n");
11766 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11767 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11769 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
11771 skip("Failed to create a UYVY overlay, skipping test.\n");
11772 goto done;
11775 memset(&surface_desc, 0, sizeof(surface_desc));
11776 surface_desc.dwSize = sizeof(surface_desc);
11777 surface_desc.dwFlags = DDSD_CAPS;
11778 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
11779 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
11780 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
11782 /* On Windows 7, and probably Vista, UpdateOverlay() will return
11783 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
11784 * surface prevents this by disabling the dwm. */
11785 hr = IDirectDrawSurface7_GetDC(primary, &dc);
11786 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
11787 hr = IDirectDrawSurface7_ReleaseDC(primary, dc);
11788 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
11790 /* Try to overlay a NULL surface. */
11791 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_SHOW, NULL);
11792 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11793 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_HIDE, NULL);
11794 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11796 /* Try to overlay an offscreen surface. */
11797 memset(&surface_desc, 0, sizeof(surface_desc));
11798 surface_desc.dwSize = sizeof(surface_desc);
11799 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
11800 surface_desc.dwWidth = 64;
11801 surface_desc.dwHeight = 64;
11802 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11803 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
11804 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
11805 U4(surface_desc).ddpfPixelFormat.dwFourCC = 0;
11806 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
11807 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
11808 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
11809 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
11810 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
11811 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
11813 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, offscreen, NULL, DDOVER_SHOW, NULL);
11814 ok(SUCCEEDED(hr) || broken(hr == DDERR_OUTOFCAPS && dwm_enabled())
11815 || broken(hr == E_NOTIMPL && ddraw_is_vmware(ddraw)),
11816 "Failed to update overlay, hr %#x.\n", hr);
11818 /* Try to overlay the primary with a non-overlay surface. */
11819 hr = IDirectDrawSurface7_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_SHOW, NULL);
11820 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
11821 hr = IDirectDrawSurface7_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_HIDE, NULL);
11822 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
11824 IDirectDrawSurface7_Release(offscreen);
11825 IDirectDrawSurface7_Release(primary);
11826 IDirectDrawSurface7_Release(overlay);
11827 done:
11828 IDirectDraw7_Release(ddraw);
11829 DestroyWindow(window);
11832 static void test_overlay_rect(void)
11834 IDirectDrawSurface7 *overlay, *primary = NULL;
11835 DDSURFACEDESC2 surface_desc;
11836 RECT rect = {0, 0, 64, 64};
11837 IDirectDraw7 *ddraw;
11838 LONG pos_x, pos_y;
11839 HRESULT hr, hr2;
11840 HWND window;
11841 HDC dc;
11843 window = create_window();
11844 ddraw = create_ddraw();
11845 ok(!!ddraw, "Failed to create a ddraw object.\n");
11846 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11847 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11849 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
11851 skip("Failed to create a UYVY overlay, skipping test.\n");
11852 goto done;
11855 memset(&surface_desc, 0, sizeof(surface_desc));
11856 surface_desc.dwSize = sizeof(surface_desc);
11857 surface_desc.dwFlags = DDSD_CAPS;
11858 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
11859 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
11860 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
11862 /* On Windows 7, and probably Vista, UpdateOverlay() will return
11863 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
11864 * surface prevents this by disabling the dwm. */
11865 hr = IDirectDrawSurface7_GetDC(primary, &dc);
11866 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
11867 hr = IDirectDrawSurface7_ReleaseDC(primary, dc);
11868 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
11870 /* On Windows 8 and newer DWM can't be turned off, making overlays unusable. */
11871 if (dwm_enabled())
11873 win_skip("Cannot disable DWM, skipping overlay test.\n");
11874 goto done;
11877 /* The dx sdk sort of implies that rect must be set when DDOVER_SHOW is
11878 * used. This is not true in Windows Vista and earlier, but changed in
11879 * Windows 7. */
11880 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
11881 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
11882 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_HIDE, NULL);
11883 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
11884 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_SHOW, NULL);
11885 ok(hr == DD_OK || hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11887 /* Show that the overlay position is the (top, left) coordinate of the
11888 * destination rectangle. */
11889 OffsetRect(&rect, 32, 16);
11890 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
11891 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
11892 pos_x = -1; pos_y = -1;
11893 hr = IDirectDrawSurface7_GetOverlayPosition(overlay, &pos_x, &pos_y);
11894 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
11895 ok(pos_x == rect.left, "Got unexpected pos_x %d, expected %d.\n", pos_x, rect.left);
11896 ok(pos_y == rect.top, "Got unexpected pos_y %d, expected %d.\n", pos_y, rect.top);
11898 /* Passing a NULL dest rect sets the position to 0/0. Visually it can be
11899 * seen that the overlay overlays the whole primary(==screen). */
11900 hr2 = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, NULL, 0, NULL);
11901 ok(hr2 == DD_OK || hr2 == DDERR_INVALIDPARAMS || hr2 == DDERR_OUTOFCAPS, "Got unexpected hr %#x.\n", hr2);
11902 hr = IDirectDrawSurface7_GetOverlayPosition(overlay, &pos_x, &pos_y);
11903 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
11904 if (SUCCEEDED(hr2))
11906 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
11907 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
11909 else
11911 ok(pos_x == 32, "Got unexpected pos_x %d.\n", pos_x);
11912 ok(pos_y == 16, "Got unexpected pos_y %d.\n", pos_y);
11915 /* The position cannot be retrieved when the overlay is not shown. */
11916 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_HIDE, NULL);
11917 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
11918 pos_x = -1; pos_y = -1;
11919 hr = IDirectDrawSurface7_GetOverlayPosition(overlay, &pos_x, &pos_y);
11920 ok(hr == DDERR_OVERLAYNOTVISIBLE, "Got unexpected hr %#x.\n", hr);
11921 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
11922 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
11924 IDirectDrawSurface7_Release(overlay);
11925 done:
11926 if (primary)
11927 IDirectDrawSurface7_Release(primary);
11928 IDirectDraw7_Release(ddraw);
11929 DestroyWindow(window);
11932 static void test_blt(void)
11934 IDirectDrawSurface7 *surface, *rt;
11935 DDSURFACEDESC2 surface_desc;
11936 IDirect3DDevice7 *device;
11937 IDirectDraw7 *ddraw;
11938 IDirect3D7 *d3d;
11939 unsigned int i;
11940 ULONG refcount;
11941 HWND window;
11942 HRESULT hr;
11944 static struct
11946 RECT src_rect;
11947 RECT dst_rect;
11948 HRESULT hr;
11950 test_data[] =
11952 {{160, 0, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit. */
11953 {{160, 480, 640, 0}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, flipped source. */
11954 {{640, 0, 160, 480}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, mirrored source. */
11955 {{160, 0, 480, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched x. */
11956 {{160, 160, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched y. */
11957 {{ 0, 0, 640, 480}, { 0, 0, 640, 480}, DD_OK}, /* Full surface blit. */
11958 {{ 0, 0, 640, 480}, { 0, 480, 640, 0}, DDERR_INVALIDRECT}, /* Full surface, flipped destination. */
11959 {{ 0, 0, 640, 480}, {640, 0, 0, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored destination. */
11960 {{ 0, 480, 640, 0}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, flipped source. */
11961 {{640, 0, 0, 480}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored source. */
11964 window = create_window();
11965 if (!(device = create_device(window, DDSCL_NORMAL)))
11967 skip("Failed to create a 3D device, skipping test.\n");
11968 DestroyWindow(window);
11969 return;
11972 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
11973 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
11974 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
11975 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
11976 IDirect3D7_Release(d3d);
11977 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
11978 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11980 memset(&surface_desc, 0, sizeof(surface_desc));
11981 surface_desc.dwSize = sizeof(surface_desc);
11982 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
11983 surface_desc.dwWidth = 640;
11984 surface_desc.dwHeight = 480;
11985 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11986 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11987 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11989 hr = IDirectDrawSurface7_Blt(surface, NULL, surface, NULL, 0, NULL);
11990 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
11992 hr = IDirectDrawSurface7_Blt(surface, NULL, rt, NULL, 0, NULL);
11993 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
11995 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
11997 hr = IDirectDrawSurface7_Blt(surface, &test_data[i].dst_rect,
11998 surface, &test_data[i].src_rect, DDBLT_WAIT, NULL);
11999 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
12001 hr = IDirectDrawSurface7_Blt(surface, &test_data[i].dst_rect,
12002 rt, &test_data[i].src_rect, DDBLT_WAIT, NULL);
12003 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
12005 hr = IDirectDrawSurface7_Blt(surface, &test_data[i].dst_rect,
12006 NULL, &test_data[i].src_rect, DDBLT_WAIT, NULL);
12007 ok(hr == DDERR_INVALIDPARAMS, "Test %u: Got unexpected hr %#x.\n", i, hr);
12009 hr = IDirectDrawSurface7_Blt(surface, &test_data[i].dst_rect, NULL, NULL, DDBLT_WAIT, NULL);
12010 ok(hr == DDERR_INVALIDPARAMS, "Test %u: Got unexpected hr %#x.\n", i, hr);
12013 IDirectDrawSurface7_Release(surface);
12014 IDirectDrawSurface7_Release(rt);
12015 IDirectDraw7_Release(ddraw);
12016 refcount = IDirect3DDevice7_Release(device);
12017 ok(!refcount, "Device has %u references left.\n", refcount);
12018 DestroyWindow(window);
12021 static void test_blt_z_alpha(void)
12023 DWORD blt_flags[] =
12025 /* 0 */
12026 DDBLT_ALPHADEST,
12027 DDBLT_ALPHADESTCONSTOVERRIDE,
12028 DDBLT_ALPHADESTNEG,
12029 DDBLT_ALPHADESTSURFACEOVERRIDE,
12030 DDBLT_ALPHAEDGEBLEND,
12031 /* 5 */
12032 DDBLT_ALPHASRC,
12033 DDBLT_ALPHASRCCONSTOVERRIDE,
12034 DDBLT_ALPHASRCNEG,
12035 DDBLT_ALPHASRCSURFACEOVERRIDE,
12036 DDBLT_ZBUFFER,
12037 /* 10 */
12038 DDBLT_ZBUFFERDESTCONSTOVERRIDE,
12039 DDBLT_ZBUFFERDESTOVERRIDE,
12040 DDBLT_ZBUFFERSRCCONSTOVERRIDE,
12041 DDBLT_ZBUFFERSRCOVERRIDE,
12043 IDirectDrawSurface7 *src_surface, *dst_surface;
12044 DDSURFACEDESC2 surface_desc;
12045 IDirectDraw7 *ddraw;
12046 DDPIXELFORMAT pf;
12047 ULONG refcount;
12048 unsigned int i;
12049 D3DCOLOR color;
12050 HWND window;
12051 HRESULT hr;
12052 DDBLTFX fx;
12054 window = create_window();
12055 ddraw = create_ddraw();
12056 ok(!!ddraw, "Failed to create a ddraw object.\n");
12057 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12058 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12060 memset(&pf, 0, sizeof(pf));
12061 pf.dwSize = sizeof(pf);
12062 pf.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
12063 U1(pf).dwRGBBitCount = 32;
12064 U2(pf).dwRBitMask = 0x00ff0000;
12065 U3(pf).dwGBitMask = 0x0000ff00;
12066 U4(pf).dwBBitMask = 0x000000ff;
12067 U5(pf).dwRGBAlphaBitMask = 0xff000000;
12069 memset(&surface_desc, 0, sizeof(surface_desc));
12070 surface_desc.dwSize = sizeof(surface_desc);
12071 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
12072 surface_desc.dwWidth = 64;
12073 surface_desc.dwHeight = 64;
12074 U4(surface_desc).ddpfPixelFormat = pf;
12075 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12077 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
12078 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
12079 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
12080 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
12082 memset(&fx, 0, sizeof(fx));
12083 fx.dwSize = sizeof(fx);
12084 fx.dwZBufferOpCode = D3DCMP_NEVER;
12085 fx.dwZDestConstBitDepth = 32;
12086 U1(fx).dwZDestConst = 0x11111111;
12087 fx.dwZSrcConstBitDepth = 32;
12088 U2(fx).dwZSrcConst = 0xeeeeeeee;
12089 fx.dwAlphaEdgeBlendBitDepth = 8;
12090 fx.dwAlphaEdgeBlend = 0x7f;
12091 fx.dwAlphaDestConstBitDepth = 8;
12092 U3(fx).dwAlphaDestConst = 0xdd;
12093 fx.dwAlphaSrcConstBitDepth = 8;
12094 U4(fx).dwAlphaSrcConst = 0x22;
12096 for (i = 0; i < ARRAY_SIZE(blt_flags); ++i)
12098 U5(fx).dwFillColor = 0x3300ff00;
12099 hr = IDirectDrawSurface7_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
12100 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
12102 U5(fx).dwFillColor = 0xccff0000;
12103 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
12104 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
12106 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, src_surface, NULL, blt_flags[i] | DDBLT_WAIT, &fx);
12107 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
12109 color = get_surface_color(dst_surface, 32, 32);
12110 ok(compare_color(color, 0x0000ff00, 0), "Test %u: Got unexpected color 0x%08x.\n", i, color);
12113 IDirectDrawSurface7_Release(dst_surface);
12114 IDirectDrawSurface7_Release(src_surface);
12115 refcount = IDirectDraw7_Release(ddraw);
12116 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
12117 DestroyWindow(window);
12120 static void test_cross_device_blt(void)
12122 IDirectDrawSurface7 *surface, *surface2, *sysmem_surface;
12123 IDirect3DDevice7 *device, *device2;
12124 IDirectDraw7 *ddraw, *ddraw2;
12125 DDSURFACEDESC2 surface_desc;
12126 HWND window, window2;
12127 IDirect3D7 *d3d;
12128 ULONG refcount;
12129 D3DCOLOR color;
12130 DDBLTFX fx;
12131 HRESULT hr;
12133 window = create_window();
12134 if (!(device = create_device(window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
12136 skip("Failed to create a 3D device.\n");
12137 DestroyWindow(window);
12138 return;
12141 window2 = create_window();
12142 if (!(device2 = create_device(window2, DDSCL_NORMAL)))
12144 skip("Failed to create a 3D device.\n");
12145 IDirect3DDevice7_Release(device);
12146 DestroyWindow(window);
12147 DestroyWindow(window2);
12148 return;
12151 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
12152 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
12153 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
12154 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
12155 IDirect3D7_Release(d3d);
12157 hr = IDirect3DDevice7_GetDirect3D(device2, &d3d);
12158 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
12159 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw2);
12160 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
12161 IDirect3D7_Release(d3d);
12163 memset(&surface_desc, 0, sizeof(surface_desc));
12164 surface_desc.dwSize = sizeof(surface_desc);
12165 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
12166 surface_desc.dwWidth = 640;
12167 surface_desc.dwHeight = 480;
12168 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
12169 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &sysmem_surface, NULL);
12170 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12172 memset(&surface_desc, 0, sizeof(surface_desc));
12173 surface_desc.dwSize = sizeof(surface_desc);
12174 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
12175 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_VIDEOMEMORY;
12176 U5(surface_desc).dwBackBufferCount = 2;
12177 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12178 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12180 memset(&surface_desc, 0, sizeof(surface_desc));
12181 surface_desc.dwSize = sizeof(surface_desc);
12182 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
12183 surface_desc.dwWidth = 640;
12184 surface_desc.dwHeight = 480;
12185 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
12186 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
12187 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
12188 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
12189 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00007c00;
12190 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x000003e0;
12191 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x0000001f;
12192 hr = IDirectDraw7_CreateSurface(ddraw2, &surface_desc, &surface2, NULL);
12193 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12195 memset(&fx, 0, sizeof(fx));
12196 fx.dwSize = sizeof(fx);
12197 U5(fx).dwFillColor = 0xff0000ff;
12198 hr = IDirectDrawSurface7_Blt(surface2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
12199 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
12201 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
12202 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
12203 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
12204 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12205 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
12206 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
12207 color = get_surface_color(surface, 320, 240);
12208 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
12210 hr = IDirectDrawSurface7_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
12211 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
12212 color = get_surface_color(sysmem_surface, 320, 240);
12213 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
12215 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12216 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12217 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
12218 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
12220 hr = IDirectDrawSurface7_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
12221 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
12222 color = get_surface_color(sysmem_surface, 320, 240);
12223 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
12225 IDirectDrawSurface7_Release(surface2);
12226 memset(&surface_desc, 0, sizeof(surface_desc));
12227 surface_desc.dwSize = sizeof(surface_desc);
12228 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
12229 surface_desc.dwWidth = 640;
12230 surface_desc.dwHeight = 480;
12231 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
12232 hr = IDirectDraw7_CreateSurface(ddraw2, &surface_desc, &surface2, NULL);
12233 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12234 hr = IDirectDrawSurface7_Blt(surface2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
12235 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
12237 hr = IDirectDrawSurface7_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
12238 todo_wine ok(hr == D3D_OK, "Failed to blit, hr %#x.\n", hr);
12239 color = get_surface_color(sysmem_surface, 320, 240);
12240 todo_wine ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
12242 IDirectDrawSurface7_Release(surface);
12243 IDirectDrawSurface7_Release(surface2);
12244 IDirectDrawSurface7_Release(sysmem_surface);
12245 IDirectDraw7_Release(ddraw);
12246 IDirectDraw7_Release(ddraw2);
12247 refcount = IDirect3DDevice7_Release(device);
12248 ok(!refcount, "Device has %u references left.\n", refcount);
12249 refcount = IDirect3DDevice7_Release(device2);
12250 ok(!refcount, "Device has %u references left.\n", refcount);
12251 DestroyWindow(window);
12252 DestroyWindow(window2);
12255 static void test_color_clamping(void)
12257 static D3DMATRIX mat =
12259 1.0f, 0.0f, 0.0f, 0.0f,
12260 0.0f, 1.0f, 0.0f, 0.0f,
12261 0.0f, 0.0f, 1.0f, 0.0f,
12262 0.0f, 0.0f, 0.0f, 1.0f,
12264 static struct vec3 quad[] =
12266 {-1.0f, -1.0f, 0.1f},
12267 {-1.0f, 1.0f, 0.1f},
12268 { 1.0f, -1.0f, 0.1f},
12269 { 1.0f, 1.0f, 0.1f},
12271 IDirect3DDevice7 *device;
12272 IDirectDrawSurface7 *rt;
12273 ULONG refcount;
12274 D3DCOLOR color;
12275 HWND window;
12276 HRESULT hr;
12278 window = create_window();
12279 if (!(device = create_device(window, DDSCL_NORMAL)))
12281 skip("Failed to create a 3D device, skipping test.\n");
12282 DestroyWindow(window);
12283 return;
12286 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
12287 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
12289 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
12290 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
12291 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
12292 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
12293 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
12294 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
12295 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
12296 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
12297 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
12298 ok(SUCCEEDED(hr), "Failed to disable Z test, hr %#x.\n", hr);
12299 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
12300 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
12301 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
12302 ok(SUCCEEDED(hr), "Failed to disable stencil test, hr %#x.\n", hr);
12303 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
12304 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
12305 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
12306 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
12308 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0xff404040);
12309 ok(SUCCEEDED(hr), "Failed to set texture factor, hr %#x.\n", hr);
12310 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_ADD);
12311 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
12312 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
12313 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
12314 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_SPECULAR);
12315 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
12316 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_MODULATE);
12317 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
12318 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TFACTOR);
12319 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
12320 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
12321 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
12323 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
12324 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12326 hr = IDirect3DDevice7_BeginScene(device);
12327 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12329 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
12330 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12332 hr = IDirect3DDevice7_EndScene(device);
12333 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12335 color = get_surface_color(rt, 320, 240);
12336 ok(compare_color(color, 0x00404040, 1), "Got unexpected color 0x%08x.\n", color);
12338 IDirectDrawSurface7_Release(rt);
12339 refcount = IDirect3DDevice7_Release(device);
12340 ok(!refcount, "Device has %u references left.\n", refcount);
12341 DestroyWindow(window);
12344 static void test_getdc(void)
12346 DDSCAPS2 caps = {DDSCAPS_COMPLEX, DDSCAPS2_CUBEMAP_NEGATIVEZ, 0, {0}};
12347 IDirectDrawSurface7 *surface, *surface2, *tmp;
12348 DDSURFACEDESC2 surface_desc, map_desc;
12349 IDirectDraw7 *ddraw;
12350 unsigned int i;
12351 HWND window;
12352 HDC dc, dc2;
12353 HRESULT hr;
12355 static const struct
12357 const char *name;
12358 DDPIXELFORMAT format;
12359 BOOL getdc_supported;
12360 HRESULT alt_result;
12362 test_data[] =
12364 {"D3DFMT_A8R8G8B8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
12365 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}}, TRUE},
12366 {"D3DFMT_X8R8G8B8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
12367 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}}, TRUE},
12368 {"D3DFMT_R5G6B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
12369 {0x0000f800}, {0x000007e0}, {0x0000001f}, {0x00000000}}, TRUE},
12370 {"D3DFMT_X1R5G5B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
12371 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00000000}}, TRUE},
12372 {"D3DFMT_A1R5G5B5", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
12373 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00008000}}, TRUE},
12374 {"D3DFMT_A4R4G4B4", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
12375 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x0000f000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
12376 {"D3DFMT_X4R4G4B4", {sizeof(test_data->format), DDPF_RGB, 0, {16},
12377 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
12378 {"D3DFMT_A2R10G10B10", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
12379 {0xc0000000}, {0x3ff00000}, {0x000ffc00}, {0x000003ff}}, TRUE},
12380 {"D3DFMT_A8B8G8R8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
12381 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0xff000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
12382 {"D3DFMT_X8B8G8R8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
12383 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
12384 {"D3DFMT_R3G3B2", {sizeof(test_data->format), DDPF_RGB, 0, {8},
12385 {0x000000e0}, {0x0000001c}, {0x00000003}, {0x00000000}}, FALSE},
12386 /* GetDC() on a P8 surface fails unless the display mode is 8 bpp.
12387 * This is not implemented in wine yet, so disable the test for now.
12388 * Succeeding P8 GetDC() calls are tested in the ddraw:visual test.
12389 {"D3DFMT_P8", {sizeof(test_data->format), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0, {8 },
12390 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
12392 {"D3DFMT_L8", {sizeof(test_data->format), DDPF_LUMINANCE, 0, {8},
12393 {0x000000ff}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
12394 {"D3DFMT_A8L8", {sizeof(test_data->format), DDPF_ALPHAPIXELS | DDPF_LUMINANCE, 0, {16},
12395 {0x000000ff}, {0x00000000}, {0x00000000}, {0x0000ff00}}, FALSE},
12396 {"D3DFMT_DXT1", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','1'), {0},
12397 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
12398 {"D3DFMT_DXT2", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','2'), {0},
12399 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
12400 {"D3DFMT_DXT3", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','3'), {0},
12401 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
12402 {"D3DFMT_DXT4", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','4'), {0},
12403 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
12404 {"D3DFMT_DXT5", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','5'), {0},
12405 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
12408 window = create_window();
12409 ddraw = create_ddraw();
12410 ok(!!ddraw, "Failed to create a ddraw object.\n");
12411 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12412 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12414 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
12416 memset(&surface_desc, 0, sizeof(surface_desc));
12417 surface_desc.dwSize = sizeof(surface_desc);
12418 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
12419 surface_desc.dwWidth = 64;
12420 surface_desc.dwHeight = 64;
12421 U4(surface_desc).ddpfPixelFormat = test_data[i].format;
12422 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12424 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
12426 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
12427 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
12428 if (FAILED(hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
12430 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", test_data[i].name, hr);
12431 continue;
12435 dc = (void *)0x1234;
12436 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12437 if (test_data[i].getdc_supported)
12438 ok(SUCCEEDED(hr) || broken(hr == test_data[i].alt_result),
12439 "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12440 else
12441 ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12443 if (SUCCEEDED(hr))
12445 unsigned int width_bytes;
12446 DIBSECTION dib;
12447 HBITMAP bitmap;
12448 DWORD type;
12449 int size;
12451 type = GetObjectType(dc);
12452 ok(type == OBJ_MEMDC, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
12453 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
12454 type = GetObjectType(bitmap);
12455 ok(type == OBJ_BITMAP, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
12457 size = GetObjectA(bitmap, sizeof(dib), &dib);
12458 ok(size == sizeof(dib), "Got unexpected size %d for format %s.\n", size, test_data[i].name);
12459 ok(!dib.dsBm.bmType, "Got unexpected type %#x for format %s.\n",
12460 dib.dsBm.bmType, test_data[i].name);
12461 ok(dib.dsBm.bmWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
12462 dib.dsBm.bmWidth, test_data[i].name);
12463 ok(dib.dsBm.bmHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
12464 dib.dsBm.bmHeight, test_data[i].name);
12465 width_bytes = ((dib.dsBm.bmWidth * U1(test_data[i].format).dwRGBBitCount + 31) >> 3) & ~3;
12466 ok(dib.dsBm.bmWidthBytes == width_bytes, "Got unexpected width bytes %d for format %s.\n",
12467 dib.dsBm.bmWidthBytes, test_data[i].name);
12468 ok(dib.dsBm.bmPlanes == 1, "Got unexpected plane count %d for format %s.\n",
12469 dib.dsBm.bmPlanes, test_data[i].name);
12470 ok(dib.dsBm.bmBitsPixel == U1(test_data[i].format).dwRGBBitCount,
12471 "Got unexpected bit count %d for format %s.\n",
12472 dib.dsBm.bmBitsPixel, test_data[i].name);
12473 ok(!!dib.dsBm.bmBits, "Got unexpected bits %p for format %s.\n",
12474 dib.dsBm.bmBits, test_data[i].name);
12476 ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "Got unexpected size %u for format %s.\n",
12477 dib.dsBmih.biSize, test_data[i].name);
12478 ok(dib.dsBmih.biWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
12479 dib.dsBmih.biHeight, test_data[i].name);
12480 ok(dib.dsBmih.biHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
12481 dib.dsBmih.biHeight, test_data[i].name);
12482 ok(dib.dsBmih.biPlanes == 1, "Got unexpected plane count %u for format %s.\n",
12483 dib.dsBmih.biPlanes, test_data[i].name);
12484 ok(dib.dsBmih.biBitCount == U1(test_data[i].format).dwRGBBitCount,
12485 "Got unexpected bit count %u for format %s.\n",
12486 dib.dsBmih.biBitCount, test_data[i].name);
12487 ok(dib.dsBmih.biCompression == (U1(test_data[i].format).dwRGBBitCount == 16 ? BI_BITFIELDS : BI_RGB)
12488 || broken(U1(test_data[i].format).dwRGBBitCount == 32 && dib.dsBmih.biCompression == BI_BITFIELDS),
12489 "Got unexpected compression %#x for format %s.\n",
12490 dib.dsBmih.biCompression, test_data[i].name);
12491 ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
12492 dib.dsBmih.biSizeImage, test_data[i].name);
12493 ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n",
12494 dib.dsBmih.biXPelsPerMeter, test_data[i].name);
12495 ok(!dib.dsBmih.biYPelsPerMeter, "Got unexpected vertical resolution %d for format %s.\n",
12496 dib.dsBmih.biYPelsPerMeter, test_data[i].name);
12497 ok(!dib.dsBmih.biClrUsed, "Got unexpected used colour count %u for format %s.\n",
12498 dib.dsBmih.biClrUsed, test_data[i].name);
12499 ok(!dib.dsBmih.biClrImportant, "Got unexpected important colour count %u for format %s.\n",
12500 dib.dsBmih.biClrImportant, test_data[i].name);
12502 if (dib.dsBmih.biCompression == BI_BITFIELDS)
12504 ok((dib.dsBitfields[0] == U2(test_data[i].format).dwRBitMask
12505 && dib.dsBitfields[1] == U3(test_data[i].format).dwGBitMask
12506 && dib.dsBitfields[2] == U4(test_data[i].format).dwBBitMask)
12507 || broken(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2]),
12508 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
12509 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
12511 else
12513 ok(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2],
12514 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
12515 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
12517 ok(!dib.dshSection, "Got unexpected section %p for format %s.\n", dib.dshSection, test_data[i].name);
12518 ok(!dib.dsOffset, "Got unexpected offset %u for format %s.\n", dib.dsOffset, test_data[i].name);
12520 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12521 ok(hr == DD_OK, "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12523 else
12525 ok(!dc, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
12528 IDirectDrawSurface7_Release(surface);
12530 if (FAILED(hr))
12531 continue;
12533 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
12534 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_TEXTUREMANAGE;
12535 if (FAILED(hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
12537 skip("Failed to create cube texture for format %s (hr %#x), skipping tests.\n", test_data[i].name, hr);
12538 continue;
12541 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &surface2);
12542 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
12543 hr = IDirectDrawSurface7_GetAttachedSurface(surface2, &caps, &tmp);
12544 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
12545 IDirectDrawSurface7_Release(surface2);
12546 hr = IDirectDrawSurface7_GetAttachedSurface(tmp, &caps, &surface2);
12547 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
12548 IDirectDrawSurface7_Release(tmp);
12550 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12551 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12552 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12553 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12554 hr = IDirectDrawSurface7_GetDC(surface2, &dc);
12555 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12556 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc);
12557 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12559 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12560 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12561 dc2 = (void *)0x1234;
12562 hr = IDirectDrawSurface7_GetDC(surface, &dc2);
12563 ok(hr == DDERR_DCALREADYCREATED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12564 ok(dc2 == (void *)0x1234, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
12565 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12566 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12567 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12568 ok(hr == DDERR_NODC, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12570 map_desc.dwSize = sizeof(map_desc);
12571 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12572 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12573 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12574 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12575 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12576 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12577 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12578 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12580 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12581 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12582 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12583 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12584 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12585 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12587 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12588 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12589 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12590 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12591 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12592 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12593 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12594 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12596 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12597 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12598 hr = IDirectDrawSurface7_GetDC(surface2, &dc2);
12599 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12600 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc2);
12601 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12602 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12603 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12605 hr = IDirectDrawSurface7_GetDC(surface2, &dc);
12606 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12607 hr = IDirectDrawSurface7_GetDC(surface, &dc2);
12608 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12609 hr = IDirectDrawSurface7_ReleaseDC(surface, dc2);
12610 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12611 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc);
12612 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12614 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12615 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12616 hr = IDirectDrawSurface7_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12617 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12618 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
12619 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12620 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12621 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12623 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12624 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12625 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12626 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12627 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12628 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12629 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12630 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12632 hr = IDirectDrawSurface7_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12633 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12634 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12635 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12636 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12637 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12638 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
12639 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12641 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12642 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12643 hr = IDirectDrawSurface7_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12644 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12645 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
12646 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12647 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12648 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12650 hr = IDirectDrawSurface7_GetDC(surface2, &dc);
12651 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12652 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12653 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12654 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12655 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12656 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc);
12657 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12659 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12660 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12661 hr = IDirectDrawSurface7_GetDC(surface2, &dc);
12662 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12663 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12664 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12665 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc);
12666 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12667 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12668 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12670 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
12671 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12672 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12673 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12674 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
12675 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12676 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12677 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12678 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
12679 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12681 IDirectDrawSurface7_Release(surface2);
12682 IDirectDrawSurface7_Release(surface);
12685 IDirectDraw7_Release(ddraw);
12686 DestroyWindow(window);
12689 static void test_draw_primitive(void)
12691 static WORD indices[] = {0, 1, 2, 3};
12692 static struct vec3 quad[] =
12694 {-1.0f, -1.0f, 0.0f},
12695 {-1.0f, 1.0f, 0.0f},
12696 { 1.0f, -1.0f, 0.0f},
12697 { 1.0f, 1.0f, 0.0f},
12699 D3DDRAWPRIMITIVESTRIDEDDATA strided;
12700 D3DVERTEXBUFFERDESC vb_desc;
12701 IDirect3DVertexBuffer7 *vb;
12702 IDirect3DDevice7 *device;
12703 IDirect3D7 *d3d;
12704 ULONG refcount;
12705 HWND window;
12706 HRESULT hr;
12707 void *data;
12709 window = create_window();
12710 if (!(device = create_device(window, DDSCL_NORMAL)))
12712 skip("Failed to create a 3D device, skipping test.\n");
12713 DestroyWindow(window);
12714 return;
12717 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
12718 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
12720 memset(&vb_desc, 0, sizeof(vb_desc));
12721 vb_desc.dwSize = sizeof(vb_desc);
12722 vb_desc.dwFVF = D3DFVF_XYZ;
12723 vb_desc.dwNumVertices = 4;
12724 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &vb, 0);
12725 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
12727 IDirect3D7_Release(d3d);
12729 memset(&strided, 0, sizeof(strided));
12731 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, NULL, 0, 0);
12732 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12733 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device,
12734 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, NULL, 0, 0);
12735 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12736 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, NULL, 0, 0);
12737 todo_wine ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
12738 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, NULL, 0, 0);
12739 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12740 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, 0);
12741 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12742 hr = IDirect3DDevice7_DrawPrimitiveStrided(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, 0);
12743 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12744 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, 0);
12745 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12747 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, indices, 4, 0);
12748 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12749 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device,
12750 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, indices, 4, 0);
12751 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12752 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, indices, 4, 0);
12753 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12755 strided.position.lpvData = quad;
12756 strided.position.dwStride = sizeof(*quad);
12757 hr = IDirect3DVertexBuffer7_Lock(vb, 0, &data, NULL);
12758 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
12759 memcpy(data, quad, sizeof(quad));
12760 hr = IDirect3DVertexBuffer7_Unlock(vb);
12761 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
12763 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, NULL, 0, 0);
12764 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12765 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device,
12766 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, NULL, 0, 0);
12767 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12768 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, NULL, 0, 0);
12769 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12770 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
12771 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12772 hr = IDirect3DDevice7_DrawPrimitiveStrided(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, 0);
12773 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12774 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, 0);
12775 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12777 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, indices, 4, 0);
12778 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12779 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device,
12780 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, indices, 4, 0);
12781 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12782 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, indices, 4, 0);
12783 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12785 IDirect3DVertexBuffer7_Release(vb);
12786 refcount = IDirect3DDevice7_Release(device);
12787 ok(!refcount, "Device has %u references left.\n", refcount);
12788 DestroyWindow(window);
12791 static void test_edge_antialiasing_blending(void)
12793 IDirectDrawSurface7 *offscreen;
12794 DDSURFACEDESC2 surface_desc;
12795 D3DDEVICEDESC7 device_desc;
12796 IDirect3DDevice7 *device;
12797 IDirectDraw7 *ddraw;
12798 IDirect3D7 *d3d;
12799 ULONG refcount;
12800 D3DCOLOR color;
12801 HWND window;
12802 HRESULT hr;
12804 static D3DMATRIX mat =
12806 1.0f, 0.0f, 0.0f, 0.0f,
12807 0.0f, 1.0f, 0.0f, 0.0f,
12808 0.0f, 0.0f, 1.0f, 0.0f,
12809 0.0f, 0.0f, 0.0f, 1.0f,
12811 static struct
12813 struct vec3 position;
12814 DWORD diffuse;
12816 green_quad[] =
12818 {{-1.0f, -1.0f, 0.1f}, 0x7f00ff00},
12819 {{-1.0f, 1.0f, 0.1f}, 0x7f00ff00},
12820 {{ 1.0f, -1.0f, 0.1f}, 0x7f00ff00},
12821 {{ 1.0f, 1.0f, 0.1f}, 0x7f00ff00},
12823 static struct
12825 struct vec3 position;
12826 DWORD diffuse;
12828 red_quad[] =
12830 {{-1.0f, -1.0f, 0.1f}, 0xccff0000},
12831 {{-1.0f, 1.0f, 0.1f}, 0xccff0000},
12832 {{ 1.0f, -1.0f, 0.1f}, 0xccff0000},
12833 {{ 1.0f, 1.0f, 0.1f}, 0xccff0000},
12836 window = create_window();
12837 if (!(device = create_device(window, DDSCL_NORMAL)))
12839 skip("Failed to create a 3D device.\n");
12840 DestroyWindow(window);
12841 return;
12844 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
12845 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
12846 trace("Line edge antialiasing support: %#x.\n",
12847 device_desc.dpcLineCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
12848 trace("Triangle edge antialiasing support: %#x.\n",
12849 device_desc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
12851 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
12852 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
12853 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
12854 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
12855 IDirect3D7_Release(d3d);
12857 memset(&surface_desc, 0, sizeof(surface_desc));
12858 surface_desc.dwSize = sizeof(surface_desc);
12859 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
12860 surface_desc.dwWidth = 640;
12861 surface_desc.dwHeight = 480;
12862 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
12863 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
12864 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
12865 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
12866 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
12867 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
12868 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
12869 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
12870 ok(hr == D3D_OK, "Creating the offscreen render target failed, hr %#x.\n", hr);
12872 hr = IDirect3DDevice7_SetRenderTarget(device, offscreen, 0);
12873 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
12875 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
12876 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
12877 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
12878 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
12879 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
12880 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
12881 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
12882 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
12883 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
12884 ok(SUCCEEDED(hr), "Failed to disable Z test, hr %#x.\n", hr);
12885 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
12886 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
12887 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
12888 ok(SUCCEEDED(hr), "Failed to disable stencil test, hr %#x.\n", hr);
12889 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
12890 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
12891 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
12892 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
12894 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
12895 ok(SUCCEEDED(hr), "Failed to enable blending, hr %#x.\n", hr);
12896 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
12897 ok(SUCCEEDED(hr), "Failed to set src blend, hr %#x.\n", hr);
12898 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_DESTALPHA);
12899 ok(SUCCEEDED(hr), "Failed to set dest blend, hr %#x.\n", hr);
12901 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
12902 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
12903 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
12904 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
12905 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
12906 ok(SUCCEEDED(hr), "Failed to set alpha op, hr %#x.\n", hr);
12907 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
12908 ok(SUCCEEDED(hr), "Failed to set alpha arg, hr %#x.\n", hr);
12910 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
12911 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12912 hr = IDirect3DDevice7_BeginScene(device);
12913 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12914 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12915 green_quad, 4, 0);
12916 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12917 hr = IDirect3DDevice7_EndScene(device);
12918 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12919 color = get_surface_color(offscreen, 320, 240);
12920 ok(compare_color(color, 0x00cc7f00, 1), "Got unexpected color 0x%08x.\n", color);
12922 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
12923 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12924 hr = IDirect3DDevice7_BeginScene(device);
12925 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12926 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12927 red_quad, 4, 0);
12928 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12929 hr = IDirect3DDevice7_EndScene(device);
12930 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12931 color = get_surface_color(offscreen, 320, 240);
12932 ok(compare_color(color, 0x00cc7f00, 1), "Got unexpected color 0x%08x.\n", color);
12934 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
12935 ok(SUCCEEDED(hr), "Failed to disable blending, hr %#x.\n", hr);
12937 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
12938 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12939 hr = IDirect3DDevice7_BeginScene(device);
12940 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12941 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12942 green_quad, 4, 0);
12943 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12944 hr = IDirect3DDevice7_EndScene(device);
12945 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12946 color = get_surface_color(offscreen, 320, 240);
12947 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12949 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
12950 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12951 hr = IDirect3DDevice7_BeginScene(device);
12952 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12953 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12954 red_quad, 4, 0);
12955 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12956 hr = IDirect3DDevice7_EndScene(device);
12957 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12958 color = get_surface_color(offscreen, 320, 240);
12959 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
12961 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_EDGEANTIALIAS, TRUE);
12962 ok(SUCCEEDED(hr), "Failed to enable edge antialiasing, hr %#x.\n", hr);
12964 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
12965 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12966 hr = IDirect3DDevice7_BeginScene(device);
12967 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12968 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12969 green_quad, 4, 0);
12970 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12971 hr = IDirect3DDevice7_EndScene(device);
12972 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12973 color = get_surface_color(offscreen, 320, 240);
12974 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
12976 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
12977 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12978 hr = IDirect3DDevice7_BeginScene(device);
12979 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12980 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
12981 red_quad, 4, 0);
12982 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12983 hr = IDirect3DDevice7_EndScene(device);
12984 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12985 color = get_surface_color(offscreen, 320, 240);
12986 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
12988 IDirectDrawSurface7_Release(offscreen);
12989 IDirectDraw7_Release(ddraw);
12990 refcount = IDirect3DDevice7_Release(device);
12991 ok(!refcount, "Device has %u references left.\n", refcount);
12992 DestroyWindow(window);
12995 static void test_display_mode_surface_pixel_format(void)
12997 unsigned int width, height, bpp;
12998 IDirectDrawSurface7 *surface;
12999 DDSURFACEDESC2 surface_desc;
13000 IDirectDraw7 *ddraw;
13001 ULONG refcount;
13002 HWND window;
13003 HRESULT hr;
13005 if (!(ddraw = create_ddraw()))
13007 skip("Failed to create ddraw.\n");
13008 return;
13011 surface_desc.dwSize = sizeof(surface_desc);
13012 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
13013 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr);
13014 width = surface_desc.dwWidth;
13015 height = surface_desc.dwHeight;
13017 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
13018 0, 0, width, height, NULL, NULL, NULL, NULL);
13019 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
13020 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13022 bpp = 0;
13023 if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 16, 0, 0)))
13024 bpp = 16;
13025 if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 24, 0, 0)))
13026 bpp = 24;
13027 if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
13028 bpp = 32;
13029 ok(bpp, "Set display mode failed.\n");
13031 surface_desc.dwSize = sizeof(surface_desc);
13032 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
13033 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr);
13034 ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width);
13035 ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height);
13036 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
13037 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
13039 memset(&surface_desc, 0, sizeof(surface_desc));
13040 surface_desc.dwSize = sizeof(surface_desc);
13041 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
13042 U5(surface_desc).dwBackBufferCount = 1;
13043 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE;
13044 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
13045 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
13046 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
13047 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
13048 ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width);
13049 ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height);
13050 ok(U4(surface_desc).ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n",
13051 U4(surface_desc).ddpfPixelFormat.dwFlags);
13052 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
13053 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
13054 IDirectDrawSurface7_Release(surface);
13056 memset(&surface_desc, 0, sizeof(surface_desc));
13057 surface_desc.dwSize = sizeof(surface_desc);
13058 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
13059 surface_desc.dwWidth = width;
13060 surface_desc.dwHeight = height;
13061 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13062 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
13063 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
13064 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
13065 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
13066 ok(U4(surface_desc).ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n",
13067 U4(surface_desc).ddpfPixelFormat.dwFlags);
13068 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
13069 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
13070 IDirectDrawSurface7_Release(surface);
13072 refcount = IDirectDraw7_Release(ddraw);
13073 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
13074 DestroyWindow(window);
13077 static void test_surface_desc_size(void)
13079 union
13081 DWORD dwSize;
13082 DDSURFACEDESC desc1;
13083 DDSURFACEDESC2 desc2;
13084 BYTE blob[1024];
13085 } desc;
13086 IDirectDrawSurface7 *surface7;
13087 IDirectDrawSurface3 *surface3;
13088 IDirectDrawSurface *surface;
13089 DDSURFACEDESC2 surface_desc;
13090 HRESULT expected_hr, hr;
13091 IDirectDraw7 *ddraw;
13092 unsigned int i, j;
13093 ULONG refcount;
13095 static const struct
13097 unsigned int caps;
13098 const char *name;
13100 surface_caps[] =
13102 {DDSCAPS_OFFSCREENPLAIN, "offscreenplain"},
13103 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, "systemmemory texture"},
13104 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, "videomemory texture"},
13106 static const unsigned int desc_sizes[] =
13108 sizeof(DDSURFACEDESC),
13109 sizeof(DDSURFACEDESC2),
13110 sizeof(DDSURFACEDESC) + 1,
13111 sizeof(DDSURFACEDESC2) + 1,
13112 2 * sizeof(DDSURFACEDESC),
13113 2 * sizeof(DDSURFACEDESC2),
13114 sizeof(DDSURFACEDESC) - 1,
13115 sizeof(DDSURFACEDESC2) - 1,
13116 sizeof(DDSURFACEDESC) / 2,
13117 sizeof(DDSURFACEDESC2) / 2,
13121 sizeof(desc) / 2,
13122 sizeof(desc) - 100,
13125 if (!(ddraw = create_ddraw()))
13127 skip("Failed to create ddraw.\n");
13128 return;
13130 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
13131 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13133 for (i = 0; i < ARRAY_SIZE(surface_caps); ++i)
13135 memset(&surface_desc, 0, sizeof(surface_desc));
13136 surface_desc.dwSize = sizeof(surface_desc);
13137 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
13138 surface_desc.ddsCaps.dwCaps = surface_caps[i].caps;
13139 surface_desc.dwHeight = 128;
13140 surface_desc.dwWidth = 128;
13141 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface7, NULL)))
13143 skip("Failed to create surface, type %s.\n", surface_caps[i].name);
13144 continue;
13146 hr = IDirectDrawSurface_QueryInterface(surface7, &IID_IDirectDrawSurface, (void **)&surface);
13147 ok(hr == DD_OK, "Failed to query IDirectDrawSurface, hr %#x, type %s.\n", hr, surface_caps[i].name);
13148 hr = IDirectDrawSurface_QueryInterface(surface7, &IID_IDirectDrawSurface3, (void **)&surface3);
13149 ok(hr == DD_OK, "Failed to query IDirectDrawSurface3, hr %#x, type %s.\n", hr, surface_caps[i].name);
13151 /* GetSurfaceDesc() */
13152 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
13154 memset(&desc, 0, sizeof(desc));
13155 desc.dwSize = desc_sizes[j];
13156 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC) ? DD_OK : DDERR_INVALIDPARAMS;
13157 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &desc.desc1);
13158 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13159 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13161 memset(&desc, 0, sizeof(desc));
13162 desc.dwSize = desc_sizes[j];
13163 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC) ? DD_OK : DDERR_INVALIDPARAMS;
13164 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &desc.desc1);
13165 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13166 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13168 memset(&desc, 0, sizeof(desc));
13169 desc.dwSize = desc_sizes[j];
13170 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC2) ? DD_OK : DDERR_INVALIDPARAMS;
13171 hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &desc.desc2);
13172 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13173 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13176 /* Lock() */
13177 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
13179 const BOOL ignore_size = surface_caps[i].caps & DDSCAPS_TEXTURE
13180 && !(surface_caps[i].caps & DDSCAPS_VIDEOMEMORY);
13181 const BOOL valid_size = desc_sizes[j] == sizeof(DDSURFACEDESC)
13182 || desc_sizes[j] == sizeof(DDSURFACEDESC2);
13183 DWORD expected_texture_stage;
13185 memset(&desc, 0, sizeof(desc));
13186 desc.dwSize = desc_sizes[j];
13187 desc.desc2.dwTextureStage = 0xdeadbeef;
13188 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
13189 hr = IDirectDrawSurface_Lock(surface, NULL, &desc.desc1, 0, 0);
13190 expected_hr = ignore_size || valid_size ? DD_OK : DDERR_INVALIDPARAMS;
13191 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13192 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13193 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
13194 desc_sizes[j], desc.dwSize, surface_caps[i].name);
13195 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
13196 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
13197 if (SUCCEEDED(hr))
13199 ok(desc.desc1.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
13200 desc.desc1.dwWidth, desc_sizes[j], surface_caps[i].name);
13201 ok(desc.desc1.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
13202 desc.desc1.dwHeight, desc_sizes[j], surface_caps[i].name);
13203 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
13204 todo_wine_if(!expected_texture_stage)
13205 ok(desc.desc2.dwTextureStage == expected_texture_stage,
13206 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
13207 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
13208 IDirectDrawSurface_Unlock(surface, NULL);
13211 memset(&desc, 0, sizeof(desc));
13212 desc.dwSize = desc_sizes[j];
13213 desc.desc2.dwTextureStage = 0xdeadbeef;
13214 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
13215 hr = IDirectDrawSurface3_Lock(surface3, NULL, &desc.desc1, 0, 0);
13216 expected_hr = ignore_size || valid_size ? DD_OK : DDERR_INVALIDPARAMS;
13217 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13218 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13219 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
13220 desc_sizes[j], desc.dwSize, surface_caps[i].name);
13221 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
13222 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
13223 if (SUCCEEDED(hr))
13225 ok(desc.desc1.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
13226 desc.desc1.dwWidth, desc_sizes[j], surface_caps[i].name);
13227 ok(desc.desc1.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
13228 desc.desc1.dwHeight, desc_sizes[j], surface_caps[i].name);
13229 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
13230 todo_wine_if(!expected_texture_stage)
13231 ok(desc.desc2.dwTextureStage == expected_texture_stage,
13232 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
13233 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
13234 IDirectDrawSurface3_Unlock(surface3, NULL);
13237 memset(&desc, 0, sizeof(desc));
13238 desc.dwSize = desc_sizes[j];
13239 desc.desc2.dwTextureStage = 0xdeadbeef;
13240 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
13241 hr = IDirectDrawSurface7_Lock(surface7, NULL, &desc.desc2, 0, 0);
13242 expected_hr = ignore_size || valid_size ? DD_OK : DDERR_INVALIDPARAMS;
13243 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13244 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13245 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
13246 desc_sizes[j], desc.dwSize, surface_caps[i].name);
13247 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
13248 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
13249 if (SUCCEEDED(hr))
13251 ok(desc.desc2.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
13252 desc.desc2.dwWidth, desc_sizes[j], surface_caps[i].name);
13253 ok(desc.desc2.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
13254 desc.desc2.dwHeight, desc_sizes[j], surface_caps[i].name);
13255 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
13256 ok(desc.desc2.dwTextureStage == expected_texture_stage,
13257 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
13258 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
13259 IDirectDrawSurface7_Unlock(surface7, NULL);
13263 IDirectDrawSurface7_Release(surface7);
13264 IDirectDrawSurface3_Release(surface3);
13265 IDirectDrawSurface_Release(surface);
13268 /* GetDisplayMode() */
13269 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
13271 memset(&desc, 0xcc, sizeof(desc));
13272 desc.dwSize = desc_sizes[j];
13273 expected_hr = (desc.dwSize == sizeof(DDSURFACEDESC) || desc.dwSize == sizeof(DDSURFACEDESC2))
13274 ? DD_OK : DDERR_INVALIDPARAMS;
13275 hr = IDirectDraw7_GetDisplayMode(ddraw, &desc.desc2);
13276 ok(hr == expected_hr, "Got hr %#x, expected %#x, size %u.\n", hr, expected_hr, desc_sizes[j]);
13277 if (SUCCEEDED(hr))
13279 ok(desc.dwSize == sizeof(DDSURFACEDESC2), "Wrong size %u for %u.\n", desc.dwSize, desc_sizes[j]);
13280 ok(desc.blob[desc_sizes[j]] == 0xcc, "Overflow for size %u.\n", desc_sizes[j]);
13281 ok(desc.blob[desc_sizes[j] - 1] != 0xcc, "Struct not cleared for size %u.\n", desc_sizes[j]);
13285 refcount = IDirectDraw7_Release(ddraw);
13286 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
13289 static void test_get_surface_from_dc(void)
13291 IDirectDrawSurface *surface1, *tmp1;
13292 IDirectDrawSurface7 *surface, *tmp;
13293 DDSURFACEDESC2 surface_desc;
13294 IDirectDraw7 *ddraw;
13295 HDC dc, device_dc;
13296 ULONG refcount;
13297 HWND window;
13298 HRESULT hr;
13299 DWORD ret;
13301 window = create_window();
13302 ddraw = create_ddraw();
13303 ok(!!ddraw, "Failed to create a ddraw object.\n");
13304 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
13305 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13307 memset(&surface_desc, 0, sizeof(surface_desc));
13308 surface_desc.dwSize = sizeof(surface_desc);
13309 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
13310 surface_desc.dwWidth = 64;
13311 surface_desc.dwHeight = 64;
13312 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13314 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
13315 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13316 hr = IDirectDrawSurface7_QueryInterface(surface, &IID_IDirectDrawSurface, (void **)&surface1);
13317 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
13319 refcount = get_refcount((IUnknown *)surface1);
13320 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
13321 refcount = get_refcount((IUnknown *)surface);
13322 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
13324 hr = IDirectDrawSurface7_GetDC(surface, &dc);
13325 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
13327 tmp1 = (void *)0xdeadbeef;
13328 device_dc = (void *)0xdeadbeef;
13329 hr = GetSurfaceFromDC(NULL, &tmp1, &device_dc);
13330 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
13331 ok(!tmp1, "Got unexpected surface %p.\n", tmp1);
13332 ok(!device_dc, "Got unexpected device_dc %p.\n", device_dc);
13334 device_dc = (void *)0xdeadbeef;
13335 hr = GetSurfaceFromDC(dc, NULL, &device_dc);
13336 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
13337 ok(device_dc == (void *)0xdeadbeef, "Got unexpected device_dc %p.\n", device_dc);
13339 tmp1 = (void *)0xdeadbeef;
13340 hr = GetSurfaceFromDC(dc, &tmp1, NULL);
13341 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
13342 ok(!tmp1, "Got unexpected surface %p.\n", tmp1);
13344 hr = GetSurfaceFromDC(dc, &tmp1, &device_dc);
13345 ok(SUCCEEDED(hr), "GetSurfaceFromDC failed, hr %#x.\n", hr);
13346 ok(tmp1 == surface1, "Got unexpected surface %p, expected %p.\n", tmp1, surface1);
13347 IDirectDrawSurface_Release(tmp1);
13349 ret = GetObjectType(device_dc);
13350 todo_wine ok(ret == OBJ_DC, "Got unexpected object type %#x.\n", ret);
13351 ret = GetDeviceCaps(device_dc, TECHNOLOGY);
13352 todo_wine ok(ret == DT_RASDISPLAY, "Got unexpected technology %#x.\n", ret);
13354 hr = IDirectDraw7_GetSurfaceFromDC(ddraw, dc, NULL);
13355 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
13357 hr = IDirectDraw7_GetSurfaceFromDC(ddraw, dc, &tmp);
13358 ok(SUCCEEDED(hr), "GetSurfaceFromDC failed, hr %#x.\n", hr);
13359 ok(tmp == surface, "Got unexpected surface %p, expected %p.\n", tmp, surface);
13361 refcount = get_refcount((IUnknown *)surface1);
13362 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
13363 refcount = get_refcount((IUnknown *)surface);
13364 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
13366 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
13367 ok(SUCCEEDED(hr), "ReleaseDC failed, hr %#x.\n", hr);
13369 IDirectDrawSurface_Release(tmp);
13371 dc = CreateCompatibleDC(NULL);
13372 ok(!!dc, "CreateCompatibleDC failed.\n");
13374 tmp1 = (void *)0xdeadbeef;
13375 device_dc = (void *)0xdeadbeef;
13376 hr = GetSurfaceFromDC(dc, &tmp1, &device_dc);
13377 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
13378 ok(!tmp1, "Got unexpected surface %p.\n", tmp1);
13379 ok(!device_dc, "Got unexpected device_dc %p.\n", device_dc);
13381 tmp = (void *)0xdeadbeef;
13382 hr = IDirectDraw7_GetSurfaceFromDC(ddraw, dc, &tmp);
13383 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
13384 ok(!tmp, "Got unexpected surface %p.\n", tmp);
13386 ok(DeleteDC(dc), "DeleteDC failed.\n");
13388 tmp = (void *)0xdeadbeef;
13389 hr = IDirectDraw7_GetSurfaceFromDC(ddraw, NULL, &tmp);
13390 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
13391 ok(!tmp, "Got unexpected surface %p.\n", tmp);
13393 IDirectDrawSurface7_Release(surface);
13394 IDirectDrawSurface_Release(surface1);
13395 IDirectDraw7_Release(ddraw);
13396 DestroyWindow(window);
13399 static void test_ck_operation(void)
13401 IDirectDrawSurface7 *src, *dst;
13402 IDirectDrawSurface *src1, *dst1;
13403 DDSURFACEDESC2 surface_desc;
13404 IDirectDraw7 *ddraw;
13405 ULONG refcount;
13406 HWND window;
13407 HRESULT hr;
13408 D3DCOLOR *color;
13409 unsigned int i;
13410 DDCOLORKEY ckey;
13411 DDBLTFX fx;
13413 window = create_window();
13414 ddraw = create_ddraw();
13415 ok(!!ddraw, "Failed to create a ddraw object.\n");
13416 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
13417 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13419 memset(&surface_desc, 0, sizeof(surface_desc));
13420 surface_desc.dwSize = sizeof(surface_desc);
13421 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
13422 surface_desc.dwWidth = 4;
13423 surface_desc.dwHeight = 1;
13424 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13425 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
13426 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
13427 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
13428 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
13429 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
13430 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
13431 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13433 surface_desc.dwFlags |= DDSD_CKSRCBLT;
13434 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff00ff;
13435 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff00ff;
13436 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
13437 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13439 hr = IDirectDrawSurface7_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13440 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13441 ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n");
13442 color = surface_desc.lpSurface;
13443 color[0] = 0x77010203;
13444 color[1] = 0x00010203;
13445 color[2] = 0x77ff00ff;
13446 color[3] = 0x00ff00ff;
13447 hr = IDirectDrawSurface7_Unlock(src, NULL);
13448 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13450 for (i = 0; i < 2; ++i)
13452 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13453 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13454 color = surface_desc.lpSurface;
13455 color[0] = 0xcccccccc;
13456 color[1] = 0xcccccccc;
13457 color[2] = 0xcccccccc;
13458 color[3] = 0xcccccccc;
13459 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13460 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13462 if (i)
13464 hr = IDirectDrawSurface7_BltFast(dst, 0, 0, src, NULL, DDBLTFAST_SRCCOLORKEY);
13465 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13467 else
13469 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, NULL);
13470 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13473 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT | DDLOCK_READONLY, NULL);
13474 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13475 ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n");
13476 color = surface_desc.lpSurface;
13477 /* Different behavior on some drivers / windows versions. Some versions ignore the X channel when
13478 * color keying, but copy it to the destination surface. Others (sysmem surfaces) apply it for
13479 * color keying, but do not copy it into the destination surface. Nvidia neither uses it for
13480 * color keying nor copies it. */
13481 ok((color[0] == 0x77010203 && color[1] == 0x00010203
13482 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* AMD, Wine */
13483 || broken(color[0] == 0x00010203 && color[1] == 0x00010203
13484 && color[2] == 0x00ff00ff && color[3] == 0xcccccccc) /* Sysmem surfaces? */
13485 || broken(color[0] == 0x00010203 && color[1] == 0x00010203
13486 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Nvidia */
13487 || broken(color[0] == 0xff010203 && color[1] == 0xff010203
13488 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Testbot */,
13489 "Destination data after blitting is %08x %08x %08x %08x, i=%u.\n",
13490 color[0], color[1], color[2], color[3], i);
13491 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13492 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13495 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13496 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
13497 ok(ckey.dwColorSpaceLowValue == 0x00ff00ff && ckey.dwColorSpaceHighValue == 0x00ff00ff,
13498 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13500 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
13501 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13502 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13504 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
13505 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13506 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
13507 ok(ckey.dwColorSpaceLowValue == 0x0000ff00 && ckey.dwColorSpaceHighValue == 0x0000ff00,
13508 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13510 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0;
13511 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0;
13512 hr = IDirectDrawSurface7_GetSurfaceDesc(src, &surface_desc);
13513 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
13514 ok(surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue == 0x0000ff00
13515 && surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue == 0x0000ff00,
13516 "Got unexpected color key low=%08x high=%08x.\n", surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue,
13517 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue);
13519 /* Test SetColorKey with dwColorSpaceHighValue < dwColorSpaceLowValue */
13520 ckey.dwColorSpaceLowValue = 0x000000ff;
13521 ckey.dwColorSpaceHighValue = 0x00000000;
13522 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13523 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13525 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
13526 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13527 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
13528 ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff,
13529 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13531 ckey.dwColorSpaceLowValue = 0x000000ff;
13532 ckey.dwColorSpaceHighValue = 0x00000001;
13533 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13534 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13536 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
13537 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13538 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
13539 ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff,
13540 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13542 ckey.dwColorSpaceLowValue = 0x000000fe;
13543 ckey.dwColorSpaceHighValue = 0x000000fd;
13544 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13545 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13547 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
13548 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13549 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
13550 ok(ckey.dwColorSpaceLowValue == 0x000000fe && ckey.dwColorSpaceHighValue == 0x000000fe,
13551 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13553 IDirectDrawSurface7_Release(src);
13554 IDirectDrawSurface7_Release(dst);
13556 /* Test source and destination keys and where they are read from. Use a surface with alpha
13557 * to avoid driver-dependent content in the X channel. */
13558 memset(&surface_desc, 0, sizeof(surface_desc));
13559 surface_desc.dwSize = sizeof(surface_desc);
13560 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
13561 surface_desc.dwWidth = 6;
13562 surface_desc.dwHeight = 1;
13563 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13564 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
13565 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
13566 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
13567 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
13568 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
13569 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
13570 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
13571 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13572 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
13573 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13575 ckey.dwColorSpaceLowValue = 0x0000ff00;
13576 ckey.dwColorSpaceHighValue = 0x0000ff00;
13577 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
13578 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13579 ckey.dwColorSpaceLowValue = 0x00ff0000;
13580 ckey.dwColorSpaceHighValue = 0x00ff0000;
13581 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_DESTBLT, &ckey);
13582 ok(SUCCEEDED(hr) || hr == DDERR_NOCOLORKEYHW, "Failed to set color key, hr %#x.\n", hr);
13583 if (FAILED(hr))
13585 /* Nvidia reject dest keys, AMD allows them. This applies to vidmem and sysmem surfaces. */
13586 skip("Failed to set destination color key, skipping related tests.\n");
13587 goto done;
13590 ckey.dwColorSpaceLowValue = 0x000000ff;
13591 ckey.dwColorSpaceHighValue = 0x000000ff;
13592 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13593 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13594 ckey.dwColorSpaceLowValue = 0x000000aa;
13595 ckey.dwColorSpaceHighValue = 0x000000aa;
13596 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_DESTBLT, &ckey);
13597 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13599 memset(&fx, 0, sizeof(fx));
13600 fx.dwSize = sizeof(fx);
13601 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x00110000;
13602 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x00110000;
13603 fx.ddckDestColorkey.dwColorSpaceHighValue = 0x00001100;
13604 fx.ddckDestColorkey.dwColorSpaceLowValue = 0x00001100;
13606 hr = IDirectDrawSurface7_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13607 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13608 color = surface_desc.lpSurface;
13609 color[0] = 0x000000ff; /* Applies to src blt key in src surface. */
13610 color[1] = 0x000000aa; /* Applies to dst blt key in src surface. */
13611 color[2] = 0x00ff0000; /* Dst color key in dst surface. */
13612 color[3] = 0x0000ff00; /* Src color key in dst surface. */
13613 color[4] = 0x00001100; /* Src color key in ddbltfx. */
13614 color[5] = 0x00110000; /* Dst color key in ddbltfx. */
13615 hr = IDirectDrawSurface7_Unlock(src, NULL);
13616 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13618 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13619 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13620 color = surface_desc.lpSurface;
13621 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
13622 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13623 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13625 /* Test a blit without keying. */
13626 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, 0, &fx);
13627 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13629 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13630 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13631 color = surface_desc.lpSurface;
13632 /* Should have copied src data unmodified to dst. */
13633 ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
13634 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
13635 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13636 color[0], color[1], color[2], color[3], color[4], color[5]);
13638 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
13639 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13640 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13642 /* Src key. */
13643 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx);
13644 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13646 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13647 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13648 color = surface_desc.lpSurface;
13649 /* Src key applied to color[0]. It is unmodified, the others are copied. */
13650 ok(color[0] == 0x55555555 && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
13651 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
13652 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13653 color[0], color[1], color[2], color[3], color[4], color[5]);
13655 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
13656 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13657 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13659 /* Src override. */
13660 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, &fx);
13661 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13663 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13664 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13665 color = surface_desc.lpSurface;
13666 /* Override key applied to color[5]. It is unmodified, the others are copied. */
13667 ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
13668 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x55555555,
13669 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13670 color[0], color[1], color[2], color[3], color[4], color[5]);
13672 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
13673 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13674 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13676 /* Src override AND src key. That is not supposed to work. */
13677 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE, &fx);
13678 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13680 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13681 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13682 color = surface_desc.lpSurface;
13683 /* Ensure the destination was not changed. */
13684 ok(color[0] == 0x55555555 && color[1] == 0x55555555 && color[2] == 0x55555555 &&
13685 color[3] == 0x55555555 && color[4] == 0x55555555 && color[5] == 0x55555555,
13686 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13687 color[0], color[1], color[2], color[3], color[4], color[5]);
13689 /* Use different dst colors for the dst key test. */
13690 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13691 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13692 color[2] = 0x00001100; /* Dest key in override. */
13693 color[3] = 0x00001100; /* Dest key in override. */
13694 color[4] = 0x000000aa; /* Dest key in src surface. */
13695 color[5] = 0x000000aa; /* Dest key in src surface. */
13696 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13697 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13699 /* Dest key blit. The key is taken from the DESTINATION surface in v7! */
13700 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
13701 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13703 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13704 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13705 color = surface_desc.lpSurface;
13706 /* Dst key applied to color[0,1], they are the only changed pixels. */
13707 todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 &&
13708 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
13709 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13710 color[0], color[1], color[2], color[3], color[4], color[5]);
13712 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13713 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13714 color[2] = 0x00001100; /* Dest key in override. */
13715 color[3] = 0x00001100; /* Dest key in override. */
13716 color[4] = 0x000000aa; /* Dest key in src surface. */
13717 color[5] = 0x000000aa; /* Dest key in src surface. */
13718 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13719 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13721 /* What happens with a QI'd older version of the interface? It takes the key
13722 * from the source surface. */
13723 hr = IDirectDrawSurface7_QueryInterface(src, &IID_IDirectDrawSurface, (void **)&src1);
13724 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
13725 hr = IDirectDrawSurface7_QueryInterface(dst, &IID_IDirectDrawSurface, (void **)&dst1);
13726 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
13728 hr = IDirectDrawSurface_Blt(dst1, NULL, src1, NULL, DDBLT_KEYDEST, &fx);
13729 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13731 IDirectDrawSurface_Release(dst1);
13732 IDirectDrawSurface_Release(src1);
13734 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13735 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13736 color = surface_desc.lpSurface;
13737 /* Dst key applied to color[4,5], they are the only changed pixels. */
13738 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
13739 color[3] == 0x00001100 && color[4] == 0x00001100 && color[5] == 0x00110000,
13740 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13741 color[0], color[1], color[2], color[3], color[4], color[5]);
13743 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13744 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13745 color[2] = 0x00001100; /* Dest key in override. */
13746 color[3] = 0x00001100; /* Dest key in override. */
13747 color[4] = 0x000000aa; /* Dest key in src surface. */
13748 color[5] = 0x000000aa; /* Dest key in src surface. */
13749 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13750 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13752 /* Dest override key blit. */
13753 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, &fx);
13754 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13756 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13757 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13758 color = surface_desc.lpSurface;
13759 /* Dst key applied to color[2,3], they are the only changed pixels. */
13760 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00ff0000 &&
13761 color[3] == 0x0000ff00 && color[4] == 0x000000aa && color[5] == 0x000000aa,
13762 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13763 color[0], color[1], color[2], color[3], color[4], color[5]);
13765 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13766 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13767 color[2] = 0x00001100; /* Dest key in override. */
13768 color[3] = 0x00001100; /* Dest key in override. */
13769 color[4] = 0x000000aa; /* Dest key in src surface. */
13770 color[5] = 0x000000aa; /* Dest key in src surface. */
13771 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13772 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13774 /* Dest override together with surface key. Supposed to fail. */
13775 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYDESTOVERRIDE, &fx);
13776 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13778 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13779 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13780 color = surface_desc.lpSurface;
13781 /* Destination is unchanged. */
13782 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
13783 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
13784 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13785 color[0], color[1], color[2], color[3], color[4], color[5]);
13786 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13787 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13789 /* Source and destination key. This is driver dependent. New HW treats it like
13790 * DDBLT_KEYSRC. Older HW and some software renderers apply both keys. */
13791 if (0)
13793 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYSRC, &fx);
13794 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13796 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13797 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13798 color = surface_desc.lpSurface;
13799 /* Color[0] is filtered by the src key, 2-5 are filtered by the dst key, if
13800 * the driver applies it. */
13801 ok(color[0] == 0x00ff0000 && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
13802 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
13803 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13804 color[0], color[1], color[2], color[3], color[4], color[5]);
13806 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13807 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13808 color[2] = 0x00001100; /* Dest key in override. */
13809 color[3] = 0x00001100; /* Dest key in override. */
13810 color[4] = 0x000000aa; /* Dest key in src surface. */
13811 color[5] = 0x000000aa; /* Dest key in src surface. */
13812 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13813 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13816 /* Override keys without ddbltfx parameter fail */
13817 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, NULL);
13818 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13819 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, NULL);
13820 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13822 /* Try blitting without keys in the source surface. */
13823 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, NULL);
13824 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13825 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_DESTBLT, NULL);
13826 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13828 /* That fails now. Do not bother to check that the data is unmodified. */
13829 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx);
13830 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13832 /* Dest key blit still works, the destination surface key is used in v7. */
13833 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
13834 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13836 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13837 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13838 color = surface_desc.lpSurface;
13839 /* Dst key applied to color[0,1], they are the only changed pixels. */
13840 todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 &&
13841 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
13842 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13843 color[0], color[1], color[2], color[3], color[4], color[5]);
13844 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13845 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13847 /* Try blitting without keys in the destination surface. */
13848 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_SRCBLT, NULL);
13849 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13850 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_DESTBLT, NULL);
13851 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13853 /* This fails, as sanity would dictate. */
13854 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
13855 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13857 done:
13858 IDirectDrawSurface7_Release(src);
13859 IDirectDrawSurface7_Release(dst);
13860 refcount = IDirectDraw7_Release(ddraw);
13861 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
13862 DestroyWindow(window);
13865 static void test_vb_refcount(void)
13867 ULONG prev_d3d_refcount, prev_device_refcount;
13868 ULONG cur_d3d_refcount, cur_device_refcount;
13869 IDirect3DVertexBuffer7 *vb, *vb7;
13870 D3DVERTEXBUFFERDESC vb_desc;
13871 IDirect3DVertexBuffer *vb1;
13872 IDirect3DDevice7 *device;
13873 IDirect3D7 *d3d;
13874 ULONG refcount;
13875 IUnknown *unk;
13876 HWND window;
13877 HRESULT hr;
13879 window = create_window();
13880 if (!(device = create_device(window, DDSCL_NORMAL)))
13882 skip("Failed to create a 3D device, skipping test.\n");
13883 DestroyWindow(window);
13884 return;
13887 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
13888 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
13890 prev_d3d_refcount = get_refcount((IUnknown *)d3d);
13891 prev_device_refcount = get_refcount((IUnknown *)device);
13893 memset(&vb_desc, 0, sizeof(vb_desc));
13894 vb_desc.dwSize = sizeof(vb_desc);
13895 vb_desc.dwFVF = D3DFVF_XYZ;
13896 vb_desc.dwNumVertices = 4;
13897 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &vb, 0);
13898 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
13900 cur_d3d_refcount = get_refcount((IUnknown *)d3d);
13901 cur_device_refcount = get_refcount((IUnknown *)device);
13902 ok(cur_d3d_refcount > prev_d3d_refcount, "D3D object refcount didn't change from %u.\n", prev_d3d_refcount);
13903 ok(cur_device_refcount == prev_device_refcount, "Device refcount changed from %u to %u.\n",
13904 prev_device_refcount, cur_device_refcount);
13906 prev_d3d_refcount = cur_d3d_refcount;
13907 hr = IDirect3DVertexBuffer7_QueryInterface(vb, &IID_IDirect3DVertexBuffer7, (void **)&vb7);
13908 ok(hr == DD_OK, "Failed to query IDirect3DVertexBuffer7, hr %#x.\n", hr);
13909 cur_d3d_refcount = get_refcount((IUnknown *)d3d);
13910 ok(cur_d3d_refcount == prev_d3d_refcount, "D3D object refcount changed from %u to %u.\n",
13911 prev_d3d_refcount, cur_d3d_refcount);
13912 IDirect3DVertexBuffer7_Release(vb7);
13914 hr = IDirect3DVertexBuffer7_QueryInterface(vb, &IID_IDirect3DVertexBuffer, (void **)&vb1);
13915 ok(hr == E_NOINTERFACE, "Querying IDirect3DVertexBuffer returned unexpected hr %#x.\n", hr);
13917 hr = IDirect3DVertexBuffer_QueryInterface(vb, &IID_IUnknown, (void **)&unk);
13918 ok(hr == DD_OK, "Failed to query IUnknown, hr %#x.\n", hr);
13919 ok((IUnknown *)vb == unk,
13920 "IDirect3DVertexBuffer7 and IUnknown interface pointers don't match, %p != %p.\n", vb, unk);
13921 IUnknown_Release(unk);
13923 refcount = IDirect3DVertexBuffer7_Release(vb);
13924 ok(!refcount, "Vertex buffer has %u references left.\n", refcount);
13926 IDirect3D7_Release(d3d);
13927 refcount = IDirect3DDevice7_Release(device);
13928 ok(!refcount, "Device has %u references left.\n", refcount);
13929 DestroyWindow(window);
13932 static void test_compute_sphere_visibility(void)
13934 static D3DVALUE clip_plane[4] = {1.0f, 0.0f, 0.0f, 0.5f};
13935 static D3DMATRIX proj_1 =
13937 1.810660f, 0.000000f, 0.000000f, 0.000000f,
13938 0.000000f, 2.414213f, 0.000000f, 0.000000f,
13939 0.000000f, 0.000000f, 1.020408f, 1.000000f,
13940 0.000000f, 0.000000f, -0.102041f, 0.000000f,
13942 static D3DMATRIX proj_2 =
13944 10.0f, 0.0f, 0.0f, 0.0f,
13945 0.0f, 10.0f, 0.0f, 0.0f,
13946 0.0f, 0.0f, 10.0f, 0.0f,
13947 0.0f, 0.0f, 0.0f, 1.0f,
13949 static D3DMATRIX view_1 =
13951 1.000000f, 0.000000f, 0.000000f, 0.000000f,
13952 0.000000f, 0.768221f, -0.640185f, 0.000000f,
13953 -0.000000f, 0.640185f, 0.768221f, 0.000000f,
13954 -14.852037f, 9.857489f, 11.600972f, 1.000000f,
13956 static D3DMATRIX identity =
13958 1.0f, 0.0f, 0.0f, 0.0f,
13959 0.0f, 1.0f, 0.0f, 0.0f,
13960 0.0f, 0.0f, 1.0f, 0.0f,
13961 0.0f, 0.0f, 0.0f, 1.0f,
13963 static struct
13965 D3DMATRIX *view, *proj;
13966 unsigned int sphere_count;
13967 D3DVECTOR center[3];
13968 D3DVALUE radius[3];
13969 DWORD enable_planes;
13970 const DWORD expected[3];
13972 tests[] =
13974 {&view_1, &proj_1, 1, {{{11.461533f}, {-4.761727f}, {-1.171646f}}}, {38.252632f}, 0, {0x3f}},
13975 {&view_1, &proj_1, 3, {{{-3.515620f}, {-1.560661f}, {-12.464638f}},
13976 {{14.290396f}, {-2.981143f}, {-24.311312f}},
13977 {{1.461626f}, {-6.093709f}, {-13.901010f}}},
13978 {4.354097f, 12.500704f, 17.251318f}, 0, {0x103d, 0x3f, 0x3f}},
13979 {&identity, &proj_2, 1, {{{0.0f}, {0.0f}, {0.05f}}}, {0.04f}, 0, {0}},
13980 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.5f}}}, {0.5f}, 0, {0}},
13981 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.0f}}}, {0.0f}, 0, {0}},
13982 {&identity, &identity, 1, {{{-1.0f}, {-1.0f}, {0.5f}}}, {0.25f}, 0, {0x9}}, /* 5 */
13983 {&identity, &identity, 1, {{{-20.0f}, {0.0f}, {0.5f}}}, {3.0f}, 0, {0x103d}},
13984 {&identity, &identity, 1, {{{20.0f}, {0.0f}, {0.5f}}}, {3.0f}, 0, {0x203e}},
13985 {&identity, &identity, 1, {{{0.0f}, {-20.0f}, {0.5f}}}, {3.0f}, 0, {0x803b}},
13986 {&identity, &identity, 1, {{{0.0f}, {20.0f}, {0.5f}}}, {3.0f}, 0, {0x4037}},
13987 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {-20.0f}}}, {3.0f}, 0, {0x1001f}}, /* 10 */
13988 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {20.0f}}}, {3.0f}, 0, {0x2002f}},
13989 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.0f}}}, {5.0f}, 1, {0x7f}},
13990 {&identity, &identity, 1, {{{-0.5f}, {0.0f}, {0.0f}}}, {5.0f}, 1, {0x7f}},
13991 {&identity, &identity, 1, {{{-0.5f}, {0.0f}, {0.0f}}}, {1.0f}, 1, {0x51}},
13992 {&identity, &identity, 1, {{{-2.5f}, {0.0f}, {0.0f}}}, {1.0f}, 1, {0x41051}}, /* 15 */
13994 IDirect3DDevice7 *device;
13995 unsigned int i, j;
13996 DWORD result[3];
13997 ULONG refcount;
13998 HWND window;
13999 HRESULT hr;
14001 window = create_window();
14002 if (!(device = create_device(window, DDSCL_NORMAL)))
14004 skip("Failed to create a 3D device, skipping test.\n");
14005 DestroyWindow(window);
14006 return;
14009 hr = IDirect3DDevice7_SetClipPlane(device, 0, clip_plane);
14010 ok(SUCCEEDED(hr), "Failed to set user clip plane, hr %#x.\n", hr);
14012 IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &identity);
14014 for (i = 0; i < ARRAY_SIZE(tests); ++i)
14016 IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, tests[i].view);
14017 IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, tests[i].proj);
14019 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE,
14020 tests[i].enable_planes);
14021 ok(SUCCEEDED(hr), "Failed to enable / disable user clip planes, hr %#x.\n", hr);
14023 hr = IDirect3DDevice7_ComputeSphereVisibility(device, tests[i].center, tests[i].radius,
14024 tests[i].sphere_count, 0, result);
14025 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14027 for (j = 0; j < tests[i].sphere_count; ++j)
14028 ok(result[j] == tests[i].expected[j], "Test %u sphere %u: expected %#x, got %#x.\n",
14029 i, j, tests[i].expected[j], result[j]);
14032 refcount = IDirect3DDevice7_Release(device);
14033 ok(!refcount, "Device has %u references left.\n", refcount);
14034 DestroyWindow(window);
14037 static void test_clip_planes_limits(void)
14039 IDirect3DDevice7 *device;
14040 D3DDEVICEDESC7 caps;
14041 unsigned int i;
14042 ULONG refcount;
14043 float plane[4];
14044 HWND window;
14045 DWORD state;
14046 HRESULT hr;
14048 window = create_window();
14049 if (!(device = create_device(window, DDSCL_NORMAL)))
14051 skip("Failed to create 3D device.\n");
14052 DestroyWindow(window);
14053 return;
14056 memset(&caps, 0, sizeof(caps));
14057 hr = IDirect3DDevice7_GetCaps(device, &caps);
14058 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
14060 trace("Max user clip planes: %u.\n", caps.wMaxUserClipPlanes);
14062 for (i = 0; i < caps.wMaxUserClipPlanes; ++i)
14064 memset(plane, 0xff, sizeof(plane));
14065 hr = IDirect3DDevice7_GetClipPlane(device, i, plane);
14066 ok(hr == D3D_OK, "Failed to get clip plane %u, hr %#x.\n", i, hr);
14067 ok(!plane[0] && !plane[1] && !plane[2] && !plane[3],
14068 "Got unexpected plane %u: %.8e, %.8e, %.8e, %.8e.\n",
14069 i, plane[0], plane[1], plane[2], plane[3]);
14072 plane[0] = 2.0f;
14073 plane[1] = 8.0f;
14074 plane[2] = 5.0f;
14075 for (i = 0; i < caps.wMaxUserClipPlanes; ++i)
14077 plane[3] = i;
14078 hr = IDirect3DDevice7_SetClipPlane(device, i, plane);
14079 ok(hr == D3D_OK, "Failed to set clip plane %u, hr %#x.\n", i, hr);
14081 for (i = 0; i < caps.wMaxUserClipPlanes; ++i)
14083 memset(plane, 0xff, sizeof(plane));
14084 hr = IDirect3DDevice7_GetClipPlane(device, i, plane);
14085 ok(hr == D3D_OK, "Failed to get clip plane %u, hr %#x.\n", i, hr);
14086 ok(plane[0] == 2.0f && plane[1] == 8.0f && plane[2] == 5.0f && plane[3] == i,
14087 "Got unexpected plane %u: %.8e, %.8e, %.8e, %.8e.\n",
14088 i, plane[0], plane[1], plane[2], plane[3]);
14091 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE, 0xffffffff);
14092 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
14093 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE, &state);
14094 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
14095 ok(state == 0xffffffff, "Got unexpected state %#x.\n", state);
14096 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE, 0x80000000);
14097 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
14098 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE, &state);
14099 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
14100 ok(state == 0x80000000, "Got unexpected state %#x.\n", state);
14102 refcount = IDirect3DDevice7_Release(device);
14103 ok(!refcount, "Device has %u references left.\n", refcount);
14104 DestroyWindow(window);
14107 static void test_texture_stages_limits(void)
14109 IDirectDrawSurface7 *texture;
14110 DDSURFACEDESC2 surface_desc;
14111 IDirect3DDevice7 *device;
14112 IDirectDraw7 *ddraw;
14113 IDirect3D7 *d3d;
14114 unsigned int i;
14115 ULONG refcount;
14116 HWND window;
14117 HRESULT hr;
14119 window = create_window();
14120 if (!(device = create_device(window, DDSCL_NORMAL)))
14122 skip("Failed to create 3D device.\n");
14123 DestroyWindow(window);
14124 return;
14126 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
14127 ok(SUCCEEDED(hr), "Failed to get Direct3D interface, hr %#x.\n", hr);
14128 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
14129 ok(SUCCEEDED(hr), "Failed to get DirectDraw interface, hr %#x.\n", hr);
14130 IDirect3D7_Release(d3d);
14132 memset(&surface_desc, 0, sizeof(surface_desc));
14133 surface_desc.dwSize = sizeof(surface_desc);
14134 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
14135 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
14136 surface_desc.dwWidth = 16;
14137 surface_desc.dwHeight = 16;
14138 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
14139 ok(hr == DD_OK, "Failed to create surface, hr %#x.\n", hr);
14141 for (i = 0; i < 8; ++i)
14143 hr = IDirect3DDevice7_SetTexture(device, i, texture);
14144 ok(hr == D3D_OK, "Failed to set texture %u, hr %#x.\n", i, hr);
14145 hr = IDirect3DDevice7_SetTexture(device, i, NULL);
14146 ok(hr == D3D_OK, "Failed to set texture %u, hr %#x.\n", i, hr);
14147 hr = IDirect3DDevice7_SetTextureStageState(device, i, D3DTSS_COLOROP, D3DTOP_ADD);
14148 ok(hr == D3D_OK, "Failed to set texture stage state %u, hr %#x.\n", i, hr);
14151 IDirectDrawSurface7_Release(texture);
14152 IDirectDraw7_Release(ddraw);
14153 refcount = IDirect3DDevice7_Release(device);
14154 ok(!refcount, "Device has %u references left.\n", refcount);
14155 DestroyWindow(window);
14158 static void test_set_render_state(void)
14160 IDirect3DDevice7 *device;
14161 ULONG refcount;
14162 HWND window;
14163 DWORD state;
14164 HRESULT hr;
14166 window = create_window();
14167 if (!(device = create_device(window, DDSCL_NORMAL)))
14169 skip("Failed to create 3D device.\n");
14170 DestroyWindow(window);
14171 return;
14174 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZVISIBLE, TRUE);
14175 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14176 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZVISIBLE, FALSE);
14177 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14179 /* States deprecated in D3D7 */
14180 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
14181 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14182 state = 0xdeadbeef;
14183 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, &state);
14184 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14185 ok(state == 0xdeadbeef, "Got unexpected render state %#x.\n", state);
14186 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
14187 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14188 state = 0xdeadbeef;
14189 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, &state);
14190 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14191 ok(state == 0xdeadbeef, "Got unexpected render state %#x.\n", state);
14193 refcount = IDirect3DDevice7_Release(device);
14194 ok(!refcount, "Device has %u references left.\n", refcount);
14195 DestroyWindow(window);
14198 static void test_map_synchronisation(void)
14200 LARGE_INTEGER frequency, diff, ts[3];
14201 IDirect3DVertexBuffer7 *buffer;
14202 unsigned int i, j, tri_count;
14203 D3DVERTEXBUFFERDESC vb_desc;
14204 IDirect3DDevice7 *device;
14205 BOOL unsynchronised, ret;
14206 IDirectDrawSurface7 *rt;
14207 IDirectDraw7 *ddraw;
14208 IDirect3D7 *d3d;
14209 D3DCOLOR colour;
14210 ULONG refcount;
14211 HWND window;
14212 HRESULT hr;
14214 static const struct
14216 unsigned int flags;
14217 BOOL unsynchronised;
14219 tests[] =
14221 {0, FALSE},
14222 {DDLOCK_NOOVERWRITE, TRUE},
14223 {DDLOCK_DISCARDCONTENTS, FALSE},
14224 {DDLOCK_NOOVERWRITE | DDLOCK_DISCARDCONTENTS, TRUE},
14227 static const struct quad
14229 struct
14231 struct vec3 position;
14232 DWORD diffuse;
14233 } strip[4];
14235 quad1 =
14238 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
14239 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
14240 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
14241 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
14244 quad2 =
14247 {{-1.0f, -1.0f, 0.0f}, 0xffffff00},
14248 {{-1.0f, 1.0f, 0.0f}, 0xffffff00},
14249 {{ 1.0f, -1.0f, 0.0f}, 0xffffff00},
14250 {{ 1.0f, 1.0f, 0.0f}, 0xffffff00},
14253 struct quad *quads;
14255 window = create_window();
14256 ok(!!window, "Failed to create a window.\n");
14258 if (!(device = create_device(window, DDSCL_NORMAL)))
14260 skip("Failed to create a D3D device, skipping tests.\n");
14261 DestroyWindow(window);
14262 return;
14265 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
14266 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
14267 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
14268 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
14269 /* Maps are always synchronised on WARP. */
14270 if (ddraw_is_warp(ddraw))
14272 skip("Running on WARP, skipping test.\n");
14273 goto done;
14276 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
14277 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
14279 tri_count = 0x1000;
14281 ret = QueryPerformanceFrequency(&frequency);
14282 ok(ret, "Failed to get performance counter frequency.\n");
14284 vb_desc.dwSize = sizeof(vb_desc);
14285 vb_desc.dwCaps = D3DVBCAPS_WRITEONLY;
14286 vb_desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
14287 vb_desc.dwNumVertices = tri_count + 2;
14288 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &buffer, 0);
14289 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
14290 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&quads, NULL);
14291 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
14292 for (j = 0; j < vb_desc.dwNumVertices / 4; ++j)
14294 quads[j] = quad1;
14296 hr = IDirect3DVertexBuffer7_Unlock(buffer);
14297 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
14299 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
14300 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
14302 /* Initial draw to initialise states, compile shaders, etc. */
14303 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
14304 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14305 hr = IDirect3DDevice7_BeginScene(device);
14306 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14307 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, vb_desc.dwNumVertices, 0);
14308 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14309 hr = IDirect3DDevice7_EndScene(device);
14310 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14311 /* Read the result to ensure the GPU has finished drawing. */
14312 colour = get_surface_color(rt, 320, 240);
14314 /* Time drawing tri_count triangles. */
14315 ret = QueryPerformanceCounter(&ts[0]);
14316 ok(ret, "Failed to read performance counter.\n");
14317 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
14318 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14319 hr = IDirect3DDevice7_BeginScene(device);
14320 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14321 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, vb_desc.dwNumVertices, 0);
14322 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14323 hr = IDirect3DDevice7_EndScene(device);
14324 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14325 colour = get_surface_color(rt, 320, 240);
14326 /* Time drawing a single triangle. */
14327 ret = QueryPerformanceCounter(&ts[1]);
14328 ok(ret, "Failed to read performance counter.\n");
14329 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
14330 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14331 hr = IDirect3DDevice7_BeginScene(device);
14332 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14333 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 3, 0);
14334 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14335 hr = IDirect3DDevice7_EndScene(device);
14336 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14337 colour = get_surface_color(rt, 320, 240);
14338 ret = QueryPerformanceCounter(&ts[2]);
14339 ok(ret, "Failed to read performance counter.\n");
14341 IDirect3DVertexBuffer7_Release(buffer);
14343 /* Estimate the number of triangles we can draw in 100ms. */
14344 diff.QuadPart = ts[1].QuadPart - ts[0].QuadPart + ts[1].QuadPart - ts[2].QuadPart;
14345 tri_count = (tri_count * frequency.QuadPart) / (diff.QuadPart * 10);
14346 tri_count = ((tri_count + 2 + 3) & ~3) - 2;
14347 vb_desc.dwNumVertices = tri_count + 2;
14349 for (i = 0; i < ARRAY_SIZE(tests); ++i)
14351 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &buffer, 0);
14352 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
14353 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&quads, NULL);
14354 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
14355 for (j = 0; j < vb_desc.dwNumVertices / 4; ++j)
14357 quads[j] = quad1;
14359 hr = IDirect3DVertexBuffer7_Unlock(buffer);
14360 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
14362 /* Start a draw operation. */
14363 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
14364 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14365 hr = IDirect3DDevice7_BeginScene(device);
14366 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14367 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, vb_desc.dwNumVertices, 0);
14368 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14369 hr = IDirect3DDevice7_EndScene(device);
14370 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14372 /* Map the last quad while the draw is in progress. */
14373 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_WAIT | tests[i].flags, (void **)&quads, NULL);
14374 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
14375 quads[(vb_desc.dwNumVertices / 4) - 1] = quad2;
14376 hr = IDirect3DVertexBuffer7_Unlock(buffer);
14377 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
14379 colour = get_surface_color(rt, 320, 240);
14380 unsynchronised = compare_color(colour, 0x00ffff00, 1);
14381 ok(tests[i].unsynchronised == unsynchronised, "Expected %s map for flags %#x.\n",
14382 tests[i].unsynchronised ? "unsynchronised" : "synchronised", tests[i].flags);
14384 IDirect3DVertexBuffer7_Release(buffer);
14387 IDirectDrawSurface7_Release(rt);
14388 done:
14389 IDirectDraw7_Release(ddraw);
14390 IDirect3D7_Release(d3d);
14391 refcount = IDirect3DDevice7_Release(device);
14392 ok(!refcount, "Device has %u references left.\n", refcount);
14393 DestroyWindow(window);
14396 static void test_depth_readback(void)
14398 DWORD depth, expected_depth, max_diff, raw_value, passed_fmts = 0;
14399 IDirectDrawSurface7 *rt, *ds;
14400 DDSURFACEDESC2 surface_desc;
14401 IDirect3DDevice7 *device;
14402 unsigned int i, x, y;
14403 IDirectDraw7 *ddraw;
14404 IDirect3D7 *d3d;
14405 ULONG refcount;
14406 HWND window;
14407 HRESULT hr;
14408 RECT r;
14409 BOOL all_zero, all_one, all_pass;
14411 static struct
14413 struct vec3 position;
14414 DWORD diffuse;
14416 quad[] =
14418 {{-1.0f, -1.0f, 0.1f}, 0xff00ff00},
14419 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
14420 {{ 1.0f, -1.0f, 1.0f}, 0xff00ff00},
14421 {{ 1.0f, 1.0f, 0.9f}, 0xff00ff00},
14424 static const struct
14426 unsigned int z_depth, s_depth, z_mask, s_mask;
14427 BOOL todo;
14429 tests[] =
14431 {16, 0, 0x0000ffff, 0x00000000},
14432 {24, 0, 0x00ffffff, 0x00000000},
14433 {32, 0, 0x00ffffff, 0x00000000},
14434 {32, 8, 0x00ffffff, 0xff000000, TRUE},
14435 {32, 0, 0xffffffff, 0x00000000},
14438 window = create_window();
14439 ok(!!window, "Failed to create a window.\n");
14441 if (!(device = create_device(window, DDSCL_NORMAL)))
14443 skip("Failed to create a D3D device, skipping tests.\n");
14444 DestroyWindow(window);
14445 return;
14448 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
14449 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
14450 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
14451 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
14453 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
14454 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
14456 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
14457 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
14459 ds = get_depth_stencil(device);
14460 hr = IDirectDrawSurface7_DeleteAttachedSurface(rt, 0, ds);
14461 ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
14462 IDirectDrawSurface7_Release(ds);
14464 for (i = 0; i < ARRAY_SIZE(tests); ++i)
14466 memset(&surface_desc, 0, sizeof(surface_desc));
14467 surface_desc.dwSize = sizeof(surface_desc);
14468 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
14469 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
14470 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
14471 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
14472 if (tests[i].s_depth)
14473 U4(surface_desc).ddpfPixelFormat.dwFlags |= DDPF_STENCILBUFFER;
14474 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = tests[i].z_depth;
14475 U2(U4(surface_desc).ddpfPixelFormat).dwStencilBitDepth = tests[i].s_depth;
14476 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = tests[i].z_mask;
14477 U4(U4(surface_desc).ddpfPixelFormat).dwStencilBitMask = tests[i].s_mask;
14478 surface_desc.dwWidth = 640;
14479 surface_desc.dwHeight = 480;
14480 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL);
14481 if (FAILED(hr))
14483 skip("Format %u not supported, skipping test.\n", i);
14484 continue;
14487 hr = IDirectDrawSurface_AddAttachedSurface(rt, ds);
14488 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
14489 hr = IDirect3DDevice7_SetRenderTarget(device, rt, 0);
14490 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
14492 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 1.0f, 0);
14493 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14494 hr = IDirect3DDevice7_BeginScene(device);
14495 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14496 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, 4, 0);
14497 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14498 hr = IDirect3DDevice7_EndScene(device);
14499 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14501 all_zero = all_one = all_pass = TRUE;
14502 for (y = 60; y < 480; y += 120)
14504 for (x = 80; x < 640; x += 160)
14506 SetRect(&r, x, y, x + 1, y + 1);
14507 memset(&surface_desc, 0, sizeof(surface_desc));
14508 surface_desc.dwSize = sizeof(surface_desc);
14509 hr = IDirectDrawSurface7_Lock(ds, &r, &surface_desc, DDLOCK_READONLY, NULL);
14510 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14512 raw_value = *((DWORD *)surface_desc.lpSurface);
14513 if (raw_value)
14514 all_zero = FALSE;
14515 if (raw_value != 0x00ffffff)
14516 all_one = FALSE;
14518 depth = raw_value & tests[i].z_mask;
14519 expected_depth = (x * (0.9 / 640.0) + y * (0.1 / 480.0)) * tests[i].z_mask;
14520 max_diff = ((0.5f * 0.9f) / 640.0f) * tests[i].z_mask;
14521 /* This test is very reliably on AMD, but fails in a number of interesting ways on Nvidia GPUs:
14523 * Geforce 7 GPUs work only with D16. D24 and D24S8 return 0, D24X8 broken data.
14525 * Geforce 9 GPUs return return broken data for D16 that resembles the expected data in
14526 * the lower 8 bits and has 0xff in the upper 8 bits. D24X8 works, D24 and D24S8 return
14527 * 0x00ffffff.
14529 * Geforce GTX 650 has working D16 and D24, but D24S8 returns 0.
14531 * Arx Fatalis is broken on the Geforce 9 in the same way it was broken in Wine (bug 43654).
14532 * The !tests[i].s_depth is supposed to rule out D16 on GF9 and D24X8 on GF7. */
14533 todo_wine_if(tests[i].todo)
14534 ok(abs(expected_depth - depth) <= max_diff
14535 || (ddraw_is_nvidia(ddraw) && (all_zero || all_one || !tests[i].s_depth)),
14536 "Test %u: Got depth 0x%08x (diff %d), expected 0x%08x+/-%u, at %u, %u.\n",
14537 i, depth, expected_depth - depth, expected_depth, max_diff, x, y);
14538 if (abs(expected_depth - depth) > max_diff)
14539 all_pass = FALSE;
14541 hr = IDirectDrawSurface7_Unlock(ds, &r);
14542 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14545 if (all_pass)
14546 passed_fmts++;
14548 hr = IDirectDrawSurface7_DeleteAttachedSurface(rt, 0, ds);
14549 ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
14550 IDirectDrawSurface7_Release(ds);
14553 ok(passed_fmts, "Not a single format passed the tests, this is bad even by Nvidia's standards.\n");
14555 IDirectDrawSurface7_Release(rt);
14556 IDirectDraw7_Release(ddraw);
14557 IDirect3D7_Release(d3d);
14558 refcount = IDirect3DDevice7_Release(device);
14559 ok(!refcount, "Device has %u references left.\n", refcount);
14560 DestroyWindow(window);
14563 static void test_clear(void)
14565 IDirect3DDevice7 *device;
14566 IDirectDrawSurface7 *rt;
14567 D3DVIEWPORT7 vp, old_vp;
14568 IDirectDraw7 *ddraw;
14569 D3DRECT rect_negneg;
14570 IDirect3D7 *d3d;
14571 D3DRECT rect[2];
14572 D3DCOLOR color;
14573 ULONG refcount;
14574 HWND window;
14575 HRESULT hr;
14577 window = create_window();
14578 if (!(device = create_device(window, DDSCL_NORMAL)))
14580 skip("Failed to create 3D device.\n");
14581 DestroyWindow(window);
14582 return;
14585 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
14586 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
14587 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
14588 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
14590 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
14591 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
14593 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
14594 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14596 /* Positive x, negative y. */
14597 U1(rect[0]).x1 = 0;
14598 U2(rect[0]).y1 = 480;
14599 U3(rect[0]).x2 = 320;
14600 U4(rect[0]).y2 = 240;
14602 /* Positive x, positive y. */
14603 U1(rect[1]).x1 = 0;
14604 U2(rect[1]).y1 = 0;
14605 U3(rect[1]).x2 = 320;
14606 U4(rect[1]).y2 = 240;
14608 /* Clear 2 rectangles with one call. Unlike d3d8/9, the refrast does not
14609 * refuse negative rectangles, but it will not clear them either. */
14610 hr = IDirect3DDevice7_Clear(device, 2, rect, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
14611 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14613 color = get_surface_color(rt, 160, 360);
14614 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 3 (pos, neg) has color 0x%08x.\n", color);
14615 color = get_surface_color(rt, 160, 120);
14616 ok(compare_color(color, 0x00ff0000, 0), "Clear rectangle 1 (pos, pos) has color 0x%08x.\n", color);
14617 color = get_surface_color(rt, 480, 360);
14618 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 4 (NULL) has color 0x%08x.\n", color);
14619 color = get_surface_color(rt, 480, 120);
14620 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 4 (neg, neg) has color 0x%08x.\n", color);
14622 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
14623 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14624 /* negative x, negative y.
14625 * Also ignored, except on WARP, which clears the entire screen. */
14626 U1(rect_negneg).x1 = 640;
14627 U2(rect_negneg).y1 = 240;
14628 U3(rect_negneg).x2 = 320;
14629 U4(rect_negneg).y2 = 0;
14630 hr = IDirect3DDevice7_Clear(device, 1, &rect_negneg, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
14631 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14633 color = get_surface_color(rt, 160, 360);
14634 ok(compare_color(color, 0x00ffffff, 0)
14635 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
14636 "Got unexpected color 0x%08x.\n", color);
14637 color = get_surface_color(rt, 160, 120);
14638 ok(compare_color(color, 0x00ffffff, 0)
14639 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
14640 "Got unexpected color 0x%08x.\n", color);
14641 color = get_surface_color(rt, 480, 360);
14642 ok(compare_color(color, 0x00ffffff, 0)
14643 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
14644 "Got unexpected color 0x%08x.\n", color);
14645 color = get_surface_color(rt, 480, 120);
14646 ok(compare_color(color, 0x00ffffff, 0)
14647 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
14648 "Got unexpected color 0x%08x.\n", color);
14650 /* Test how the viewport affects clears. */
14651 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
14652 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14653 hr = IDirect3DDevice7_GetViewport(device, &old_vp);
14654 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
14656 vp.dwX = 160;
14657 vp.dwY = 120;
14658 vp.dwWidth = 160;
14659 vp.dwHeight = 120;
14660 vp.dvMinZ = 0.0f;
14661 vp.dvMaxZ = 1.0f;
14662 hr = IDirect3DDevice7_SetViewport(device, &vp);
14663 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
14664 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
14665 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14667 vp.dwX = 320;
14668 vp.dwY = 240;
14669 vp.dwWidth = 320;
14670 vp.dwHeight = 240;
14671 vp.dvMinZ = 0.0f;
14672 vp.dvMaxZ = 1.0f;
14673 hr = IDirect3DDevice7_SetViewport(device, &vp);
14674 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
14676 U1(rect[0]).x1 = 160;
14677 U2(rect[0]).y1 = 120;
14678 U3(rect[0]).x2 = 480;
14679 U4(rect[0]).y2 = 360;
14680 hr = IDirect3DDevice7_Clear(device, 1, &rect[0], D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
14681 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14683 hr = IDirect3DDevice7_SetViewport(device, &old_vp);
14684 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
14686 color = get_surface_color(rt, 158, 118);
14687 ok(compare_color(color, 0x00ffffff, 0), "(158, 118) has color 0x%08x.\n", color);
14688 color = get_surface_color(rt, 162, 118);
14689 ok(compare_color(color, 0x00ffffff, 0), "(162, 118) has color 0x%08x.\n", color);
14690 color = get_surface_color(rt, 158, 122);
14691 ok(compare_color(color, 0x00ffffff, 0), "(158, 122) has color 0x%08x.\n", color);
14692 color = get_surface_color(rt, 162, 122);
14693 ok(compare_color(color, 0x000000ff, 0), "(162, 122) has color 0x%08x.\n", color);
14695 color = get_surface_color(rt, 318, 238);
14696 ok(compare_color(color, 0x000000ff, 0), "(318, 238) has color 0x%08x.\n", color);
14697 color = get_surface_color(rt, 322, 238);
14698 ok(compare_color(color, 0x00ffffff, 0), "(322, 328) has color 0x%08x.\n", color);
14699 color = get_surface_color(rt, 318, 242);
14700 ok(compare_color(color, 0x00ffffff, 0), "(318, 242) has color 0x%08x.\n", color);
14701 color = get_surface_color(rt, 322, 242);
14702 ok(compare_color(color, 0x0000ff00, 0), "(322, 242) has color 0x%08x.\n", color);
14704 color = get_surface_color(rt, 478, 358);
14705 ok(compare_color(color, 0x0000ff00, 0), "(478, 358) has color 0x%08x.\n", color);
14706 color = get_surface_color(rt, 482, 358);
14707 ok(compare_color(color, 0x00ffffff, 0), "(482, 358) has color 0x%08x.\n", color);
14708 color = get_surface_color(rt, 478, 362);
14709 ok(compare_color(color, 0x00ffffff, 0), "(478, 362) has color 0x%08x.\n", color);
14710 color = get_surface_color(rt, 482, 362);
14711 ok(compare_color(color, 0x00ffffff, 0), "(482, 362) has color 0x%08x.\n", color);
14713 /* COLORWRITEENABLE, SRGBWRITEENABLE and scissor rectangles do not exist
14714 * in d3d7. */
14716 IDirectDrawSurface7_Release(rt);
14717 IDirectDraw7_Release(ddraw);
14718 IDirect3D7_Release(d3d);
14719 refcount = IDirect3DDevice7_Release(device);
14720 ok(!refcount, "Device has %u references left.\n", refcount);
14721 DestroyWindow(window);
14724 struct enum_surfaces_param
14726 IDirectDrawSurface7 *surfaces[8];
14727 unsigned int count;
14730 static HRESULT WINAPI enum_surfaces_cb(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
14732 struct enum_surfaces_param *param = context;
14733 BOOL found = FALSE;
14734 unsigned int i;
14736 for (i = 0; i < ARRAY_SIZE(param->surfaces); ++i)
14738 if (param->surfaces[i] == surface)
14740 found = TRUE;
14741 break;
14745 ok(found, "Unexpected surface %p enumerated.\n", surface);
14746 IDirectDrawSurface7_Release(surface);
14747 ++param->count;
14749 return DDENUMRET_OK;
14752 static void test_enum_surfaces(void)
14754 struct enum_surfaces_param param = {{0}};
14755 DDSURFACEDESC2 desc;
14756 IDirectDraw7 *ddraw;
14757 HRESULT hr;
14759 ddraw = create_ddraw();
14760 ok(!!ddraw, "Failed to create a ddraw object.\n");
14762 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
14763 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
14765 memset(&desc, 0, sizeof(desc));
14766 desc.dwSize = sizeof(desc);
14767 desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
14768 desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
14769 U2(desc).dwMipMapCount = 3;
14770 desc.dwWidth = 32;
14771 desc.dwHeight = 32;
14772 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &desc, &param.surfaces[0], NULL)))
14774 win_skip("Failed to create a texture, skipping tests.\n");
14775 IDirectDraw7_Release(ddraw);
14776 return;
14779 hr = IDirectDrawSurface7_GetAttachedSurface(param.surfaces[0], &desc.ddsCaps, &param.surfaces[1]);
14780 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
14781 hr = IDirectDrawSurface7_GetAttachedSurface(param.surfaces[1], &desc.ddsCaps, &param.surfaces[2]);
14782 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
14783 hr = IDirectDrawSurface7_GetAttachedSurface(param.surfaces[2], &desc.ddsCaps, &param.surfaces[3]);
14784 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
14785 ok(!param.surfaces[3], "Got unexpected pointer %p.\n", param.surfaces[3]);
14787 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
14788 &desc, &param, enum_surfaces_cb);
14789 ok(SUCCEEDED(hr), "Failed to enumerate surfaces, hr %#x.\n", hr);
14790 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
14792 param.count = 0;
14793 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
14794 NULL, &param, enum_surfaces_cb);
14795 ok(SUCCEEDED(hr), "Failed to enumerate surfaces, hr %#x.\n", hr);
14796 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
14798 IDirectDrawSurface7_Release(param.surfaces[2]);
14799 IDirectDrawSurface7_Release(param.surfaces[1]);
14800 IDirectDrawSurface7_Release(param.surfaces[0]);
14801 IDirectDraw7_Release(ddraw);
14804 static void test_viewport(void)
14806 static struct
14808 D3DVIEWPORT7 vp;
14809 RECT expected_rect;
14810 const char *message;
14812 tests[] =
14814 {{ 0, 0, 640, 480}, { 0, 120, 479, 359}, "Viewport (0, 0) - (640, 480)"},
14815 {{ 0, 0, 320, 240}, { 0, 60, 239, 179}, "Viewport (0, 0) - (320, 240)"},
14816 {{ 0, 0, 1280, 960}, { 0, 240, 639, 479}, "Viewport (0, 0) - (1280, 960)"},
14817 {{ 0, 0, 2000, 1600}, {-10, -10, -10, -10}, "Viewport (0, 0) - (2000, 1600)"},
14818 {{100, 100, 640, 480}, {100, 220, 579, 459}, "Viewport (100, 100) - (640, 480)"},
14819 {{ 0, 0, 8192, 8192}, {-10, -10, -10, -10}, "Viewport (0, 0) - (8192, 8192)"},
14821 static struct vec3 quad[] =
14823 {-1.5f, -0.5f, 0.1f},
14824 {-1.5f, 0.5f, 0.1f},
14825 { 0.5f, -0.5f, 0.1f},
14826 { 0.5f, 0.5f, 0.1f},
14828 static const struct vec2 rt_sizes[] =
14830 {640, 480}, {1280, 960}, {320, 240}, {800, 600},
14832 IDirectDrawSurface7 *rt, *ds;
14833 DDSURFACEDESC2 surface_desc;
14834 IDirect3DDevice7 *device;
14835 IDirectDraw7 *ddraw;
14836 DDPIXELFORMAT z_fmt;
14837 unsigned int i, j;
14838 IDirect3D7 *d3d;
14839 ULONG refcount;
14840 HWND window;
14841 HRESULT hr;
14843 window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
14844 0, 0, 640, 480, 0, 0, 0, 0);
14845 if (!(device = create_device(window, DDSCL_NORMAL)))
14847 skip("Failed to create a 3D device, skipping test.\n");
14848 DestroyWindow(window);
14849 return;
14852 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
14853 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
14854 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
14855 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
14856 IDirect3D7_Release(d3d);
14858 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
14859 ok(SUCCEEDED(hr), "Failed to disable depth test, hr %#x.\n", hr);
14860 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
14861 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
14863 hr = IDirect3DDevice7_SetViewport(device, NULL);
14864 ok(hr == E_INVALIDARG, "Setting NULL viewport data returned unexpected hr %#x.\n", hr);
14866 ds = get_depth_stencil(device);
14867 memset(&surface_desc, 0, sizeof(surface_desc));
14868 surface_desc.dwSize = sizeof(surface_desc);
14869 hr = IDirectDrawSurface7_GetSurfaceDesc(ds, &surface_desc);
14870 z_fmt = U4(surface_desc).ddpfPixelFormat;
14872 for (i = 0; i < ARRAY_SIZE(rt_sizes); ++i)
14874 if (i)
14876 memset(&surface_desc, 0, sizeof(surface_desc));
14877 surface_desc.dwSize = sizeof(surface_desc);
14878 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
14879 surface_desc.dwWidth = rt_sizes[i].x;
14880 surface_desc.dwHeight = rt_sizes[i].y;
14881 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
14882 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &rt, NULL);
14883 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x (i %u).\n", hr, i);
14885 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
14886 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
14887 U4(surface_desc).ddpfPixelFormat = z_fmt;
14888 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL);
14889 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x (i %u).\n", hr, i);
14890 hr = IDirectDrawSurface7_AddAttachedSurface(rt, ds);
14891 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x (i %u).\n", hr, i);
14893 hr = IDirect3DDevice7_SetRenderTarget(device, rt, 0);
14894 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x (i %u).\n", hr, i);
14896 else
14898 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
14899 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
14902 for (j = 0; j < ARRAY_SIZE(tests); ++j)
14904 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 1.0f, 0);
14905 ok(SUCCEEDED(hr), "Failed to clear, hr %#x (i %u, j %u).\n", hr, i, j);
14907 hr = IDirect3DDevice7_SetViewport(device, &tests[j].vp);
14908 if (tests[j].vp.dwX + tests[j].vp.dwWidth > rt_sizes[i].x
14909 || tests[j].vp.dwY + tests[j].vp.dwHeight > rt_sizes[i].y)
14911 ok(hr == E_INVALIDARG, "Setting the viewport returned unexpected hr %#x (i %u, j %u).\n", hr, i, j);
14912 continue;
14914 else
14916 ok(SUCCEEDED(hr), "Failed to set the viewport, hr %#x (i %u, j %u).\n", hr, i, j);
14919 hr = IDirect3DDevice7_BeginScene(device);
14920 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x (i %u, j %u).\n", hr, i, j);
14921 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
14922 ok(SUCCEEDED(hr), "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
14923 hr = IDirect3DDevice7_EndScene(device);
14924 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x (i %u, j %u).\n", hr, i, j);
14926 check_rect(rt, tests[j].expected_rect, tests[j].message);
14929 hr = IDirectDrawSurface7_DeleteAttachedSurface(rt, 0, ds);
14930 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x (i %u).\n", hr, i);
14931 IDirectDrawSurface7_Release(ds);
14933 IDirectDrawSurface7_Release(rt);
14936 refcount = IDirect3DDevice7_Release(device);
14937 ok(!refcount, "Device has %u references left.\n", refcount);
14938 IDirectDraw7_Release(ddraw);
14939 DestroyWindow(window);
14942 static unsigned int validate_loaded_surface(IDirectDrawSurface7 *surface, unsigned int face,
14943 unsigned int level, const RECT *src_rect, const POINT *dst_point)
14945 DDSURFACEDESC2 surface_desc;
14946 unsigned int diff, x, y;
14947 HRESULT hr;
14949 memset(&surface_desc, 0, sizeof(surface_desc));
14950 surface_desc.dwSize = sizeof(surface_desc);
14951 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14952 ok(SUCCEEDED(hr), "Failed to map surface, hr %#x.\n", hr);
14954 for (y = 0, diff = 0; y < surface_desc.dwHeight; ++y)
14956 DWORD *texture_row = (DWORD *)((char *)surface_desc.lpSurface + y * U1(surface_desc).lPitch);
14958 for (x = 0; x < surface_desc.dwWidth; ++x)
14960 DWORD colour = texture_row[x];
14961 DWORD r = (colour & 0xff0000) >> 16;
14962 DWORD g = (colour & 0xff00) >> 8;
14963 DWORD b = (colour & 0xff);
14965 if (x < dst_point->x || x >= dst_point->x + src_rect->right - src_rect->left
14966 || y < dst_point->y || y >= dst_point->y + src_rect->bottom - src_rect->top)
14968 if (colour & 0xffffff)
14969 ++diff;
14971 else
14973 if (r != ((face << 4) | level)
14974 || g != x + src_rect->left - dst_point->x
14975 || b != y + src_rect->top - dst_point->y)
14976 ++diff;
14981 hr = IDirectDrawSurface7_Unlock(surface, NULL);
14982 ok(SUCCEEDED(hr), "Failed to unmap surface, hr %#x.\n", hr);
14984 return diff;
14987 static void test_device_load(void)
14989 IDirectDrawSurface7 *src_surface, *dst_surface, *surface, *tmp;
14990 DDSCAPS2 mip_caps = {0, DDSCAPS2_MIPMAPSUBLEVEL, 0, {0}};
14991 IDirectDrawPalette *src_palette, *dst_palette, *palette;
14992 unsigned int i, j, k, l, x, y;
14993 DDSURFACEDESC2 surface_desc;
14994 IDirect3DDevice7 *device;
14995 PALETTEENTRY table1[256];
14996 D3DDEVICEDESC7 d3d_caps;
14997 DDCOLORKEY colour_key;
14998 IDirectDraw7 *ddraw;
14999 BOOL cube_support;
15000 IDirect3D7 *d3d;
15001 ULONG refcount;
15002 HWND window;
15003 DDBLTFX fx;
15004 HRESULT hr;
15006 #define TEX_MIP 0x01
15007 #define TEX_CUBE 0x02
15008 #define NULL_COORDS 0x04
15010 /* Creating partial cube maps (e.g. created with just
15011 * DDSCAPS2_CUBEMAP_POSITIVEX) BSODs some Windows machines. (Radeon X1600,
15012 * Windows XP, Catalyst 10.2 driver, 6.14.10.6925)
15014 * Passing non-toplevel surfaces to IDirect3DDevice7_Load() crashes on
15015 * native. (Windows XP / NVIDIA, Windows 98 / RGB software rasteriser) */
15016 static const struct
15018 unsigned int src_w, src_h, src_mip_count;
15019 RECT src_rect;
15020 DWORD src_flags;
15021 unsigned int dst_w, dst_h, dst_mip_count;
15022 POINT dst_point;
15023 DWORD dst_flags;
15024 HRESULT hr;
15026 tests[] =
15028 {128, 128, 0, { 0, 0, 0, 0}, TEX_MIP, 128, 128, 0, { 0, 0}, TEX_MIP, DDERR_INVALIDPARAMS},
15029 {128, 128, 0, { 0, 0, 100, 100}, TEX_MIP, 128, 128, 0, {50, 50}, TEX_MIP, DDERR_INVALIDPARAMS},
15030 {128, 128, 0, {30, 20, 93, 52}, TEX_MIP, 128, 128, 0, {31, 31}, TEX_MIP, D3D_OK},
15031 {128, 128, 0, { 0, 0, 0, 0}, NULL_COORDS, 128, 128, 0, { 0, 0}, NULL_COORDS, D3D_OK},
15032 {128, 128, 0, { 0, 0, 0, 0}, NULL_COORDS, 256, 128, 0, { 0, 0}, NULL_COORDS, DDERR_INVALIDPARAMS},
15033 {256, 128, 0, { 0, 0, 0, 0}, NULL_COORDS, 128, 128, 0, { 0, 0}, NULL_COORDS, DDERR_INVALIDPARAMS},
15034 {128, 128, 0, {30, 20, 93, 52}, TEX_MIP | TEX_CUBE, 128, 128, 0, {10, 10}, TEX_MIP | TEX_CUBE, D3D_OK},
15035 {128, 128, 0, { 0, 0, 0, 0}, NULL_COORDS, 128, 128, 0, { 0, 0}, TEX_CUBE | NULL_COORDS, DDERR_INVALIDPARAMS},
15036 {128, 128, 0, {30, 20, 93, 52}, TEX_MIP, 128, 128, 4, {31, 31}, TEX_MIP, D3D_OK},
15037 {128, 128, 4, {30, 20, 93, 52}, TEX_MIP, 128, 128, 0, {31, 31}, TEX_MIP, DDERR_INVALIDPARAMS},
15038 {128, 128, 0, {32, 32, 96, 96}, TEX_MIP, 32, 32, 0, {32, 32}, 0, D3D_OK},
15039 {128, 128, 0, { 0, 0, 64, 64}, TEX_MIP, 32, 32, 4, { 0, 0}, TEX_MIP, D3D_OK},
15042 window = create_window();
15043 if (!(device = create_device(window, DDSCL_NORMAL)))
15045 skip("Failed to create a 3D device, skipping test.\n");
15046 DestroyWindow(window);
15047 return;
15050 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
15051 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
15052 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
15053 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
15054 IDirect3D7_Release(d3d);
15056 memset(&d3d_caps, 0, sizeof(d3d_caps));
15057 hr = IDirect3DDevice7_GetCaps(device, &d3d_caps);
15058 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
15059 cube_support = d3d_caps.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP;
15061 for (i = 0; i < ARRAY_SIZE(tests); ++i)
15063 unsigned int src_count, dst_count;
15064 POINT dst_point, dst_point_broken;
15065 RECT src_rect, src_rect_broken;
15067 if ((tests[i].src_flags | tests[i].dst_flags) & TEX_CUBE && !cube_support)
15069 skip("No cubemap support, skipping test %u.\n", i);
15070 continue;
15073 memset(&surface_desc, 0, sizeof(surface_desc));
15074 surface_desc.dwSize = sizeof(surface_desc);
15075 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
15076 if (tests[i].src_mip_count)
15077 surface_desc.dwFlags |= DDSD_MIPMAPCOUNT;
15078 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
15079 if (tests[i].src_flags & (TEX_MIP | TEX_CUBE))
15080 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
15081 if (tests[i].src_flags & TEX_MIP)
15082 surface_desc.ddsCaps.dwCaps |= DDSCAPS_MIPMAP;
15083 if (tests[i].src_flags & TEX_CUBE)
15084 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
15085 surface_desc.dwWidth = tests[i].src_w;
15086 surface_desc.dwHeight = tests[i].src_h;
15087 U2(surface_desc).dwMipMapCount = tests[i].src_mip_count;
15088 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
15089 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
15090 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
15091 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
15092 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
15093 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
15094 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
15095 ok(SUCCEEDED(hr), "Test %u: Failed to create source surface, hr %#x.\n", i, hr);
15097 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
15098 if (tests[i].dst_mip_count)
15099 surface_desc.dwFlags |= DDSD_MIPMAPCOUNT;
15100 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
15101 if (tests[i].dst_flags & (TEX_MIP | TEX_CUBE))
15102 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
15103 if (tests[i].dst_flags & TEX_MIP)
15104 surface_desc.ddsCaps.dwCaps |= DDSCAPS_MIPMAP;
15105 surface_desc.ddsCaps.dwCaps2 = 0;
15106 if (tests[i].dst_flags & TEX_CUBE)
15107 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
15108 surface_desc.dwWidth = tests[i].dst_w;
15109 surface_desc.dwHeight = tests[i].dst_h;
15110 U2(surface_desc).dwMipMapCount = tests[i].dst_mip_count;
15111 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
15112 ok(SUCCEEDED(hr), "Test %u: Failed to create destination surface, hr %#x.\n", i, hr);
15114 src_count = dst_count = 1;
15115 if (tests[i].src_flags & TEX_MIP)
15116 src_count = tests[i].src_mip_count ? tests[i].src_mip_count : 8;
15117 if (tests[i].dst_flags & TEX_MIP)
15118 dst_count = tests[i].dst_mip_count ? tests[i].dst_mip_count : 8;
15120 surface = src_surface;
15121 IDirectDrawSurface7_AddRef(surface);
15122 for (j = 0;;)
15124 DDSCAPS2 face_caps = {0, 0, 0, {0}};
15126 /* Check the number of created mipmaps. */
15127 if (tests[i].src_flags & TEX_MIP)
15129 memset(&surface_desc, 0, sizeof(surface_desc));
15130 surface_desc.dwSize = sizeof(surface_desc);
15131 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
15132 ok(SUCCEEDED(hr), "Test %u: Failed to get surface description, hr %#x.\n", i, hr);
15133 ok(U2(surface_desc).dwMipMapCount == src_count,
15134 "Test %u: Got unexpected mip count %u, expected %u.\n",
15135 i, U2(surface_desc).dwMipMapCount, src_count);
15138 for (k = 0; ; ++k)
15140 memset(&surface_desc, 0, sizeof(surface_desc));
15141 surface_desc.dwSize = sizeof(surface_desc);
15142 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
15143 ok(SUCCEEDED(hr), "Test %u: Failed to map surface, hr %#x.\n", i, hr);
15145 for (y = 0; y < surface_desc.dwHeight; ++y)
15147 DWORD *texture_row = (DWORD *)((BYTE *)surface_desc.lpSurface + y * U1(surface_desc).lPitch);
15149 for (x = 0; x < surface_desc.dwWidth; ++x)
15151 /* The face number is stored in the high 4 bits of the
15152 * red component, the mip-level in the low 4 bits. The
15153 * x-coordinate is stored in the green component, and
15154 * the y-coordinate in the blue component. */
15155 texture_row[x] = (j << 20) | (k << 16) | (x << 8) | y;
15159 hr = IDirectDrawSurface7_Unlock(surface, NULL);
15160 ok(SUCCEEDED(hr), "Test %u: Failed to unmap surface, hr %#x.\n", i, hr);
15162 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &mip_caps, &tmp);
15163 IDirectDrawSurface7_Release(surface);
15164 if (FAILED(hr))
15165 break;
15166 surface = tmp;
15169 if (!(tests[i].src_flags & TEX_CUBE) || ++j >= 6)
15170 break;
15172 face_caps.dwCaps2 = DDSCAPS2_CUBEMAP | (DDSCAPS2_CUBEMAP_POSITIVEX << j);
15173 hr = IDirectDrawSurface7_GetAttachedSurface(src_surface, &face_caps, &surface);
15174 ok(SUCCEEDED(hr), "Test %u: Failed to get face %u.\n", i, j);
15177 surface = dst_surface;
15178 IDirectDrawSurface7_AddRef(surface);
15179 for (j = 0;;)
15181 DDSCAPS2 face_caps = {0, 0, 0, {0}};
15183 /* Check the number of created mipmaps. */
15184 if (tests[i].dst_flags & TEX_MIP)
15186 memset(&surface_desc, 0, sizeof(surface_desc));
15187 surface_desc.dwSize = sizeof(surface_desc);
15188 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
15189 ok(SUCCEEDED(hr), "Test %u: Failed to get surface description, hr %#x.\n", i, hr);
15190 ok(U2(surface_desc).dwMipMapCount == dst_count,
15191 "Test %u: Got unexpected mip count %u, expected %u.\n",
15192 i, U2(surface_desc).dwMipMapCount, dst_count);
15195 for (;;)
15197 memset(&fx, 0, sizeof(fx));
15198 fx.dwSize = sizeof(fx);
15199 U5(fx).dwFillColor = 0x00000000;
15200 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
15201 ok(SUCCEEDED(hr), "Test %u: Failed to clear surface, hr %#x.\n", i, hr);
15203 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &mip_caps, &tmp);
15204 IDirectDrawSurface7_Release(surface);
15205 if (FAILED(hr))
15206 break;
15207 surface = tmp;
15210 if (!(tests[i].dst_flags & TEX_CUBE) || ++j >= 6)
15211 break;
15213 face_caps.dwCaps2 = DDSCAPS2_CUBEMAP | (DDSCAPS2_CUBEMAP_POSITIVEX << j);
15214 hr = IDirectDrawSurface7_GetAttachedSurface(dst_surface, &face_caps, &surface);
15215 ok(SUCCEEDED(hr), "Test %u: Failed to get face %u.\n", i, j);
15218 src_rect = tests[i].src_rect;
15219 dst_point = tests[i].dst_point;
15220 hr = IDirect3DDevice7_Load(device,
15221 dst_surface, tests[i].dst_flags & NULL_COORDS ? NULL : &dst_point,
15222 src_surface, tests[i].src_flags & NULL_COORDS ? NULL : &src_rect,
15223 tests[i].dst_flags & TEX_CUBE ? DDSCAPS2_CUBEMAP_ALLFACES : 0);
15224 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x.\n", i, hr);
15226 if (SUCCEEDED(hr))
15228 unsigned int level_offset, level_offset_broken;
15230 for (level_offset = 0, k = tests[i].src_w; k > tests[i].dst_w; ++level_offset, k /= 2);
15231 level_offset_broken = src_count - dst_count;
15233 surface = dst_surface;
15234 IDirectDrawSurface7_AddRef(surface);
15235 for (j = 0;;)
15237 DDSCAPS2 face_caps = {0, 0, 0, {0}};
15239 if (tests[i].src_flags & NULL_COORDS)
15240 SetRect(&src_rect, 0, 0, tests[i].src_w, tests[i].src_h);
15241 else
15242 src_rect = tests[i].src_rect;
15244 if (tests[i].dst_flags & NULL_COORDS)
15245 dst_point.x = dst_point.y = 0;
15246 else
15247 dst_point = tests[i].dst_point;
15249 for (k = 0; k < level_offset; ++k)
15251 dst_point.x /= 2;
15252 dst_point.y /= 2;
15253 src_rect.top /= 2;
15254 src_rect.left /= 2;
15255 src_rect.right = (src_rect.right + 1) / 2;
15256 src_rect.bottom = (src_rect.bottom + 1) / 2;
15259 for (k = 0; ; ++k)
15261 unsigned int diff, diff2, diff3;
15263 diff = validate_loaded_surface(surface, j, k + level_offset, &src_rect, &dst_point);
15265 /* On some newer (XP+) versions of Windows, it appears the
15266 * source/destination coordinates are divided too often.
15267 * This works correctly on Windows 98 with the RGB
15268 * software rasteriser. */
15269 src_rect_broken = src_rect;
15270 dst_point_broken = dst_point;
15271 for (l = 0; l < level_offset; ++l)
15273 dst_point_broken.x /= 2;
15274 dst_point_broken.y /= 2;
15275 src_rect_broken.top /= 2;
15276 src_rect_broken.left /= 2;
15277 src_rect_broken.right = (src_rect_broken.right + 1) / 2;
15278 src_rect_broken.bottom = (src_rect_broken.bottom + 1) / 2;
15280 diff2 = validate_loaded_surface(surface, j, k + level_offset,
15281 &src_rect_broken, &dst_point_broken);
15283 /* On Windows 8+ things are slightly worse still. Instead
15284 * of applying the correct level offset twice, like on
15285 * XP+, an incorrect offset is applied in addition to the
15286 * correct one. Additionally, on Windows 8+, this offset
15287 * also affects the selected source mip-level, as opposed
15288 * to Windows XP+ where it only affects the
15289 * source/destination coordinates. */
15290 src_rect_broken = src_rect;
15291 dst_point_broken = dst_point;
15292 for (l = 0; l < level_offset_broken; ++l)
15294 dst_point_broken.x /= 2;
15295 dst_point_broken.y /= 2;
15296 src_rect_broken.top /= 2;
15297 src_rect_broken.left /= 2;
15298 src_rect_broken.right = (src_rect_broken.right + 1) / 2;
15299 src_rect_broken.bottom = (src_rect_broken.bottom + 1) / 2;
15301 diff3 = validate_loaded_surface(surface, j, k + level_offset_broken,
15302 &src_rect_broken, &dst_point_broken);
15304 ok(!diff || broken(!diff2 || !diff3), "Test %u, face %u, level %u: "
15305 "Unexpected destination texture level pixels; %u/%u/%u differences.\n",
15306 i, j, k, diff, diff2, diff3);
15308 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &mip_caps, &tmp);
15309 IDirectDrawSurface7_Release(surface);
15310 if (FAILED(hr))
15311 break;
15312 surface = tmp;
15314 dst_point.x /= 2;
15315 dst_point.y /= 2;
15316 src_rect.top /= 2;
15317 src_rect.left /= 2;
15318 src_rect.right = (src_rect.right + 1) / 2;
15319 src_rect.bottom = (src_rect.bottom + 1) / 2;
15322 if (!(tests[i].dst_flags & TEX_CUBE) || ++j >= 6)
15323 break;
15325 face_caps.dwCaps2 = DDSCAPS2_CUBEMAP | (DDSCAPS2_CUBEMAP_POSITIVEX << j);
15326 hr = IDirectDrawSurface7_GetAttachedSurface(dst_surface, &face_caps, &surface);
15327 ok(SUCCEEDED(hr), "Test %u: Failed to get face %u.\n", i, j);
15331 IDirectDrawSurface7_Release(dst_surface);
15332 IDirectDrawSurface7_Release(src_surface);
15334 #undef TEX_MIP
15335 #undef TEX_CUBE
15336 #undef NULL_COORDS
15338 memset(&surface_desc, 0, sizeof(surface_desc));
15339 surface_desc.dwSize = sizeof(surface_desc);
15340 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
15341 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
15342 surface_desc.dwWidth = 128;
15343 surface_desc.dwHeight = 128;
15344 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
15345 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
15346 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
15347 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
15348 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
15349 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
15350 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
15351 hr = IDirectDrawSurface7_GetAttachedSurface(src_surface, &mip_caps, &surface);
15352 ok(SUCCEEDED(hr), "Failed to get surface, hr %#x.\n", hr);
15354 /* Test palette copying. */
15355 memset(table1, 0, sizeof(table1));
15356 table1[0].peBlue = 1;
15357 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &src_palette, NULL);
15358 ok(SUCCEEDED(hr), "Failed to create source palette, hr %#x.\n", hr);
15359 table1[0].peBlue = 3;
15360 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &dst_palette, NULL);
15361 ok(SUCCEEDED(hr), "Failed to create destination palette, hr %#x.\n", hr);
15363 hr = IDirectDrawSurface7_SetPalette(src_surface, src_palette);
15364 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
15366 hr = IDirect3DDevice7_Load(device, dst_surface, NULL, src_surface, NULL, 0);
15367 ok(SUCCEEDED(hr), "Failed to load texture, hr %#x.\n", hr);
15369 hr = IDirectDrawSurface7_GetPalette(surface, &palette);
15370 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
15371 hr = IDirectDrawSurface7_GetPalette(dst_surface, &palette);
15372 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
15374 hr = IDirectDrawSurface7_SetPalette(surface, src_palette);
15375 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x.\n", hr);
15376 hr = IDirectDrawSurface7_SetPalette(dst_surface, dst_palette);
15377 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
15379 hr = IDirect3DDevice7_Load(device, dst_surface, NULL, src_surface, NULL, 0);
15380 ok(SUCCEEDED(hr), "Failed to load texture, hr %#x.\n", hr);
15382 hr = IDirectDrawSurface7_GetPalette(dst_surface, &palette);
15383 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
15384 ok(palette == dst_palette, "Got unexpected palette %p, expected %p.\n", palette, dst_palette);
15385 memset(table1, 0, sizeof(table1));
15386 hr = IDirectDrawPalette_GetEntries(palette, 0, 0, 256, table1);
15387 ok(SUCCEEDED(hr), "Failed to retrieve palette entries, hr %#x.\n", hr);
15388 ok(table1[0].peBlue == 1, "Got unexpected palette colour %#x.\n", (unsigned int)table1[0].peBlue);
15389 IDirectDrawPalette_Release(palette);
15391 IDirectDrawPalette_Release(dst_palette);
15392 IDirectDrawPalette_Release(src_palette);
15394 /* Test colour-key copying. */
15395 colour_key.dwColorSpaceLowValue = 32;
15396 colour_key.dwColorSpaceHighValue = 64;
15397 hr = IDirectDrawSurface7_SetColorKey(src_surface, DDCKEY_SRCBLT, &colour_key);
15398 ok(SUCCEEDED(hr), "Failed to set colour-key, hr %#x.\n", hr);
15399 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &colour_key);
15400 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x.\n", hr);
15402 hr = IDirectDrawSurface7_GetColorKey(dst_surface, DDCKEY_SRCBLT, &colour_key);
15403 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
15405 hr = IDirect3DDevice7_Load(device, dst_surface, NULL, src_surface, NULL, 0);
15406 ok(SUCCEEDED(hr), "Failed to load texture, hr %#x.\n", hr);
15408 hr = IDirectDrawSurface7_GetColorKey(dst_surface, DDCKEY_SRCBLT, &colour_key);
15409 ok(SUCCEEDED(hr), "Failed to get colour-key, hr %#x.\n", hr);
15410 ok(colour_key.dwColorSpaceLowValue == 32, "Got unexpected value %u.\n", colour_key.dwColorSpaceLowValue);
15411 ok(colour_key.dwColorSpaceHighValue == 32, "Got unexpected value %u.\n", colour_key.dwColorSpaceHighValue);
15413 IDirectDrawSurface7_Release(surface);
15414 IDirectDrawSurface7_Release(dst_surface);
15415 IDirectDrawSurface7_Release(src_surface);
15417 IDirectDraw7_Release(ddraw);
15418 refcount = IDirect3DDevice7_Release(device);
15419 ok(!refcount, "Device has %u references left.\n", refcount);
15420 DestroyWindow(window);
15423 static void test_color_vertex(void)
15425 IDirect3DDevice7 *device;
15426 IDirectDrawSurface7 *rt;
15427 D3DMATERIAL7 material;
15428 D3DCOLOR colour;
15429 unsigned int i;
15430 ULONG refcount;
15431 HWND window;
15432 HRESULT hr;
15434 static struct
15436 struct vec3 position;
15437 DWORD diffuse;
15438 DWORD specular;
15440 quad_2c[] =
15442 {{-1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff00ff00},
15443 {{-1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff00ff00},
15444 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff00ff00},
15445 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff00ff00},
15447 static struct
15449 struct vec3 position;
15450 DWORD colour;
15452 quad_1c[] =
15454 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
15455 {{-1.0f, 1.0f, 0.0f}, 0xffff0000},
15456 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000},
15457 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000},
15459 static struct
15461 struct vec3 position;
15463 quad_0c[] =
15465 {{-1.0f, -1.0f, 0.0f}},
15466 {{-1.0f, 1.0f, 0.0f}},
15467 {{ 1.0f, -1.0f, 0.0f}},
15468 {{ 1.0f, 1.0f, 0.0f}},
15471 /* The idea here is to set up ambient light parameters in a way that the
15472 * ambient colour from the material is just passed through. The emissive
15473 * colour is just passed through anyway. The sum of ambient + emissive
15474 * should allow deduction of where the material colour came from. */
15475 static const struct
15477 DWORD fvf, color_vertex, ambient, emissive, result;
15478 void *vtx;
15480 tests[] =
15482 {D3DFVF_DIFFUSE | D3DFVF_SPECULAR, FALSE, D3DMCS_COLOR1, D3DMCS_COLOR2, 0x000000c0, quad_2c},
15484 {D3DFVF_DIFFUSE | D3DFVF_SPECULAR, TRUE, D3DMCS_COLOR1, D3DMCS_COLOR2, 0x00ffff00, quad_2c},
15485 {D3DFVF_DIFFUSE | D3DFVF_SPECULAR, TRUE, D3DMCS_MATERIAL, D3DMCS_COLOR2, 0x0000ff80, quad_2c},
15486 {D3DFVF_DIFFUSE | D3DFVF_SPECULAR, TRUE, D3DMCS_COLOR1, D3DMCS_MATERIAL, 0x00ff0040, quad_2c},
15487 {D3DFVF_DIFFUSE | D3DFVF_SPECULAR, TRUE, D3DMCS_COLOR1, D3DMCS_COLOR1, 0x00ff0000, quad_2c},
15488 {D3DFVF_DIFFUSE | D3DFVF_SPECULAR, TRUE, D3DMCS_COLOR2, D3DMCS_COLOR2, 0x0000ff00, quad_2c},
15490 {D3DFVF_SPECULAR, TRUE, D3DMCS_COLOR1, D3DMCS_COLOR2, 0x00ff0080, quad_1c},
15491 {D3DFVF_SPECULAR, TRUE, D3DMCS_COLOR1, D3DMCS_MATERIAL, 0x000000c0, quad_1c},
15492 {D3DFVF_SPECULAR, TRUE, D3DMCS_MATERIAL, D3DMCS_COLOR2, 0x00ff0080, quad_1c},
15493 {D3DFVF_DIFFUSE, TRUE, D3DMCS_COLOR1, D3DMCS_COLOR2, 0x00ff0040, quad_1c},
15494 {D3DFVF_DIFFUSE, TRUE, D3DMCS_COLOR1, D3DMCS_MATERIAL, 0x00ff0040, quad_1c},
15495 {D3DFVF_DIFFUSE, TRUE, D3DMCS_COLOR2, D3DMCS_MATERIAL, 0x000000c0, quad_1c},
15497 {0, TRUE, D3DMCS_COLOR1, D3DMCS_COLOR2, 0x000000c0, quad_0c},
15500 window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
15501 0, 0, 640, 480, 0, 0, 0, 0);
15502 if (!(device = create_device(window, DDSCL_NORMAL)))
15504 skip("Failed to create a 3D device, skipping test.\n");
15505 DestroyWindow(window);
15506 return;
15508 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
15509 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
15511 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
15512 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
15513 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_AMBIENT, 0xffffffff);
15514 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
15516 memset(&material, 0, sizeof(material));
15517 U3(U1(material).ambient).b = 0.5f;
15518 U3(U3(material).emissive).b = 0.25f;
15519 hr = IDirect3DDevice7_SetMaterial(device, &material);
15520 ok(SUCCEEDED(hr), "Failed to set material, hr %#x\n", hr);
15522 for (i = 0; i < ARRAY_SIZE(tests); ++i)
15524 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORVERTEX, tests[i].color_vertex);
15525 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
15526 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_AMBIENTMATERIALSOURCE, tests[i].ambient);
15527 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
15528 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_EMISSIVEMATERIALSOURCE, tests[i].emissive);
15529 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
15530 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
15531 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
15533 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x77777777, 0.0f, 0);
15534 ok(SUCCEEDED(hr), "Failed to clear depth/stencil, hr %#x.\n", hr);
15536 hr = IDirect3DDevice7_BeginScene(device);
15537 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
15538 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
15539 D3DFVF_XYZ | tests[i].fvf, tests[i].vtx, 4, 0);
15540 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
15541 hr = IDirect3DDevice7_EndScene(device);
15542 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
15544 colour = get_surface_color(rt, 320, 240);
15545 ok(compare_color(colour, tests[i].result, 1),
15546 "Expected colour 0x%08x for test %u, got 0x%08x.\n",
15547 tests[i].result, i, colour);
15550 IDirectDrawSurface7_Release(rt);
15551 refcount = IDirect3DDevice7_Release(device);
15552 ok(!refcount, "Device has %u references left.\n", refcount);
15553 DestroyWindow(window);
15556 static IDirectDraw7 *killfocus_ddraw;
15557 static IDirectDrawSurface7 *killfocus_surface;
15559 static LRESULT CALLBACK killfocus_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
15561 ULONG ref;
15563 if (message == WM_KILLFOCUS)
15565 ref = IDirectDrawSurface7_Release(killfocus_surface);
15566 ok(!ref, "Unexpected surface refcount %u.\n", ref);
15567 ref = IDirectDraw7_Release(killfocus_ddraw);
15568 ok(!ref, "Unexpected ddraw refcount %u.\n", ref);
15569 killfocus_ddraw = NULL;
15572 return DefWindowProcA(window, message, wparam, lparam);
15575 static void test_killfocus(void)
15577 DDSURFACEDESC2 surface_desc;
15578 HRESULT hr;
15579 HWND window;
15580 WNDCLASSA wc = {0};
15582 wc.lpfnWndProc = killfocus_proc;
15583 wc.lpszClassName = "ddraw_killfocus_wndproc_wc";
15584 ok(RegisterClassA(&wc), "Failed to register window class.\n");
15586 window = CreateWindowA("ddraw_killfocus_wndproc_wc", "d3d7_test", WS_OVERLAPPEDWINDOW,
15587 0, 0, 640, 480, 0, 0, 0, 0);
15589 killfocus_ddraw = create_ddraw();
15590 ok(!!killfocus_ddraw, "Failed to create a ddraw object.\n");
15592 hr = IDirectDraw7_SetCooperativeLevel(killfocus_ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
15593 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
15595 memset(&surface_desc, 0, sizeof(surface_desc));
15596 surface_desc.dwSize = sizeof(surface_desc);
15597 surface_desc.dwFlags = DDSD_CAPS;
15598 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
15599 hr = IDirectDraw7_CreateSurface(killfocus_ddraw, &surface_desc, &killfocus_surface, NULL);
15600 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
15602 SetForegroundWindow(GetDesktopWindow());
15603 ok(!killfocus_ddraw, "WM_KILLFOCUS was not received.\n");
15605 DestroyWindow(window);
15606 UnregisterClassA("ddraw_killfocus_wndproc_wc", GetModuleHandleA(NULL));
15609 static void test_sysmem_draw(void)
15611 IDirectDrawSurface7 *rt, *texture;
15612 DDSURFACEDESC2 surface_desc;
15613 D3DVERTEXBUFFERDESC vb_desc;
15614 IDirect3DVertexBuffer7 *vb;
15615 IDirect3DDevice7 *device;
15616 IDirectDraw7 *ddraw;
15617 IDirect3D7 *d3d;
15618 D3DCOLOR colour;
15619 ULONG refcount;
15620 HWND window;
15621 HRESULT hr;
15622 BYTE *data;
15624 static const struct
15626 struct vec3 position;
15627 DWORD diffuse;
15629 quad[] =
15631 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
15632 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
15633 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
15634 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
15636 static WORD indices[] = {0, 1, 2, 3};
15638 window = create_window();
15639 ok(!!window, "Failed to create a window.\n");
15641 if (!(device = create_device(window, DDSCL_NORMAL)))
15643 skip("Failed to create a 3D device, skipping test.\n");
15644 DestroyWindow(window);
15645 return;
15648 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
15649 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15650 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
15651 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15652 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
15653 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15655 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
15656 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15658 vb_desc.dwSize = sizeof(vb_desc);
15659 vb_desc.dwCaps = D3DVBCAPS_SYSTEMMEMORY;
15660 vb_desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
15661 vb_desc.dwNumVertices = 4;
15662 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &vb, 0);
15663 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15665 hr = IDirect3DVertexBuffer7_Lock(vb, 0, (void **)&data, NULL);
15666 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15667 memcpy(data, quad, sizeof(quad));
15668 hr = IDirect3DVertexBuffer7_Unlock(vb);
15669 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15671 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x77777777, 0.0f, 0);
15672 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15674 hr = IDirect3DDevice7_BeginScene(device);
15675 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15676 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, 0);
15677 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15678 hr = IDirect3DDevice7_EndScene(device);
15679 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15681 colour = get_surface_color(rt, 320, 240);
15682 ok(compare_color(colour, 0x00007f7f, 1), "Got unexpected colour 0x%08x.\n", colour);
15684 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x77777777, 0.0f, 0);
15685 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15687 hr = IDirect3DDevice7_BeginScene(device);
15688 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15689 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, indices, 4, 0);
15690 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15691 hr = IDirect3DDevice7_EndScene(device);
15692 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15694 colour = get_surface_color(rt, 320, 240);
15695 ok(compare_color(colour, 0x00007f7f, 1), "Got unexpected colour 0x%08x.\n", colour);
15697 memset(&surface_desc, 0, sizeof(surface_desc));
15698 surface_desc.dwSize = sizeof(surface_desc);
15699 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
15700 surface_desc.dwHeight = 2;
15701 surface_desc.dwWidth = 2;
15702 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
15703 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
15704 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
15705 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
15706 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
15707 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
15708 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
15709 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
15710 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
15711 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15712 hr = IDirect3DDevice7_SetTexture(device, 0, texture);
15713 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
15715 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x77777777, 0.0f, 0);
15716 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
15718 hr = IDirect3DDevice7_BeginScene(device);
15719 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
15720 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, 0);
15721 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
15722 hr = IDirect3DDevice7_EndScene(device);
15723 ok(hr == D3D_OK || hr == D3DERR_SCENE_END_FAILED, "Got unexpected hr %#x.\n", hr);
15725 IDirectDrawSurface7_Release(texture);
15726 IDirect3DVertexBuffer7_Release(vb);
15727 IDirectDrawSurface7_Release(rt);
15728 IDirectDraw7_Release(ddraw);
15729 IDirect3D7_Release(d3d);
15730 refcount = IDirect3DDevice7_Release(device);
15731 ok(!refcount, "Device has %u references left.\n", refcount);
15732 DestroyWindow(window);
15735 static void test_gdi_surface(void)
15737 IDirectDrawSurface7 *primary, *backbuffer, *gdi_surface;
15738 DDSCAPS2 caps = {DDSCAPS_BACKBUFFER, 0, 0, {0}};
15739 DDSURFACEDESC2 surface_desc;
15740 IDirectDraw7 *ddraw;
15741 ULONG refcount;
15742 HWND window;
15743 HRESULT hr;
15745 window = create_window();
15746 ddraw = create_ddraw();
15747 ok(!!ddraw, "Failed to create a ddraw object.\n");
15748 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
15749 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15751 /* Retrieving the GDI surface requires a primary surface to exist. */
15752 gdi_surface = (void *)0xc0dec0de;
15753 hr = IDirectDraw7_GetGDISurface(ddraw, &gdi_surface);
15754 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
15755 ok(!gdi_surface, "Got unexpected surface %p.\n", gdi_surface);
15757 hr = IDirectDraw7_FlipToGDISurface(ddraw);
15758 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
15760 memset(&surface_desc, 0, sizeof(surface_desc));
15761 surface_desc.dwSize = sizeof(surface_desc);
15762 surface_desc.dwFlags = DDSD_CAPS;
15763 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
15764 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
15765 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15767 hr = IDirectDraw7_GetGDISurface(ddraw, &gdi_surface);
15768 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15769 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
15770 IDirectDrawSurface7_Release(gdi_surface);
15772 /* Flipping to the GDI surface requires the primary surface to be
15773 * flippable. */
15774 hr = IDirectDraw7_FlipToGDISurface(ddraw);
15775 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
15777 IDirectDrawSurface7_Release(primary);
15779 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
15780 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15782 memset(&surface_desc, 0, sizeof(surface_desc));
15783 surface_desc.dwSize = sizeof(surface_desc);
15784 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
15785 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
15786 U5(surface_desc).dwBackBufferCount = 1;
15787 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
15788 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15789 hr = IDirectDrawSurface7_GetAttachedSurface(primary, &caps, &backbuffer);
15790 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15791 ok(backbuffer != primary, "Got unexpected backbuffer %p.\n", backbuffer);
15793 hr = IDirectDraw7_GetGDISurface(ddraw, &gdi_surface);
15794 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15795 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
15796 IDirectDrawSurface7_Release(gdi_surface);
15798 hr = IDirectDrawSurface7_Flip(primary, NULL, DDFLIP_WAIT);
15799 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15800 hr = IDirectDraw7_GetGDISurface(ddraw, &gdi_surface);
15801 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15802 ok(gdi_surface == backbuffer || broken(gdi_surface == primary),
15803 "Got unexpected surface %p, expected %p.\n", gdi_surface, backbuffer);
15804 IDirectDrawSurface7_Release(gdi_surface);
15806 hr = IDirectDraw7_FlipToGDISurface(ddraw);
15807 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15809 hr = IDirectDraw7_GetGDISurface(ddraw, &gdi_surface);
15810 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15811 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
15812 IDirectDrawSurface7_Release(gdi_surface);
15814 hr = IDirectDraw7_FlipToGDISurface(ddraw);
15815 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15817 IDirectDrawSurface7_Release(backbuffer);
15818 IDirectDrawSurface7_Release(primary);
15820 refcount = IDirectDraw7_Release(ddraw);
15821 ok(!refcount, "%u references left.\n", refcount);
15822 DestroyWindow(window);
15825 static void test_multiply_transform(void)
15827 IDirect3DDevice7 *device;
15828 D3DMATRIX ret_mat;
15829 DWORD stateblock;
15830 unsigned int i;
15831 ULONG refcount;
15832 HWND window;
15833 HRESULT hr;
15835 static const D3DTRANSFORMSTATETYPE tests[] =
15837 D3DTRANSFORMSTATE_WORLD,
15838 D3DTRANSFORMSTATE_VIEW,
15839 D3DTRANSFORMSTATE_PROJECTION,
15840 D3DTRANSFORMSTATE_WORLD1,
15841 D3DTRANSFORMSTATE_WORLD2,
15842 D3DTRANSFORMSTATE_WORLD3,
15843 D3DTRANSFORMSTATE_TEXTURE0,
15844 D3DTRANSFORMSTATE_TEXTURE1,
15845 D3DTRANSFORMSTATE_TEXTURE2,
15846 D3DTRANSFORMSTATE_TEXTURE3,
15847 D3DTRANSFORMSTATE_TEXTURE4,
15848 D3DTRANSFORMSTATE_TEXTURE5,
15849 D3DTRANSFORMSTATE_TEXTURE6,
15850 D3DTRANSFORMSTATE_TEXTURE7,
15853 D3DMATRIX mat1 =
15855 1.0f, 0.0f, 0.0f, 0.0f,
15856 0.0f, 1.0f, 0.0f, 0.0f,
15857 0.0f, 0.0f, 1.0f, 0.0f,
15858 0.0f, 0.0f, 0.0f, 1.0f,
15860 mat2 =
15862 2.0f, 0.0f, 0.0f, 0.0f,
15863 0.0f, 2.0f, 0.0f, 0.0f,
15864 0.0f, 0.0f, 2.0f, 0.0f,
15865 0.0f, 0.0f, 0.0f, 2.0f,
15868 window = create_window();
15869 if (!(device = create_device(window, DDSCL_NORMAL)))
15871 skip("Failed to create 3D device.\n");
15872 DestroyWindow(window);
15873 return;
15876 for (i = 0; i < ARRAY_SIZE(tests); ++i)
15878 hr = IDirect3DDevice7_GetTransform(device, tests[i], &ret_mat);
15879 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
15880 ok(!memcmp(&ret_mat, &mat1, sizeof(mat1)), "Test %u: Got unexpected transform matrix.\n", i);
15882 hr = IDirect3DDevice7_MultiplyTransform(device, tests[i], &mat2);
15883 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
15885 hr = IDirect3DDevice7_GetTransform(device, tests[i], &ret_mat);
15886 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
15887 ok(!memcmp(&ret_mat, &mat2, sizeof(mat2)), "Test %u: Got unexpected transform matrix.\n", i);
15889 /* MultiplyTransform() goes directly into the primary stateblock. */
15891 hr = IDirect3DDevice7_SetTransform(device, tests[i], &mat1);
15892 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
15894 hr = IDirect3DDevice7_BeginStateBlock(device);
15895 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
15897 hr = IDirect3DDevice7_MultiplyTransform(device, tests[i], &mat2);
15898 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
15900 hr = IDirect3DDevice7_EndStateBlock(device, &stateblock);
15901 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
15903 hr = IDirect3DDevice7_GetTransform(device, tests[i], &ret_mat);
15904 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
15905 ok(!memcmp(&ret_mat, &mat2, sizeof(mat2)), "Test %u: Got unexpected transform matrix.\n", i);
15907 hr = IDirect3DDevice7_CaptureStateBlock(device, stateblock);
15908 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
15910 hr = IDirect3DDevice7_SetTransform(device, tests[i], &mat1);
15911 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
15913 hr = IDirect3DDevice7_ApplyStateBlock(device, stateblock);
15914 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
15916 hr = IDirect3DDevice7_GetTransform(device, tests[i], &ret_mat);
15917 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
15918 ok(!memcmp(&ret_mat, &mat1, sizeof(mat1)), "Test %u: Got unexpected transform matrix.\n", i);
15920 IDirect3DDevice7_DeleteStateBlock(device, stateblock);
15923 refcount = IDirect3DDevice7_Release(device);
15924 ok(!refcount, "Device has %u references left.\n", refcount);
15925 DestroyWindow(window);
15928 static void test_alphatest(void)
15930 #define ALPHATEST_PASSED 0x0000ff00
15931 #define ALPHATEST_FAILED 0x00ff0000
15932 IDirect3DDevice7 *device;
15933 IDirectDrawSurface7 *rt;
15934 unsigned int i;
15935 D3DCOLOR color;
15936 ULONG refcount;
15937 HWND window;
15938 DWORD value;
15939 HRESULT hr;
15941 static const struct
15943 D3DCMPFUNC func;
15944 D3DCOLOR color_less;
15945 D3DCOLOR color_equal;
15946 D3DCOLOR color_greater;
15948 test_data[] =
15950 {D3DCMP_NEVER, ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_FAILED},
15951 {D3DCMP_LESS, ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_FAILED},
15952 {D3DCMP_EQUAL, ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_FAILED},
15953 {D3DCMP_LESSEQUAL, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_FAILED},
15954 {D3DCMP_GREATER, ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_PASSED},
15955 {D3DCMP_NOTEQUAL, ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_PASSED},
15956 {D3DCMP_GREATEREQUAL, ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_PASSED},
15957 {D3DCMP_ALWAYS, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_PASSED},
15959 static struct
15961 struct vec3 position;
15962 DWORD diffuse;
15964 quad[] =
15966 {{-1.0f, -1.0f, 0.1f}, ALPHATEST_PASSED | 0x80000000},
15967 {{-1.0f, 1.0f, 0.1f}, ALPHATEST_PASSED | 0x80000000},
15968 {{ 1.0f, -1.0f, 0.1f}, ALPHATEST_PASSED | 0x80000000},
15969 {{ 1.0f, 1.0f, 0.1f}, ALPHATEST_PASSED | 0x80000000},
15972 window = create_window();
15973 if (!(device = create_device(window, DDSCL_NORMAL)))
15975 skip("Failed to create a 3D device.\n");
15976 DestroyWindow(window);
15977 return;
15979 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
15980 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
15982 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
15983 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
15984 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
15985 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
15986 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
15987 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
15988 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHATESTENABLE, TRUE);
15989 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
15991 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
15993 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHAFUNC, test_data[i].func);
15994 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
15996 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, ALPHATEST_FAILED, 0.0f, 0);
15997 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
15998 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHAREF, 0x70);
15999 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16000 hr = IDirect3DDevice7_BeginScene(device);
16001 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16002 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
16003 D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, ARRAY_SIZE(quad), 0);
16004 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16005 hr = IDirect3DDevice7_EndScene(device);
16006 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16007 color = get_surface_color(rt, 320, 240);
16008 ok(compare_color(color, test_data[i].color_greater, 0),
16009 "Alphatest failed, color 0x%08x, expected 0x%08x, alpha > ref, func %u.\n",
16010 color, test_data[i].color_greater, test_data[i].func);
16012 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, ALPHATEST_FAILED, 0.0f, 0);
16013 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16014 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHAREF, 0xff70);
16015 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16016 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ALPHAREF, &value);
16017 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16018 ok(value == 0xff70, "Got unexpected value %#x.\n", value);
16019 hr = IDirect3DDevice7_BeginScene(device);
16020 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16021 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
16022 D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, ARRAY_SIZE(quad), 0);
16023 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16024 hr = IDirect3DDevice7_EndScene(device);
16025 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16026 color = get_surface_color(rt, 320, 240);
16027 ok(compare_color(color, test_data[i].color_greater, 0),
16028 "Alphatest failed, color 0x%08x, expected 0x%08x, alpha > ref, func %u.\n",
16029 color, test_data[i].color_greater, test_data[i].func);
16032 IDirectDrawSurface7_Release(rt);
16033 refcount = IDirect3DDevice7_Release(device);
16034 ok(!refcount, "Device has %u references left.\n", refcount);
16035 DestroyWindow(window);
16038 static void test_clipper_refcount(void)
16040 IDirectDrawSurface7 *surface;
16041 IDirectDrawClipper *clipper, *clipper2;
16042 DDSURFACEDESC2 surface_desc;
16043 IDirectDraw7 *ddraw;
16044 IDirectDraw *ddraw1;
16045 ULONG refcount;
16046 HWND window;
16047 HRESULT hr;
16048 BOOL changed;
16049 const IDirectDrawClipperVtbl *orig_vtbl;
16051 window = create_window();
16052 ddraw = create_ddraw();
16053 ok(!!ddraw, "Failed to create a ddraw object.\n");
16054 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
16055 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16057 memset(&surface_desc, 0, sizeof(surface_desc));
16058 surface_desc.dwSize = sizeof(surface_desc);
16059 surface_desc.dwFlags = DDSD_CAPS;
16060 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
16061 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
16062 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16064 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
16065 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
16066 refcount = get_refcount((IUnknown *)clipper);
16067 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
16069 /* Show that clipper validation doesn't somehow happen through per-clipper vtable
16070 * pointers. */
16071 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper2, NULL);
16072 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
16073 ok(clipper->lpVtbl == clipper2->lpVtbl, "Got different clipper vtables %p and %p.\n",
16074 clipper->lpVtbl, clipper2->lpVtbl);
16075 orig_vtbl = clipper->lpVtbl;
16076 IDirectDrawClipper_Release(clipper2);
16078 /* Surfaces hold a reference to clippers. No surprises there. */
16079 hr = IDirectDrawSurface7_SetClipper(surface, clipper);
16080 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
16081 refcount = get_refcount((IUnknown *)clipper);
16082 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
16084 hr = IDirectDrawSurface7_GetClipper(surface, &clipper2);
16085 ok(SUCCEEDED(hr), "Failed to get clipper, hr %#x.\n", hr);
16086 ok(clipper == clipper2, "Got clipper %p, expected %p.\n", clipper2, clipper);
16087 refcount = IDirectDrawClipper_Release(clipper2);
16088 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
16090 hr = IDirectDrawSurface7_SetClipper(surface, NULL);
16091 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
16092 refcount = get_refcount((IUnknown *)clipper);
16093 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
16095 hr = IDirectDrawSurface7_SetClipper(surface, clipper);
16096 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
16097 refcount = get_refcount((IUnknown *)clipper);
16098 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
16100 refcount = IDirectDrawSurface7_Release(surface);
16101 ok(!refcount, "%u references left.\n", refcount);
16102 refcount = get_refcount((IUnknown *)clipper);
16103 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
16105 /* SetClipper with an invalid pointer crashes. */
16107 /* Clipper methods work with a broken vtable, with the exception of Release. */
16108 clipper->lpVtbl = (void *)0xdeadbeef;
16109 refcount = orig_vtbl->AddRef(clipper);
16110 todo_wine ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
16111 refcount = orig_vtbl->Release(clipper);
16112 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
16114 clipper->lpVtbl = orig_vtbl;
16115 refcount = orig_vtbl->Release(clipper);
16116 todo_wine ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
16118 /* Fix the refcount difference because Wine did not increase the ref in the
16119 * AddRef call above. */
16120 if (refcount)
16122 refcount = IDirectDrawClipper_Release(clipper);
16123 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
16126 /* Steal the reference and see what happens - releasing the surface works fine.
16127 * The clipper is destroyed and not kept alive by a hidden refcount - trying to
16128 * release it after the GetClipper call is likely to crash, and certain to crash
16129 * if we allocate and zero as much heap memory as we can get. */
16130 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
16131 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16132 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
16133 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
16134 hr = IDirectDrawSurface7_SetClipper(surface, clipper);
16135 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
16137 IDirectDrawClipper_Release(clipper);
16138 IDirectDrawClipper_Release(clipper);
16140 hr = IDirectDrawSurface7_GetClipper(surface, &clipper2);
16141 ok(SUCCEEDED(hr), "Failed to get clipper, hr %#x.\n", hr);
16142 ok(clipper == clipper2, "Got clipper %p, expected %p.\n", clipper2, clipper);
16144 /* Show that invoking the Release method does not crash, but don't get the
16145 * vtable through the clipper pointer because it is no longer pointing to
16146 * valid memory. */
16147 refcount = orig_vtbl->Release(clipper);
16148 ok(!refcount, "%u references left.\n", refcount);
16150 refcount = IDirectDrawSurface7_Release(surface);
16151 ok(!refcount, "%u references left.\n", refcount);
16153 /* It looks like the protection against invalid thispointers is part of
16154 * the IDirectDrawClipper method implementation, not IDirectDrawSurface. */
16155 clipper = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 0x1000);
16156 ok(!!clipper, "failed to allocate memory\n");
16158 /* Assigning the vtable to our fake clipper does NOT make a difference on
16159 * native - there is a different member of the clipper implementation struct
16160 * that is used to determine if a clipper is valid. */
16161 clipper->lpVtbl = orig_vtbl;
16163 refcount = orig_vtbl->AddRef(clipper);
16164 todo_wine ok(!refcount, "Got refcount %u.\n", refcount);
16165 refcount = orig_vtbl->AddRef((IDirectDrawClipper *)(ULONG_PTR)0xdeadbeef);
16166 ok(!refcount, "Got refcount %u.\n", refcount);
16168 changed = 0x1234;
16169 hr = orig_vtbl->IsClipListChanged(clipper, &changed);
16170 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
16171 todo_wine ok(changed == 0x1234, "'changed' changed: %x.\n", changed);
16173 changed = 0x1234;
16174 hr = orig_vtbl->IsClipListChanged((IDirectDrawClipper *)(ULONG_PTR)0xdeadbeef, &changed);
16175 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
16176 ok(changed == 0x1234, "'changed' changed: %x.\n", changed);
16178 /* Nope, we can't initialize our fake clipper. */
16179 hr = IDirectDraw7_QueryInterface(ddraw, &IID_IDirectDraw, (void **)&ddraw1);
16180 ok(SUCCEEDED(hr), "Failed to get ddraw1 interface, hr %#x.\n", hr);
16182 hr = orig_vtbl->Initialize(clipper, ddraw1, 0);
16183 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
16185 IDirectDraw_Release(ddraw1);
16187 HeapFree(GetProcessHeap(), 0, clipper);
16189 refcount = IDirectDraw7_Release(ddraw);
16190 ok(!refcount, "%u references left.\n", refcount);
16191 DestroyWindow(window);
16194 static void test_begin_end_state_block(void)
16196 DWORD stateblock, stateblock2;
16197 IDirect3DDevice7 *device;
16198 ULONG refcount;
16199 DWORD value;
16200 HWND window;
16201 HRESULT hr;
16203 window = create_window();
16204 if (!(device = create_device(window, DDSCL_NORMAL)))
16206 skip("Failed to create 3D device.\n");
16207 DestroyWindow(window);
16208 return;
16211 hr = IDirect3DDevice7_BeginStateBlock(device);
16212 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16214 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
16215 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16217 stateblock = 0xdeadbeef;
16218 hr = IDirect3DDevice7_EndStateBlock(device, &stateblock);
16219 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16220 ok(!!stateblock && stateblock != 0xdeadbeef, "Got unexpected stateblock %#x.\n", stateblock);
16222 stateblock2 = 0xdeadbeef;
16223 hr = IDirect3DDevice7_EndStateBlock(device, &stateblock2);
16224 ok(hr == D3DERR_NOTINBEGINSTATEBLOCK, "Got unexpected hr %#x.\n", hr);
16225 ok(stateblock2 == 0xdeadbeef, "Got unexpected stateblock %#x.\n", stateblock2);
16227 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &value);
16228 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16229 ok(value == TRUE, "Got unexpected value %#x.\n", value);
16231 hr = IDirect3DDevice7_BeginStateBlock(device);
16232 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16234 hr = IDirect3DDevice7_BeginStateBlock(device);
16235 ok(hr == D3DERR_INBEGINSTATEBLOCK, "Got unexpected hr %#x.\n", hr);
16237 hr = IDirect3DDevice7_ApplyStateBlock(device, stateblock);
16238 ok(hr == D3DERR_INBEGINSTATEBLOCK, "Got unexpected hr %#x.\n", hr);
16240 hr = IDirect3DDevice7_CaptureStateBlock(device, stateblock);
16241 ok(hr == D3DERR_INBEGINSTATEBLOCK, "Got unexpected hr %#x.\n", hr);
16243 hr = IDirect3DDevice7_CreateStateBlock(device, D3DSBT_ALL, &stateblock2);
16244 ok(hr == D3DERR_INBEGINSTATEBLOCK, "Got unexpected hr %#x.\n", hr);
16246 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &value);
16247 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16248 ok(value == TRUE, "Got unexpected value %#x.\n", value);
16250 hr = IDirect3DDevice7_EndStateBlock(device, &stateblock2);
16251 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16253 hr = IDirect3DDevice7_ApplyStateBlock(device, stateblock2);
16254 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16256 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &value);
16257 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16258 ok(value == TRUE, "Got unexpected value %#x.\n", value);
16260 refcount = IDirect3DDevice7_Release(device);
16261 ok(!refcount, "Device has %u references left.\n", refcount);
16262 DestroyWindow(window);
16265 START_TEST(ddraw7)
16267 DDDEVICEIDENTIFIER2 identifier;
16268 HMODULE module, dwmapi;
16269 DEVMODEW current_mode;
16270 IDirectDraw7 *ddraw;
16272 module = GetModuleHandleA("ddraw.dll");
16273 if (!(pDirectDrawCreateEx = (void *)GetProcAddress(module, "DirectDrawCreateEx")))
16275 win_skip("DirectDrawCreateEx not available, skipping tests.\n");
16276 return;
16279 if (!(ddraw = create_ddraw()))
16281 skip("Failed to create a ddraw object, skipping tests.\n");
16282 return;
16285 if (ddraw_get_identifier(ddraw, &identifier))
16287 trace("Driver string: \"%s\"\n", identifier.szDriver);
16288 trace("Description string: \"%s\"\n", identifier.szDescription);
16289 trace("Driver version %d.%d.%d.%d\n",
16290 HIWORD(U(identifier.liDriverVersion).HighPart), LOWORD(U(identifier.liDriverVersion).HighPart),
16291 HIWORD(U(identifier.liDriverVersion).LowPart), LOWORD(U(identifier.liDriverVersion).LowPart));
16293 IDirectDraw7_Release(ddraw);
16295 memset(&current_mode, 0, sizeof(current_mode));
16296 current_mode.dmSize = sizeof(current_mode);
16297 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
16298 registry_mode.dmSize = sizeof(registry_mode);
16299 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
16300 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
16301 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
16303 skip("Current mode does not match registry mode, skipping test.\n");
16304 return;
16307 if ((dwmapi = LoadLibraryA("dwmapi.dll")))
16308 pDwmIsCompositionEnabled = (void *)GetProcAddress(dwmapi, "DwmIsCompositionEnabled");
16310 test_process_vertices();
16311 test_coop_level_create_device_window();
16312 test_clipper_blt();
16313 test_coop_level_d3d_state();
16314 test_surface_interface_mismatch();
16315 test_coop_level_threaded();
16316 test_depth_blit();
16317 test_texture_load_ckey();
16318 test_zenable();
16319 test_ck_rgba();
16320 test_ck_default();
16321 test_ck_complex();
16322 test_surface_qi();
16323 test_device_qi();
16324 test_wndproc();
16325 test_window_style();
16326 test_redundant_mode_set();
16327 test_coop_level_mode_set();
16328 test_coop_level_mode_set_multi();
16329 test_initialize();
16330 test_coop_level_surf_create();
16331 test_vb_discard();
16332 test_coop_level_multi_window();
16333 test_draw_strided();
16334 test_lighting();
16335 test_specular_lighting();
16336 test_clear_rect_count();
16337 test_coop_level_versions();
16338 test_fog_special();
16339 test_lighting_interface_versions();
16340 test_coop_level_activateapp();
16341 test_texturemanage();
16342 test_block_formats_creation();
16343 test_unsupported_formats();
16344 test_rt_caps();
16345 test_primary_caps();
16346 test_surface_lock();
16347 test_surface_discard();
16348 test_flip();
16349 test_set_surface_desc();
16350 test_user_memory_getdc();
16351 test_sysmem_overlay();
16352 test_primary_palette();
16353 test_surface_attachment();
16354 test_private_data();
16355 test_pixel_format();
16356 test_create_surface_pitch();
16357 test_mipmap();
16358 test_palette_complex();
16359 test_p8_blit();
16360 test_material();
16361 test_palette_gdi();
16362 test_palette_alpha();
16363 test_vb_writeonly();
16364 test_lost_device();
16365 test_resource_priority();
16366 test_surface_desc_lock();
16367 test_fog_interpolation();
16368 test_fog_process_vertices();
16369 test_negative_fixedfunction_fog();
16370 test_table_fog_zw();
16371 test_signed_formats();
16372 test_color_fill();
16373 test_texcoordindex();
16374 test_colorkey_precision();
16375 test_range_colorkey();
16376 test_shademode();
16377 test_lockrect_invalid();
16378 test_yv12_overlay();
16379 test_offscreen_overlay();
16380 test_overlay_rect();
16381 test_blt();
16382 test_blt_z_alpha();
16383 test_cross_device_blt();
16384 test_color_clamping();
16385 test_getdc();
16386 test_draw_primitive();
16387 test_edge_antialiasing_blending();
16388 test_display_mode_surface_pixel_format();
16389 test_surface_desc_size();
16390 test_get_surface_from_dc();
16391 test_ck_operation();
16392 test_vb_refcount();
16393 test_compute_sphere_visibility();
16394 test_clip_planes_limits();
16395 test_texture_stages_limits();
16396 test_set_render_state();
16397 test_map_synchronisation();
16398 test_depth_readback();
16399 test_clear();
16400 test_enum_surfaces();
16401 test_viewport();
16402 test_device_load();
16403 test_color_vertex();
16404 test_killfocus();
16405 test_sysmem_draw();
16406 test_gdi_surface();
16407 test_multiply_transform();
16408 test_alphatest();
16409 test_clipper_refcount();
16410 test_begin_end_state_block();