ddraw/test: Completely disable the refcount stealing GetClipper call.
[wine.git] / dlls / ddraw / tests / ddraw7.c
blob51223e62acd1eebafa8fcbe7dc9f1dee430a7979
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 BOOL ddraw_is_amd(IDirectDraw7 *ddraw)
153 return ddraw_is_vendor(ddraw, 0x1002);
156 static IDirectDrawSurface7 *create_overlay(IDirectDraw7 *ddraw,
157 unsigned int width, unsigned int height, DWORD format)
159 IDirectDrawSurface7 *surface;
160 DDSURFACEDESC2 desc;
162 memset(&desc, 0, sizeof(desc));
163 desc.dwSize = sizeof(desc);
164 desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
165 desc.dwWidth = width;
166 desc.dwHeight = height;
167 desc.ddsCaps.dwCaps = DDSCAPS_OVERLAY;
168 U4(desc).ddpfPixelFormat.dwSize = sizeof(U4(desc).ddpfPixelFormat);
169 U4(desc).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
170 U4(desc).ddpfPixelFormat.dwFourCC = format;
172 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &desc, &surface, NULL)))
173 return NULL;
174 return surface;
177 static HWND create_window(void)
179 RECT r = {0, 0, 640, 480};
181 AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
183 return CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
184 CW_USEDEFAULT, CW_USEDEFAULT, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL);
187 static DWORD WINAPI create_window_thread_proc(void *param)
189 struct create_window_thread_param *p = param;
190 DWORD res;
191 BOOL ret;
193 p->window = create_window();
194 ret = SetEvent(p->window_created);
195 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
197 for (;;)
199 MSG msg;
201 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
202 DispatchMessageA(&msg);
203 res = WaitForSingleObject(p->destroy_window, 100);
204 if (res == WAIT_OBJECT_0)
205 break;
206 if (res != WAIT_TIMEOUT)
208 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
209 break;
213 DestroyWindow(p->window);
215 return 0;
218 static void create_window_thread(struct create_window_thread_param *p)
220 DWORD res, tid;
222 p->window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
223 ok(!!p->window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
224 p->destroy_window = CreateEventA(NULL, FALSE, FALSE, NULL);
225 ok(!!p->destroy_window, "CreateEvent failed, last error %#x.\n", GetLastError());
226 p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
227 ok(!!p->thread, "Failed to create thread, last error %#x.\n", GetLastError());
228 res = WaitForSingleObject(p->window_created, INFINITE);
229 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
232 static void destroy_window_thread(struct create_window_thread_param *p)
234 SetEvent(p->destroy_window);
235 WaitForSingleObject(p->thread, INFINITE);
236 CloseHandle(p->destroy_window);
237 CloseHandle(p->window_created);
238 CloseHandle(p->thread);
241 static IDirectDrawSurface7 *get_depth_stencil(IDirect3DDevice7 *device)
243 IDirectDrawSurface7 *rt, *ret;
244 DDSCAPS2 caps = {DDSCAPS_ZBUFFER, 0, 0, {0}};
245 HRESULT hr;
247 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
248 ok(SUCCEEDED(hr), "Failed to get the render target, hr %#x.\n", hr);
249 hr = IDirectDrawSurface7_GetAttachedSurface(rt, &caps, &ret);
250 ok(SUCCEEDED(hr) || hr == DDERR_NOTFOUND, "Failed to get the z buffer, hr %#x.\n", hr);
251 IDirectDrawSurface7_Release(rt);
252 return ret;
255 static HRESULT set_display_mode(IDirectDraw7 *ddraw, DWORD width, DWORD height)
257 if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
258 return DD_OK;
259 return IDirectDraw7_SetDisplayMode(ddraw, width, height, 24, 0, 0);
262 static D3DCOLOR get_surface_color(IDirectDrawSurface7 *surface, UINT x, UINT y)
264 RECT rect = {x, y, x + 1, y + 1};
265 DDSURFACEDESC2 surface_desc;
266 D3DCOLOR color;
267 HRESULT hr;
269 memset(&surface_desc, 0, sizeof(surface_desc));
270 surface_desc.dwSize = sizeof(surface_desc);
272 hr = IDirectDrawSurface7_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY, NULL);
273 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
274 if (FAILED(hr))
275 return 0xdeadbeef;
277 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
279 hr = IDirectDrawSurface7_Unlock(surface, &rect);
280 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
282 return color;
285 #define check_rect(a, b, c) check_rect_(__LINE__, a, b, c)
286 static void check_rect_(unsigned int line, IDirectDrawSurface7 *surface, RECT r, const char *message)
288 LONG x_coords[2][2] =
290 {r.left - 1, r.left + 1},
291 {r.right + 1, r.right - 1},
293 LONG y_coords[2][2] =
295 {r.top - 1, r.top + 1},
296 {r.bottom + 1, r.bottom - 1}
298 unsigned int i, j, x_side, y_side;
299 DWORD color;
300 LONG x, y;
302 for (i = 0; i < 2; ++i)
304 for (j = 0; j < 2; ++j)
306 for (x_side = 0; x_side < 2; ++x_side)
308 for (y_side = 0; y_side < 2; ++y_side)
310 DWORD expected = (x_side == 1 && y_side == 1) ? 0x00ffffff : 0x00000000;
312 x = x_coords[i][x_side];
313 y = y_coords[j][y_side];
314 if (x < 0 || x >= 640 || y < 0 || y >= 480)
315 continue;
316 color = get_surface_color(surface, x, y);
317 ok_(__FILE__, line)(color == expected, "%s: Pixel (%d, %d) has color %08x, expected %08x.\n",
318 message, x, y, color, expected);
325 static HRESULT CALLBACK enum_z_fmt(DDPIXELFORMAT *format, void *ctx)
327 DDPIXELFORMAT *z_fmt = ctx;
329 if (U1(*format).dwZBufferBitDepth > U1(*z_fmt).dwZBufferBitDepth)
330 *z_fmt = *format;
332 return DDENUMRET_OK;
335 static IDirectDraw7 *create_ddraw(void)
337 IDirectDraw7 *ddraw;
339 if (FAILED(pDirectDrawCreateEx(NULL, (void **)&ddraw, &IID_IDirectDraw7, NULL)))
340 return NULL;
342 return ddraw;
345 static HRESULT WINAPI enum_devtype_cb(char *desc_str, char *name, D3DDEVICEDESC7 *desc, void *ctx)
347 BOOL *hal_ok = ctx;
348 if (IsEqualGUID(&desc->deviceGUID, &IID_IDirect3DTnLHalDevice))
350 *hal_ok = TRUE;
351 return DDENUMRET_CANCEL;
353 return DDENUMRET_OK;
356 static IDirect3DDevice7 *create_device(HWND window, DWORD coop_level)
358 IDirectDrawSurface7 *surface, *ds;
359 IDirect3DDevice7 *device = NULL;
360 DDSURFACEDESC2 surface_desc;
361 DDPIXELFORMAT z_fmt;
362 IDirectDraw7 *ddraw;
363 IDirect3D7 *d3d7;
364 HRESULT hr;
365 BOOL hal_ok = FALSE;
366 const GUID *devtype = &IID_IDirect3DHALDevice;
368 if (!(ddraw = create_ddraw()))
369 return NULL;
371 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, coop_level);
372 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
374 memset(&surface_desc, 0, sizeof(surface_desc));
375 surface_desc.dwSize = sizeof(surface_desc);
376 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
377 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
378 surface_desc.dwWidth = 640;
379 surface_desc.dwHeight = 480;
381 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
382 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
384 if (coop_level & DDSCL_NORMAL)
386 IDirectDrawClipper *clipper;
388 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
389 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
390 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
391 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
392 hr = IDirectDrawSurface7_SetClipper(surface, clipper);
393 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\n", hr);
394 IDirectDrawClipper_Release(clipper);
397 hr = IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d7);
398 IDirectDraw7_Release(ddraw);
399 if (FAILED(hr))
401 IDirectDrawSurface7_Release(surface);
402 return NULL;
405 hr = IDirect3D7_EnumDevices(d3d7, enum_devtype_cb, &hal_ok);
406 ok(SUCCEEDED(hr), "Failed to enumerate devices, hr %#x.\n", hr);
407 if (hal_ok) devtype = &IID_IDirect3DTnLHalDevice;
409 memset(&z_fmt, 0, sizeof(z_fmt));
410 hr = IDirect3D7_EnumZBufferFormats(d3d7, devtype, enum_z_fmt, &z_fmt);
411 if (FAILED(hr) || !z_fmt.dwSize)
413 IDirect3D7_Release(d3d7);
414 IDirectDrawSurface7_Release(surface);
415 return NULL;
418 memset(&surface_desc, 0, sizeof(surface_desc));
419 surface_desc.dwSize = sizeof(surface_desc);
420 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
421 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
422 U4(surface_desc).ddpfPixelFormat = z_fmt;
423 surface_desc.dwWidth = 640;
424 surface_desc.dwHeight = 480;
425 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL);
426 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
427 if (FAILED(hr))
429 IDirect3D7_Release(d3d7);
430 IDirectDrawSurface7_Release(surface);
431 return NULL;
434 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
435 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
436 IDirectDrawSurface7_Release(ds);
437 if (FAILED(hr))
439 IDirect3D7_Release(d3d7);
440 IDirectDrawSurface7_Release(surface);
441 return NULL;
444 hr = IDirect3D7_CreateDevice(d3d7, devtype, surface, &device);
445 IDirect3D7_Release(d3d7);
446 IDirectDrawSurface7_Release(surface);
447 if (FAILED(hr))
448 return NULL;
450 return device;
453 struct message
455 UINT message;
456 BOOL check_wparam;
457 WPARAM expect_wparam;
458 HRESULT ddraw_state;
461 static const struct message *expect_messages;
462 static IDirectDraw7 *focus_test_ddraw;
464 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
466 HRESULT hr;
468 if (expect_messages && message == expect_messages->message)
470 if (expect_messages->check_wparam)
471 ok (wparam == expect_messages->expect_wparam,
472 "Got unexpected wparam %lx for message %x, expected %lx.\n",
473 wparam, message, expect_messages->expect_wparam);
475 if (focus_test_ddraw)
477 hr = IDirectDraw7_TestCooperativeLevel(focus_test_ddraw);
478 ok(hr == expect_messages->ddraw_state, "Got ddraw state %#x on message %#x, expected %#x.\n",
479 hr, message, expect_messages->ddraw_state);
482 ++expect_messages;
485 return DefWindowProcA(hwnd, message, wparam, lparam);
488 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
489 * interface. This prevents subsequent SetCooperativeLevel() calls on a
490 * different window from failing with DDERR_HWNDALREADYSET. */
491 static void fix_wndproc(HWND window, LONG_PTR proc)
493 IDirectDraw7 *ddraw;
494 HRESULT hr;
496 if (!(ddraw = create_ddraw()))
497 return;
499 SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
500 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
501 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
502 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
503 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
505 IDirectDraw7_Release(ddraw);
508 static void test_process_vertices(void)
510 IDirect3DVertexBuffer7 *src_vb, *dst_vb1, *dst_vb2;
511 D3DVERTEXBUFFERDESC vb_desc;
512 IDirect3DDevice7 *device;
513 struct vec4 *dst_data;
514 struct vec3 *dst_data2;
515 struct vec3 *src_data;
516 IDirect3D7 *d3d7;
517 D3DVIEWPORT7 vp;
518 HWND window;
519 HRESULT hr;
521 static D3DMATRIX world =
523 0.0f, 1.0f, 0.0f, 0.0f,
524 1.0f, 0.0f, 0.0f, 0.0f,
525 0.0f, 0.0f, 0.0f, 1.0f,
526 0.0f, 1.0f, 1.0f, 1.0f,
528 static D3DMATRIX view =
530 2.0f, 0.0f, 0.0f, 0.0f,
531 0.0f, -1.0f, 0.0f, 0.0f,
532 0.0f, 0.0f, 1.0f, 0.0f,
533 0.0f, 0.0f, 0.0f, 3.0f,
535 static D3DMATRIX proj =
537 1.0f, 0.0f, 0.0f, 1.0f,
538 0.0f, 1.0f, 1.0f, 0.0f,
539 0.0f, 1.0f, 1.0f, 0.0f,
540 1.0f, 0.0f, 0.0f, 1.0f,
543 window = create_window();
544 if (!(device = create_device(window, DDSCL_NORMAL)))
546 skip("Failed to create a 3D device, skipping test.\n");
547 DestroyWindow(window);
548 return;
551 hr = IDirect3DDevice7_GetDirect3D(device, &d3d7);
552 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
554 memset(&vb_desc, 0, sizeof(vb_desc));
555 vb_desc.dwSize = sizeof(vb_desc);
556 vb_desc.dwFVF = D3DFVF_XYZ;
557 vb_desc.dwNumVertices = 4;
558 hr = IDirect3D7_CreateVertexBuffer(d3d7, &vb_desc, &src_vb, 0);
559 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
561 hr = IDirect3DVertexBuffer7_Lock(src_vb, 0, (void **)&src_data, NULL);
562 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
563 src_data[0].x = 0.0f;
564 src_data[0].y = 0.0f;
565 src_data[0].z = 0.0f;
566 src_data[1].x = 1.0f;
567 src_data[1].y = 1.0f;
568 src_data[1].z = 1.0f;
569 src_data[2].x = -1.0f;
570 src_data[2].y = -1.0f;
571 src_data[2].z = 0.5f;
572 src_data[3].x = 0.5f;
573 src_data[3].y = -0.5f;
574 src_data[3].z = 0.25f;
575 hr = IDirect3DVertexBuffer7_Unlock(src_vb);
576 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
578 memset(&vb_desc, 0, sizeof(vb_desc));
579 vb_desc.dwSize = sizeof(vb_desc);
580 vb_desc.dwFVF = D3DFVF_XYZRHW;
581 vb_desc.dwNumVertices = 4;
582 /* MSDN says that the last parameter must be 0 - check that. */
583 hr = IDirect3D7_CreateVertexBuffer(d3d7, &vb_desc, &dst_vb1, 4);
584 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
586 memset(&vb_desc, 0, sizeof(vb_desc));
587 vb_desc.dwSize = sizeof(vb_desc);
588 vb_desc.dwFVF = D3DFVF_XYZ;
589 vb_desc.dwNumVertices = 5;
590 /* MSDN says that the last parameter must be 0 - check that. */
591 hr = IDirect3D7_CreateVertexBuffer(d3d7, &vb_desc, &dst_vb2, 12345678);
592 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
594 memset(&vp, 0, sizeof(vp));
595 vp.dwX = 64;
596 vp.dwY = 64;
597 vp.dwWidth = 128;
598 vp.dwHeight = 128;
599 vp.dvMinZ = 0.0f;
600 vp.dvMaxZ = 1.0f;
601 hr = IDirect3DDevice7_SetViewport(device, &vp);
602 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
604 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
605 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
606 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb2, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
607 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
609 hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
610 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
611 ok(compare_vec4(&dst_data[0], +1.280e+2f, +1.280e+2f, +0.000e+0f, +1.000e+0f, 4096),
612 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
613 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
614 ok(compare_vec4(&dst_data[1], +1.920e+2f, +6.400e+1f, +1.000e+0f, +1.000e+0f, 4096),
615 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
616 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
617 ok(compare_vec4(&dst_data[2], +6.400e+1f, +1.920e+2f, +5.000e-1f, +1.000e+0f, 4096),
618 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
619 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
620 ok(compare_vec4(&dst_data[3], +1.600e+2f, +1.600e+2f, +2.500e-1f, +1.000e+0f, 4096),
621 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
622 dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
623 hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
624 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
626 hr = IDirect3DVertexBuffer7_Lock(dst_vb2, 0, (void **)&dst_data2, NULL);
627 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
628 /* Small thing without much practical meaning, but I stumbled upon it,
629 * so let's check for it: If the output vertex buffer has no RHW value,
630 * the RHW value of the last vertex is written into the next vertex. */
631 ok(compare_vec3(&dst_data2[4], +1.000e+0f, +0.000e+0f, +0.000e+0f, 4096),
632 "Got unexpected vertex 4 {%.8e, %.8e, %.8e}.\n",
633 dst_data2[4].x, dst_data2[4].y, dst_data2[4].z);
634 hr = IDirect3DVertexBuffer7_Unlock(dst_vb2);
635 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
637 /* Test degenerate viewport z ranges. */
638 vp.dvMinZ = 0.0f;
639 vp.dvMaxZ = 0.0f;
640 hr = IDirect3DDevice7_SetViewport(device, &vp);
641 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
643 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
644 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
645 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb2, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
646 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
648 hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
649 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
650 ok(compare_vec4(&dst_data[0], +1.280e+2f, +1.280e+2f, +0.000e+0f, +1.000e+0f, 4096),
651 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
652 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
653 ok(compare_vec4(&dst_data[1], +1.920e+2f, +6.400e+1f, +1.000e-3f, +1.000e+0f, 4096),
654 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
655 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
656 ok(compare_vec4(&dst_data[2], +6.400e+1f, +1.920e+2f, +5.000e-4f, +1.000e+0f, 4096),
657 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
658 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
659 ok(compare_vec4(&dst_data[3], +1.600e+2f, +1.600e+2f, +2.500e-4f, +1.000e+0f, 4096),
660 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
661 dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
662 hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
663 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
665 vp.dvMinZ = 1.0f;
666 vp.dvMaxZ = 0.0f;
667 hr = IDirect3DDevice7_SetViewport(device, &vp);
668 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
670 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
671 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
672 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb2, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
673 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
675 hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
676 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
677 ok(compare_vec4(&dst_data[0], +1.280e+2f, +1.280e+2f, +1.000e+0f, +1.000e+0f, 4096),
678 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
679 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
680 ok(compare_vec4(&dst_data[1], +1.920e+2f, +6.400e+1f, +1.001e+0f, +1.000e+0f, 4096),
681 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
682 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
683 ok(compare_vec4(&dst_data[2], +6.400e+1f, +1.920e+2f, +1.0005e+0f, +1.000e+0f, 4096),
684 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
685 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
686 ok(compare_vec4(&dst_data[3], +1.600e+2f, +1.600e+2f, +1.00025e+0f, +1.000e+0f, 4096),
687 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
688 dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
689 hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
690 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
692 /* Try a more complicated viewport, same vertices. */
693 memset(&vp, 0, sizeof(vp));
694 vp.dwX = 10;
695 vp.dwY = 5;
696 vp.dwWidth = 246;
697 vp.dwHeight = 130;
698 vp.dvMinZ = -2.0f;
699 vp.dvMaxZ = 4.0f;
700 hr = IDirect3DDevice7_SetViewport(device, &vp);
701 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
703 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
704 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
706 hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
707 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
708 ok(compare_vec4(&dst_data[0], +1.330e+2f, +7.000e+1f, -2.000e+0f, +1.000e+0f, 4096),
709 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
710 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
711 ok(compare_vec4(&dst_data[1], +2.560e+2f, +5.000e+0f, +4.000e+0f, +1.000e+0f, 4096),
712 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
713 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
714 ok(compare_vec4(&dst_data[2], +1.000e+1f, +1.350e+2f, +1.000e+0f, +1.000e+0f, 4096),
715 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
716 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
717 ok(compare_vec4(&dst_data[3], +1.945e+2f, +1.025e+2f, -5.000e-1f, +1.000e+0f, 4096),
718 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
719 dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
720 hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
721 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
723 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &world);
724 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
725 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &view);
726 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
727 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &proj);
728 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
730 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
731 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
733 hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
734 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
735 ok(compare_vec4(&dst_data[0], +2.560e+2f, +7.000e+1f, -2.000e+0f, +3.333e-1f, 4096),
736 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
737 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
738 ok(compare_vec4(&dst_data[1], +2.560e+2f, +7.813e+1f, -2.750e+0f, +1.250e-1f, 4096),
739 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
740 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
741 ok(compare_vec4(&dst_data[2], +2.560e+2f, +4.400e+1f, +4.000e-1f, +4.000e-1f, 4096),
742 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
743 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
744 ok(compare_vec4(&dst_data[3], +2.560e+2f, +8.182e+1f, -3.091e+0f, +3.636e-1f, 4096),
745 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
746 dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
747 hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
748 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
750 IDirect3DVertexBuffer7_Release(dst_vb2);
751 IDirect3DVertexBuffer7_Release(dst_vb1);
752 IDirect3DVertexBuffer7_Release(src_vb);
753 IDirect3D7_Release(d3d7);
754 IDirect3DDevice7_Release(device);
755 DestroyWindow(window);
758 static void test_coop_level_create_device_window(void)
760 HWND focus_window, device_window;
761 IDirectDraw7 *ddraw;
762 HRESULT hr;
764 focus_window = create_window();
765 ddraw = create_ddraw();
766 ok(!!ddraw, "Failed to create a ddraw object.\n");
768 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
769 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
770 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
771 ok(!device_window, "Unexpected device window found.\n");
772 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
773 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
774 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
775 ok(!device_window, "Unexpected device window found.\n");
776 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
777 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
778 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
779 ok(!device_window, "Unexpected device window found.\n");
780 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
781 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
782 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
783 ok(!device_window, "Unexpected device window found.\n");
784 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
785 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
786 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
787 ok(!device_window, "Unexpected device window found.\n");
789 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
790 if (broken(hr == DDERR_INVALIDPARAMS))
792 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
793 IDirectDraw7_Release(ddraw);
794 DestroyWindow(focus_window);
795 return;
798 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
799 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
800 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
801 ok(!device_window, "Unexpected device window found.\n");
802 hr = IDirectDraw7_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
803 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
804 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
805 ok(!device_window, "Unexpected device window found.\n");
807 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
808 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
809 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
810 ok(!device_window, "Unexpected device window found.\n");
811 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
812 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
813 ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
814 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
815 ok(!!device_window, "Device window not found.\n");
817 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
818 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
819 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
820 ok(!device_window, "Unexpected device window found.\n");
821 hr = IDirectDraw7_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
822 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
823 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
824 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
825 ok(!!device_window, "Device window not found.\n");
827 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
828 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
829 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
830 ok(!device_window, "Unexpected device window found.\n");
831 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
832 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
833 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
834 ok(!device_window, "Unexpected device window found.\n");
835 hr = IDirectDraw7_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
836 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
837 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
838 ok(!device_window, "Unexpected device window found.\n");
839 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
840 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
841 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
842 ok(!!device_window, "Device window not found.\n");
844 IDirectDraw7_Release(ddraw);
845 DestroyWindow(focus_window);
848 static void test_clipper_blt(void)
850 IDirectDrawSurface7 *src_surface, *dst_surface;
851 RECT client_rect, src_rect;
852 IDirectDrawClipper *clipper;
853 DDSURFACEDESC2 surface_desc;
854 unsigned int i, j, x, y;
855 IDirectDraw7 *ddraw;
856 RGNDATA *rgn_data;
857 D3DCOLOR color;
858 ULONG refcount;
859 HRGN r1, r2;
860 HWND window;
861 DDBLTFX fx;
862 HRESULT hr;
863 DWORD *ptr;
864 DWORD ret;
866 static const DWORD src_data[] =
868 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
869 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
870 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
872 static const D3DCOLOR expected1[] =
874 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
875 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
876 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
877 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
879 /* Nvidia on Windows seems to have an off-by-one error
880 * when processing source rectangles. Our left = 1 and
881 * right = 5 input reads from x = {1, 2, 3}. x = 4 is
882 * read as well, but only for the edge pixels on the
883 * output image. The bug happens on the y axis as well,
884 * but we only read one row there, and all source rows
885 * contain the same data. This bug is not dependent on
886 * the presence of a clipper. */
887 static const D3DCOLOR expected1_broken[] =
889 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
890 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
891 0x00000000, 0x00000000, 0x00ff0000, 0x00ff0000,
892 0x00000000, 0x00000000, 0x0000ff00, 0x00ff0000,
894 static const D3DCOLOR expected2[] =
896 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
897 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
898 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
899 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
902 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
903 10, 10, 640, 480, 0, 0, 0, 0);
904 ShowWindow(window, SW_SHOW);
905 ddraw = create_ddraw();
906 ok(!!ddraw, "Failed to create a ddraw object.\n");
908 ret = GetClientRect(window, &client_rect);
909 ok(ret, "Failed to get client rect.\n");
910 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
911 ok(ret, "Failed to map client rect.\n");
913 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
914 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
916 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
917 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
918 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
919 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
920 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
921 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
922 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
923 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
924 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
925 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
926 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
927 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
928 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
929 ok(rgn_data->rdh.nCount >= 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
930 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
931 "Got unexpected bounding rect %s, expected %s.\n",
932 wine_dbgstr_rect(&rgn_data->rdh.rcBound), wine_dbgstr_rect(&client_rect));
933 HeapFree(GetProcessHeap(), 0, rgn_data);
935 r1 = CreateRectRgn(0, 0, 320, 240);
936 ok(!!r1, "Failed to create region.\n");
937 r2 = CreateRectRgn(320, 240, 640, 480);
938 ok(!!r2, "Failed to create region.\n");
939 CombineRgn(r1, r1, r2, RGN_OR);
940 ret = GetRegionData(r1, 0, NULL);
941 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
942 ret = GetRegionData(r1, ret, rgn_data);
943 ok(!!ret, "Failed to get region data.\n");
945 DeleteObject(r2);
946 DeleteObject(r1);
948 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
949 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
950 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
951 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
952 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
953 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
955 HeapFree(GetProcessHeap(), 0, rgn_data);
957 memset(&surface_desc, 0, sizeof(surface_desc));
958 surface_desc.dwSize = sizeof(surface_desc);
959 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
960 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
961 surface_desc.dwWidth = 640;
962 surface_desc.dwHeight = 480;
963 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
964 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
965 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
966 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
967 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
968 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
970 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
971 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
972 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
973 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
975 memset(&fx, 0, sizeof(fx));
976 fx.dwSize = sizeof(fx);
977 hr = IDirectDrawSurface7_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
978 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
979 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
980 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
982 hr = IDirectDrawSurface7_Lock(src_surface, NULL, &surface_desc, 0, NULL);
983 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
984 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
985 ptr = surface_desc.lpSurface;
986 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
987 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
988 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
989 hr = IDirectDrawSurface7_Unlock(src_surface, NULL);
990 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
992 hr = IDirectDrawSurface7_SetClipper(dst_surface, clipper);
993 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
995 SetRect(&src_rect, 1, 1, 5, 2);
996 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
997 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
998 for (i = 0; i < 4; ++i)
1000 for (j = 0; j < 4; ++j)
1002 x = 80 * ((2 * j) + 1);
1003 y = 60 * ((2 * i) + 1);
1004 color = get_surface_color(dst_surface, x, y);
1005 ok(compare_color(color, expected1[i * 4 + j], 1)
1006 || broken(compare_color(color, expected1_broken[i * 4 + j], 1)),
1007 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
1011 U5(fx).dwFillColor = 0xff0000ff;
1012 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1013 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
1014 for (i = 0; i < 4; ++i)
1016 for (j = 0; j < 4; ++j)
1018 x = 80 * ((2 * j) + 1);
1019 y = 60 * ((2 * i) + 1);
1020 color = get_surface_color(dst_surface, x, y);
1021 ok(compare_color(color, expected2[i * 4 + j], 1),
1022 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
1026 hr = IDirectDrawSurface7_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
1027 ok(hr == DDERR_BLTFASTCANTCLIP, "Got unexpected hr %#x.\n", hr);
1029 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
1030 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
1031 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1032 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
1033 DestroyWindow(window);
1034 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1035 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
1036 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
1037 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
1038 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1039 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
1040 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
1041 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
1042 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1043 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
1044 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1045 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
1047 IDirectDrawSurface7_Release(dst_surface);
1048 IDirectDrawSurface7_Release(src_surface);
1049 refcount = IDirectDrawClipper_Release(clipper);
1050 ok(!refcount, "Clipper has %u references left.\n", refcount);
1051 IDirectDraw7_Release(ddraw);
1054 static void test_coop_level_d3d_state(void)
1056 IDirectDrawSurface7 *rt, *surface;
1057 IDirect3DDevice7 *device;
1058 IDirectDraw7 *ddraw;
1059 IDirect3D7 *d3d;
1060 D3DCOLOR color;
1061 DDSCAPS2 caps;
1062 DWORD value;
1063 HWND window;
1064 HRESULT hr;
1066 static struct
1068 struct vec3 position;
1069 DWORD diffuse;
1071 quad[] =
1073 {{-1.0f, -1.0f, 0.1f}, 0x800000ff},
1074 {{-1.0f, 1.0f, 0.1f}, 0x800000ff},
1075 {{ 1.0f, -1.0f, 0.1f}, 0x800000ff},
1076 {{ 1.0f, 1.0f, 0.1f}, 0x800000ff},
1079 window = create_window();
1080 if (!(device = create_device(window, DDSCL_NORMAL)))
1082 skip("Failed to create a 3D device, skipping test.\n");
1083 DestroyWindow(window);
1084 return;
1087 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
1088 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1089 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1090 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1091 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_DESTALPHA);
1092 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1094 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1095 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1096 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
1097 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1098 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
1099 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
1100 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1101 ok(!value, "Got unexpected alpha blend enable state %#x.\n", value);
1102 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
1103 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1104 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
1105 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1106 color = get_surface_color(rt, 320, 240);
1107 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1109 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1110 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1111 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1112 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1113 IDirect3D7_Release(d3d);
1114 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1115 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1116 hr = IDirectDrawSurface7_IsLost(rt);
1117 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
1119 memset(&caps, 0, sizeof(caps));
1120 caps.dwCaps = DDSCAPS_ZBUFFER;
1121 hr = IDirectDrawSurface7_GetAttachedSurface(rt, &caps, &surface);
1122 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
1123 caps.dwCaps = DDSCAPS_FLIP;
1124 hr = IDirectDrawSurface7_GetAttachedSurface(rt, &caps, &surface);
1125 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
1127 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
1128 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1130 caps.dwCaps = DDSCAPS_ZBUFFER;
1131 hr = IDirectDrawSurface7_GetAttachedSurface(rt, &caps, &surface);
1132 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1133 IDirectDrawSurface7_Release(surface);
1135 caps.dwCaps = DDSCAPS_FLIP;
1136 hr = IDirectDrawSurface7_GetAttachedSurface(rt, &caps, &surface);
1137 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
1139 IDirectDraw7_Release(ddraw);
1141 hr = IDirect3DDevice7_GetRenderTarget(device, &surface);
1142 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1143 ok(surface == rt, "Got unexpected surface %p.\n", surface);
1144 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
1145 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1146 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
1147 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
1148 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1149 ok(!!value, "Got unexpected alpha blend enable state %#x.\n", value);
1150 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff00ff00, 1.0f, 0);
1151 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1152 color = get_surface_color(rt, 320, 240);
1153 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1155 hr = IDirect3DDevice7_BeginScene(device);
1156 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1157 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
1158 D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, ARRAY_SIZE(quad), 0);
1159 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1160 hr = IDirect3DDevice7_EndScene(device);
1161 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1162 color = get_surface_color(rt, 320, 240);
1163 ok(compare_color(color, 0x0000ff80, 1), "Got unexpected color 0x%08x.\n", color);
1165 IDirectDrawSurface7_Release(surface);
1166 IDirectDrawSurface7_Release(rt);
1167 IDirect3DDevice7_Release(device);
1168 DestroyWindow(window);
1171 static void test_surface_interface_mismatch(void)
1173 IDirectDraw7 *ddraw = NULL;
1174 IDirect3D7 *d3d = NULL;
1175 IDirectDrawSurface7 *surface = NULL, *ds;
1176 IDirectDrawSurface3 *surface3 = NULL;
1177 IDirect3DDevice7 *device = NULL;
1178 DDSURFACEDESC2 surface_desc;
1179 DDPIXELFORMAT z_fmt;
1180 ULONG refcount;
1181 HRESULT hr;
1182 D3DCOLOR color;
1183 HWND window;
1185 window = create_window();
1186 ddraw = create_ddraw();
1187 ok(!!ddraw, "Failed to create a ddraw object.\n");
1188 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1189 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1191 memset(&surface_desc, 0, sizeof(surface_desc));
1192 surface_desc.dwSize = sizeof(surface_desc);
1193 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1194 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
1195 surface_desc.dwWidth = 640;
1196 surface_desc.dwHeight = 480;
1198 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1199 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1201 hr = IDirectDrawSurface7_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
1202 ok(SUCCEEDED(hr), "Failed to QI IDirectDrawSurface3, hr %#x.\n", hr);
1204 if (FAILED(IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d)))
1206 skip("D3D interface is not available, skipping test.\n");
1207 goto cleanup;
1210 memset(&z_fmt, 0, sizeof(z_fmt));
1211 hr = IDirect3D7_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
1212 if (FAILED(hr) || !z_fmt.dwSize)
1214 skip("No depth buffer formats available, skipping test.\n");
1215 goto cleanup;
1218 memset(&surface_desc, 0, sizeof(surface_desc));
1219 surface_desc.dwSize = sizeof(surface_desc);
1220 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
1221 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1222 U4(surface_desc).ddpfPixelFormat = z_fmt;
1223 surface_desc.dwWidth = 640;
1224 surface_desc.dwHeight = 480;
1225 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL);
1226 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
1227 if (FAILED(hr))
1228 goto cleanup;
1230 /* Using a different surface interface version still works */
1231 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
1232 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
1233 refcount = IDirectDrawSurface7_Release(ds);
1234 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
1235 if (FAILED(hr))
1236 goto cleanup;
1238 /* Here too */
1239 hr = IDirect3D7_CreateDevice(d3d, &IID_IDirect3DHALDevice, (IDirectDrawSurface7 *)surface3, &device);
1240 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
1241 if (FAILED(hr))
1242 goto cleanup;
1244 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
1245 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1246 color = get_surface_color(surface, 320, 240);
1247 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1249 cleanup:
1250 if (surface3) IDirectDrawSurface3_Release(surface3);
1251 if (surface) IDirectDrawSurface7_Release(surface);
1252 if (device) IDirect3DDevice7_Release(device);
1253 if (d3d) IDirect3D7_Release(d3d);
1254 if (ddraw) IDirectDraw7_Release(ddraw);
1255 DestroyWindow(window);
1258 static void test_coop_level_threaded(void)
1260 struct create_window_thread_param p;
1261 IDirectDraw7 *ddraw;
1262 HRESULT hr;
1264 ddraw = create_ddraw();
1265 ok(!!ddraw, "Failed to create a ddraw object.\n");
1266 create_window_thread(&p);
1268 hr = IDirectDraw7_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1269 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1271 destroy_window_thread(&p);
1272 IDirectDraw7_Release(ddraw);
1275 static void test_depth_blit(void)
1277 IDirect3DDevice7 *device;
1278 static struct
1280 float x, y, z;
1281 DWORD color;
1283 quad1[] =
1285 { -1.0, 1.0, 0.50f, 0xff00ff00},
1286 { 1.0, 1.0, 0.50f, 0xff00ff00},
1287 { -1.0, -1.0, 0.50f, 0xff00ff00},
1288 { 1.0, -1.0, 0.50f, 0xff00ff00},
1290 static const D3DCOLOR expected_colors[4][4] =
1292 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1293 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1294 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1295 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1297 DDSURFACEDESC2 ddsd_new, ddsd_existing;
1299 IDirectDrawSurface7 *ds1, *ds2, *ds3, *rt;
1300 RECT src_rect, dst_rect;
1301 unsigned int i, j;
1302 D3DCOLOR color;
1303 HRESULT hr;
1304 IDirect3D7 *d3d;
1305 IDirectDraw7 *ddraw;
1306 DDBLTFX fx;
1307 HWND window;
1309 window = create_window();
1310 if (!(device = create_device(window, DDSCL_NORMAL)))
1312 skip("Failed to create a 3D device, skipping test.\n");
1313 DestroyWindow(window);
1314 return;
1317 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1318 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
1319 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1320 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
1321 IDirect3D7_Release(d3d);
1323 ds1 = get_depth_stencil(device);
1325 memset(&ddsd_new, 0, sizeof(ddsd_new));
1326 ddsd_new.dwSize = sizeof(ddsd_new);
1327 memset(&ddsd_existing, 0, sizeof(ddsd_existing));
1328 ddsd_existing.dwSize = sizeof(ddsd_existing);
1329 hr = IDirectDrawSurface7_GetSurfaceDesc(ds1, &ddsd_existing);
1330 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
1331 ddsd_new.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1332 ddsd_new.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1333 ddsd_new.dwWidth = ddsd_existing.dwWidth;
1334 ddsd_new.dwHeight = ddsd_existing.dwHeight;
1335 U4(ddsd_new).ddpfPixelFormat = U4(ddsd_existing).ddpfPixelFormat;
1336 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd_new, &ds2, NULL);
1337 ok(SUCCEEDED(hr), "Failed to create a z buffer, hr %#x.\n", hr);
1338 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd_new, &ds3, NULL);
1339 ok(SUCCEEDED(hr), "Failed to create a z buffer, hr %#x.\n", hr);
1340 IDirectDraw7_Release(ddraw);
1342 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
1343 ok(SUCCEEDED(hr), "Failed to enable z testing, hr %#x.\n", hr);
1344 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
1345 ok(SUCCEEDED(hr), "Failed to set the z function, hr %#x.\n", hr);
1346 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
1347 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
1349 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
1350 ok(SUCCEEDED(hr), "Failed to clear the z buffer, hr %#x.\n", hr);
1352 /* Partial blit. */
1353 SetRect(&src_rect, 0, 0, 320, 240);
1354 SetRect(&dst_rect, 0, 0, 320, 240);
1355 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1356 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1357 /* Different locations. */
1358 SetRect(&src_rect, 0, 0, 320, 240);
1359 SetRect(&dst_rect, 320, 240, 640, 480);
1360 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1361 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1362 /* Stretched. */
1363 SetRect(&src_rect, 0, 0, 320, 240);
1364 SetRect(&dst_rect, 0, 0, 640, 480);
1365 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1366 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1367 /* Flipped. */
1368 SetRect(&src_rect, 0, 480, 640, 0);
1369 SetRect(&dst_rect, 0, 0, 640, 480);
1370 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1371 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1372 SetRect(&src_rect, 0, 0, 640, 480);
1373 SetRect(&dst_rect, 0, 480, 640, 0);
1374 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1375 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1376 /* Full, explicit. */
1377 SetRect(&src_rect, 0, 0, 640, 480);
1378 SetRect(&dst_rect, 0, 0, 640, 480);
1379 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1380 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1381 /* Depth -> color blit: Succeeds on Win7 + Radeon HD 5700, fails on WinXP + Radeon X1600 */
1383 /* Depth blit inside a BeginScene / EndScene pair */
1384 hr = IDirect3DDevice7_BeginScene(device);
1385 ok(SUCCEEDED(hr), "Failed to start scene, hr %#x.\n", hr);
1386 /* From the current depth stencil */
1387 hr = IDirectDrawSurface7_Blt(ds2, NULL, ds1, NULL, DDBLT_WAIT, NULL);
1388 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1389 /* To the current depth stencil */
1390 hr = IDirectDrawSurface7_Blt(ds1, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1391 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1392 /* Between unbound surfaces */
1393 hr = IDirectDrawSurface7_Blt(ds3, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1394 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1395 hr = IDirect3DDevice7_EndScene(device);
1396 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1398 /* Avoid changing the depth stencil, it doesn't work properly on Windows.
1399 * Instead use DDBLT_DEPTHFILL to clear the depth stencil. Unfortunately
1400 * drivers disagree on the meaning of dwFillDepth. Only 0 seems to produce
1401 * a reliable result(z = 0.0) */
1402 memset(&fx, 0, sizeof(fx));
1403 fx.dwSize = sizeof(fx);
1404 hr = IDirectDrawSurface7_Blt(ds2, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
1405 ok(SUCCEEDED(hr), "Failed to clear the source z buffer, hr %#x.\n", hr);
1407 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET, 0xffff0000, 1.0f, 0);
1408 ok(SUCCEEDED(hr), "Failed to clear the color and z buffers, hr %#x.\n", hr);
1409 SetRect(&dst_rect, 0, 0, 320, 240);
1410 hr = IDirectDrawSurface7_Blt(ds1, &dst_rect, ds2, NULL, DDBLT_WAIT, NULL);
1411 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1412 IDirectDrawSurface7_Release(ds3);
1413 IDirectDrawSurface7_Release(ds2);
1414 IDirectDrawSurface7_Release(ds1);
1416 hr = IDirect3DDevice7_BeginScene(device);
1417 ok(SUCCEEDED(hr), "Failed to start scene, hr %#x.\n", hr);
1418 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
1419 quad1, 4, 0);
1420 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1421 hr = IDirect3DDevice7_EndScene(device);
1422 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1424 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1425 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1426 for (i = 0; i < 4; ++i)
1428 for (j = 0; j < 4; ++j)
1430 unsigned int x = 80 * ((2 * j) + 1);
1431 unsigned int y = 60 * ((2 * i) + 1);
1432 color = get_surface_color(rt, x, y);
1433 ok(compare_color(color, expected_colors[i][j], 1),
1434 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
1438 IDirectDrawSurface7_Release(rt);
1439 IDirect3DDevice7_Release(device);
1440 DestroyWindow(window);
1443 static void test_texture_load_ckey(void)
1445 HWND window;
1446 IDirect3DDevice7 *device;
1447 IDirectDraw7 *ddraw;
1448 IDirectDrawSurface7 *src;
1449 IDirectDrawSurface7 *dst;
1450 DDSURFACEDESC2 ddsd;
1451 HRESULT hr;
1452 DDCOLORKEY ckey;
1453 IDirect3D7 *d3d;
1455 window = create_window();
1456 if (!(device = create_device(window, DDSCL_NORMAL)))
1458 skip("Failed to create a 3D device, skipping test.\n");
1459 DestroyWindow(window);
1460 return;
1463 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1464 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
1465 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1466 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
1467 IDirect3D7_Release(d3d);
1469 memset(&ddsd, 0, sizeof(ddsd));
1470 ddsd.dwSize = sizeof(ddsd);
1471 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
1472 ddsd.dwHeight = 128;
1473 ddsd.dwWidth = 128;
1474 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
1475 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &src, NULL);
1476 ok(SUCCEEDED(hr), "Failed to create source texture, hr %#x.\n", hr);
1477 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1478 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &dst, NULL);
1479 ok(SUCCEEDED(hr), "Failed to create destination texture, hr %#x.\n", hr);
1481 /* No surface has a color key */
1482 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1483 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1484 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0xdeadbeef;
1485 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1486 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1487 ok(ckey.dwColorSpaceLowValue == 0xdeadbeef, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1488 ok(ckey.dwColorSpaceHighValue == 0xdeadbeef, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1490 /* Source surface has a color key */
1491 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
1492 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
1493 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1494 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1495 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1496 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1497 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1498 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1499 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1501 /* Both surfaces have a color key: Dest ckey is overwritten */
1502 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x000000ff;
1503 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1504 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1505 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1506 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1507 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1508 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1509 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1510 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1512 /* Only the destination has a color key: It is deleted. This behavior differs from
1513 * IDirect3DTexture(2)::Load */
1514 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, NULL);
1515 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1516 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
1517 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1518 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1519 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1520 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1521 todo_wine ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1523 IDirectDrawSurface7_Release(dst);
1524 IDirectDrawSurface7_Release(src);
1525 IDirectDraw7_Release(ddraw);
1526 IDirect3DDevice7_Release(device);
1527 DestroyWindow(window);
1530 static void test_zenable(void)
1532 static struct
1534 struct vec4 position;
1535 D3DCOLOR diffuse;
1537 tquad[] =
1539 {{ 0.0f, 480.0f, -0.5f, 1.0f}, 0xff00ff00},
1540 {{ 0.0f, 0.0f, -0.5f, 1.0f}, 0xff00ff00},
1541 {{640.0f, 480.0f, 1.5f, 1.0f}, 0xff00ff00},
1542 {{640.0f, 0.0f, 1.5f, 1.0f}, 0xff00ff00},
1544 IDirect3DDevice7 *device;
1545 IDirectDrawSurface7 *rt;
1546 D3DCOLOR color;
1547 HWND window;
1548 HRESULT hr;
1549 UINT x, y;
1550 UINT i, j;
1552 window = create_window();
1553 if (!(device = create_device(window, DDSCL_NORMAL)))
1555 skip("Failed to create a 3D device, skipping test.\n");
1556 DestroyWindow(window);
1557 return;
1560 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1561 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
1563 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 0.0f, 0);
1564 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1565 hr = IDirect3DDevice7_BeginScene(device);
1566 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1567 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_DIFFUSE, tquad, 4, 0);
1568 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1569 hr = IDirect3DDevice7_EndScene(device);
1570 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1572 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1573 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1574 for (i = 0; i < 4; ++i)
1576 for (j = 0; j < 4; ++j)
1578 x = 80 * ((2 * j) + 1);
1579 y = 60 * ((2 * i) + 1);
1580 color = get_surface_color(rt, x, y);
1581 ok(compare_color(color, 0x0000ff00, 1),
1582 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1585 IDirectDrawSurface7_Release(rt);
1587 IDirect3DDevice7_Release(device);
1588 DestroyWindow(window);
1591 static void test_ck_rgba(void)
1593 static struct
1595 struct vec4 position;
1596 struct vec2 texcoord;
1598 tquad[] =
1600 {{ 0.0f, 480.0f, 0.25f, 1.0f}, {0.0f, 0.0f}},
1601 {{ 0.0f, 0.0f, 0.25f, 1.0f}, {0.0f, 1.0f}},
1602 {{640.0f, 480.0f, 0.25f, 1.0f}, {1.0f, 0.0f}},
1603 {{640.0f, 0.0f, 0.25f, 1.0f}, {1.0f, 1.0f}},
1604 {{ 0.0f, 480.0f, 0.75f, 1.0f}, {0.0f, 0.0f}},
1605 {{ 0.0f, 0.0f, 0.75f, 1.0f}, {0.0f, 1.0f}},
1606 {{640.0f, 480.0f, 0.75f, 1.0f}, {1.0f, 0.0f}},
1607 {{640.0f, 0.0f, 0.75f, 1.0f}, {1.0f, 1.0f}},
1609 static const struct
1611 D3DCOLOR fill_color;
1612 BOOL color_key;
1613 BOOL blend;
1614 D3DCOLOR result1, result1_broken;
1615 D3DCOLOR result2, result2_broken;
1617 tests[] =
1619 /* r200 on Windows doesn't check the alpha component when applying the color
1620 * key, so the key matches on every texel. */
1621 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1622 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1623 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1624 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1625 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00ff0000, 0x00807f00, 0x000000ff},
1626 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x00ff0000, 0x0000ff00, 0x000000ff},
1627 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00, 0x00807f00, 0x00807f00},
1628 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1631 IDirectDrawSurface7 *texture;
1632 DDSURFACEDESC2 surface_desc;
1633 IDirect3DDevice7 *device;
1634 IDirectDrawSurface7 *rt;
1635 IDirectDraw7 *ddraw;
1636 IDirect3D7 *d3d;
1637 D3DCOLOR color;
1638 HWND window;
1639 DDBLTFX fx;
1640 HRESULT hr;
1641 UINT i;
1643 window = create_window();
1644 if (!(device = create_device(window, DDSCL_NORMAL)))
1646 skip("Failed to create a 3D device, skipping test.\n");
1647 DestroyWindow(window);
1648 return;
1651 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1652 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1653 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1654 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1655 IDirect3D7_Release(d3d);
1657 memset(&surface_desc, 0, sizeof(surface_desc));
1658 surface_desc.dwSize = sizeof(surface_desc);
1659 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1660 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1661 surface_desc.dwWidth = 256;
1662 surface_desc.dwHeight = 256;
1663 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1664 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1665 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1666 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1667 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1668 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1669 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1670 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1671 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1672 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
1673 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1675 hr = IDirect3DDevice7_SetTexture(device, 0, texture);
1676 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1677 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1678 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1679 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1680 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1682 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1683 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1685 for (i = 0; i < ARRAY_SIZE(tests); ++i)
1687 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1688 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1689 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1690 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1692 memset(&fx, 0, sizeof(fx));
1693 fx.dwSize = sizeof(fx);
1694 U5(fx).dwFillColor = tests[i].fill_color;
1695 hr = IDirectDrawSurface7_Blt(texture, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1696 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1698 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 1.0f, 0);
1699 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1700 hr = IDirect3DDevice7_BeginScene(device);
1701 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1702 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1703 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1704 hr = IDirect3DDevice7_EndScene(device);
1705 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1707 color = get_surface_color(rt, 320, 240);
1708 ok(compare_color(color, tests[i].result1, 1) || compare_color(color, tests[i].result1_broken, 1),
1709 "Expected color 0x%08x for test %u, got 0x%08x.\n",
1710 tests[i].result1, i, color);
1712 U5(fx).dwFillColor = 0xff0000ff;
1713 hr = IDirectDrawSurface7_Blt(texture, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1714 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1716 hr = IDirect3DDevice7_BeginScene(device);
1717 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1718 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[4], 4, 0);
1719 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1720 hr = IDirect3DDevice7_EndScene(device);
1721 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1723 /* This tests that fragments that are masked out by the color key are
1724 * discarded, instead of just fully transparent. */
1725 color = get_surface_color(rt, 320, 240);
1726 ok(compare_color(color, tests[i].result2, 1) || compare_color(color, tests[i].result2_broken, 1),
1727 "Expected color 0x%08x for test %u, got 0x%08x.\n",
1728 tests[i].result2, i, color);
1731 IDirectDrawSurface7_Release(rt);
1732 IDirectDrawSurface7_Release(texture);
1733 IDirectDraw7_Release(ddraw);
1734 IDirect3DDevice7_Release(device);
1735 DestroyWindow(window);
1738 static void test_ck_default(void)
1740 static struct
1742 struct vec4 position;
1743 struct vec2 texcoord;
1745 tquad[] =
1747 {{ 0.0f, 480.0f, 0.0f, 1.0f}, {0.0f, 0.0f}},
1748 {{ 0.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 1.0f}},
1749 {{640.0f, 480.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
1750 {{640.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
1752 IDirectDrawSurface7 *surface, *rt;
1753 DDSURFACEDESC2 surface_desc;
1754 IDirect3DDevice7 *device;
1755 IDirectDraw7 *ddraw;
1756 IDirect3D7 *d3d;
1757 D3DCOLOR color;
1758 DWORD value;
1759 HWND window;
1760 DDBLTFX fx;
1761 HRESULT hr;
1763 window = create_window();
1764 if (!(device = create_device(window, DDSCL_NORMAL)))
1766 skip("Failed to create a 3D device, skipping test.\n");
1767 DestroyWindow(window);
1768 return;
1771 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1772 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1773 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1774 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1775 IDirect3D7_Release(d3d);
1777 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1778 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1780 memset(&surface_desc, 0, sizeof(surface_desc));
1781 surface_desc.dwSize = sizeof(surface_desc);
1782 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1783 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1784 surface_desc.dwWidth = 256;
1785 surface_desc.dwHeight = 256;
1786 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1787 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
1788 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1789 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1790 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1791 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1792 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
1793 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
1794 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1795 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1796 hr = IDirect3DDevice7_SetTexture(device, 0, surface);
1797 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1799 memset(&fx, 0, sizeof(fx));
1800 fx.dwSize = sizeof(fx);
1801 U5(fx).dwFillColor = 0x000000ff;
1802 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1803 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
1805 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
1806 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1807 hr = IDirect3DDevice7_BeginScene(device);
1808 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1809 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1810 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1811 ok(!value, "Got unexpected color keying state %#x.\n", value);
1812 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1813 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1814 hr = IDirect3DDevice7_EndScene(device);
1815 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1816 color = get_surface_color(rt, 320, 240);
1817 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1819 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
1820 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1821 hr = IDirect3DDevice7_BeginScene(device);
1822 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1823 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
1824 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1825 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1826 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1827 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1828 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1829 ok(!!value, "Got unexpected color keying state %#x.\n", value);
1830 hr = IDirect3DDevice7_EndScene(device);
1831 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1832 color = get_surface_color(rt, 320, 240);
1833 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1835 IDirectDrawSurface7_Release(surface);
1836 IDirectDrawSurface7_Release(rt);
1837 IDirect3DDevice7_Release(device);
1838 IDirectDraw7_Release(ddraw);
1839 DestroyWindow(window);
1842 static void test_ck_complex(void)
1844 IDirectDrawSurface7 *surface, *mipmap, *tmp;
1845 D3DDEVICEDESC7 device_desc;
1846 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
1847 DDSURFACEDESC2 surface_desc;
1848 IDirect3DDevice7 *device;
1849 DDCOLORKEY color_key;
1850 IDirectDraw7 *ddraw;
1851 IDirect3D7 *d3d;
1852 unsigned int i;
1853 ULONG refcount;
1854 HWND window;
1855 HRESULT hr;
1857 window = create_window();
1858 if (!(device = create_device(window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
1860 skip("Failed to create a 3D device, skipping test.\n");
1861 DestroyWindow(window);
1862 return;
1864 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
1865 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
1866 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1867 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1868 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1869 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1870 IDirect3D7_Release(d3d);
1872 memset(&surface_desc, 0, sizeof(surface_desc));
1873 surface_desc.dwSize = sizeof(surface_desc);
1874 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1875 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1876 surface_desc.dwWidth = 128;
1877 surface_desc.dwHeight = 128;
1878 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1879 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1881 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1882 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1883 color_key.dwColorSpaceLowValue = 0x0000ff00;
1884 color_key.dwColorSpaceHighValue = 0x0000ff00;
1885 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1886 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1887 memset(&color_key, 0, sizeof(color_key));
1888 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1889 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1890 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1891 color_key.dwColorSpaceLowValue);
1892 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1893 color_key.dwColorSpaceHighValue);
1895 mipmap = surface;
1896 IDirectDrawSurface_AddRef(mipmap);
1897 for (i = 0; i < 7; ++i)
1899 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
1900 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
1901 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1902 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1904 color_key.dwColorSpaceLowValue = 0x000000ff;
1905 color_key.dwColorSpaceHighValue = 0x000000ff;
1906 hr = IDirectDrawSurface7_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1907 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x, i %u.\n", hr, i);
1909 IDirectDrawSurface_Release(mipmap);
1910 mipmap = tmp;
1913 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
1914 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
1915 IDirectDrawSurface_Release(mipmap);
1916 refcount = IDirectDrawSurface7_Release(surface);
1917 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1919 memset(&surface_desc, 0, sizeof(surface_desc));
1920 surface_desc.dwSize = sizeof(surface_desc);
1921 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
1922 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
1923 U5(surface_desc).dwBackBufferCount = 1;
1924 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1925 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1927 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1928 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1929 color_key.dwColorSpaceLowValue = 0x0000ff00;
1930 color_key.dwColorSpaceHighValue = 0x0000ff00;
1931 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1932 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1933 memset(&color_key, 0, sizeof(color_key));
1934 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1935 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1936 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1937 color_key.dwColorSpaceLowValue);
1938 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1939 color_key.dwColorSpaceHighValue);
1941 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &tmp);
1942 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
1944 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1945 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1946 color_key.dwColorSpaceLowValue = 0x0000ff00;
1947 color_key.dwColorSpaceHighValue = 0x0000ff00;
1948 hr = IDirectDrawSurface7_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1949 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1950 memset(&color_key, 0, sizeof(color_key));
1951 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1952 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1953 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1954 color_key.dwColorSpaceLowValue);
1955 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1956 color_key.dwColorSpaceHighValue);
1958 IDirectDrawSurface_Release(tmp);
1960 refcount = IDirectDrawSurface7_Release(surface);
1961 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1963 if (!(device_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP))
1965 skip("Device does not support cubemaps.\n");
1966 goto cleanup;
1968 memset(&surface_desc, 0, sizeof(surface_desc));
1969 surface_desc.dwSize = sizeof(surface_desc);
1970 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1971 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1972 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
1973 surface_desc.dwWidth = 128;
1974 surface_desc.dwHeight = 128;
1975 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1976 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1978 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1979 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1980 color_key.dwColorSpaceLowValue = 0x0000ff00;
1981 color_key.dwColorSpaceHighValue = 0x0000ff00;
1982 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1983 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1985 caps.dwCaps2 = DDSCAPS2_CUBEMAP_NEGATIVEZ;
1986 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
1987 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
1989 hr = IDirectDrawSurface7_GetColorKey(mipmap, DDCKEY_SRCBLT, &color_key);
1990 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1991 color_key.dwColorSpaceLowValue = 0x000000ff;
1992 color_key.dwColorSpaceHighValue = 0x000000ff;
1993 hr = IDirectDrawSurface7_SetColorKey(mipmap, DDCKEY_SRCBLT, &color_key);
1994 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1996 color_key.dwColorSpaceLowValue = 0;
1997 color_key.dwColorSpaceHighValue = 0;
1998 hr = IDirectDrawSurface7_GetColorKey(mipmap, DDCKEY_SRCBLT, &color_key);
1999 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
2000 ok(color_key.dwColorSpaceLowValue == 0x000000ff, "Got unexpected value 0x%08x.\n",
2001 color_key.dwColorSpaceLowValue);
2002 ok(color_key.dwColorSpaceHighValue == 0x000000ff, "Got unexpected value 0x%08x.\n",
2003 color_key.dwColorSpaceHighValue);
2005 IDirectDrawSurface_AddRef(mipmap);
2006 for (i = 0; i < 7; ++i)
2008 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
2009 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
2010 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2011 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
2013 color_key.dwColorSpaceLowValue = 0x000000ff;
2014 color_key.dwColorSpaceHighValue = 0x000000ff;
2015 hr = IDirectDrawSurface7_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2016 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x, i %u.\n", hr, i);
2018 IDirectDrawSurface_Release(mipmap);
2019 mipmap = tmp;
2022 IDirectDrawSurface7_Release(mipmap);
2024 refcount = IDirectDrawSurface7_Release(surface);
2025 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
2027 cleanup:
2028 IDirectDraw7_Release(ddraw);
2029 refcount = IDirect3DDevice7_Release(device);
2030 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
2031 DestroyWindow(window);
2034 struct qi_test
2036 REFIID iid;
2037 REFIID refcount_iid;
2038 HRESULT hr;
2041 static void test_qi(const char *test_name, IUnknown *base_iface,
2042 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
2044 ULONG refcount, expected_refcount;
2045 IUnknown *iface1, *iface2;
2046 HRESULT hr;
2047 UINT i, j;
2049 for (i = 0; i < entry_count; ++i)
2051 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
2052 ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
2053 if (SUCCEEDED(hr))
2055 for (j = 0; j < entry_count; ++j)
2057 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
2058 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
2059 if (SUCCEEDED(hr))
2061 expected_refcount = 0;
2062 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
2063 ++expected_refcount;
2064 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
2065 ++expected_refcount;
2066 refcount = IUnknown_Release(iface2);
2067 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
2068 refcount, test_name, i, j, expected_refcount);
2072 expected_refcount = 0;
2073 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
2074 ++expected_refcount;
2075 refcount = IUnknown_Release(iface1);
2076 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
2077 refcount, test_name, i, expected_refcount);
2082 static void test_surface_qi(void)
2084 static const struct qi_test tests[] =
2086 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
2087 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
2088 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
2089 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2090 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
2091 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
2092 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
2093 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
2094 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
2095 {&IID_IDirect3DDevice7, NULL, E_NOINTERFACE},
2096 {&IID_IDirect3DDevice3, NULL, E_NOINTERFACE},
2097 {&IID_IDirect3DDevice2, NULL, E_NOINTERFACE},
2098 {&IID_IDirect3DDevice, NULL, E_NOINTERFACE},
2099 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
2100 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
2101 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
2102 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
2103 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
2104 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
2105 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
2106 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
2107 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
2108 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
2109 {&IID_IDirect3D, NULL, E_NOINTERFACE},
2110 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
2111 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
2112 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
2113 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
2114 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
2115 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
2116 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
2117 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
2118 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
2119 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
2120 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
2121 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
2122 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
2123 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
2124 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
2125 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
2126 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
2127 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
2128 {NULL, NULL, E_INVALIDARG },
2131 IDirectDrawSurface7 *surface;
2132 DDSURFACEDESC2 surface_desc;
2133 IDirect3DDevice7 *device;
2134 IDirectDraw7 *ddraw;
2135 HWND window;
2136 HRESULT hr;
2138 window = create_window();
2139 /* Try to create a D3D device to see if the ddraw implementation supports
2140 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
2141 * doesn't support e.g. the IDirect3DTexture interfaces. */
2142 if (!(device = create_device(window, DDSCL_NORMAL)))
2144 skip("Failed to create a 3D device, skipping test.\n");
2145 DestroyWindow(window);
2146 return;
2148 IDirect3DDevice_Release(device);
2149 ddraw = create_ddraw();
2150 ok(!!ddraw, "Failed to create a ddraw object.\n");
2151 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2152 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2154 memset(&surface_desc, 0, sizeof(surface_desc));
2155 surface_desc.dwSize = sizeof(surface_desc);
2156 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2157 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2158 surface_desc.dwWidth = 512;
2159 surface_desc.dwHeight = 512;
2160 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, (IDirectDrawSurface7 **)0xdeadbeef, NULL);
2161 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
2162 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2163 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
2165 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface7, tests, ARRAY_SIZE(tests));
2167 IDirectDrawSurface7_Release(surface);
2168 IDirectDraw7_Release(ddraw);
2169 DestroyWindow(window);
2172 static void test_device_qi(void)
2174 static const struct qi_test tests[] =
2176 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
2177 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
2178 {&IID_IDirectDrawGammaControl, NULL, E_NOINTERFACE},
2179 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2180 {&IID_IDirectDrawSurface7, NULL, E_NOINTERFACE},
2181 {&IID_IDirectDrawSurface4, NULL, E_NOINTERFACE},
2182 {&IID_IDirectDrawSurface3, NULL, E_NOINTERFACE},
2183 {&IID_IDirectDrawSurface2, NULL, E_NOINTERFACE},
2184 {&IID_IDirectDrawSurface, NULL, E_NOINTERFACE},
2185 {&IID_IDirect3DDevice7, &IID_IDirect3DDevice7, S_OK },
2186 {&IID_IDirect3DDevice3, NULL, E_NOINTERFACE},
2187 {&IID_IDirect3DDevice2, NULL, E_NOINTERFACE},
2188 {&IID_IDirect3DDevice, NULL, E_NOINTERFACE},
2189 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
2190 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
2191 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
2192 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
2193 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
2194 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
2195 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
2196 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
2197 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
2198 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
2199 {&IID_IDirect3D, NULL, E_NOINTERFACE},
2200 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
2201 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
2202 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
2203 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
2204 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
2205 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
2206 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
2207 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
2208 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
2209 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
2210 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
2211 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
2212 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
2213 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
2214 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
2215 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
2216 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
2217 {&IID_IUnknown, &IID_IDirect3DDevice7, S_OK },
2220 IDirect3DDevice7 *device;
2221 HWND window;
2223 window = create_window();
2224 if (!(device = create_device(window, DDSCL_NORMAL)))
2226 skip("Failed to create a 3D device, skipping test.\n");
2227 DestroyWindow(window);
2228 return;
2231 test_qi("device_qi", (IUnknown *)device, &IID_IDirect3DDevice7, tests, ARRAY_SIZE(tests));
2233 IDirect3DDevice7_Release(device);
2234 DestroyWindow(window);
2237 static void test_wndproc(void)
2239 LONG_PTR proc, ddraw_proc;
2240 IDirectDraw7 *ddraw;
2241 WNDCLASSA wc = {0};
2242 HWND window;
2243 HRESULT hr;
2244 ULONG ref;
2246 static struct message messages[] =
2248 {WM_WINDOWPOSCHANGING, FALSE, 0},
2249 {WM_MOVE, FALSE, 0},
2250 {WM_SIZE, FALSE, 0},
2251 {WM_WINDOWPOSCHANGING, FALSE, 0},
2252 {WM_ACTIVATE, FALSE, 0},
2253 {WM_SETFOCUS, FALSE, 0},
2254 {0, FALSE, 0},
2257 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
2258 ddraw = create_ddraw();
2259 ok(!!ddraw, "Failed to create a ddraw object.\n");
2261 wc.lpfnWndProc = test_proc;
2262 wc.lpszClassName = "ddraw_test_wndproc_wc";
2263 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2265 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
2266 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
2268 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2269 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2270 (LONG_PTR)test_proc, proc);
2271 expect_messages = messages;
2272 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2273 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2274 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2275 expect_messages = NULL;
2276 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2277 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2278 (LONG_PTR)test_proc, proc);
2279 ref = IDirectDraw7_Release(ddraw);
2280 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2281 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2282 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2283 (LONG_PTR)test_proc, proc);
2285 /* DDSCL_NORMAL doesn't. */
2286 ddraw = create_ddraw();
2287 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2288 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2289 (LONG_PTR)test_proc, proc);
2290 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2291 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2292 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2293 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2294 (LONG_PTR)test_proc, proc);
2295 ref = IDirectDraw7_Release(ddraw);
2296 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2297 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2298 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2299 (LONG_PTR)test_proc, proc);
2301 /* The original window proc is only restored by ddraw if the current
2302 * window proc matches the one ddraw set. This also affects switching
2303 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
2304 ddraw = create_ddraw();
2305 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2306 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2307 (LONG_PTR)test_proc, proc);
2308 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2309 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2310 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2311 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2312 (LONG_PTR)test_proc, proc);
2313 ddraw_proc = proc;
2314 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2315 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2316 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2317 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2318 (LONG_PTR)test_proc, proc);
2319 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2320 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2321 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2322 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2323 (LONG_PTR)test_proc, proc);
2324 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2325 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2326 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2327 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2328 (LONG_PTR)DefWindowProcA, proc);
2329 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2330 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2331 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, ddraw_proc);
2332 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2333 (LONG_PTR)DefWindowProcA, proc);
2334 ref = IDirectDraw7_Release(ddraw);
2335 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2336 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2337 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2338 (LONG_PTR)test_proc, proc);
2340 ddraw = create_ddraw();
2341 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2342 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2343 (LONG_PTR)test_proc, proc);
2344 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2345 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2346 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2347 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2348 (LONG_PTR)test_proc, proc);
2349 ref = IDirectDraw7_Release(ddraw);
2350 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2351 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2352 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2353 (LONG_PTR)DefWindowProcA, proc);
2355 fix_wndproc(window, (LONG_PTR)test_proc);
2356 expect_messages = NULL;
2357 DestroyWindow(window);
2358 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2361 static void test_window_style(void)
2363 LONG style, exstyle, tmp, expected_style;
2364 RECT fullscreen_rect, r;
2365 IDirectDraw7 *ddraw;
2366 HWND window;
2367 HRESULT hr;
2368 ULONG ref;
2369 BOOL ret;
2371 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2372 0, 0, 100, 100, 0, 0, 0, 0);
2373 ddraw = create_ddraw();
2374 ok(!!ddraw, "Failed to create a ddraw object.\n");
2376 style = GetWindowLongA(window, GWL_STYLE);
2377 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
2378 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2380 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2381 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2383 tmp = GetWindowLongA(window, GWL_STYLE);
2384 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2385 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2386 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2388 GetWindowRect(window, &r);
2389 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
2390 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
2391 GetClientRect(window, &r);
2392 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2394 ret = SetForegroundWindow(GetDesktopWindow());
2395 ok(ret, "Failed to set foreground window.\n");
2397 tmp = GetWindowLongA(window, GWL_STYLE);
2398 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2399 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2400 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2402 ret = SetForegroundWindow(window);
2403 ok(ret, "Failed to set foreground window.\n");
2404 /* Windows 7 (but not Vista and XP) shows the window when it receives focus. Hide it again,
2405 * the next tests expect this. */
2406 ShowWindow(window, SW_HIDE);
2408 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2409 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2411 tmp = GetWindowLongA(window, GWL_STYLE);
2412 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2413 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2414 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2416 ShowWindow(window, SW_SHOW);
2417 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2418 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2420 tmp = GetWindowLongA(window, GWL_STYLE);
2421 expected_style = style | WS_VISIBLE;
2422 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2423 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2424 expected_style = exstyle | WS_EX_TOPMOST;
2425 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2427 ret = SetForegroundWindow(GetDesktopWindow());
2428 ok(ret, "Failed to set foreground window.\n");
2429 tmp = GetWindowLongA(window, GWL_STYLE);
2430 expected_style = style | WS_VISIBLE | WS_MINIMIZE;
2431 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2432 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2433 expected_style = exstyle | WS_EX_TOPMOST;
2434 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2436 ref = IDirectDraw7_Release(ddraw);
2437 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2439 DestroyWindow(window);
2442 static void test_redundant_mode_set(void)
2444 DDSURFACEDESC2 surface_desc = {0};
2445 IDirectDraw7 *ddraw;
2446 RECT q, r, s;
2447 HWND window;
2448 HRESULT hr;
2449 ULONG ref;
2451 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2452 0, 0, 100, 100, 0, 0, 0, 0);
2453 ddraw = create_ddraw();
2454 ok(!!ddraw, "Failed to create a ddraw object.\n");
2455 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2456 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2458 surface_desc.dwSize = sizeof(surface_desc);
2459 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
2460 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
2462 hr = IDirectDraw7_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2463 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
2464 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2466 GetWindowRect(window, &q);
2467 r = q;
2468 r.right /= 2;
2469 r.bottom /= 2;
2470 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
2471 GetWindowRect(window, &s);
2472 ok(EqualRect(&r, &s), "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2474 hr = IDirectDraw7_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2475 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
2476 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2478 GetWindowRect(window, &s);
2479 ok(EqualRect(&r, &s) || broken(EqualRect(&q, &s) /* Windows 10 */),
2480 "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2482 ref = IDirectDraw7_Release(ddraw);
2483 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2485 DestroyWindow(window);
2488 static SIZE screen_size, screen_size2;
2490 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2492 if (message == WM_SIZE)
2494 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2495 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2498 return test_proc(hwnd, message, wparam, lparam);
2501 static LRESULT CALLBACK mode_set_proc2(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2503 if (message == WM_SIZE)
2505 screen_size2.cx = GetSystemMetrics(SM_CXSCREEN);
2506 screen_size2.cy = GetSystemMetrics(SM_CYSCREEN);
2509 return test_proc(hwnd, message, wparam, lparam);
2512 struct test_coop_level_mode_set_enum_param
2514 DWORD ddraw_width, ddraw_height, user32_width, user32_height;
2517 static HRESULT CALLBACK test_coop_level_mode_set_enum_cb(DDSURFACEDESC2 *surface_desc, void *context)
2519 struct test_coop_level_mode_set_enum_param *param = context;
2521 if (U1(U4(*surface_desc).ddpfPixelFormat).dwRGBBitCount != registry_mode.dmBitsPerPel)
2522 return DDENUMRET_OK;
2523 if (surface_desc->dwWidth == registry_mode.dmPelsWidth
2524 && surface_desc->dwHeight == registry_mode.dmPelsHeight)
2525 return DDENUMRET_OK;
2527 if (!param->ddraw_width)
2529 param->ddraw_width = surface_desc->dwWidth;
2530 param->ddraw_height = surface_desc->dwHeight;
2531 return DDENUMRET_OK;
2533 if (surface_desc->dwWidth == param->ddraw_width && surface_desc->dwHeight == param->ddraw_height)
2534 return DDENUMRET_OK;
2536 param->user32_width = surface_desc->dwWidth;
2537 param->user32_height = surface_desc->dwHeight;
2538 return DDENUMRET_CANCEL;
2541 static void test_coop_level_mode_set(void)
2543 IDirectDrawSurface7 *primary;
2544 RECT registry_rect, ddraw_rect, user32_rect, r;
2545 IDirectDraw7 *ddraw;
2546 DDSURFACEDESC2 ddsd;
2547 WNDCLASSA wc = {0};
2548 HWND window, window2;
2549 HRESULT hr;
2550 ULONG ref;
2551 MSG msg;
2552 struct test_coop_level_mode_set_enum_param param;
2553 DEVMODEW devmode;
2554 BOOL ret;
2555 LONG change_ret;
2557 static const struct message exclusive_messages[] =
2559 {WM_WINDOWPOSCHANGING, FALSE, 0},
2560 {WM_WINDOWPOSCHANGED, FALSE, 0},
2561 {WM_SIZE, FALSE, 0},
2562 {WM_DISPLAYCHANGE, FALSE, 0},
2563 {0, FALSE, 0},
2565 static const struct message exclusive_focus_loss_messages[] =
2567 {WM_ACTIVATE, TRUE, WA_INACTIVE, DD_OK},
2568 {WM_WINDOWPOSCHANGING, FALSE, 0, DD_OK}, /* Window resize due to mode change. */
2569 {WM_WINDOWPOSCHANGED, FALSE, 0, DD_OK},
2570 {WM_SIZE, TRUE, SIZE_RESTORED, DD_OK}, /* Generated by DefWindowProc. */
2571 {WM_DISPLAYCHANGE, FALSE, 0, DD_OK},
2572 {WM_KILLFOCUS, FALSE, 0, DDERR_NOEXCLUSIVEMODE},
2573 {WM_WINDOWPOSCHANGING, FALSE, 0, DDERR_NOEXCLUSIVEMODE}, /* Window minimized. */
2574 /* Like d3d8 and d3d9 ddraw seems to use SW_SHOWMINIMIZED instead of
2575 * SW_MINIMIZED, causing a recursive window activation that does not
2576 * produce the same result in Wine yet. Ignore the difference for now.
2577 * {WM_ACTIVATE, TRUE, 0x200000 | WA_ACTIVE}, */
2578 {WM_WINDOWPOSCHANGED, FALSE, 0, DDERR_NOEXCLUSIVEMODE},
2579 {WM_MOVE, FALSE, 0, DDERR_NOEXCLUSIVEMODE},
2580 {WM_SIZE, TRUE, SIZE_MINIMIZED, DDERR_NOEXCLUSIVEMODE},
2581 {WM_ACTIVATEAPP, TRUE, FALSE, DDERR_NOEXCLUSIVEMODE},
2582 {0, FALSE, 0, 0},
2584 static const struct message exclusive_focus_restore_messages[] =
2586 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* From the ShowWindow(SW_RESTORE). */
2587 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Generated by ddraw, matches d3d9 behavior. */
2588 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching previous message. */
2589 {WM_SIZE, FALSE, 0}, /* DefWindowProc. */
2590 {WM_DISPLAYCHANGE, FALSE, 0}, /* Ddraw restores mode. */
2591 /* Native redundantly sets the window size here. */
2592 {WM_ACTIVATEAPP, TRUE, TRUE}, /* End of ddraw's hooks. */
2593 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching the one from ShowWindow. */
2594 {WM_MOVE, FALSE, 0}, /* DefWindowProc. */
2595 {WM_SIZE, TRUE, SIZE_RESTORED}, /* DefWindowProc. */
2596 {0, FALSE, 0},
2598 static const struct message sc_restore_messages[] =
2600 {WM_SYSCOMMAND, TRUE, SC_RESTORE},
2601 {WM_WINDOWPOSCHANGING, FALSE, 0},
2602 {WM_WINDOWPOSCHANGED, FALSE, 0},
2603 {WM_SIZE, TRUE, SIZE_RESTORED},
2604 {0, FALSE, 0},
2606 static const struct message sc_minimize_messages[] =
2608 {WM_SYSCOMMAND, TRUE, SC_MINIMIZE},
2609 {WM_WINDOWPOSCHANGING, FALSE, 0},
2610 {WM_WINDOWPOSCHANGED, FALSE, 0},
2611 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2612 {0, FALSE, 0},
2614 static const struct message sc_maximize_messages[] =
2616 {WM_SYSCOMMAND, TRUE, SC_MAXIMIZE},
2617 {WM_WINDOWPOSCHANGING, FALSE, 0},
2618 {WM_WINDOWPOSCHANGED, FALSE, 0},
2619 {WM_SIZE, TRUE, SIZE_MAXIMIZED},
2620 {0, FALSE, 0},
2623 static const struct message normal_messages[] =
2625 {WM_DISPLAYCHANGE, FALSE, 0},
2626 {0, FALSE, 0},
2629 ddraw = create_ddraw();
2630 ok(!!ddraw, "Failed to create a ddraw object.\n");
2632 memset(&param, 0, sizeof(param));
2633 hr = IDirectDraw7_EnumDisplayModes(ddraw, 0, NULL, &param, test_coop_level_mode_set_enum_cb);
2634 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
2635 ref = IDirectDraw7_Release(ddraw);
2636 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2638 if (!param.user32_height)
2640 skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
2641 return;
2644 SetRect(&registry_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2645 SetRect(&ddraw_rect, 0, 0, param.ddraw_width, param.ddraw_height);
2646 SetRect(&user32_rect, 0, 0, param.user32_width, param.user32_height);
2648 memset(&devmode, 0, sizeof(devmode));
2649 devmode.dmSize = sizeof(devmode);
2650 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2651 devmode.dmPelsWidth = param.user32_width;
2652 devmode.dmPelsHeight = param.user32_height;
2653 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2654 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2656 ddraw = create_ddraw();
2657 ok(!!ddraw, "Failed to create a ddraw object.\n");
2659 wc.lpfnWndProc = mode_set_proc;
2660 wc.lpszClassName = "ddraw_test_wndproc_wc";
2661 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2662 wc.lpfnWndProc = mode_set_proc2;
2663 wc.lpszClassName = "ddraw_test_wndproc_wc2";
2664 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2666 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
2667 0, 0, 100, 100, 0, 0, 0, 0);
2668 window2 = CreateWindowA("ddraw_test_wndproc_wc2", "ddraw_test", WS_OVERLAPPEDWINDOW,
2669 0, 0, 100, 100, 0, 0, 0, 0);
2671 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2672 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2674 GetWindowRect(window, &r);
2675 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2676 wine_dbgstr_rect(&r));
2678 memset(&ddsd, 0, sizeof(ddsd));
2679 ddsd.dwSize = sizeof(ddsd);
2680 ddsd.dwFlags = DDSD_CAPS;
2681 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2683 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2684 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2685 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2686 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2687 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2688 param.user32_width, ddsd.dwWidth);
2689 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2690 param.user32_height, ddsd.dwHeight);
2692 GetWindowRect(window, &r);
2693 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2694 wine_dbgstr_rect(&r));
2696 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2697 expect_messages = exclusive_messages;
2698 screen_size.cx = 0;
2699 screen_size.cy = 0;
2701 hr = IDirectDrawSurface7_IsLost(primary);
2702 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2703 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2704 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2705 hr = IDirectDrawSurface7_IsLost(primary);
2706 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2708 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2709 expect_messages = NULL;
2710 ok(screen_size.cx == param.ddraw_width && screen_size.cy == param.ddraw_height,
2711 "Expected screen size %ux%u, got %ux%u.\n",
2712 param.ddraw_width, param.ddraw_height, screen_size.cx, screen_size.cy);
2714 GetWindowRect(window, &r);
2715 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2716 wine_dbgstr_rect(&r));
2718 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2719 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2720 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2721 param.user32_width, ddsd.dwWidth);
2722 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2723 param.user32_height, ddsd.dwHeight);
2724 IDirectDrawSurface7_Release(primary);
2726 memset(&ddsd, 0, sizeof(ddsd));
2727 ddsd.dwSize = sizeof(ddsd);
2728 ddsd.dwFlags = DDSD_CAPS;
2729 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2731 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2732 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2733 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2734 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2735 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2736 param.ddraw_width, ddsd.dwWidth);
2737 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2738 param.ddraw_height, ddsd.dwHeight);
2740 GetWindowRect(window, &r);
2741 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2742 wine_dbgstr_rect(&r));
2744 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2745 expect_messages = exclusive_messages;
2746 screen_size.cx = 0;
2747 screen_size.cy = 0;
2749 hr = IDirectDrawSurface7_IsLost(primary);
2750 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2751 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2752 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2753 hr = IDirectDrawSurface7_IsLost(primary);
2754 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2756 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2757 expect_messages = NULL;
2758 ok(screen_size.cx == param.user32_width && screen_size.cy == param.user32_height,
2759 "Expected screen size %ux%u, got %ux%u.\n",
2760 param.user32_width, param.user32_height, screen_size.cx, screen_size.cy);
2762 GetWindowRect(window, &r);
2763 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2764 wine_dbgstr_rect(&r));
2766 expect_messages = exclusive_focus_loss_messages;
2767 focus_test_ddraw = ddraw;
2768 ret = SetForegroundWindow(GetDesktopWindow());
2769 ok(ret, "Failed to set foreground window.\n");
2770 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2771 focus_test_ddraw = NULL;
2773 memset(&devmode, 0, sizeof(devmode));
2774 devmode.dmSize = sizeof(devmode);
2775 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2776 ok(ret, "Failed to get display mode.\n");
2777 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2778 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpected screen size %ux%u.\n",
2779 devmode.dmPelsWidth, devmode.dmPelsHeight);
2781 expect_messages = exclusive_focus_restore_messages;
2782 ShowWindow(window, SW_RESTORE);
2783 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2785 GetWindowRect(window, &r);
2786 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2787 wine_dbgstr_rect(&r));
2788 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2789 ok(ret, "Failed to get display mode.\n");
2790 ok(devmode.dmPelsWidth == param.ddraw_width
2791 && devmode.dmPelsHeight == param.ddraw_height, "Got unexpected screen size %ux%u.\n",
2792 devmode.dmPelsWidth, devmode.dmPelsHeight);
2794 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2795 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2796 /* Normally the primary should be restored here. Unfortunately this causes the
2797 * GetSurfaceDesc call after the next display mode change to crash on the Windows 8
2798 * testbot. Another Restore call would presumably avoid the crash, but it also moots
2799 * the point of the GetSurfaceDesc call. */
2801 expect_messages = sc_minimize_messages;
2802 SendMessageA(window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
2803 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2804 expect_messages = NULL;
2806 expect_messages = sc_restore_messages;
2807 SendMessageA(window, WM_SYSCOMMAND, SC_RESTORE, 0);
2808 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2809 expect_messages = NULL;
2811 expect_messages = sc_maximize_messages;
2812 SendMessageA(window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
2813 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2814 expect_messages = NULL;
2816 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2817 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2819 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2820 expect_messages = exclusive_messages;
2821 screen_size.cx = 0;
2822 screen_size.cy = 0;
2824 hr = IDirectDrawSurface7_IsLost(primary);
2825 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2826 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
2827 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, 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 == registry_mode.dmPelsWidth
2834 && screen_size.cy == registry_mode.dmPelsHeight,
2835 "Expected screen size %ux%u, got %ux%u.\n",
2836 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size.cx, screen_size.cy);
2838 GetWindowRect(window, &r);
2839 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2840 wine_dbgstr_rect(&r));
2842 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2843 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2844 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2845 param.ddraw_width, ddsd.dwWidth);
2846 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2847 param.ddraw_height, ddsd.dwHeight);
2848 IDirectDrawSurface7_Release(primary);
2850 /* For Wine. */
2851 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
2852 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2854 memset(&ddsd, 0, sizeof(ddsd));
2855 ddsd.dwSize = sizeof(ddsd);
2856 ddsd.dwFlags = DDSD_CAPS;
2857 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2859 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2860 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2861 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2862 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2863 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2864 registry_mode.dmPelsWidth, ddsd.dwWidth);
2865 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2866 registry_mode.dmPelsHeight, ddsd.dwHeight);
2868 GetWindowRect(window, &r);
2869 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2870 wine_dbgstr_rect(&r));
2872 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2873 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2875 GetWindowRect(window, &r);
2876 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2877 wine_dbgstr_rect(&r));
2879 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2880 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2881 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2882 registry_mode.dmPelsWidth, ddsd.dwWidth);
2883 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2884 registry_mode.dmPelsHeight, ddsd.dwHeight);
2885 IDirectDrawSurface7_Release(primary);
2887 memset(&ddsd, 0, sizeof(ddsd));
2888 ddsd.dwSize = sizeof(ddsd);
2889 ddsd.dwFlags = DDSD_CAPS;
2890 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2892 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2893 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2894 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2895 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2896 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2897 registry_mode.dmPelsWidth, ddsd.dwWidth);
2898 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2899 registry_mode.dmPelsHeight, ddsd.dwHeight);
2901 GetWindowRect(window, &r);
2902 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2903 wine_dbgstr_rect(&r));
2905 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2906 expect_messages = normal_messages;
2907 screen_size.cx = 0;
2908 screen_size.cy = 0;
2910 hr = IDirectDrawSurface7_IsLost(primary);
2911 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2912 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2913 devmode.dmPelsWidth = param.user32_width;
2914 devmode.dmPelsHeight = param.user32_height;
2915 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2916 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2917 hr = IDirectDrawSurface7_IsLost(primary);
2918 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2920 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2921 expect_messages = NULL;
2922 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2924 GetWindowRect(window, &r);
2925 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2926 wine_dbgstr_rect(&r));
2928 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2929 expect_messages = normal_messages;
2930 screen_size.cx = 0;
2931 screen_size.cy = 0;
2933 hr = IDirectDrawSurface7_Restore(primary);
2934 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2935 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2936 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2937 hr = IDirectDrawSurface7_Restore(primary);
2938 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2939 hr = IDirectDrawSurface7_IsLost(primary);
2940 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2942 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2943 expect_messages = NULL;
2944 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2946 GetWindowRect(window, &r);
2947 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2948 wine_dbgstr_rect(&r));
2950 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2951 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2952 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2953 registry_mode.dmPelsWidth, ddsd.dwWidth);
2954 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2955 registry_mode.dmPelsHeight, ddsd.dwHeight);
2956 IDirectDrawSurface7_Release(primary);
2958 memset(&ddsd, 0, sizeof(ddsd));
2959 ddsd.dwSize = sizeof(ddsd);
2960 ddsd.dwFlags = DDSD_CAPS;
2961 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2963 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2964 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2965 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2966 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2967 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2968 param.ddraw_width, ddsd.dwWidth);
2969 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2970 param.ddraw_height, ddsd.dwHeight);
2972 GetWindowRect(window, &r);
2973 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2974 wine_dbgstr_rect(&r));
2976 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2977 expect_messages = normal_messages;
2978 screen_size.cx = 0;
2979 screen_size.cy = 0;
2981 hr = IDirectDrawSurface7_IsLost(primary);
2982 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2983 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
2984 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2985 hr = IDirectDrawSurface7_IsLost(primary);
2986 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2988 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2989 expect_messages = NULL;
2990 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2992 GetWindowRect(window, &r);
2993 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2994 wine_dbgstr_rect(&r));
2996 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2997 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2998 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2999 param.ddraw_width, ddsd.dwWidth);
3000 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3001 param.ddraw_height, ddsd.dwHeight);
3002 IDirectDrawSurface7_Release(primary);
3004 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3005 ok(ret, "Failed to get display mode.\n");
3006 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3007 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3008 "Expected resolution %ux%u, got %ux%u.\n",
3009 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3010 devmode.dmPelsWidth, devmode.dmPelsHeight);
3011 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3012 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3014 memset(&ddsd, 0, sizeof(ddsd));
3015 ddsd.dwSize = sizeof(ddsd);
3016 ddsd.dwFlags = DDSD_CAPS;
3017 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3019 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3020 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3021 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3022 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3023 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3024 registry_mode.dmPelsWidth, ddsd.dwWidth);
3025 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3026 registry_mode.dmPelsHeight, ddsd.dwHeight);
3028 GetWindowRect(window, &r);
3029 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3030 wine_dbgstr_rect(&r));
3032 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
3033 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
3034 * not DDSCL_FULLSCREEN. */
3035 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3036 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3038 GetWindowRect(window, &r);
3039 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3040 wine_dbgstr_rect(&r));
3042 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3043 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3044 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3045 registry_mode.dmPelsWidth, ddsd.dwWidth);
3046 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3047 registry_mode.dmPelsHeight, ddsd.dwHeight);
3048 IDirectDrawSurface7_Release(primary);
3050 memset(&ddsd, 0, sizeof(ddsd));
3051 ddsd.dwSize = sizeof(ddsd);
3052 ddsd.dwFlags = DDSD_CAPS;
3053 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3055 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3056 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3057 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3058 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3059 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3060 registry_mode.dmPelsWidth, ddsd.dwWidth);
3061 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3062 registry_mode.dmPelsHeight, ddsd.dwHeight);
3064 GetWindowRect(window, &r);
3065 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3066 wine_dbgstr_rect(&r));
3068 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3069 expect_messages = normal_messages;
3070 screen_size.cx = 0;
3071 screen_size.cy = 0;
3073 hr = IDirectDrawSurface7_IsLost(primary);
3074 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3075 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3076 devmode.dmPelsWidth = param.user32_width;
3077 devmode.dmPelsHeight = param.user32_height;
3078 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3079 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3080 hr = IDirectDrawSurface7_IsLost(primary);
3081 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3083 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3084 expect_messages = NULL;
3085 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3087 GetWindowRect(window, &r);
3088 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3089 wine_dbgstr_rect(&r));
3091 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3092 expect_messages = normal_messages;
3093 screen_size.cx = 0;
3094 screen_size.cy = 0;
3096 hr = IDirectDrawSurface7_Restore(primary);
3097 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3098 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3099 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3100 hr = IDirectDrawSurface7_Restore(primary);
3101 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3102 hr = IDirectDrawSurface7_IsLost(primary);
3103 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3105 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3106 expect_messages = NULL;
3107 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3109 GetWindowRect(window, &r);
3110 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3111 wine_dbgstr_rect(&r));
3113 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3114 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3115 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3116 registry_mode.dmPelsWidth, ddsd.dwWidth);
3117 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3118 registry_mode.dmPelsHeight, ddsd.dwHeight);
3119 IDirectDrawSurface7_Release(primary);
3121 memset(&ddsd, 0, sizeof(ddsd));
3122 ddsd.dwSize = sizeof(ddsd);
3123 ddsd.dwFlags = DDSD_CAPS;
3124 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3126 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3127 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3128 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3129 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3130 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3131 param.ddraw_width, ddsd.dwWidth);
3132 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3133 param.ddraw_height, ddsd.dwHeight);
3135 GetWindowRect(window, &r);
3136 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3137 wine_dbgstr_rect(&r));
3139 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3140 expect_messages = normal_messages;
3141 screen_size.cx = 0;
3142 screen_size.cy = 0;
3144 hr = IDirectDrawSurface7_IsLost(primary);
3145 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3146 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
3147 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3148 hr = IDirectDrawSurface7_IsLost(primary);
3149 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3151 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3152 expect_messages = NULL;
3153 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3155 GetWindowRect(window, &r);
3156 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3157 wine_dbgstr_rect(&r));
3159 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3160 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3161 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3162 param.ddraw_width, ddsd.dwWidth);
3163 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3164 param.ddraw_height, ddsd.dwHeight);
3165 IDirectDrawSurface7_Release(primary);
3167 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3168 ok(ret, "Failed to get display mode.\n");
3169 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3170 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3171 "Expected resolution %ux%u, got %ux%u.\n",
3172 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3173 devmode.dmPelsWidth, devmode.dmPelsHeight);
3174 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3175 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3177 memset(&ddsd, 0, sizeof(ddsd));
3178 ddsd.dwSize = sizeof(ddsd);
3179 ddsd.dwFlags = DDSD_CAPS;
3180 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3182 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3183 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3184 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3185 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3186 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3187 registry_mode.dmPelsWidth, ddsd.dwWidth);
3188 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3189 registry_mode.dmPelsHeight, ddsd.dwHeight);
3190 IDirectDrawSurface7_Release(primary);
3192 GetWindowRect(window, &r);
3193 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3194 wine_dbgstr_rect(&r));
3196 /* Changing the coop level from EXCLUSIVE to NORMAL restores the screen resolution */
3197 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3198 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3199 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3200 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3202 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3203 expect_messages = exclusive_messages;
3204 screen_size.cx = 0;
3205 screen_size.cy = 0;
3207 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3208 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3210 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3211 expect_messages = NULL;
3212 ok(screen_size.cx == registry_mode.dmPelsWidth
3213 && screen_size.cy == registry_mode.dmPelsHeight,
3214 "Expected screen size %ux%u, got %ux%u.\n",
3215 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3216 screen_size.cx, screen_size.cy);
3218 GetWindowRect(window, &r);
3219 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3220 wine_dbgstr_rect(&r));
3222 memset(&ddsd, 0, sizeof(ddsd));
3223 ddsd.dwSize = sizeof(ddsd);
3224 ddsd.dwFlags = DDSD_CAPS;
3225 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3227 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3228 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3229 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3230 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3231 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3232 registry_mode.dmPelsWidth, ddsd.dwWidth);
3233 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3234 registry_mode.dmPelsHeight, ddsd.dwHeight);
3235 IDirectDrawSurface7_Release(primary);
3237 /* The screen restore is a property of DDSCL_EXCLUSIVE */
3238 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3239 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3240 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3241 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3243 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3244 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3246 memset(&ddsd, 0, sizeof(ddsd));
3247 ddsd.dwSize = sizeof(ddsd);
3248 ddsd.dwFlags = DDSD_CAPS;
3249 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3251 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3252 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3253 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3254 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3255 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3256 param.ddraw_width, ddsd.dwWidth);
3257 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3258 param.ddraw_height, ddsd.dwHeight);
3259 IDirectDrawSurface7_Release(primary);
3261 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
3262 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3264 /* If the window is changed at the same time, messages are sent to the new window. */
3265 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3266 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3267 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3268 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3270 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3271 expect_messages = exclusive_messages;
3272 screen_size.cx = 0;
3273 screen_size.cy = 0;
3274 screen_size2.cx = 0;
3275 screen_size2.cy = 0;
3277 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3278 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3280 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3281 expect_messages = NULL;
3282 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n",
3283 screen_size.cx, screen_size.cy);
3284 ok(screen_size2.cx == registry_mode.dmPelsWidth && screen_size2.cy == registry_mode.dmPelsHeight,
3285 "Expected screen size 2 %ux%u, got %ux%u.\n",
3286 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size2.cx, screen_size2.cy);
3288 GetWindowRect(window, &r);
3289 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3290 wine_dbgstr_rect(&r));
3291 GetWindowRect(window2, &r);
3292 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3293 wine_dbgstr_rect(&r));
3295 memset(&ddsd, 0, sizeof(ddsd));
3296 ddsd.dwSize = sizeof(ddsd);
3297 ddsd.dwFlags = DDSD_CAPS;
3298 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3300 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3301 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3302 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3303 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3304 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3305 registry_mode.dmPelsWidth, ddsd.dwWidth);
3306 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3307 registry_mode.dmPelsHeight, ddsd.dwHeight);
3308 IDirectDrawSurface7_Release(primary);
3310 ref = IDirectDraw7_Release(ddraw);
3311 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3313 GetWindowRect(window, &r);
3314 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3315 wine_dbgstr_rect(&r));
3317 expect_messages = NULL;
3318 DestroyWindow(window);
3319 DestroyWindow(window2);
3320 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
3321 UnregisterClassA("ddraw_test_wndproc_wc2", GetModuleHandleA(NULL));
3324 static void test_coop_level_mode_set_multi(void)
3326 IDirectDraw7 *ddraw1, *ddraw2;
3327 UINT w, h;
3328 HWND window;
3329 HRESULT hr;
3330 ULONG ref;
3332 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3333 0, 0, 100, 100, 0, 0, 0, 0);
3334 ddraw1 = create_ddraw();
3335 ok(!!ddraw1, "Failed to create a ddraw object.\n");
3337 /* With just a single ddraw object, the display mode is restored on
3338 * release. */
3339 hr = set_display_mode(ddraw1, 800, 600);
3340 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3341 w = GetSystemMetrics(SM_CXSCREEN);
3342 ok(w == 800, "Got unexpected screen width %u.\n", w);
3343 h = GetSystemMetrics(SM_CYSCREEN);
3344 ok(h == 600, "Got unexpected screen height %u.\n", h);
3346 ref = IDirectDraw7_Release(ddraw1);
3347 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3348 w = GetSystemMetrics(SM_CXSCREEN);
3349 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3350 h = GetSystemMetrics(SM_CYSCREEN);
3351 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3353 /* When there are multiple ddraw objects, the display mode is restored to
3354 * the initial mode, before the first SetDisplayMode() call. */
3355 ddraw1 = create_ddraw();
3356 hr = set_display_mode(ddraw1, 800, 600);
3357 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3358 w = GetSystemMetrics(SM_CXSCREEN);
3359 ok(w == 800, "Got unexpected screen width %u.\n", w);
3360 h = GetSystemMetrics(SM_CYSCREEN);
3361 ok(h == 600, "Got unexpected screen height %u.\n", h);
3363 ddraw2 = create_ddraw();
3364 hr = set_display_mode(ddraw2, 640, 480);
3365 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3366 w = GetSystemMetrics(SM_CXSCREEN);
3367 ok(w == 640, "Got unexpected screen width %u.\n", w);
3368 h = GetSystemMetrics(SM_CYSCREEN);
3369 ok(h == 480, "Got unexpected screen height %u.\n", h);
3371 ref = IDirectDraw7_Release(ddraw2);
3372 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3373 w = GetSystemMetrics(SM_CXSCREEN);
3374 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3375 h = GetSystemMetrics(SM_CYSCREEN);
3376 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3378 ref = IDirectDraw7_Release(ddraw1);
3379 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3380 w = GetSystemMetrics(SM_CXSCREEN);
3381 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3382 h = GetSystemMetrics(SM_CYSCREEN);
3383 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3385 /* Regardless of release ordering. */
3386 ddraw1 = create_ddraw();
3387 hr = set_display_mode(ddraw1, 800, 600);
3388 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3389 w = GetSystemMetrics(SM_CXSCREEN);
3390 ok(w == 800, "Got unexpected screen width %u.\n", w);
3391 h = GetSystemMetrics(SM_CYSCREEN);
3392 ok(h == 600, "Got unexpected screen height %u.\n", h);
3394 ddraw2 = create_ddraw();
3395 hr = set_display_mode(ddraw2, 640, 480);
3396 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3397 w = GetSystemMetrics(SM_CXSCREEN);
3398 ok(w == 640, "Got unexpected screen width %u.\n", w);
3399 h = GetSystemMetrics(SM_CYSCREEN);
3400 ok(h == 480, "Got unexpected screen height %u.\n", h);
3402 ref = IDirectDraw7_Release(ddraw1);
3403 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3404 w = GetSystemMetrics(SM_CXSCREEN);
3405 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3406 h = GetSystemMetrics(SM_CYSCREEN);
3407 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3409 ref = IDirectDraw7_Release(ddraw2);
3410 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3411 w = GetSystemMetrics(SM_CXSCREEN);
3412 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3413 h = GetSystemMetrics(SM_CYSCREEN);
3414 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3416 /* But only for ddraw objects that called SetDisplayMode(). */
3417 ddraw1 = create_ddraw();
3418 ddraw2 = create_ddraw();
3419 hr = set_display_mode(ddraw2, 640, 480);
3420 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3421 w = GetSystemMetrics(SM_CXSCREEN);
3422 ok(w == 640, "Got unexpected screen width %u.\n", w);
3423 h = GetSystemMetrics(SM_CYSCREEN);
3424 ok(h == 480, "Got unexpected screen height %u.\n", h);
3426 ref = IDirectDraw7_Release(ddraw1);
3427 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3428 w = GetSystemMetrics(SM_CXSCREEN);
3429 ok(w == 640, "Got unexpected screen width %u.\n", w);
3430 h = GetSystemMetrics(SM_CYSCREEN);
3431 ok(h == 480, "Got unexpected screen height %u.\n", h);
3433 ref = IDirectDraw7_Release(ddraw2);
3434 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3435 w = GetSystemMetrics(SM_CXSCREEN);
3436 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3437 h = GetSystemMetrics(SM_CYSCREEN);
3438 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3440 /* If there's a ddraw object that's currently in exclusive mode, it blocks
3441 * restoring the display mode. */
3442 ddraw1 = create_ddraw();
3443 hr = set_display_mode(ddraw1, 800, 600);
3444 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3445 w = GetSystemMetrics(SM_CXSCREEN);
3446 ok(w == 800, "Got unexpected screen width %u.\n", w);
3447 h = GetSystemMetrics(SM_CYSCREEN);
3448 ok(h == 600, "Got unexpected screen height %u.\n", h);
3450 ddraw2 = create_ddraw();
3451 hr = set_display_mode(ddraw2, 640, 480);
3452 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3453 w = GetSystemMetrics(SM_CXSCREEN);
3454 ok(w == 640, "Got unexpected screen width %u.\n", w);
3455 h = GetSystemMetrics(SM_CYSCREEN);
3456 ok(h == 480, "Got unexpected screen height %u.\n", h);
3458 hr = IDirectDraw7_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3459 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3461 ref = IDirectDraw7_Release(ddraw1);
3462 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3463 w = GetSystemMetrics(SM_CXSCREEN);
3464 ok(w == 640, "Got unexpected screen width %u.\n", w);
3465 h = GetSystemMetrics(SM_CYSCREEN);
3466 ok(h == 480, "Got unexpected screen height %u.\n", h);
3468 ref = IDirectDraw7_Release(ddraw2);
3469 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3470 w = GetSystemMetrics(SM_CXSCREEN);
3471 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3472 h = GetSystemMetrics(SM_CYSCREEN);
3473 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3475 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
3476 ddraw1 = create_ddraw();
3477 hr = set_display_mode(ddraw1, 800, 600);
3478 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3479 w = GetSystemMetrics(SM_CXSCREEN);
3480 ok(w == 800, "Got unexpected screen width %u.\n", w);
3481 h = GetSystemMetrics(SM_CYSCREEN);
3482 ok(h == 600, "Got unexpected screen height %u.\n", h);
3484 hr = IDirectDraw7_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3485 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3487 ddraw2 = create_ddraw();
3488 hr = set_display_mode(ddraw2, 640, 480);
3489 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
3491 ref = IDirectDraw7_Release(ddraw1);
3492 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3493 w = GetSystemMetrics(SM_CXSCREEN);
3494 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3495 h = GetSystemMetrics(SM_CYSCREEN);
3496 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3498 ref = IDirectDraw7_Release(ddraw2);
3499 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3500 w = GetSystemMetrics(SM_CXSCREEN);
3501 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3502 h = GetSystemMetrics(SM_CYSCREEN);
3503 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3505 DestroyWindow(window);
3508 static void test_initialize(void)
3510 IDirectDraw7 *ddraw;
3511 HRESULT hr;
3513 ddraw = create_ddraw();
3514 ok(!!ddraw, "Failed to create a ddraw object.\n");
3516 hr = IDirectDraw7_Initialize(ddraw, NULL);
3517 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
3518 IDirectDraw7_Release(ddraw);
3520 CoInitialize(NULL);
3521 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw7, (void **)&ddraw);
3522 ok(SUCCEEDED(hr), "Failed to create IDirectDraw7 instance, hr %#x.\n", hr);
3523 hr = IDirectDraw7_Initialize(ddraw, NULL);
3524 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
3525 hr = IDirectDraw7_Initialize(ddraw, NULL);
3526 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
3527 IDirectDraw7_Release(ddraw);
3528 CoUninitialize();
3531 static void test_coop_level_surf_create(void)
3533 IDirectDrawSurface7 *surface;
3534 IDirectDraw7 *ddraw;
3535 DDSURFACEDESC2 ddsd;
3536 HRESULT hr;
3538 ddraw = create_ddraw();
3539 ok(!!ddraw, "Failed to create a ddraw object.\n");
3541 memset(&ddsd, 0, sizeof(ddsd));
3542 ddsd.dwSize = sizeof(ddsd);
3543 ddsd.dwFlags = DDSD_CAPS;
3544 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3545 surface = (void *)0xdeadbeef;
3546 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
3547 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
3548 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
3550 surface = (void *)0xdeadbeef;
3551 hr = IDirectDraw7_CreateSurface(ddraw, NULL, &surface, NULL);
3552 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
3553 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
3555 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3556 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3558 surface = (void *)0xdeadbeef;
3559 hr = IDirectDraw7_CreateSurface(ddraw, NULL, &surface, NULL);
3560 ok(hr == DDERR_INVALIDPARAMS, "Unexpected hr %#x.\n", hr);
3561 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
3563 IDirectDraw7_Release(ddraw);
3566 static void test_vb_discard(void)
3568 static const struct vec4 quad[] =
3570 { 0.0f, 480.0f, 0.0f, 1.0f},
3571 { 0.0f, 0.0f, 0.0f, 1.0f},
3572 {640.0f, 480.0f, 0.0f, 1.0f},
3573 {640.0f, 0.0f, 0.0f, 1.0f},
3576 IDirect3DDevice7 *device;
3577 IDirect3D7 *d3d;
3578 IDirect3DVertexBuffer7 *buffer;
3579 HWND window;
3580 HRESULT hr;
3581 D3DVERTEXBUFFERDESC desc;
3582 BYTE *data;
3583 static const unsigned int vbsize = 16;
3584 unsigned int i;
3586 window = create_window();
3587 if (!(device = create_device(window, DDSCL_NORMAL)))
3589 skip("Failed to create a 3D device, skipping test.\n");
3590 DestroyWindow(window);
3591 return;
3594 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
3595 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
3597 memset(&desc, 0, sizeof(desc));
3598 desc.dwSize = sizeof(desc);
3599 desc.dwCaps = D3DVBCAPS_WRITEONLY;
3600 desc.dwFVF = D3DFVF_XYZRHW;
3601 desc.dwNumVertices = vbsize;
3602 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &buffer, 0);
3603 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
3605 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3606 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3607 memcpy(data, quad, sizeof(quad));
3608 hr = IDirect3DVertexBuffer7_Unlock(buffer);
3609 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3611 hr = IDirect3DDevice7_BeginScene(device);
3612 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3613 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
3614 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3615 hr = IDirect3DDevice7_EndScene(device);
3616 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3618 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3619 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3620 memset(data, 0xaa, sizeof(struct vec4) * vbsize);
3621 hr = IDirect3DVertexBuffer7_Unlock(buffer);
3622 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3624 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3625 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3626 for (i = 0; i < sizeof(struct vec4) * vbsize; i++)
3628 if (data[i] != 0xaa)
3630 ok(FALSE, "Vertex buffer data byte %u is 0x%02x, expected 0xaa\n", i, data[i]);
3631 break;
3634 hr = IDirect3DVertexBuffer7_Unlock(buffer);
3635 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3637 IDirect3DVertexBuffer7_Release(buffer);
3638 IDirect3D7_Release(d3d);
3639 IDirect3DDevice7_Release(device);
3640 DestroyWindow(window);
3643 static void test_coop_level_multi_window(void)
3645 HWND window1, window2;
3646 IDirectDraw7 *ddraw;
3647 HRESULT hr;
3649 window1 = create_window();
3650 window2 = create_window();
3651 ddraw = create_ddraw();
3652 ok(!!ddraw, "Failed to create a ddraw object.\n");
3654 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
3655 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3656 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3657 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3658 ok(IsWindow(window1), "Window 1 was destroyed.\n");
3659 ok(IsWindow(window2), "Window 2 was destroyed.\n");
3661 IDirectDraw7_Release(ddraw);
3662 DestroyWindow(window2);
3663 DestroyWindow(window1);
3666 static void test_draw_strided(void)
3668 static struct vec3 position[] =
3670 {-1.0, -1.0, 0.0},
3671 {-1.0, 1.0, 0.0},
3672 { 1.0, 1.0, 0.0},
3673 { 1.0, -1.0, 0.0},
3675 static DWORD diffuse[] =
3677 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
3679 static WORD indices[] =
3681 0, 1, 2, 2, 3, 0
3684 IDirectDrawSurface7 *rt;
3685 IDirect3DDevice7 *device;
3686 D3DCOLOR color;
3687 HWND window;
3688 HRESULT hr;
3689 D3DDRAWPRIMITIVESTRIDEDDATA strided;
3691 window = create_window();
3692 if (!(device = create_device(window, DDSCL_NORMAL)))
3694 skip("Failed to create a 3D device, skipping test.\n");
3695 DestroyWindow(window);
3696 return;
3699 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
3700 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3702 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
3703 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
3704 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 1.0f, 0);
3705 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
3706 hr = IDirect3DDevice7_BeginScene(device);
3707 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3709 memset(&strided, 0x55, sizeof(strided));
3710 strided.position.lpvData = position;
3711 strided.position.dwStride = sizeof(*position);
3712 strided.diffuse.lpvData = diffuse;
3713 strided.diffuse.dwStride = sizeof(*diffuse);
3714 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device, D3DPT_TRIANGLELIST, D3DFVF_XYZ | D3DFVF_DIFFUSE,
3715 &strided, 4, indices, 6, 0);
3716 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3718 hr = IDirect3DDevice7_EndScene(device);
3719 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3721 color = get_surface_color(rt, 320, 240);
3722 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
3724 IDirectDrawSurface7_Release(rt);
3725 IDirect3DDevice7_Release(device);
3726 DestroyWindow(window);
3729 static void test_lighting(void)
3731 static D3DMATRIX mat =
3733 1.0f, 0.0f, 0.0f, 0.0f,
3734 0.0f, 1.0f, 0.0f, 0.0f,
3735 0.0f, 0.0f, 1.0f, 0.0f,
3736 0.0f, 0.0f, 0.0f, 1.0f,
3738 mat_singular =
3740 1.0f, 0.0f, 1.0f, 0.0f,
3741 0.0f, 1.0f, 0.0f, 0.0f,
3742 1.0f, 0.0f, 1.0f, 0.0f,
3743 0.0f, 0.0f, 0.5f, 1.0f,
3745 mat_transf =
3747 0.0f, 0.0f, 1.0f, 0.0f,
3748 0.0f, 1.0f, 0.0f, 0.0f,
3749 -1.0f, 0.0f, 0.0f, 0.0f,
3750 10.f, 10.0f, 10.0f, 1.0f,
3752 mat_nonaffine =
3754 1.0f, 0.0f, 0.0f, 0.0f,
3755 0.0f, 1.0f, 0.0f, 0.0f,
3756 0.0f, 0.0f, 1.0f, -1.0f,
3757 10.f, 10.0f, 10.0f, 0.0f,
3759 static struct vertex
3761 struct vec3 position;
3762 DWORD diffuse;
3764 unlitquad[] =
3766 {{-1.0f, -1.0f, 0.1f}, 0xffff0000},
3767 {{-1.0f, 0.0f, 0.1f}, 0xffff0000},
3768 {{ 0.0f, 0.0f, 0.1f}, 0xffff0000},
3769 {{ 0.0f, -1.0f, 0.1f}, 0xffff0000},
3771 litquad[] =
3773 {{-1.0f, 0.0f, 0.1f}, 0xff00ff00},
3774 {{-1.0f, 1.0f, 0.1f}, 0xff00ff00},
3775 {{ 0.0f, 1.0f, 0.1f}, 0xff00ff00},
3776 {{ 0.0f, 0.0f, 0.1f}, 0xff00ff00},
3778 static struct vertex_normal
3780 struct vec3 position;
3781 struct vec3 normal;
3782 DWORD diffuse;
3784 unlitnquad[] =
3786 {{0.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3787 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3788 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3789 {{1.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3791 litnquad[] =
3793 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3794 {{0.0f, 1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3795 {{1.0f, 1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3796 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3798 nquad[] =
3800 {{-1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3801 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3802 {{ 1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3803 {{ 1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3805 rotatedquad[] =
3807 {{-10.0f, -11.0f, 11.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3808 {{-10.0f, -9.0f, 11.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3809 {{-10.0f, -9.0f, 9.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3810 {{-10.0f, -11.0f, 9.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3812 translatedquad[] =
3814 {{-11.0f, -11.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3815 {{-11.0f, -9.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3816 {{ -9.0f, -9.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3817 {{ -9.0f, -11.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3819 static WORD indices[] = {0, 1, 2, 2, 3, 0};
3820 static const struct
3822 D3DMATRIX *world_matrix;
3823 void *quad;
3824 DWORD expected, expected_process_vertices;
3825 const char *message;
3826 BOOL process_vertices_todo;
3828 tests[] =
3830 {&mat, nquad, 0x000000ff, 0xff0000ff, "Lit quad with light"},
3831 {&mat_singular, nquad, 0x000000ff, 0xff000000, "Lit quad with singular world matrix", TRUE},
3832 {&mat_transf, rotatedquad, 0x000000ff, 0xff0000ff, "Lit quad with transformation matrix"},
3833 {&mat_nonaffine, translatedquad, 0x00000000, 0xff000000, "Lit quad with non-affine matrix"},
3836 DWORD nfvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL;
3837 IDirect3DVertexBuffer7 *src_vb1, *src_vb2, *dst_vb;
3838 DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
3839 struct vertex_normal *src_data2;
3840 D3DVERTEXBUFFERDESC vb_desc;
3841 struct vertex *src_data1;
3842 IDirect3DDevice7 *device;
3843 IDirectDrawSurface7 *rt;
3844 IDirectDraw7 *ddraw;
3845 IDirect3D7 *d3d;
3846 D3DCOLOR color;
3847 ULONG refcount;
3848 unsigned int i;
3849 BOOL is_warp;
3850 HWND window;
3851 HRESULT hr;
3852 struct
3854 struct vec4 position;
3855 DWORD diffuse;
3856 DWORD specular;
3858 *dst_data;
3860 window = create_window();
3861 if (!(device = create_device(window, DDSCL_NORMAL)))
3863 skip("Failed to create a 3D device, skipping test.\n");
3864 DestroyWindow(window);
3865 return;
3867 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
3868 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3869 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
3870 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3872 is_warp = ddraw_is_warp(ddraw);
3874 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
3875 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3877 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
3878 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3880 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
3881 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3882 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
3883 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3884 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
3885 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3886 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
3887 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3888 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
3889 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3890 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
3891 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3892 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
3893 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3894 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
3895 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3897 hr = IDirect3DDevice7_BeginScene(device);
3898 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3900 memset(&vb_desc, 0, sizeof(vb_desc));
3901 vb_desc.dwSize = sizeof(vb_desc);
3902 vb_desc.dwFVF = fvf;
3903 vb_desc.dwNumVertices = 2;
3904 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &src_vb1, 0);
3905 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3906 vb_desc.dwSize = sizeof(vb_desc);
3907 vb_desc.dwFVF = nfvf;
3908 vb_desc.dwNumVertices = 2;
3909 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &src_vb2, 0);
3910 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3912 memset(&vb_desc, 0, sizeof(vb_desc));
3913 vb_desc.dwSize = sizeof(vb_desc);
3914 vb_desc.dwFVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR;
3915 vb_desc.dwNumVertices = 4;
3916 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &dst_vb, 0);
3917 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3919 hr = IDirect3DVertexBuffer7_Lock(src_vb1, 0, (void **)&src_data1, NULL);
3920 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3921 memcpy(src_data1, unlitquad, sizeof(*src_data1));
3922 memcpy(&src_data1[1], litquad, sizeof(*src_data1));
3923 hr = IDirect3DVertexBuffer7_Unlock(src_vb1);
3924 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3926 hr = IDirect3DVertexBuffer7_Lock(src_vb2, 0, (void **)&src_data2, NULL);
3927 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3928 memcpy(src_data2, unlitnquad, sizeof(*src_data2));
3929 memcpy(&src_data2[1], litnquad, sizeof(*src_data2));
3930 hr = IDirect3DVertexBuffer7_Unlock(src_vb2);
3931 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3933 /* No lights are defined... That means, lit vertices should be entirely black. */
3934 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
3935 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3936 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0,
3937 1, src_vb1, 0, device, 0);
3938 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3939 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, unlitquad, 4,
3940 indices, 6, 0);
3941 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3943 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
3944 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3945 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 1,
3946 1, src_vb1, 1, device, 0);
3947 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3948 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, litquad, 4,
3949 indices, 6, 0);
3950 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3952 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
3953 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3954 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 2,
3955 1, src_vb2, 0, device, 0);
3956 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3957 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, unlitnquad, 4,
3958 indices, 6, 0);
3959 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3961 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
3962 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3963 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 3,
3964 1, src_vb2, 1, device, 0);
3965 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3966 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, litnquad, 4,
3967 indices, 6, 0);
3968 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3970 hr = IDirect3DDevice7_EndScene(device);
3971 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3973 hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL);
3974 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3976 color = get_surface_color(rt, 160, 360);
3977 ok(color == 0x00ff0000, "Unlit quad without normals has color 0x%08x, expected 0x00ff0000.\n", color);
3978 ok(dst_data[0].diffuse == 0xffff0000,
3979 "Unlit quad without normals has color 0x%08x, expected 0xffff0000.\n", dst_data[0].diffuse);
3980 ok(!dst_data[0].specular,
3981 "Unexpected specular color 0x%08x.\n", dst_data[0].specular);
3982 color = get_surface_color(rt, 160, 120);
3983 /* Broken on some of WARP drivers. */
3984 ok(color == 0x00000000 || broken(is_warp && (color == 0x000000ff || color == 0x00ff00ff)),
3985 "Lit quad without normals has color 0x%08x, expected 0x00000000.\n", color);
3986 ok(dst_data[1].diffuse == 0xff000000,
3987 "Lit quad without normals has color 0x%08x, expected 0xff000000.\n", dst_data[1].diffuse);
3988 ok(!dst_data[1].specular,
3989 "Unexpected specular color 0x%08x.\n", dst_data[1].specular);
3990 color = get_surface_color(rt, 480, 360);
3991 ok(color == 0x000000ff, "Unlit quad with normals has color 0x%08x, expected 0x000000ff.\n", color);
3992 ok(dst_data[2].diffuse == 0xff0000ff,
3993 "Unlit quad with normals has color 0x%08x, expected 0xff0000ff.\n", dst_data[2].diffuse);
3994 ok(!dst_data[2].specular,
3995 "Unexpected specular color 0x%08x.\n", dst_data[2].specular);
3996 color = get_surface_color(rt, 480, 120);
3997 ok(color == 0x00000000 || broken(is_warp && (color == 0x000000ff || color == 0x00ff00ff)),
3998 "Lit quad with normals has color 0x%08x, expected 0x00000000.\n", color);
3999 ok(dst_data[3].diffuse == 0xff000000,
4000 "Lit quad with normals has color 0x%08x, expected 0xff000000.\n", dst_data[3].diffuse);
4001 ok(!dst_data[3].specular,
4002 "Unexpected specular color 0x%08x.\n", dst_data[3].specular);
4004 hr = IDirect3DVertexBuffer7_Unlock(dst_vb);
4005 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4007 hr = IDirect3DDevice7_LightEnable(device, 0, TRUE);
4008 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4010 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4012 hr = IDirect3DVertexBuffer7_Lock(src_vb2, 0, (void **)&src_data2, NULL);
4013 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4014 memcpy(src_data2, tests[i].quad, sizeof(*src_data2));
4015 hr = IDirect3DVertexBuffer7_Unlock(src_vb2);
4016 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4018 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, tests[i].world_matrix);
4019 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4021 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
4022 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4024 hr = IDirect3DDevice7_BeginScene(device);
4025 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4027 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 0,
4028 1, src_vb2, 0, device, 0);
4029 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4031 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, tests[i].quad,
4032 4, indices, 6, 0);
4033 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4035 hr = IDirect3DDevice7_EndScene(device);
4036 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4038 hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL);
4039 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4041 color = get_surface_color(rt, 320, 240);
4042 ok(color == tests[i].expected || broken(is_warp && (color == 0x000000ff || color == 0x00ff00ff)),
4043 "%s has color 0x%08x.\n", tests[i].message, color);
4044 todo_wine_if(tests[i].process_vertices_todo)
4045 ok(dst_data[0].diffuse == tests[i].expected_process_vertices,
4046 "%s has color 0x%08x.\n", tests[i].message, dst_data[0].diffuse);
4047 ok(!dst_data[0].specular,
4048 "%s has specular color 0x%08x.\n", tests[i].message, dst_data[0].specular);
4050 hr = IDirect3DVertexBuffer7_Unlock(dst_vb);
4051 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4054 IDirect3DVertexBuffer7_Release(src_vb1);
4055 IDirect3DVertexBuffer7_Release(src_vb2);
4056 IDirect3DVertexBuffer7_Release(dst_vb);
4058 IDirectDrawSurface7_Release(rt);
4060 IDirectDraw7_Release(ddraw);
4061 IDirect3D7_Release(d3d);
4062 refcount = IDirect3DDevice7_Release(device);
4063 ok(!refcount, "Device has %u references left.\n", refcount);
4064 DestroyWindow(window);
4067 static void test_specular_lighting(void)
4069 static const unsigned int vertices_side = 5;
4070 const unsigned int indices_count = (vertices_side - 1) * (vertices_side - 1) * 2 * 3;
4071 static const DWORD fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
4072 static D3DMATRIX mat =
4074 1.0f, 0.0f, 0.0f, 0.0f,
4075 0.0f, 1.0f, 0.0f, 0.0f,
4076 0.0f, 0.0f, 1.0f, 0.0f,
4077 0.0f, 0.0f, 0.0f, 1.0f,
4079 static const struct vertex
4081 struct vec3 position;
4082 struct vec3 normal;
4084 vertices[] =
4086 {{-0.5f, -0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4087 {{ 0.0f, -0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4088 {{ 0.5f, -0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4089 {{-0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4090 {{ 0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4091 {{ 0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4092 {{-0.5f, 0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4093 {{ 0.0f, 0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4094 {{ 0.5f, 0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4097 static D3DLIGHT7 directional =
4099 D3DLIGHT_DIRECTIONAL,
4100 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4101 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4102 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4103 {{0.0f}, {0.0f}, {0.0f}},
4104 {{0.0f}, {0.0f}, {1.0f}},
4106 point =
4108 D3DLIGHT_POINT,
4109 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4110 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4111 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4112 {{0.0f}, {0.0f}, {0.0f}},
4113 {{0.0f}, {0.0f}, {0.0f}},
4114 100.0f,
4115 0.0f,
4116 0.0f, 0.0f, 1.0f,
4118 spot =
4120 D3DLIGHT_SPOT,
4121 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4122 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4123 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4124 {{0.0f}, {0.0f}, {0.0f}},
4125 {{0.0f}, {0.0f}, {1.0f}},
4126 100.0f,
4127 1.0f,
4128 0.0f, 0.0f, 1.0f,
4129 M_PI / 12.0f, M_PI / 3.0f
4131 /* The chosen range value makes the test fail when using a manhattan
4132 * distance metric vs the correct euclidean distance. */
4133 point_range =
4135 D3DLIGHT_POINT,
4136 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4137 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4138 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4139 {{0.0f}, {0.0f}, {0.0f}},
4140 {{0.0f}, {0.0f}, {0.0f}},
4141 1.2f,
4142 0.0f,
4143 0.0f, 0.0f, 1.0f,
4145 point_side =
4147 D3DLIGHT_POINT,
4148 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4149 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4150 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4151 {{-1.1f}, {0.0f}, {1.1f}},
4152 {{0.0f}, {0.0f}, {0.0f}},
4153 100.0f,
4154 0.0f,
4155 1.0f, 0.0f, 0.0f,
4157 static const struct expected_color
4159 unsigned int x, y;
4160 D3DCOLOR color;
4162 expected_directional[] =
4164 {160, 120, 0x00ffffff},
4165 {320, 120, 0x00ffffff},
4166 {480, 120, 0x00ffffff},
4167 {160, 240, 0x00ffffff},
4168 {320, 240, 0x00ffffff},
4169 {480, 240, 0x00ffffff},
4170 {160, 360, 0x00ffffff},
4171 {320, 360, 0x00ffffff},
4172 {480, 360, 0x00ffffff},
4174 expected_directional_local[] =
4176 {160, 120, 0x003c3c3c},
4177 {320, 120, 0x00717171},
4178 {480, 120, 0x003c3c3c},
4179 {160, 240, 0x00717171},
4180 {320, 240, 0x00ffffff},
4181 {480, 240, 0x00717171},
4182 {160, 360, 0x003c3c3c},
4183 {320, 360, 0x00717171},
4184 {480, 360, 0x003c3c3c},
4186 expected_point[] =
4188 {160, 120, 0x00282828},
4189 {320, 120, 0x005a5a5a},
4190 {480, 120, 0x00282828},
4191 {160, 240, 0x005a5a5a},
4192 {320, 240, 0x00ffffff},
4193 {480, 240, 0x005a5a5a},
4194 {160, 360, 0x00282828},
4195 {320, 360, 0x005a5a5a},
4196 {480, 360, 0x00282828},
4198 expected_point_local[] =
4200 {160, 120, 0x00000000},
4201 {320, 120, 0x00070707},
4202 {480, 120, 0x00000000},
4203 {160, 240, 0x00070707},
4204 {320, 240, 0x00ffffff},
4205 {480, 240, 0x00070707},
4206 {160, 360, 0x00000000},
4207 {320, 360, 0x00070707},
4208 {480, 360, 0x00000000},
4210 expected_spot[] =
4212 {160, 120, 0x00000000},
4213 {320, 120, 0x00141414},
4214 {480, 120, 0x00000000},
4215 {160, 240, 0x00141414},
4216 {320, 240, 0x00ffffff},
4217 {480, 240, 0x00141414},
4218 {160, 360, 0x00000000},
4219 {320, 360, 0x00141414},
4220 {480, 360, 0x00000000},
4222 expected_spot_local[] =
4224 {160, 120, 0x00000000},
4225 {320, 120, 0x00020202},
4226 {480, 120, 0x00000000},
4227 {160, 240, 0x00020202},
4228 {320, 240, 0x00ffffff},
4229 {480, 240, 0x00020202},
4230 {160, 360, 0x00000000},
4231 {320, 360, 0x00020202},
4232 {480, 360, 0x00000000},
4234 expected_point_range[] =
4236 {160, 120, 0x00000000},
4237 {320, 120, 0x005a5a5a},
4238 {480, 120, 0x00000000},
4239 {160, 240, 0x005a5a5a},
4240 {320, 240, 0x00ffffff},
4241 {480, 240, 0x005a5a5a},
4242 {160, 360, 0x00000000},
4243 {320, 360, 0x005a5a5a},
4244 {480, 360, 0x00000000},
4246 expected_point_side[] =
4248 {160, 120, 0x00000000},
4249 {320, 120, 0x00000000},
4250 {480, 120, 0x00000000},
4251 {160, 240, 0x00000000},
4252 {320, 240, 0x00000000},
4253 {480, 240, 0x00000000},
4254 {160, 360, 0x00000000},
4255 {320, 360, 0x00000000},
4256 {480, 360, 0x00000000},
4258 expected_directional_local_0[] =
4260 {160, 120, 0x00ffffff},
4261 {320, 120, 0x00ffffff},
4262 {480, 120, 0x00ffffff},
4263 {160, 240, 0x00ffffff},
4264 {320, 240, 0x00ffffff},
4265 {480, 240, 0x00ffffff},
4266 {160, 360, 0x00ffffff},
4267 {320, 360, 0x00ffffff},
4268 {480, 360, 0x00ffffff},
4270 expected_point_0[] =
4272 {160, 120, 0x00aaaaaa},
4273 {320, 120, 0x00cccccc},
4274 {480, 120, 0x00aaaaaa},
4275 {160, 240, 0x00cccccc},
4276 {320, 240, 0x00ffffff},
4277 {480, 240, 0x00cccccc},
4278 {160, 360, 0x00aaaaaa},
4279 {320, 360, 0x00cccccc},
4280 {480, 360, 0x00aaaaaa},
4282 expected_spot_0[] =
4284 {160, 120, 0x00000000},
4285 {320, 120, 0x002e2e2e},
4286 {480, 120, 0x00000000},
4287 {160, 240, 0x002e2e2e},
4288 {320, 240, 0x00ffffff},
4289 {480, 240, 0x002e2e2e},
4290 {160, 360, 0x00000000},
4291 {320, 360, 0x002e2e2e},
4292 {480, 360, 0x00000000},
4294 expected_point_range_0[] =
4296 {160, 120, 0x00000000},
4297 {320, 120, 0x00cccccc},
4298 {480, 120, 0x00000000},
4299 {160, 240, 0x00cccccc},
4300 {320, 240, 0x00ffffff},
4301 {480, 240, 0x00cccccc},
4302 {160, 360, 0x00000000},
4303 {320, 360, 0x00cccccc},
4304 {480, 360, 0x00000000},
4306 static const struct
4308 D3DLIGHT7 *light;
4309 BOOL local_viewer;
4310 float specular_power;
4311 const struct expected_color *expected, *expected_process_vertices;
4312 unsigned int expected_count;
4313 BOOL todo_process_vertices;
4315 tests[] =
4317 {&directional, FALSE, 30.0f, expected_directional, expected_directional,
4318 ARRAY_SIZE(expected_directional)},
4319 {&directional, TRUE, 30.0f, expected_directional_local, expected_directional_local,
4320 ARRAY_SIZE(expected_directional_local)},
4321 {&point, FALSE, 30.0f, expected_point, expected_point, ARRAY_SIZE(expected_point)},
4322 {&point, TRUE, 30.0f, expected_point_local, expected_point_local, ARRAY_SIZE(expected_point_local)},
4323 {&spot, FALSE, 30.0f, expected_spot, expected_spot, ARRAY_SIZE(expected_spot)},
4324 {&spot, TRUE, 30.0f, expected_spot_local, expected_spot_local, ARRAY_SIZE(expected_spot_local)},
4325 {&point_range, FALSE, 30.0f, expected_point_range, expected_point_range,
4326 ARRAY_SIZE(expected_point_range)},
4328 /* For zero material shininess _ProcessVertices() seem to keep non-zero material shininess set previously. */
4329 {&point_side, TRUE, 0.0f, expected_point_side, expected_point_side, ARRAY_SIZE(expected_point_side), TRUE},
4330 {&directional, FALSE, 0.0f, expected_directional, expected_directional,
4331 ARRAY_SIZE(expected_directional), TRUE},
4332 {&directional, TRUE, 0.0f, expected_directional_local_0, expected_directional_local,
4333 ARRAY_SIZE(expected_directional_local_0), TRUE},
4334 {&point, FALSE, 0.0f, expected_point_0, expected_point, ARRAY_SIZE(expected_point_0), TRUE},
4335 {&point, TRUE, 0.0f, expected_point_0, expected_point_local, ARRAY_SIZE(expected_point_0), TRUE},
4336 {&spot, FALSE, 0.0f, expected_spot_0, expected_spot, ARRAY_SIZE(expected_spot_0), TRUE},
4337 {&spot, TRUE, 0.0f, expected_spot_0, expected_spot_local, ARRAY_SIZE(expected_spot_0), TRUE},
4338 {&point_range, FALSE, 0.0f, expected_point_range_0, expected_point_range, ARRAY_SIZE(expected_point_range_0), TRUE},
4341 IDirect3DVertexBuffer7 *src_vb, *dst_vb;
4342 D3DCOLOR color, expected_color;
4343 D3DVERTEXBUFFERDESC vb_desc;
4344 IDirect3DDevice7 *device;
4345 unsigned int i, j, x, y;
4346 IDirectDrawSurface7 *rt;
4347 D3DMATERIAL7 material;
4348 struct vec3 *src_data;
4349 struct vertex *quad;
4350 IDirect3D7 *d3d;
4351 ULONG refcount;
4352 WORD *indices;
4353 HWND window;
4354 HRESULT hr;
4355 struct
4357 struct vec4 position;
4358 DWORD diffuse;
4359 DWORD specular;
4360 } *dst_data;
4362 window = create_window();
4363 if (!(device = create_device(window, DDSCL_NORMAL)))
4365 skip("Failed to create a 3D device, skipping test.\n");
4366 DestroyWindow(window);
4367 return;
4369 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
4370 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4372 quad = heap_alloc(vertices_side * vertices_side * sizeof(*quad));
4373 indices = heap_alloc(indices_count * sizeof(*indices));
4374 for (i = 0, y = 0; y < vertices_side; ++y)
4376 for (x = 0; x < vertices_side; ++x)
4378 quad[i].position.x = x * 2.0f / (vertices_side - 1) - 1.0f;
4379 quad[i].position.y = y * 2.0f / (vertices_side - 1) - 1.0f;
4380 quad[i].position.z = 1.0f;
4381 quad[i].normal.x = 0.0f;
4382 quad[i].normal.y = 0.0f;
4383 quad[i++].normal.z = -1.0f;
4386 for (i = 0, y = 0; y < (vertices_side - 1); ++y)
4388 for (x = 0; x < (vertices_side - 1); ++x)
4390 indices[i++] = y * vertices_side + x + 1;
4391 indices[i++] = y * vertices_side + x;
4392 indices[i++] = (y + 1) * vertices_side + x;
4393 indices[i++] = y * vertices_side + x + 1;
4394 indices[i++] = (y + 1) * vertices_side + x;
4395 indices[i++] = (y + 1) * vertices_side + x + 1;
4399 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
4400 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4402 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
4403 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4404 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
4405 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4406 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
4407 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4408 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
4409 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4410 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
4411 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4412 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
4413 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4415 hr = IDirect3DDevice7_LightEnable(device, 0, TRUE);
4416 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4417 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, TRUE);
4418 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4420 memset(&vb_desc, 0, sizeof(vb_desc));
4421 vb_desc.dwSize = sizeof(vb_desc);
4422 vb_desc.dwFVF = fvf;
4423 vb_desc.dwNumVertices = ARRAY_SIZE(vertices);
4424 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &src_vb, 0);
4425 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4426 hr = IDirect3DVertexBuffer7_Lock(src_vb, 0, (void **)&src_data, NULL);
4427 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4428 memcpy(src_data, vertices, sizeof(vertices));
4429 hr = IDirect3DVertexBuffer7_Unlock(src_vb);
4430 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4432 memset(&vb_desc, 0, sizeof(vb_desc));
4433 vb_desc.dwSize = sizeof(vb_desc);
4434 vb_desc.dwFVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR;
4435 vb_desc.dwNumVertices = ARRAY_SIZE(vertices);
4436 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &dst_vb, 0);
4437 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4439 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4441 hr = IDirect3DDevice7_SetLight(device, 0, tests[i].light);
4442 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4444 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LOCALVIEWER, tests[i].local_viewer);
4445 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4447 memset(&material, 0, sizeof(material));
4448 U1(U2(material).specular).r = 1.0f;
4449 U2(U2(material).specular).g = 1.0f;
4450 U3(U2(material).specular).b = 1.0f;
4451 U4(U2(material).specular).a = 0.5f;
4452 U4(material).power = tests[i].specular_power;
4453 hr = IDirect3DDevice7_SetMaterial(device, &material);
4454 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4456 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
4457 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4459 hr = IDirect3DDevice7_BeginScene(device);
4460 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4462 hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL);
4463 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4464 memset(dst_data, 0, sizeof(*dst_data) * ARRAY_SIZE(vertices));
4465 hr = IDirect3DVertexBuffer7_Unlock(dst_vb);
4466 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4468 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 0,
4469 ARRAY_SIZE(vertices), src_vb, 0, device, 0);
4470 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4472 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, quad,
4473 vertices_side * vertices_side, indices, indices_count, 0);
4474 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4476 hr = IDirect3DDevice7_EndScene(device);
4477 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4479 hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL);
4480 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4482 ok(tests[i].expected_count == ARRAY_SIZE(vertices), "Array size mismatch.\n");
4483 for (j = 0; j < tests[i].expected_count; ++j)
4485 color = get_surface_color(rt, tests[i].expected[j].x, tests[i].expected[j].y);
4486 ok(compare_color(color, tests[i].expected[j].color, 1),
4487 "Expected color 0x%08x at location (%u, %u), got 0x%08x, case %u.\n",
4488 tests[i].expected[j].color, tests[i].expected[j].x,
4489 tests[i].expected[j].y, color, i);
4490 ok(!dst_data[j].diffuse, "Expected color 0x00000000 for vertex %u, got 0x%08x, case %u.\n",
4491 j, dst_data[j].diffuse, i);
4492 expected_color = tests[i].expected_process_vertices[j].color | 0x80000000;
4493 todo_wine_if(tests[i].todo_process_vertices && dst_data[j].specular != expected_color)
4494 ok(compare_color(dst_data[j].specular, expected_color, 1),
4495 "Expected color 0x%08x for vertex %u, got 0x%08x, case %u.\n",
4496 expected_color, j, dst_data[j].specular, i);
4498 hr = IDirect3DVertexBuffer7_Unlock(dst_vb);
4499 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4502 IDirect3DVertexBuffer7_Release(dst_vb);
4503 IDirect3DVertexBuffer7_Release(src_vb);
4504 IDirectDrawSurface7_Release(rt);
4506 IDirect3D7_Release(d3d);
4507 refcount = IDirect3DDevice7_Release(device);
4508 ok(!refcount, "Device has %u references left.\n", refcount);
4509 DestroyWindow(window);
4510 heap_free(indices);
4511 heap_free(quad);
4514 static void test_clear_rect_count(void)
4516 IDirectDrawSurface7 *rt;
4517 IDirect3DDevice7 *device;
4518 D3DCOLOR color;
4519 HWND window;
4520 HRESULT hr;
4521 D3DRECT rect = {{0}, {0}, {640}, {480}};
4523 window = create_window();
4524 if (!(device = create_device(window, DDSCL_NORMAL)))
4526 skip("Failed to create a 3D device, skipping test.\n");
4527 DestroyWindow(window);
4528 return;
4531 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
4532 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4534 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ffffff, 1.0f, 0);
4535 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4536 hr = IDirect3DDevice7_Clear(device, 0, &rect, D3DCLEAR_TARGET, 0x00ff0000, 1.0f, 0);
4537 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4539 color = get_surface_color(rt, 320, 240);
4540 ok(compare_color(color, 0x00ffffff, 1) || broken(compare_color(color, 0x00ff0000, 1)),
4541 "Clear with count = 0, rect != NULL has color %#08x.\n", color);
4543 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ffffff, 1.0f, 0);
4544 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4545 hr = IDirect3DDevice7_Clear(device, 1, NULL, D3DCLEAR_TARGET, 0x0000ff00, 1.0f, 0);
4546 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4548 color = get_surface_color(rt, 320, 240);
4549 ok(compare_color(color, 0x0000ff00, 1),
4550 "Clear with count = 1, rect = NULL has color %#08x.\n", color);
4552 IDirectDrawSurface7_Release(rt);
4553 IDirect3DDevice7_Release(device);
4554 DestroyWindow(window);
4557 static BOOL test_mode_restored(IDirectDraw7 *ddraw, HWND window)
4559 DDSURFACEDESC2 ddsd1, ddsd2;
4560 HRESULT hr;
4562 memset(&ddsd1, 0, sizeof(ddsd1));
4563 ddsd1.dwSize = sizeof(ddsd1);
4564 hr = IDirectDraw7_GetDisplayMode(ddraw, &ddsd1);
4565 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
4567 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4568 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4569 hr = set_display_mode(ddraw, 640, 480);
4570 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
4571 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4572 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4574 memset(&ddsd2, 0, sizeof(ddsd2));
4575 ddsd2.dwSize = sizeof(ddsd2);
4576 hr = IDirectDraw7_GetDisplayMode(ddraw, &ddsd2);
4577 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
4578 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
4579 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
4581 return ddsd1.dwWidth == ddsd2.dwWidth && ddsd1.dwHeight == ddsd2.dwHeight;
4584 static void test_coop_level_versions(void)
4586 HWND window;
4587 IDirectDraw *ddraw;
4588 HRESULT hr;
4589 BOOL restored;
4590 IDirectDrawSurface *surface;
4591 IDirectDraw7 *ddraw7;
4592 DDSURFACEDESC ddsd;
4594 window = create_window();
4595 ddraw7 = create_ddraw();
4596 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4597 /* Newly created ddraw objects restore the mode on ddraw2+::SetCooperativeLevel(NORMAL) */
4598 restored = test_mode_restored(ddraw7, window);
4599 ok(restored, "Display mode not restored in new ddraw object\n");
4601 /* A failing ddraw1::SetCooperativeLevel call does not have an effect */
4602 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4603 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4605 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4606 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
4607 restored = test_mode_restored(ddraw7, window);
4608 ok(restored, "Display mode not restored after bad ddraw1::SetCooperativeLevel call\n");
4610 /* A successful one does */
4611 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4612 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4613 restored = test_mode_restored(ddraw7, window);
4614 ok(!restored, "Display mode restored after good ddraw1::SetCooperativeLevel call\n");
4616 IDirectDraw_Release(ddraw);
4617 IDirectDraw7_Release(ddraw7);
4619 ddraw7 = create_ddraw();
4620 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4621 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4622 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4624 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_SETFOCUSWINDOW);
4625 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4626 restored = test_mode_restored(ddraw7, window);
4627 ok(!restored, "Display mode restored after ddraw1::SetCooperativeLevel(SETFOCUSWINDOW) call\n");
4629 IDirectDraw_Release(ddraw);
4630 IDirectDraw7_Release(ddraw7);
4632 /* A failing call does not restore the ddraw2+ behavior */
4633 ddraw7 = create_ddraw();
4634 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4635 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4636 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4638 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4639 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4640 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4641 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
4642 restored = test_mode_restored(ddraw7, window);
4643 ok(!restored, "Display mode restored after good-bad ddraw1::SetCooperativeLevel() call sequence\n");
4645 IDirectDraw_Release(ddraw);
4646 IDirectDraw7_Release(ddraw7);
4648 /* Neither does a sequence of successful calls with the new interface */
4649 ddraw7 = create_ddraw();
4650 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4651 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4652 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4654 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4655 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4656 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4657 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4658 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
4659 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4661 restored = test_mode_restored(ddraw7, window);
4662 ok(!restored, "Display mode restored after ddraw1-ddraw7 SetCooperativeLevel() call sequence\n");
4663 IDirectDraw_Release(ddraw);
4664 IDirectDraw7_Release(ddraw7);
4666 /* ddraw1::CreateSurface does not triger the ddraw1 behavior */
4667 ddraw7 = create_ddraw();
4668 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4669 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4670 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4672 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
4673 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4675 memset(&ddsd, 0, sizeof(ddsd));
4676 ddsd.dwSize = sizeof(ddsd);
4677 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
4678 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4679 ddsd.dwWidth = ddsd.dwHeight = 8;
4680 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
4681 ok(SUCCEEDED(hr), "CreateSurface failed, hr %#x.\n", hr);
4682 IDirectDrawSurface_Release(surface);
4683 restored = test_mode_restored(ddraw7, window);
4684 ok(restored, "Display mode not restored after ddraw1::CreateSurface() call\n");
4686 IDirectDraw_Release(ddraw);
4687 IDirectDraw7_Release(ddraw7);
4688 DestroyWindow(window);
4691 static void test_fog_special(void)
4693 static struct
4695 struct vec3 position;
4696 D3DCOLOR diffuse;
4698 quad[] =
4700 {{ -1.0f, 1.0f, 0.0f}, 0xff00ff00},
4701 {{ 1.0f, 1.0f, 1.0f}, 0xff00ff00},
4702 {{ -1.0f, -1.0f, 0.0f}, 0xff00ff00},
4703 {{ 1.0f, -1.0f, 1.0f}, 0xff00ff00},
4705 static const struct
4707 DWORD vertexmode, tablemode;
4708 D3DCOLOR color_left, color_right;
4710 tests[] =
4712 {D3DFOG_LINEAR, D3DFOG_NONE, 0x00ff0000, 0x00ff0000},
4713 {D3DFOG_NONE, D3DFOG_LINEAR, 0x0000ff00, 0x00ff0000},
4715 union
4717 float f;
4718 DWORD d;
4719 } conv;
4720 D3DCOLOR color;
4721 HRESULT hr;
4722 unsigned int i;
4723 HWND window;
4724 IDirect3DDevice7 *device;
4725 IDirectDrawSurface7 *rt;
4727 window = create_window();
4728 if (!(device = create_device(window, DDSCL_NORMAL)))
4730 skip("Failed to create a 3D device, skipping test.\n");
4731 DestroyWindow(window);
4732 return;
4735 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
4736 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4738 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
4739 ok(SUCCEEDED(hr), "Failed to enable fog, hr %#x.\n", hr);
4740 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0xffff0000);
4741 ok(SUCCEEDED(hr), "Failed to set fog color, hr %#x.\n", hr);
4742 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
4743 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
4744 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
4745 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
4747 conv.f = 0.5f;
4748 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGSTART, conv.d);
4749 ok(SUCCEEDED(hr), "Failed to set fog start, hr %#x.\n", hr);
4750 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGEND, conv.d);
4751 ok(SUCCEEDED(hr), "Failed to set fog end, hr %#x.\n", hr);
4753 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4755 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x000000ff, 1.0f, 0);
4756 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4758 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, tests[i].vertexmode);
4759 ok(SUCCEEDED(hr), "Failed to set fogvertexmode, hr %#x.\n", hr);
4760 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, tests[i].tablemode);
4761 ok(SUCCEEDED(hr), "Failed to set fogtablemode, hr %#x.\n", hr);
4763 hr = IDirect3DDevice7_BeginScene(device);
4764 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4765 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, 4, 0);
4766 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4767 hr = IDirect3DDevice7_EndScene(device);
4768 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4770 color = get_surface_color(rt, 310, 240);
4771 ok(compare_color(color, tests[i].color_left, 1),
4772 "Expected left color 0x%08x, got 0x%08x, case %u.\n", tests[i].color_left, color, i);
4773 color = get_surface_color(rt, 330, 240);
4774 ok(compare_color(color, tests[i].color_right, 1),
4775 "Expected right color 0x%08x, got 0x%08x, case %u.\n", tests[i].color_right, color, i);
4778 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
4779 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
4781 IDirectDrawSurface7_Release(rt);
4782 IDirect3DDevice7_Release(device);
4783 DestroyWindow(window);
4786 static void test_lighting_interface_versions(void)
4788 IDirect3DDevice7 *device;
4789 IDirectDrawSurface7 *rt;
4790 D3DCOLOR color;
4791 HWND window;
4792 HRESULT hr;
4793 DWORD rs;
4794 unsigned int i;
4795 ULONG ref;
4796 D3DMATERIAL7 material;
4797 static D3DVERTEX quad[] =
4799 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4800 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4801 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4802 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4805 #define FVF_COLORVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_SPECULAR)
4806 static struct
4808 struct vec3 position;
4809 struct vec3 normal;
4810 DWORD diffuse, specular;
4812 quad2[] =
4814 {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4815 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4816 {{-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4817 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4820 static D3DLVERTEX lquad[] =
4822 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4823 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4824 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4825 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4828 #define FVF_LVERTEX2 (D3DFVF_LVERTEX & ~D3DFVF_RESERVED1)
4829 static struct
4831 struct vec3 position;
4832 DWORD diffuse, specular;
4833 struct vec2 texcoord;
4835 lquad2[] =
4837 {{-1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
4838 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
4839 {{-1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
4840 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
4843 static D3DTLVERTEX tlquad[] =
4845 {{ 0.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4846 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4847 {{ 640.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4848 {{ 640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4851 static const struct
4853 DWORD vertextype;
4854 void *data;
4855 DWORD d3drs_lighting, d3drs_specular;
4856 DWORD draw_flags;
4857 D3DCOLOR color;
4859 tests[] =
4861 /* Lighting is enabled when D3DFVF_XYZ is used and D3DRENDERSTATE_LIGHTING is
4862 * enabled. D3DDP_DONOTLIGHT is ignored. Lighting is also enabled when normals
4863 * are not available
4865 * Note that the specular result is 0x00000000 when lighting is on even if the
4866 * input vertex has specular color because D3DRENDERSTATE_COLORVERTEX is not
4867 * enabled */
4869 /* 0 */
4870 { D3DFVF_VERTEX, quad, FALSE, FALSE, 0, 0x00ffffff},
4871 { D3DFVF_VERTEX, quad, TRUE, FALSE, 0, 0x0000ff00},
4872 { D3DFVF_VERTEX, quad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
4873 { D3DFVF_VERTEX, quad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
4874 { D3DFVF_VERTEX, quad, FALSE, TRUE, 0, 0x00ffffff},
4875 { D3DFVF_VERTEX, quad, TRUE, TRUE, 0, 0x0000ff00},
4876 { D3DFVF_VERTEX, quad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
4877 { D3DFVF_VERTEX, quad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
4879 /* 8 */
4880 { FVF_COLORVERTEX, quad2, FALSE, FALSE, 0, 0x00ff0000},
4881 { FVF_COLORVERTEX, quad2, TRUE, FALSE, 0, 0x0000ff00},
4882 { FVF_COLORVERTEX, quad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4883 { FVF_COLORVERTEX, quad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
4884 { FVF_COLORVERTEX, quad2, FALSE, TRUE, 0, 0x00ff8080},
4885 { FVF_COLORVERTEX, quad2, TRUE, TRUE, 0, 0x0000ff00},
4886 { FVF_COLORVERTEX, quad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4887 { FVF_COLORVERTEX, quad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
4889 /* 16 */
4890 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, 0, 0x00ff0000},
4891 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, 0, 0x0000ff00},
4892 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4893 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
4894 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, 0, 0x00ff8080},
4895 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, 0, 0x0000ff00},
4896 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4897 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
4899 /* 24 */
4900 { FVF_LVERTEX2, lquad2, FALSE, FALSE, 0, 0x00ff0000},
4901 { FVF_LVERTEX2, lquad2, TRUE, FALSE, 0, 0x0000ff00},
4902 { FVF_LVERTEX2, lquad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4903 { FVF_LVERTEX2, lquad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
4904 { FVF_LVERTEX2, lquad2, FALSE, TRUE, 0, 0x00ff8080},
4905 { FVF_LVERTEX2, lquad2, TRUE, TRUE, 0, 0x0000ff00},
4906 { FVF_LVERTEX2, lquad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4907 { FVF_LVERTEX2, lquad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
4909 /* 32 */
4910 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, 0, 0x000000ff},
4911 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, 0, 0x000000ff},
4912 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
4913 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
4914 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, 0, 0x008080ff},
4915 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, 0, 0x008080ff},
4916 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
4917 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
4920 window = create_window();
4921 if (!(device = create_device(window, DDSCL_NORMAL)))
4923 skip("Failed to create a 3D device, skipping test.\n");
4924 DestroyWindow(window);
4925 return;
4928 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
4929 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4931 memset(&material, 0, sizeof(material));
4932 U2(U3(material).emissive).g = 1.0f;
4933 hr = IDirect3DDevice7_SetMaterial(device, &material);
4934 ok(SUCCEEDED(hr), "Failed set material, hr %#x.\n", hr);
4935 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
4936 ok(SUCCEEDED(hr), "Failed to disable z test, hr %#x.\n", hr);
4938 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &rs);
4939 ok(SUCCEEDED(hr), "Failed to get lighting render state, hr %#x.\n", hr);
4940 ok(rs == TRUE, "Initial D3DRENDERSTATE_LIGHTING is %#x, expected TRUE.\n", rs);
4941 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, &rs);
4942 ok(SUCCEEDED(hr), "Failed to get specularenable render state, hr %#x.\n", hr);
4943 ok(rs == FALSE, "Initial D3DRENDERSTATE_SPECULARENABLE is %#x, expected FALSE.\n", rs);
4945 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4947 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff202020, 0.0f, 0);
4948 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
4950 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, tests[i].d3drs_lighting);
4951 ok(SUCCEEDED(hr), "Failed to set lighting render state, hr %#x.\n", hr);
4952 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE,
4953 tests[i].d3drs_specular);
4954 ok(SUCCEEDED(hr), "Failed to set specularenable render state, hr %#x.\n", hr);
4956 hr = IDirect3DDevice7_BeginScene(device);
4957 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4958 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
4959 tests[i].vertextype, tests[i].data, 4, tests[i].draw_flags | D3DDP_WAIT);
4960 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4961 hr = IDirect3DDevice7_EndScene(device);
4962 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4964 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &rs);
4965 ok(SUCCEEDED(hr), "Failed to get lighting render state, hr %#x.\n", hr);
4966 ok(rs == tests[i].d3drs_lighting, "D3DRENDERSTATE_LIGHTING is %#x, expected %#x.\n",
4967 rs, tests[i].d3drs_lighting);
4969 color = get_surface_color(rt, 320, 240);
4970 ok(compare_color(color, tests[i].color, 1),
4971 "Got unexpected color 0x%08x, expected 0x%08x, test %u.\n",
4972 color, tests[i].color, i);
4975 IDirectDrawSurface7_Release(rt);
4976 ref = IDirect3DDevice7_Release(device);
4977 ok(ref == 0, "Device not properly released, refcount %u.\n", ref);
4978 DestroyWindow(window);
4981 static struct
4983 BOOL received;
4984 IDirectDraw7 *ddraw;
4985 HWND window;
4986 DWORD coop_level;
4987 } activateapp_testdata;
4989 static LRESULT CALLBACK activateapp_test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
4991 if (message == WM_ACTIVATEAPP)
4993 if (activateapp_testdata.ddraw)
4995 HRESULT hr;
4996 activateapp_testdata.received = FALSE;
4997 hr = IDirectDraw7_SetCooperativeLevel(activateapp_testdata.ddraw,
4998 activateapp_testdata.window, activateapp_testdata.coop_level);
4999 ok(SUCCEEDED(hr), "Recursive SetCooperativeLevel call failed, hr %#x.\n", hr);
5000 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP during recursive SetCooperativeLevel call.\n");
5002 activateapp_testdata.received = TRUE;
5005 return DefWindowProcA(hwnd, message, wparam, lparam);
5008 static void test_coop_level_activateapp(void)
5010 IDirectDraw7 *ddraw;
5011 HRESULT hr;
5012 HWND window;
5013 WNDCLASSA wc = {0};
5014 DDSURFACEDESC2 ddsd;
5015 IDirectDrawSurface7 *surface;
5017 ddraw = create_ddraw();
5018 ok(!!ddraw, "Failed to create a ddraw object.\n");
5020 wc.lpfnWndProc = activateapp_test_proc;
5021 wc.lpszClassName = "ddraw_test_wndproc_wc";
5022 ok(RegisterClassA(&wc), "Failed to register window class.\n");
5024 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
5025 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
5027 /* Exclusive with window already active. */
5028 SetForegroundWindow(window);
5029 activateapp_testdata.received = FALSE;
5030 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5031 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5032 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP although window was already active.\n");
5033 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5034 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5036 /* Exclusive with window not active. */
5037 SetForegroundWindow(GetDesktopWindow());
5038 activateapp_testdata.received = FALSE;
5039 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5040 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5041 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
5042 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5043 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5045 /* Normal with window not active, then exclusive with the same window. */
5046 SetForegroundWindow(GetDesktopWindow());
5047 activateapp_testdata.received = FALSE;
5048 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5049 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5050 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP when setting DDSCL_NORMAL.\n");
5051 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5052 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5053 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
5054 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5055 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5057 /* Recursive set of DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. */
5058 SetForegroundWindow(GetDesktopWindow());
5059 activateapp_testdata.received = FALSE;
5060 activateapp_testdata.ddraw = ddraw;
5061 activateapp_testdata.window = window;
5062 activateapp_testdata.coop_level = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
5063 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5064 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5065 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
5066 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5067 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5069 /* The recursive call seems to have some bad effect on native ddraw, despite (apparently)
5070 * succeeding. Another switch to exclusive and back to normal is needed to release the
5071 * window properly. Without doing this, SetCooperativeLevel(EXCLUSIVE) will not send
5072 * WM_ACTIVATEAPP messages. */
5073 activateapp_testdata.ddraw = NULL;
5074 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5075 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5076 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5077 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5079 /* Setting DDSCL_NORMAL with recursive invocation. */
5080 SetForegroundWindow(GetDesktopWindow());
5081 activateapp_testdata.received = FALSE;
5082 activateapp_testdata.ddraw = ddraw;
5083 activateapp_testdata.window = window;
5084 activateapp_testdata.coop_level = DDSCL_NORMAL;
5085 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5086 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5087 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
5089 /* DDraw is in exclusive mode now. */
5090 memset(&ddsd, 0, sizeof(ddsd));
5091 ddsd.dwSize = sizeof(ddsd);
5092 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
5093 U5(ddsd).dwBackBufferCount = 1;
5094 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
5095 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5096 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5097 IDirectDrawSurface7_Release(surface);
5099 /* Recover again, just to be sure. */
5100 activateapp_testdata.ddraw = NULL;
5101 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5102 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5103 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5104 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5106 DestroyWindow(window);
5107 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
5108 IDirectDraw7_Release(ddraw);
5111 static void test_texturemanage(void)
5113 IDirectDraw7 *ddraw;
5114 HRESULT hr;
5115 DDSURFACEDESC2 ddsd;
5116 IDirectDrawSurface7 *surface;
5117 unsigned int i;
5118 DDCAPS hal_caps, hel_caps;
5119 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
5120 static const struct
5122 DWORD caps_in, caps2_in;
5123 HRESULT hr;
5124 DWORD caps_out, caps2_out;
5126 tests[] =
5128 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
5129 ~0U, ~0U},
5130 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
5131 ~0U, ~0U},
5132 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
5133 ~0U, ~0U},
5134 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
5135 ~0U, ~0U},
5136 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DD_OK,
5137 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE},
5138 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DD_OK,
5139 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE},
5140 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
5141 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_LOCALVIDMEM, 0},
5142 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
5143 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0},
5145 {0, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
5146 ~0U, ~0U},
5147 {0, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
5148 ~0U, ~0U},
5149 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
5150 ~0U, ~0U},
5151 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
5152 ~0U, ~0U},
5153 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
5154 ~0U, ~0U},
5155 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
5156 ~0U, ~0U},
5157 {DDSCAPS_VIDEOMEMORY, 0, DD_OK,
5158 DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY, 0},
5159 {DDSCAPS_SYSTEMMEMORY, 0, DD_OK,
5160 DDSCAPS_SYSTEMMEMORY, 0},
5163 ddraw = create_ddraw();
5164 ok(!!ddraw, "Failed to create a ddraw object.\n");
5165 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5166 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5168 memset(&hal_caps, 0, sizeof(hal_caps));
5169 hal_caps.dwSize = sizeof(hal_caps);
5170 memset(&hel_caps, 0, sizeof(hel_caps));
5171 hel_caps.dwSize = sizeof(hel_caps);
5172 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, &hel_caps);
5173 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
5174 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps)
5176 skip("Managed textures not supported, skipping managed texture test.\n");
5177 IDirectDraw7_Release(ddraw);
5178 return;
5181 for (i = 0; i < ARRAY_SIZE(tests); ++i)
5183 memset(&ddsd, 0, sizeof(ddsd));
5184 ddsd.dwSize = sizeof(ddsd);
5185 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
5186 ddsd.ddsCaps.dwCaps = tests[i].caps_in;
5187 ddsd.ddsCaps.dwCaps2 = tests[i].caps2_in;
5188 ddsd.dwWidth = 4;
5189 ddsd.dwHeight = 4;
5191 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5192 if (tests[i].hr == DD_OK && is_ddraw64 && (tests[i].caps_in & DDSCAPS_TEXTURE))
5193 todo_wine ok(hr == E_NOINTERFACE, "Test %u: Got unexpected hr %#x.\n", i, hr);
5194 else
5195 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, tests[i].hr);
5196 if (FAILED(hr))
5197 continue;
5199 memset(&ddsd, 0, sizeof(ddsd));
5200 ddsd.dwSize = sizeof(ddsd);
5201 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
5202 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5204 ok(ddsd.ddsCaps.dwCaps == tests[i].caps_out,
5205 "Input caps %#x, %#x, expected output caps %#x, got %#x, case %u.\n",
5206 tests[i].caps_in, tests[i].caps2_in, tests[i].caps_out, ddsd.ddsCaps.dwCaps, i);
5207 ok(ddsd.ddsCaps.dwCaps2 == tests[i].caps2_out,
5208 "Input caps %#x, %#x, expected output caps %#x, got %#x, case %u.\n",
5209 tests[i].caps_in, tests[i].caps2_in, tests[i].caps2_out, ddsd.ddsCaps.dwCaps2, i);
5211 IDirectDrawSurface7_Release(surface);
5214 IDirectDraw7_Release(ddraw);
5217 #define SUPPORT_DXT1 0x01
5218 #define SUPPORT_DXT2 0x02
5219 #define SUPPORT_DXT3 0x04
5220 #define SUPPORT_DXT4 0x08
5221 #define SUPPORT_DXT5 0x10
5222 #define SUPPORT_YUY2 0x20
5223 #define SUPPORT_UYVY 0x40
5225 static HRESULT WINAPI test_block_formats_creation_cb(DDPIXELFORMAT *fmt, void *ctx)
5227 DWORD *supported_fmts = ctx;
5229 if (!(fmt->dwFlags & DDPF_FOURCC))
5230 return DDENUMRET_OK;
5232 switch (fmt->dwFourCC)
5234 case MAKEFOURCC('D','X','T','1'):
5235 *supported_fmts |= SUPPORT_DXT1;
5236 break;
5237 case MAKEFOURCC('D','X','T','2'):
5238 *supported_fmts |= SUPPORT_DXT2;
5239 break;
5240 case MAKEFOURCC('D','X','T','3'):
5241 *supported_fmts |= SUPPORT_DXT3;
5242 break;
5243 case MAKEFOURCC('D','X','T','4'):
5244 *supported_fmts |= SUPPORT_DXT4;
5245 break;
5246 case MAKEFOURCC('D','X','T','5'):
5247 *supported_fmts |= SUPPORT_DXT5;
5248 break;
5249 case MAKEFOURCC('Y','U','Y','2'):
5250 *supported_fmts |= SUPPORT_YUY2;
5251 break;
5252 case MAKEFOURCC('U','Y','V','Y'):
5253 *supported_fmts |= SUPPORT_UYVY;
5254 break;
5255 default:
5256 break;
5259 return DDENUMRET_OK;
5262 static void test_block_formats_creation(void)
5264 HRESULT hr, expect_hr;
5265 unsigned int i, j, w, h;
5266 HWND window;
5267 IDirectDraw7 *ddraw;
5268 IDirect3D7 *d3d;
5269 IDirect3DDevice7 *device;
5270 IDirectDrawSurface7 *surface;
5271 DWORD supported_fmts = 0, supported_overlay_fmts = 0;
5272 DWORD num_fourcc_codes = 0, *fourcc_codes;
5273 DDSURFACEDESC2 ddsd;
5274 DDCAPS hal_caps;
5275 void *mem;
5277 static const struct
5279 DWORD fourcc;
5280 const char *name;
5281 DWORD support_flag;
5282 unsigned int block_width;
5283 unsigned int block_height;
5284 unsigned int block_size;
5285 BOOL create_size_checked, overlay;
5287 formats[] =
5289 {MAKEFOURCC('D','X','T','1'), "D3DFMT_DXT1", SUPPORT_DXT1, 4, 4, 8, TRUE, FALSE},
5290 {MAKEFOURCC('D','X','T','2'), "D3DFMT_DXT2", SUPPORT_DXT2, 4, 4, 16, TRUE, FALSE},
5291 {MAKEFOURCC('D','X','T','3'), "D3DFMT_DXT3", SUPPORT_DXT3, 4, 4, 16, TRUE, FALSE},
5292 {MAKEFOURCC('D','X','T','4'), "D3DFMT_DXT4", SUPPORT_DXT4, 4, 4, 16, TRUE, FALSE},
5293 {MAKEFOURCC('D','X','T','5'), "D3DFMT_DXT5", SUPPORT_DXT5, 4, 4, 16, TRUE, FALSE},
5294 {MAKEFOURCC('Y','U','Y','2'), "D3DFMT_YUY2", SUPPORT_YUY2, 2, 1, 4, FALSE, TRUE },
5295 {MAKEFOURCC('U','Y','V','Y'), "D3DFMT_UYVY", SUPPORT_UYVY, 2, 1, 4, FALSE, TRUE },
5297 static const struct
5299 DWORD caps, caps2;
5300 const char *name;
5301 BOOL overlay;
5303 types[] =
5305 /* DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY fails to create any fourcc
5306 * surface with DDERR_INVALIDPIXELFORMAT. Don't care about it for now.
5308 * Nvidia returns E_FAIL on DXTN DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY.
5309 * Other hw / drivers successfully create those surfaces. Ignore them, this
5310 * suggests that no game uses this, otherwise Nvidia would support it. */
5312 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0,
5313 "videomemory texture", FALSE
5316 DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY, 0,
5317 "videomemory overlay", TRUE
5320 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0,
5321 "systemmemory texture", FALSE
5324 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
5325 "managed texture", FALSE
5328 enum size_type
5330 SIZE_TYPE_ZERO,
5331 SIZE_TYPE_PITCH,
5332 SIZE_TYPE_SIZE,
5334 static const struct
5336 DWORD flags;
5337 enum size_type size_type;
5338 int rel_size;
5339 HRESULT hr;
5341 user_mem_tests[] =
5343 {DDSD_LINEARSIZE, SIZE_TYPE_ZERO, 0, DD_OK},
5344 {DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
5345 {DDSD_PITCH, SIZE_TYPE_ZERO, 0, DD_OK},
5346 {DDSD_PITCH, SIZE_TYPE_PITCH, 0, DD_OK},
5347 {DDSD_LPSURFACE, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
5348 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
5349 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_PITCH, 0, DDERR_INVALIDPARAMS},
5350 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
5351 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 1, DD_OK},
5352 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, -1, DDERR_INVALIDPARAMS},
5353 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
5354 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_PITCH, 0, DDERR_INVALIDPARAMS},
5355 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_SIZE, 0, DDERR_INVALIDPARAMS},
5356 {DDSD_LPSURFACE | DDSD_PITCH | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DDERR_INVALIDPARAMS},
5359 window = create_window();
5360 if (!(device = create_device(window, DDSCL_NORMAL)))
5362 skip("Failed to create a 3D device, skipping test.\n");
5363 DestroyWindow(window);
5364 return;
5367 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
5368 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
5369 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **) &ddraw);
5370 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
5371 IDirect3D7_Release(d3d);
5373 hr = IDirect3DDevice7_EnumTextureFormats(device, test_block_formats_creation_cb,
5374 &supported_fmts);
5375 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
5377 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
5378 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
5379 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5380 num_fourcc_codes * sizeof(*fourcc_codes));
5381 if (!fourcc_codes)
5382 goto cleanup;
5383 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
5384 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
5385 for (i = 0; i < num_fourcc_codes; i++)
5387 for (j = 0; j < ARRAY_SIZE(formats); ++j)
5389 if (fourcc_codes[i] == formats[j].fourcc)
5390 supported_overlay_fmts |= formats[j].support_flag;
5393 HeapFree(GetProcessHeap(), 0, fourcc_codes);
5395 memset(&hal_caps, 0, sizeof(hal_caps));
5396 hal_caps.dwSize = sizeof(hal_caps);
5397 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
5398 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
5400 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 2 * 2 * 16 + 1);
5402 for (i = 0; i < ARRAY_SIZE(formats); ++i)
5404 for (j = 0; j < ARRAY_SIZE(types); ++j)
5406 BOOL support;
5408 if (formats[i].overlay != types[j].overlay
5409 || (types[j].overlay && !(hal_caps.dwCaps & DDCAPS_OVERLAY)))
5410 continue;
5412 if (formats[i].overlay)
5413 support = supported_overlay_fmts & formats[i].support_flag;
5414 else
5415 support = supported_fmts & formats[i].support_flag;
5417 for (w = 1; w <= 8; w++)
5419 for (h = 1; h <= 8; h++)
5421 BOOL block_aligned = TRUE;
5422 BOOL todo = FALSE;
5424 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
5425 block_aligned = FALSE;
5427 memset(&ddsd, 0, sizeof(ddsd));
5428 ddsd.dwSize = sizeof(ddsd);
5429 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
5430 ddsd.ddsCaps.dwCaps = types[j].caps;
5431 ddsd.ddsCaps.dwCaps2 = types[j].caps2;
5432 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
5433 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
5434 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
5435 ddsd.dwWidth = w;
5436 ddsd.dwHeight = h;
5438 /* TODO: Handle power of two limitations. I cannot test the pow2
5439 * behavior on windows because I have no hardware that doesn't at
5440 * least support np2_conditional. There's probably no HW that
5441 * supports DXTN textures but no conditional np2 textures. */
5442 if (!support && !(types[j].caps & DDSCAPS_SYSTEMMEMORY))
5443 expect_hr = DDERR_INVALIDPARAMS;
5444 else if (formats[i].create_size_checked && !block_aligned)
5446 expect_hr = DDERR_INVALIDPARAMS;
5447 if (!(types[j].caps & DDSCAPS_TEXTURE))
5448 todo = TRUE;
5450 else
5451 expect_hr = D3D_OK;
5453 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5454 todo_wine_if (todo)
5455 ok(hr == expect_hr,
5456 "Got unexpected hr %#x for format %s, resource type %s, size %ux%u, expected %#x.\n",
5457 hr, formats[i].name, types[j].name, w, h, expect_hr);
5459 if (SUCCEEDED(hr))
5460 IDirectDrawSurface7_Release(surface);
5465 if (formats[i].overlay)
5466 continue;
5468 for (j = 0; j < ARRAY_SIZE(user_mem_tests); ++j)
5470 memset(&ddsd, 0, sizeof(ddsd));
5471 ddsd.dwSize = sizeof(ddsd);
5472 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | user_mem_tests[j].flags;
5473 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE;
5475 switch (user_mem_tests[j].size_type)
5477 case SIZE_TYPE_ZERO:
5478 U1(ddsd).dwLinearSize = 0;
5479 break;
5481 case SIZE_TYPE_PITCH:
5482 U1(ddsd).dwLinearSize = 2 * formats[i].block_size;
5483 break;
5485 case SIZE_TYPE_SIZE:
5486 U1(ddsd).dwLinearSize = 2 * 2 * formats[i].block_size;
5487 break;
5489 U1(ddsd).dwLinearSize += user_mem_tests[j].rel_size;
5491 ddsd.lpSurface = mem;
5492 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
5493 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
5494 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
5495 ddsd.dwWidth = 8;
5496 ddsd.dwHeight = 8;
5498 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5499 ok(hr == user_mem_tests[j].hr, "Test %u: Got unexpected hr %#x, format %s.\n", j, hr, formats[i].name);
5501 if (FAILED(hr))
5502 continue;
5504 memset(&ddsd, 0, sizeof(ddsd));
5505 ddsd.dwSize = sizeof(ddsd);
5506 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
5507 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", j, hr);
5508 ok(ddsd.dwFlags == (DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_LINEARSIZE),
5509 "Test %u: Got unexpected flags %#x.\n", j, ddsd.dwFlags);
5510 if (user_mem_tests[j].flags & DDSD_LPSURFACE)
5511 ok(U1(ddsd).dwLinearSize == ~0u, "Test %u: Got unexpected linear size %#x.\n",
5512 j, U1(ddsd).dwLinearSize);
5513 else
5514 ok(U1(ddsd).dwLinearSize == 2 * 2 * formats[i].block_size,
5515 "Test %u: Got unexpected linear size %#x, expected %#x.\n",
5516 j, U1(ddsd).dwLinearSize, 2 * 2 * formats[i].block_size);
5517 IDirectDrawSurface7_Release(surface);
5521 HeapFree(GetProcessHeap(), 0, mem);
5522 cleanup:
5523 IDirectDraw7_Release(ddraw);
5524 IDirect3DDevice7_Release(device);
5525 DestroyWindow(window);
5528 struct format_support_check
5530 const DDPIXELFORMAT *format;
5531 BOOL supported;
5534 static HRESULT WINAPI test_unsupported_formats_cb(DDPIXELFORMAT *fmt, void *ctx)
5536 struct format_support_check *format = ctx;
5538 if (!memcmp(format->format, fmt, sizeof(*fmt)))
5540 format->supported = TRUE;
5541 return DDENUMRET_CANCEL;
5544 return DDENUMRET_OK;
5547 static void test_unsupported_formats(void)
5549 HRESULT hr;
5550 BOOL expect_success;
5551 HWND window;
5552 IDirectDraw7 *ddraw;
5553 IDirect3D7 *d3d;
5554 IDirect3DDevice7 *device;
5555 IDirectDrawSurface7 *surface;
5556 DDSURFACEDESC2 ddsd;
5557 unsigned int i, j;
5558 DWORD expected_caps;
5559 static const struct
5561 const char *name;
5562 DDPIXELFORMAT fmt;
5564 formats[] =
5567 "D3DFMT_A8R8G8B8",
5569 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
5570 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
5574 "D3DFMT_P8",
5576 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
5577 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
5581 static const DWORD caps[] = {0, DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY};
5583 window = create_window();
5584 if (!(device = create_device(window, DDSCL_NORMAL)))
5586 skip("Failed to create a 3D device, skipping test.\n");
5587 DestroyWindow(window);
5588 return;
5591 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
5592 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
5593 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **) &ddraw);
5594 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
5595 IDirect3D7_Release(d3d);
5597 for (i = 0; i < ARRAY_SIZE(formats); ++i)
5599 struct format_support_check check = {&formats[i].fmt, FALSE};
5600 hr = IDirect3DDevice7_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
5601 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
5603 for (j = 0; j < ARRAY_SIZE(caps); ++j)
5605 memset(&ddsd, 0, sizeof(ddsd));
5606 ddsd.dwSize = sizeof(ddsd);
5607 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
5608 U4(ddsd).ddpfPixelFormat = formats[i].fmt;
5609 ddsd.dwWidth = 4;
5610 ddsd.dwHeight = 4;
5611 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | caps[j];
5613 if (caps[j] & DDSCAPS_VIDEOMEMORY && !check.supported)
5614 expect_success = FALSE;
5615 else
5616 expect_success = TRUE;
5618 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5619 ok(SUCCEEDED(hr) == expect_success,
5620 "Got unexpected hr %#x for format %s, caps %#x, expected %s.\n",
5621 hr, formats[i].name, caps[j], expect_success ? "success" : "failure");
5622 if (FAILED(hr))
5623 continue;
5625 memset(&ddsd, 0, sizeof(ddsd));
5626 ddsd.dwSize = sizeof(ddsd);
5627 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
5628 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5630 if (caps[j] & DDSCAPS_VIDEOMEMORY)
5631 expected_caps = DDSCAPS_VIDEOMEMORY;
5632 else if (caps[j] & DDSCAPS_SYSTEMMEMORY)
5633 expected_caps = DDSCAPS_SYSTEMMEMORY;
5634 else if (check.supported)
5635 expected_caps = DDSCAPS_VIDEOMEMORY;
5636 else
5637 expected_caps = DDSCAPS_SYSTEMMEMORY;
5639 ok(ddsd.ddsCaps.dwCaps & expected_caps,
5640 "Expected capability %#x, format %s, input cap %#x.\n",
5641 expected_caps, formats[i].name, caps[j]);
5643 IDirectDrawSurface7_Release(surface);
5647 IDirectDraw7_Release(ddraw);
5648 IDirect3DDevice7_Release(device);
5649 DestroyWindow(window);
5652 static void test_rt_caps(void)
5654 const GUID *devtype = &IID_IDirect3DHALDevice;
5655 PALETTEENTRY palette_entries[256];
5656 IDirectDrawPalette *palette;
5657 IDirectDraw7 *ddraw;
5658 BOOL hal_ok = FALSE;
5659 DDPIXELFORMAT z_fmt;
5660 IDirect3D7 *d3d;
5661 unsigned int i;
5662 ULONG refcount;
5663 HWND window;
5664 HRESULT hr;
5666 static const DDPIXELFORMAT p8_fmt =
5668 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
5669 {8}, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000},
5672 const struct
5674 const DDPIXELFORMAT *pf;
5675 DWORD caps_in;
5676 DWORD caps_out;
5677 HRESULT create_device_hr;
5678 HRESULT set_rt_hr, alternative_set_rt_hr;
5680 test_data[] =
5683 NULL,
5684 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
5685 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5686 D3D_OK,
5687 D3D_OK,
5688 D3D_OK,
5691 NULL,
5692 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5693 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5694 D3D_OK,
5695 D3D_OK,
5696 D3D_OK,
5699 NULL,
5700 DDSCAPS_OFFSCREENPLAIN,
5701 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5702 DDERR_INVALIDCAPS,
5703 DDERR_INVALIDCAPS,
5704 DDERR_INVALIDCAPS,
5707 NULL,
5708 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5709 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5710 D3DERR_SURFACENOTINVIDMEM,
5711 DDERR_INVALIDPARAMS,
5712 D3D_OK,
5715 NULL,
5716 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5717 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5718 DDERR_INVALIDCAPS,
5719 DDERR_INVALIDCAPS,
5720 DDERR_INVALIDCAPS,
5723 NULL,
5724 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
5725 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5726 D3D_OK,
5727 D3D_OK,
5728 D3D_OK,
5731 NULL,
5732 DDSCAPS_3DDEVICE,
5733 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5734 D3D_OK,
5735 D3D_OK,
5736 D3D_OK,
5739 NULL,
5741 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5742 DDERR_INVALIDCAPS,
5743 DDERR_INVALIDCAPS,
5744 DDERR_INVALIDCAPS,
5747 NULL,
5748 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5749 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5750 D3DERR_SURFACENOTINVIDMEM,
5751 DDERR_INVALIDPARAMS,
5752 D3D_OK,
5755 NULL,
5756 DDSCAPS_SYSTEMMEMORY,
5757 DDSCAPS_SYSTEMMEMORY,
5758 DDERR_INVALIDCAPS,
5759 DDERR_INVALIDCAPS,
5760 DDERR_INVALIDCAPS,
5763 &p8_fmt,
5765 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5766 DDERR_INVALIDCAPS,
5767 DDERR_INVALIDCAPS,
5768 DDERR_INVALIDCAPS,
5771 &p8_fmt,
5772 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5773 ~0U /* AMD r200 */,
5774 DDERR_NOPALETTEATTACHED,
5775 DDERR_INVALIDCAPS,
5776 DDERR_INVALIDCAPS,
5779 &p8_fmt,
5780 DDSCAPS_OFFSCREENPLAIN,
5781 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5782 DDERR_INVALIDCAPS,
5783 DDERR_INVALIDCAPS,
5784 DDERR_INVALIDCAPS,
5787 &p8_fmt,
5788 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5789 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5790 DDERR_NOPALETTEATTACHED,
5791 DDERR_INVALIDCAPS,
5792 DDERR_INVALIDCAPS,
5795 &p8_fmt,
5796 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5797 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5798 DDERR_INVALIDCAPS,
5799 DDERR_INVALIDCAPS,
5800 DDERR_INVALIDCAPS,
5803 &z_fmt,
5804 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
5805 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5806 DDERR_INVALIDCAPS,
5807 DDERR_INVALIDPIXELFORMAT,
5808 DDERR_INVALIDPIXELFORMAT,
5811 &z_fmt,
5812 DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5813 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5814 DDERR_INVALIDCAPS,
5815 DDERR_INVALIDPIXELFORMAT,
5816 DDERR_INVALIDPIXELFORMAT,
5819 &z_fmt,
5820 DDSCAPS_ZBUFFER,
5821 DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5822 DDERR_INVALIDCAPS,
5823 DDERR_INVALIDCAPS,
5824 DDERR_INVALIDCAPS,
5827 &z_fmt,
5828 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5829 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5830 DDERR_INVALIDCAPS,
5831 DDERR_INVALIDPARAMS,
5832 DDERR_INVALIDPIXELFORMAT,
5835 &z_fmt,
5836 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
5837 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
5838 DDERR_INVALIDCAPS,
5839 DDERR_INVALIDCAPS,
5840 DDERR_INVALIDCAPS,
5844 window = create_window();
5845 ddraw = create_ddraw();
5846 ok(!!ddraw, "Failed to create a ddraw object.\n");
5847 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5848 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5850 if (FAILED(IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d)))
5852 skip("D3D interface is not available, skipping test.\n");
5853 goto done;
5856 hr = IDirect3D7_EnumDevices(d3d, enum_devtype_cb, &hal_ok);
5857 ok(SUCCEEDED(hr), "Failed to enumerate devices, hr %#x.\n", hr);
5858 if (hal_ok)
5859 devtype = &IID_IDirect3DTnLHalDevice;
5861 memset(&z_fmt, 0, sizeof(z_fmt));
5862 hr = IDirect3D7_EnumZBufferFormats(d3d, devtype, enum_z_fmt, &z_fmt);
5863 if (FAILED(hr) || !z_fmt.dwSize)
5865 skip("No depth buffer formats available, skipping test.\n");
5866 IDirect3D7_Release(d3d);
5867 goto done;
5870 memset(palette_entries, 0, sizeof(palette_entries));
5871 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
5872 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
5874 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
5876 IDirectDrawSurface7 *surface, *rt, *expected_rt, *tmp;
5877 DDSURFACEDESC2 surface_desc;
5878 IDirect3DDevice7 *device;
5880 memset(&surface_desc, 0, sizeof(surface_desc));
5881 surface_desc.dwSize = sizeof(surface_desc);
5882 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5883 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5884 if (test_data[i].pf)
5886 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
5887 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
5889 surface_desc.dwWidth = 640;
5890 surface_desc.dwHeight = 480;
5891 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5892 ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
5893 i, test_data[i].caps_in, hr);
5895 memset(&surface_desc, 0, sizeof(surface_desc));
5896 surface_desc.dwSize = sizeof(surface_desc);
5897 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
5898 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
5899 ok(test_data[i].caps_out == ~0U || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out,
5900 "Test %u: Got unexpected caps %#x, expected %#x.\n",
5901 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
5903 hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
5904 ok(hr == test_data[i].create_device_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n",
5905 i, hr, test_data[i].create_device_hr);
5906 if (FAILED(hr))
5908 if (hr == DDERR_NOPALETTEATTACHED)
5910 hr = IDirectDrawSurface7_SetPalette(surface, palette);
5911 ok(SUCCEEDED(hr), "Test %u: Failed to set palette, hr %#x.\n", i, hr);
5912 hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
5913 if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
5914 ok(hr == DDERR_INVALIDPIXELFORMAT, "Test %u: Got unexpected hr %#x.\n", i, hr);
5915 else
5916 ok(hr == D3DERR_SURFACENOTINVIDMEM, "Test %u: Got unexpected hr %#x.\n", i, hr);
5918 IDirectDrawSurface7_Release(surface);
5920 memset(&surface_desc, 0, sizeof(surface_desc));
5921 surface_desc.dwSize = sizeof(surface_desc);
5922 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5923 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
5924 surface_desc.dwWidth = 640;
5925 surface_desc.dwHeight = 480;
5926 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5927 ok(SUCCEEDED(hr), "Test %u: Failed to create surface, hr %#x.\n", i, hr);
5929 hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
5930 ok(SUCCEEDED(hr), "Test %u: Failed to create device, hr %#x.\n", i, hr);
5933 memset(&surface_desc, 0, sizeof(surface_desc));
5934 surface_desc.dwSize = sizeof(surface_desc);
5935 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5936 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5937 if (test_data[i].pf)
5939 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
5940 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
5942 surface_desc.dwWidth = 640;
5943 surface_desc.dwHeight = 480;
5944 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &rt, NULL);
5945 ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
5946 i, test_data[i].caps_in, hr);
5948 hr = IDirect3DDevice7_SetRenderTarget(device, rt, 0);
5949 ok(hr == test_data[i].set_rt_hr || broken(hr == test_data[i].alternative_set_rt_hr),
5950 "Test %u: Got unexpected hr %#x, expected %#x.\n",
5951 i, hr, test_data[i].set_rt_hr);
5952 if (SUCCEEDED(hr) || hr == DDERR_INVALIDPIXELFORMAT)
5953 expected_rt = rt;
5954 else
5955 expected_rt = surface;
5957 hr = IDirect3DDevice7_GetRenderTarget(device, &tmp);
5958 ok(SUCCEEDED(hr), "Test %u: Failed to get render target, hr %#x.\n", i, hr);
5959 ok(tmp == expected_rt, "Test %u: Got unexpected rt %p.\n", i, tmp);
5961 IDirectDrawSurface7_Release(tmp);
5962 IDirectDrawSurface7_Release(rt);
5963 refcount = IDirect3DDevice7_Release(device);
5964 ok(refcount == 0, "Test %u: The device was not properly freed, refcount %u.\n", i, refcount);
5965 refcount = IDirectDrawSurface7_Release(surface);
5966 ok(refcount == 0, "Test %u: The surface was not properly freed, refcount %u.\n", i, refcount);
5969 IDirectDrawPalette_Release(palette);
5970 IDirect3D7_Release(d3d);
5972 done:
5973 refcount = IDirectDraw7_Release(ddraw);
5974 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
5975 DestroyWindow(window);
5978 static void test_primary_caps(void)
5980 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
5981 IDirectDrawSurface7 *surface;
5982 DDSURFACEDESC2 surface_desc;
5983 IDirectDraw7 *ddraw;
5984 unsigned int i;
5985 ULONG refcount;
5986 HWND window;
5987 HRESULT hr;
5989 static const struct
5991 DWORD coop_level;
5992 DWORD caps_in;
5993 DWORD back_buffer_count;
5994 HRESULT hr;
5995 DWORD caps_out;
5997 test_data[] =
6000 DDSCL_NORMAL,
6001 DDSCAPS_PRIMARYSURFACE,
6002 ~0u,
6003 DD_OK,
6004 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE,
6007 DDSCL_NORMAL,
6008 DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE,
6009 ~0u,
6010 DDERR_INVALIDCAPS,
6011 ~0u,
6014 DDSCL_NORMAL,
6015 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
6016 ~0u,
6017 DDERR_INVALIDCAPS,
6018 ~0u,
6021 DDSCL_NORMAL,
6022 DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER,
6023 ~0u,
6024 DDERR_INVALIDCAPS,
6025 ~0u,
6028 DDSCL_NORMAL,
6029 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP,
6030 ~0u,
6031 DDERR_INVALIDCAPS,
6032 ~0u,
6035 DDSCL_NORMAL,
6036 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX,
6037 ~0u,
6038 DDERR_INVALIDCAPS,
6039 ~0u,
6042 DDSCL_NORMAL,
6043 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
6044 ~0u,
6045 DDERR_INVALIDCAPS,
6046 ~0u,
6049 DDSCL_NORMAL,
6050 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
6052 DDERR_INVALIDCAPS,
6053 ~0u,
6056 DDSCL_NORMAL,
6057 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
6059 DDERR_NOEXCLUSIVEMODE,
6060 ~0u,
6063 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
6064 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
6066 DDERR_INVALIDCAPS,
6067 ~0u,
6070 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
6071 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
6073 DD_OK,
6074 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX,
6077 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
6078 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER,
6080 DDERR_INVALIDCAPS,
6081 ~0u,
6084 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
6085 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_BACKBUFFER,
6087 DDERR_INVALIDCAPS,
6088 ~0u,
6092 window = create_window();
6093 ddraw = create_ddraw();
6094 ok(!!ddraw, "Failed to create a ddraw object.\n");
6096 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
6098 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, test_data[i].coop_level);
6099 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6101 memset(&surface_desc, 0, sizeof(surface_desc));
6102 surface_desc.dwSize = sizeof(surface_desc);
6103 surface_desc.dwFlags = DDSD_CAPS;
6104 if (test_data[i].back_buffer_count != ~0u)
6105 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
6106 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
6107 U5(surface_desc).dwBackBufferCount = test_data[i].back_buffer_count;
6108 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6109 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
6110 if (FAILED(hr))
6111 continue;
6113 memset(&surface_desc, 0, sizeof(surface_desc));
6114 surface_desc.dwSize = sizeof(surface_desc);
6115 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
6116 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
6117 ok((surface_desc.ddsCaps.dwCaps & ~placement) == test_data[i].caps_out,
6118 "Test %u: Got unexpected caps %#x, expected %#x.\n",
6119 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
6121 IDirectDrawSurface7_Release(surface);
6124 refcount = IDirectDraw7_Release(ddraw);
6125 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
6126 DestroyWindow(window);
6129 static void test_surface_lock(void)
6131 IDirectDraw7 *ddraw;
6132 IDirect3D7 *d3d = NULL;
6133 IDirectDrawSurface7 *surface;
6134 IDirect3DDevice7 *device;
6135 HRESULT hr, expected_hr;
6136 HWND window;
6137 unsigned int i;
6138 DDSURFACEDESC2 ddsd;
6139 ULONG refcount;
6140 DDPIXELFORMAT z_fmt;
6141 BOOL hal_ok = FALSE;
6142 const GUID *devtype = &IID_IDirect3DHALDevice;
6143 D3DDEVICEDESC7 device_desc;
6144 BOOL cubemap_supported;
6145 static const struct
6147 DWORD caps;
6148 DWORD caps2;
6149 const char *name;
6151 tests[] =
6154 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
6156 "videomemory offscreenplain"
6159 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
6161 "systemmemory offscreenplain"
6164 DDSCAPS_PRIMARYSURFACE,
6166 "primary"
6169 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
6171 "videomemory texture"
6174 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
6175 DDSCAPS2_OPAQUE,
6176 "opaque videomemory texture"
6179 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
6181 "systemmemory texture"
6184 DDSCAPS_TEXTURE,
6185 DDSCAPS2_TEXTUREMANAGE,
6186 "managed texture"
6189 DDSCAPS_TEXTURE,
6190 DDSCAPS2_D3DTEXTUREMANAGE,
6191 "managed texture"
6194 DDSCAPS_TEXTURE,
6195 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_OPAQUE,
6196 "opaque managed texture"
6199 DDSCAPS_TEXTURE,
6200 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_OPAQUE,
6201 "opaque managed texture"
6204 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
6206 "render target"
6209 DDSCAPS_ZBUFFER,
6211 "Z buffer"
6214 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY,
6215 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
6216 "videomemory cube"
6219 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY,
6220 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_OPAQUE,
6221 "opaque videomemory cube"
6224 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_SYSTEMMEMORY,
6225 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
6226 "systemmemory cube"
6229 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
6230 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
6231 "managed cube"
6234 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
6235 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
6236 "managed cube"
6239 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
6240 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_OPAQUE,
6241 "opaque managed cube"
6244 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
6245 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_OPAQUE,
6246 "opaque managed cube"
6250 window = create_window();
6251 ddraw = create_ddraw();
6252 ok(!!ddraw, "Failed to create a ddraw object.\n");
6253 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6254 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6256 if (FAILED(IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d)))
6258 skip("D3D interface is not available, skipping test.\n");
6259 goto done;
6262 hr = IDirect3D7_EnumDevices(d3d, enum_devtype_cb, &hal_ok);
6263 ok(SUCCEEDED(hr), "Failed to enumerate devices, hr %#x.\n", hr);
6264 if (hal_ok)
6265 devtype = &IID_IDirect3DTnLHalDevice;
6267 memset(&z_fmt, 0, sizeof(z_fmt));
6268 hr = IDirect3D7_EnumZBufferFormats(d3d, devtype, enum_z_fmt, &z_fmt);
6269 if (FAILED(hr) || !z_fmt.dwSize)
6271 skip("No depth buffer formats available, skipping test.\n");
6272 goto done;
6275 memset(&ddsd, 0, sizeof(ddsd));
6276 ddsd.dwSize = sizeof(ddsd);
6277 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6278 ddsd.dwWidth = 64;
6279 ddsd.dwHeight = 64;
6280 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
6281 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6282 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6284 hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
6285 ok(SUCCEEDED(hr), "Failed to create device, hr %#x.\n", hr);
6286 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
6287 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6288 cubemap_supported = !!(device_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP);
6289 IDirect3DDevice7_Release(device);
6291 IDirectDrawSurface7_Release(surface);
6293 for (i = 0; i < ARRAY_SIZE(tests); ++i)
6295 if (!cubemap_supported && tests[i].caps2 & DDSCAPS2_CUBEMAP)
6296 continue;
6298 memset(&ddsd, 0, sizeof(ddsd));
6299 ddsd.dwSize = sizeof(ddsd);
6300 ddsd.dwFlags = DDSD_CAPS;
6301 if (!(tests[i].caps & DDSCAPS_PRIMARYSURFACE))
6303 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
6304 ddsd.dwWidth = 64;
6305 ddsd.dwHeight = 64;
6307 if (tests[i].caps & DDSCAPS_ZBUFFER)
6309 ddsd.dwFlags |= DDSD_PIXELFORMAT;
6310 U4(ddsd).ddpfPixelFormat = z_fmt;
6312 ddsd.ddsCaps.dwCaps = tests[i].caps;
6313 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
6315 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6316 ok(SUCCEEDED(hr), "Failed to create surface, type %s, hr %#x.\n", tests[i].name, hr);
6318 memset(&ddsd, 0, sizeof(ddsd));
6319 ddsd.dwSize = sizeof(ddsd);
6320 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
6321 ok(SUCCEEDED(hr), "Failed to lock surface, type %s, hr %#x.\n", tests[i].name, hr);
6322 if (SUCCEEDED(hr))
6324 ok(ddsd.dwSize == sizeof(ddsd), "Got unexpected dwSize %u, type %s.\n", ddsd.dwSize, tests[i].name);
6325 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6326 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
6329 memset(&ddsd, 0, sizeof(ddsd));
6330 expected_hr = tests[i].caps & DDSCAPS_TEXTURE && !(tests[i].caps & DDSCAPS_VIDEOMEMORY)
6331 ? DD_OK : DDERR_INVALIDPARAMS;
6332 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
6333 ok(hr == expected_hr, "Got hr %#x, expected %#x, type %s.\n", hr, expected_hr, tests[i].name);
6334 if (SUCCEEDED(hr))
6336 ok(!ddsd.dwSize, "Got unexpected dwSize %u, type %s.\n", ddsd.dwSize, tests[i].name);
6337 ok(!!ddsd.lpSurface, "Got NULL lpSurface, type %s.\n", tests[i].name);
6338 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6339 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
6342 IDirectDrawSurface7_Release(surface);
6345 done:
6346 if (d3d)
6347 IDirect3D7_Release(d3d);
6348 refcount = IDirectDraw7_Release(ddraw);
6349 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
6350 DestroyWindow(window);
6353 static void test_surface_discard(void)
6355 IDirect3DDevice7 *device;
6356 IDirect3D7 *d3d;
6357 IDirectDraw7 *ddraw;
6358 HRESULT hr;
6359 HWND window;
6360 DDSURFACEDESC2 ddsd;
6361 IDirectDrawSurface7 *surface, *target;
6362 void *addr;
6363 static const struct
6365 DWORD caps, caps2;
6366 BOOL discard;
6368 tests[] =
6370 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, TRUE},
6371 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
6372 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, TRUE},
6373 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
6374 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE},
6375 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
6376 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE},
6377 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
6379 unsigned int i;
6381 window = create_window();
6382 if (!(device = create_device(window, DDSCL_NORMAL)))
6384 skip("Failed to create a 3D device, skipping test.\n");
6385 DestroyWindow(window);
6386 return;
6388 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
6389 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
6390 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
6391 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
6392 hr = IDirect3DDevice7_GetRenderTarget(device, &target);
6393 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
6395 for (i = 0; i < ARRAY_SIZE(tests); ++i)
6397 BOOL discarded;
6399 memset(&ddsd, 0, sizeof(ddsd));
6400 ddsd.dwSize = sizeof(ddsd);
6401 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6402 ddsd.ddsCaps.dwCaps = tests[i].caps;
6403 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
6404 ddsd.dwWidth = 64;
6405 ddsd.dwHeight = 64;
6406 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6407 ok(SUCCEEDED(hr), "Failed to create offscreen surface, hr %#x, case %u.\n", hr, i);
6409 memset(&ddsd, 0, sizeof(ddsd));
6410 ddsd.dwSize = sizeof(ddsd);
6411 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, 0, NULL);
6412 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6413 addr = ddsd.lpSurface;
6414 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6415 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6417 memset(&ddsd, 0, sizeof(ddsd));
6418 ddsd.dwSize = sizeof(ddsd);
6419 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
6420 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6421 discarded = ddsd.lpSurface != addr;
6422 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6423 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6425 hr = IDirectDrawSurface7_Blt(target, NULL, surface, NULL, DDBLT_WAIT, NULL);
6426 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
6428 memset(&ddsd, 0, sizeof(ddsd));
6429 ddsd.dwSize = sizeof(ddsd);
6430 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
6431 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6432 discarded |= ddsd.lpSurface != addr;
6433 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6434 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6436 IDirectDrawSurface7_Release(surface);
6438 /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler,
6439 * AMD r500, evergreen). Windows XP, at least on AMD r200, does not. */
6440 ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i);
6443 IDirectDrawSurface7_Release(target);
6444 IDirectDraw7_Release(ddraw);
6445 IDirect3D7_Release(d3d);
6446 IDirect3DDevice7_Release(device);
6447 DestroyWindow(window);
6450 static void fill_surface(IDirectDrawSurface7 *surface, D3DCOLOR color)
6452 DDSURFACEDESC2 surface_desc = {sizeof(surface_desc)};
6453 HRESULT hr;
6454 unsigned int x, y;
6455 DWORD *ptr;
6457 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
6458 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6460 for (y = 0; y < surface_desc.dwHeight; ++y)
6462 ptr = (DWORD *)((BYTE *)surface_desc.lpSurface + y * U1(surface_desc).lPitch);
6463 for (x = 0; x < surface_desc.dwWidth; ++x)
6465 ptr[x] = color;
6469 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6470 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6473 static void test_flip(void)
6475 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
6476 IDirectDrawSurface7 *frontbuffer, *backbuffer1, *backbuffer2, *backbuffer3, *surface;
6477 DDSCAPS2 caps = {DDSCAPS_FLIP, 0, 0, {0}};
6478 DDSURFACEDESC2 surface_desc;
6479 D3DDEVICEDESC7 device_desc;
6480 IDirect3DDevice7 *device;
6481 BOOL sysmem_primary;
6482 IDirectDraw7 *ddraw;
6483 DWORD expected_caps;
6484 unsigned int i;
6485 D3DCOLOR color;
6486 ULONG refcount;
6487 HWND window;
6488 HRESULT hr;
6490 static const struct
6492 const char *name;
6493 DWORD caps;
6495 test_data[] =
6497 {"PRIMARYSURFACE", DDSCAPS_PRIMARYSURFACE},
6498 {"OFFSCREENPLAIN", DDSCAPS_OFFSCREENPLAIN},
6499 {"TEXTURE", DDSCAPS_TEXTURE},
6502 window = create_window();
6503 ddraw = create_ddraw();
6504 ok(!!ddraw, "Failed to create a ddraw object.\n");
6506 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6507 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6509 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
6511 /* Creating a flippable texture induces a BSoD on some versions of the
6512 * Intel graphics driver. At least Intel GMA 950 with driver version
6513 * 6.14.10.4926 on Windows XP SP3 is affected. */
6514 if ((test_data[i].caps & DDSCAPS_TEXTURE) && ddraw_is_intel(ddraw))
6516 win_skip("Skipping flippable texture test.\n");
6517 continue;
6520 memset(&surface_desc, 0, sizeof(surface_desc));
6521 surface_desc.dwSize = sizeof(surface_desc);
6522 surface_desc.dwFlags = DDSD_CAPS;
6523 if (!(test_data[i].caps & DDSCAPS_PRIMARYSURFACE))
6524 surface_desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
6525 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
6526 surface_desc.dwWidth = 512;
6527 surface_desc.dwHeight = 512;
6528 U5(surface_desc).dwBackBufferCount = 3;
6529 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6530 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6532 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_FLIP;
6533 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
6534 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6535 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6537 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_COMPLEX;
6538 surface_desc.ddsCaps.dwCaps |= DDSCAPS_FLIP;
6539 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6540 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6542 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
6543 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6544 if (is_ddraw64 && test_data[i].caps & DDSCAPS_TEXTURE)
6545 todo_wine ok(hr == E_NOINTERFACE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6546 else todo_wine_if(test_data[i].caps & DDSCAPS_TEXTURE)
6547 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
6548 if (FAILED(hr))
6549 continue;
6551 memset(&surface_desc, 0, sizeof(surface_desc));
6552 surface_desc.dwSize = sizeof(surface_desc);
6553 hr = IDirectDrawSurface7_GetSurfaceDesc(frontbuffer, &surface_desc);
6554 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6555 expected_caps = DDSCAPS_FRONTBUFFER | DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
6556 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
6557 expected_caps |= DDSCAPS_VISIBLE;
6558 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6559 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6560 sysmem_primary = surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
6562 hr = IDirectDrawSurface7_GetAttachedSurface(frontbuffer, &caps, &backbuffer1);
6563 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6564 memset(&surface_desc, 0, sizeof(surface_desc));
6565 surface_desc.dwSize = sizeof(surface_desc);
6566 hr = IDirectDrawSurface7_GetSurfaceDesc(backbuffer1, &surface_desc);
6567 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6568 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
6569 test_data[i].name, U5(surface_desc).dwBackBufferCount);
6570 expected_caps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER);
6571 expected_caps |= DDSCAPS_BACKBUFFER;
6572 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6573 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6575 hr = IDirectDrawSurface7_GetAttachedSurface(backbuffer1, &caps, &backbuffer2);
6576 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6577 memset(&surface_desc, 0, sizeof(surface_desc));
6578 surface_desc.dwSize = sizeof(surface_desc);
6579 hr = IDirectDrawSurface7_GetSurfaceDesc(backbuffer2, &surface_desc);
6580 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6581 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
6582 test_data[i].name, U5(surface_desc).dwBackBufferCount);
6583 expected_caps &= ~DDSCAPS_BACKBUFFER;
6584 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6585 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6587 hr = IDirectDrawSurface7_GetAttachedSurface(backbuffer2, &caps, &backbuffer3);
6588 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6589 memset(&surface_desc, 0, sizeof(surface_desc));
6590 surface_desc.dwSize = sizeof(surface_desc);
6591 hr = IDirectDrawSurface7_GetSurfaceDesc(backbuffer3, &surface_desc);
6592 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6593 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
6594 test_data[i].name, U5(surface_desc).dwBackBufferCount);
6595 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6596 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6598 hr = IDirectDrawSurface7_GetAttachedSurface(backbuffer3, &caps, &surface);
6599 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6600 ok(surface == frontbuffer, "%s: Got unexpected surface %p, expected %p.\n",
6601 test_data[i].name, surface, frontbuffer);
6602 IDirectDrawSurface7_Release(surface);
6604 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
6605 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
6606 hr = IDirectDrawSurface7_IsLost(frontbuffer);
6607 ok(hr == DD_OK, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6608 hr = IDirectDrawSurface7_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6609 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
6610 ok(hr == DDERR_NOEXCLUSIVEMODE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6611 else
6612 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6613 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6614 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
6615 hr = IDirectDrawSurface7_IsLost(frontbuffer);
6616 todo_wine ok(hr == DDERR_SURFACELOST, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6617 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
6618 ok(SUCCEEDED(hr), "%s: Failed to restore surfaces, hr %#x.\n", test_data[i].name, hr);
6620 memset(&surface_desc, 0, sizeof(surface_desc));
6621 surface_desc.dwSize = sizeof(surface_desc);
6622 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6623 surface_desc.ddsCaps.dwCaps = 0;
6624 surface_desc.dwWidth = 640;
6625 surface_desc.dwHeight = 480;
6626 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6627 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
6628 hr = IDirectDrawSurface7_Flip(frontbuffer, surface, DDFLIP_WAIT);
6629 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6630 IDirectDrawSurface7_Release(surface);
6632 hr = IDirectDrawSurface7_Flip(frontbuffer, frontbuffer, DDFLIP_WAIT);
6633 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6634 hr = IDirectDrawSurface7_Flip(backbuffer1, NULL, DDFLIP_WAIT);
6635 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6636 hr = IDirectDrawSurface7_Flip(backbuffer2, NULL, DDFLIP_WAIT);
6637 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6638 hr = IDirectDrawSurface7_Flip(backbuffer3, NULL, DDFLIP_WAIT);
6639 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6641 /* The Nvidia Geforce 7 driver cannot do a color fill on a texture backbuffer after
6642 * the backbuffer has been locked. Do it ourselves as a workaround. Unlike ddraw1
6643 * and 2 GetSurfaceDesc does not cause issues in ddraw4 and ddraw7. */
6644 fill_surface(backbuffer1, 0xffff0000);
6645 fill_surface(backbuffer2, 0xff00ff00);
6646 fill_surface(backbuffer3, 0xff0000ff);
6648 hr = IDirectDrawSurface7_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6649 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6650 color = get_surface_color(backbuffer1, 320, 240);
6651 /* The testbot seems to just copy the contents of one surface to all the
6652 * others, instead of properly flipping. */
6653 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
6654 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6655 color = get_surface_color(backbuffer2, 320, 240);
6656 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6657 fill_surface(backbuffer3, 0xffff0000);
6659 hr = IDirectDrawSurface7_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6660 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6661 color = get_surface_color(backbuffer1, 320, 240);
6662 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
6663 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6664 color = get_surface_color(backbuffer2, 320, 240);
6665 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6666 fill_surface(backbuffer3, 0xff00ff00);
6668 hr = IDirectDrawSurface7_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6669 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6670 color = get_surface_color(backbuffer1, 320, 240);
6671 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
6672 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6673 color = get_surface_color(backbuffer2, 320, 240);
6674 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6675 fill_surface(backbuffer3, 0xff0000ff);
6677 hr = IDirectDrawSurface7_Flip(frontbuffer, backbuffer1, DDFLIP_WAIT);
6678 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6679 color = get_surface_color(backbuffer2, 320, 240);
6680 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
6681 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6682 color = get_surface_color(backbuffer3, 320, 240);
6683 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6684 fill_surface(backbuffer1, 0xffff0000);
6686 hr = IDirectDrawSurface7_Flip(frontbuffer, backbuffer2, DDFLIP_WAIT);
6687 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6688 color = get_surface_color(backbuffer1, 320, 240);
6689 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6690 color = get_surface_color(backbuffer3, 320, 240);
6691 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
6692 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6693 fill_surface(backbuffer2, 0xff00ff00);
6695 hr = IDirectDrawSurface7_Flip(frontbuffer, backbuffer3, DDFLIP_WAIT);
6696 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6697 color = get_surface_color(backbuffer1, 320, 240);
6698 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
6699 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6700 color = get_surface_color(backbuffer2, 320, 240);
6701 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6703 IDirectDrawSurface7_Release(backbuffer3);
6704 IDirectDrawSurface7_Release(backbuffer2);
6705 IDirectDrawSurface7_Release(backbuffer1);
6706 IDirectDrawSurface7_Release(frontbuffer);
6709 if (!(device = create_device(window, DDSCL_NORMAL)))
6711 skip("Failed to create 3D device.\n");
6712 goto done;
6714 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
6715 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6716 IDirect3DDevice7_Release(device);
6717 if (!(device_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP))
6719 skip("Cubemaps are not supported.\n");
6720 goto done;
6723 memset(&surface_desc, 0, sizeof(surface_desc));
6724 surface_desc.dwSize = sizeof(surface_desc);
6725 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6726 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_TEXTURE;
6727 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
6728 surface_desc.dwWidth = 128;
6729 surface_desc.dwHeight = 128;
6730 U5(surface_desc).dwBackBufferCount = 3;
6731 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6732 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x.\n", hr);
6734 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_FLIP;
6735 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
6736 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6737 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6739 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_COMPLEX;
6740 surface_desc.ddsCaps.dwCaps |= DDSCAPS_FLIP;
6741 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6742 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x.\n", hr);
6744 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
6745 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6746 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6748 U5(surface_desc).dwBackBufferCount = 1;
6749 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6750 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6752 U5(surface_desc).dwBackBufferCount = 0;
6753 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6754 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x.\n", hr);
6756 done:
6757 refcount = IDirectDraw7_Release(ddraw);
6758 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
6759 DestroyWindow(window);
6762 static void reset_ddsd(DDSURFACEDESC2 *ddsd)
6764 memset(ddsd, 0, sizeof(*ddsd));
6765 ddsd->dwSize = sizeof(*ddsd);
6768 static void test_set_surface_desc(void)
6770 IDirectDraw7 *ddraw;
6771 HWND window;
6772 HRESULT hr;
6773 DDSURFACEDESC2 ddsd;
6774 IDirectDrawSurface7 *surface;
6775 BYTE data[16*16*4];
6776 ULONG ref;
6777 unsigned int i;
6778 static const struct
6780 DWORD caps, caps2;
6781 BOOL supported;
6782 const char *name;
6784 invalid_caps_tests[] =
6786 {DDSCAPS_VIDEOMEMORY, 0, FALSE, "videomemory plain"},
6787 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, TRUE, "systemmemory texture"},
6788 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE, "managed texture"},
6789 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE, "managed texture"},
6790 {DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY, 0, FALSE, "systemmemory primary"},
6793 window = create_window();
6794 ddraw = create_ddraw();
6795 ok(!!ddraw, "Failed to create a ddraw object.\n");
6796 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6797 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6799 reset_ddsd(&ddsd);
6800 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
6801 ddsd.dwWidth = 8;
6802 ddsd.dwHeight = 8;
6803 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6804 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6805 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6806 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6807 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6808 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6809 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6811 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6812 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6814 reset_ddsd(&ddsd);
6815 ddsd.dwFlags = DDSD_LPSURFACE;
6816 ddsd.lpSurface = data;
6817 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6818 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6820 /* Redundantly setting the same lpSurface is not an error. */
6821 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6822 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6824 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6825 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6826 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
6827 ok(ddsd.lpSurface == NULL, "lpSurface is %p, expected NULL.\n", ddsd.lpSurface);
6829 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, 0, NULL);
6830 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6831 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
6832 ok(ddsd.lpSurface == data, "lpSurface is %p, expected %p.\n", data, data);
6833 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6834 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6836 reset_ddsd(&ddsd);
6837 ddsd.dwFlags = DDSD_LPSURFACE;
6838 ddsd.lpSurface = data;
6839 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 1);
6840 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with flags=1 returned %#x.\n", hr);
6842 ddsd.lpSurface = NULL;
6843 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6844 ok(hr == DDERR_INVALIDPARAMS, "Setting lpSurface=NULL returned %#x.\n", hr);
6846 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, NULL, 0);
6847 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with NULL desc returned %#x.\n", hr);
6849 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6850 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6851 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
6852 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
6853 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#x.\n", 0);
6855 /* Setting the caps is an error. This also means the original description cannot be reapplied. */
6856 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6857 ok(hr == DDERR_INVALIDPARAMS, "Setting the original desc returned %#x.\n", hr);
6859 ddsd.dwFlags = DDSD_CAPS;
6860 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6861 ok(hr == DDERR_INVALIDPARAMS, "Setting DDSD_CAPS returned %#x.\n", hr);
6863 /* dwCaps = 0 is allowed, but ignored. Caps2 can be anything and is ignored too. */
6864 ddsd.dwFlags = DDSD_CAPS | DDSD_LPSURFACE;
6865 ddsd.lpSurface = data;
6866 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6867 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
6868 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6869 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6870 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
6871 ddsd.ddsCaps.dwCaps = 0;
6872 ddsd.ddsCaps.dwCaps2 = 0xdeadbeef;
6873 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6874 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6876 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6877 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6878 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
6879 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
6880 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#x.\n", 0);
6882 /* Setting the height is allowed, but it cannot be set to 0, and only if LPSURFACE is set too. */
6883 reset_ddsd(&ddsd);
6884 ddsd.dwFlags = DDSD_HEIGHT;
6885 ddsd.dwHeight = 16;
6886 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6887 ok(hr == DDERR_INVALIDPARAMS, "Setting height without lpSurface returned %#x.\n", hr);
6889 ddsd.lpSurface = data;
6890 ddsd.dwFlags = DDSD_HEIGHT | DDSD_LPSURFACE;
6891 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6892 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6894 ddsd.dwHeight = 0;
6895 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6896 ok(hr == DDERR_INVALIDPARAMS, "Setting height=0 returned %#x.\n", hr);
6898 reset_ddsd(&ddsd);
6899 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6900 ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr);
6901 ok(ddsd.dwWidth == 8, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
6902 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
6904 /* Pitch and width can be set, but only together, and only with LPSURFACE. They must not be 0. */
6905 reset_ddsd(&ddsd);
6906 ddsd.dwFlags = DDSD_PITCH;
6907 U1(ddsd).lPitch = 8 * 4;
6908 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6909 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch without lpSurface or width returned %#x.\n", hr);
6911 ddsd.dwFlags = DDSD_WIDTH;
6912 ddsd.dwWidth = 16;
6913 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6914 ok(hr == DDERR_INVALIDPARAMS, "Setting width without lpSurface or pitch returned %#x.\n", hr);
6916 ddsd.dwFlags = DDSD_PITCH | DDSD_LPSURFACE;
6917 ddsd.lpSurface = data;
6918 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6919 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch and lpSurface without width returned %#x.\n", hr);
6921 ddsd.dwFlags = DDSD_WIDTH | DDSD_LPSURFACE;
6922 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6923 ok(hr == DDERR_INVALIDPARAMS, "Setting width and lpSurface without pitch returned %#x.\n", hr);
6925 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6926 U1(ddsd).lPitch = 16 * 4;
6927 ddsd.dwWidth = 16;
6928 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6929 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6931 reset_ddsd(&ddsd);
6932 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6933 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6934 ok(ddsd.dwWidth == 16, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
6935 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
6936 ok(U1(ddsd).lPitch == 16 * 4, "SetSurfaceDesc: Expected pitch 64, got %u.\n", U1(ddsd).lPitch);
6938 /* The pitch must be 32 bit aligned and > 0, but is not verified for sanity otherwise.
6940 * VMware rejects those calls, but all real drivers accept it. Mark the VMware behavior broken. */
6941 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6942 U1(ddsd).lPitch = 4 * 4;
6943 ddsd.lpSurface = data;
6944 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6945 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
6947 U1(ddsd).lPitch = 4;
6948 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6949 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
6951 U1(ddsd).lPitch = 16 * 4 + 1;
6952 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6953 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
6955 U1(ddsd).lPitch = 16 * 4 + 3;
6956 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6957 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
6959 U1(ddsd).lPitch = -4;
6960 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6961 ok(hr == DDERR_INVALIDPARAMS, "Setting negative pitch returned %#x.\n", hr);
6963 U1(ddsd).lPitch = 16 * 4;
6964 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6965 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6967 reset_ddsd(&ddsd);
6968 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6969 U1(ddsd).lPitch = 0;
6970 ddsd.dwWidth = 16;
6971 ddsd.lpSurface = data;
6972 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6973 ok(hr == DDERR_INVALIDPARAMS, "Setting zero pitch returned %#x.\n", hr);
6975 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
6976 U1(ddsd).lPitch = 16 * 4;
6977 ddsd.dwWidth = 0;
6978 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6979 ok(hr == DDERR_INVALIDPARAMS, "Setting zero width returned %#x.\n", hr);
6981 /* Setting the pixelformat without LPSURFACE is an error, but with LPSURFACE it works. */
6982 ddsd.dwFlags = DDSD_PIXELFORMAT;
6983 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6984 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6985 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6986 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6987 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6988 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6989 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6990 ok(hr == DDERR_INVALIDPARAMS, "Setting the pixel format returned %#x.\n", hr);
6992 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_LPSURFACE;
6993 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6994 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6996 /* Can't set color keys. */
6997 reset_ddsd(&ddsd);
6998 ddsd.dwFlags = DDSD_CKSRCBLT;
6999 ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff0000;
7000 ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff0000;
7001 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7002 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
7004 ddsd.dwFlags = DDSD_CKSRCBLT | DDSD_LPSURFACE;
7005 ddsd.lpSurface = data;
7006 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7007 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
7009 IDirectDrawSurface7_Release(surface);
7011 /* SetSurfaceDesc needs systemmemory surfaces.
7013 * As a sidenote, fourcc surfaces aren't allowed in sysmem, thus testing
7014 * DDSD_LINEARSIZE is moot. */
7015 for (i = 0; i < ARRAY_SIZE(invalid_caps_tests); ++i)
7017 reset_ddsd(&ddsd);
7018 ddsd.dwFlags = DDSD_CAPS;
7019 ddsd.ddsCaps.dwCaps = invalid_caps_tests[i].caps;
7020 ddsd.ddsCaps.dwCaps2 = invalid_caps_tests[i].caps2;
7021 if (!(invalid_caps_tests[i].caps & DDSCAPS_PRIMARYSURFACE))
7023 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7024 ddsd.dwWidth = 8;
7025 ddsd.dwHeight = 8;
7026 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
7027 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
7028 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
7029 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7030 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7031 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7034 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
7035 if (is_ddraw64 && (invalid_caps_tests[i].caps & DDSCAPS_TEXTURE))
7036 todo_wine ok(hr == E_NOINTERFACE, "Test %u: Got unexpected hr %#x.\n", i, hr);
7037 else
7038 ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWHW, "Test %u: Got unexpected hr %#x.\n", i, hr);
7039 if (FAILED(hr))
7040 continue;
7042 reset_ddsd(&ddsd);
7043 ddsd.dwFlags = DDSD_LPSURFACE;
7044 ddsd.lpSurface = data;
7045 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7046 if (invalid_caps_tests[i].supported)
7048 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7050 else
7052 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
7053 invalid_caps_tests[i].name, hr);
7055 /* Check priority of error conditions. */
7056 ddsd.dwFlags = DDSD_WIDTH;
7057 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7058 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
7059 invalid_caps_tests[i].name, hr);
7062 IDirectDrawSurface7_Release(surface);
7065 ref = IDirectDraw7_Release(ddraw);
7066 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
7067 DestroyWindow(window);
7070 static void test_user_memory_getdc(void)
7072 IDirectDraw7 *ddraw;
7073 HWND window;
7074 HRESULT hr;
7075 DDSURFACEDESC2 ddsd;
7076 IDirectDrawSurface7 *surface;
7077 DWORD data[16][16];
7078 HGDIOBJ *bitmap;
7079 DIBSECTION dib;
7080 ULONG ref;
7081 int size;
7082 HDC dc;
7083 unsigned int x, y;
7085 window = create_window();
7086 ddraw = create_ddraw();
7087 ok(!!ddraw, "Failed to create a ddraw object.\n");
7088 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7089 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7091 reset_ddsd(&ddsd);
7092 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
7093 ddsd.dwWidth = 16;
7094 ddsd.dwHeight = 16;
7095 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
7096 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
7097 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
7098 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7099 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7100 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7101 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
7102 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
7103 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7105 memset(data, 0xaa, sizeof(data));
7106 reset_ddsd(&ddsd);
7107 ddsd.dwFlags = DDSD_LPSURFACE;
7108 ddsd.lpSurface = data;
7109 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7110 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7112 hr = IDirectDrawSurface7_GetDC(surface, &dc);
7113 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7114 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
7115 ok(!!bitmap, "Failed to get bitmap.\n");
7116 size = GetObjectA(bitmap, sizeof(dib), &dib);
7117 ok(size == sizeof(dib), "Got unexpected size %d.\n", size);
7118 ok(dib.dsBm.bmBits == data, "Got unexpected bits %p, expected %p.\n", dib.dsBm.bmBits, data);
7119 BitBlt(dc, 0, 0, 16, 8, NULL, 0, 0, WHITENESS);
7120 BitBlt(dc, 0, 8, 16, 8, NULL, 0, 0, BLACKNESS);
7121 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
7122 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7124 ok(data[0][0] == 0xffffffff, "Expected color 0xffffffff, got %#x.\n", data[0][0]);
7125 ok(data[15][15] == 0x00000000, "Expected color 0x00000000, got %#x.\n", data[15][15]);
7127 ddsd.dwFlags = DDSD_LPSURFACE | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH;
7128 ddsd.lpSurface = data;
7129 ddsd.dwWidth = 4;
7130 ddsd.dwHeight = 8;
7131 U1(ddsd).lPitch = sizeof(*data);
7132 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7133 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7135 memset(data, 0xaa, sizeof(data));
7136 hr = IDirectDrawSurface7_GetDC(surface, &dc);
7137 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7138 BitBlt(dc, 0, 0, 4, 8, NULL, 0, 0, BLACKNESS);
7139 BitBlt(dc, 1, 1, 2, 2, NULL, 0, 0, WHITENESS);
7140 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
7141 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7143 for (y = 0; y < 4; y++)
7145 for (x = 0; x < 4; x++)
7147 if ((x == 1 || x == 2) && (y == 1 || y == 2))
7148 ok(data[y][x] == 0xffffffff, "Expected color 0xffffffff on position %ux%u, got %#x.\n",
7149 x, y, data[y][x]);
7150 else
7151 ok(data[y][x] == 0x00000000, "Expected color 0x00000000 on position %ux%u, got %#x.\n",
7152 x, y, data[y][x]);
7155 ok(data[0][5] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 5x0, got %#x.\n",
7156 data[0][5]);
7157 ok(data[7][3] == 0x00000000, "Expected color 0x00000000 on position 3x7, got %#x.\n",
7158 data[7][3]);
7159 ok(data[7][4] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 4x7, got %#x.\n",
7160 data[7][4]);
7161 ok(data[8][0] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 0x8, got %#x.\n",
7162 data[8][0]);
7164 IDirectDrawSurface7_Release(surface);
7165 ref = IDirectDraw7_Release(ddraw);
7166 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
7167 DestroyWindow(window);
7170 static void test_sysmem_overlay(void)
7172 IDirectDraw7 *ddraw;
7173 HWND window;
7174 HRESULT hr;
7175 DDSURFACEDESC2 ddsd;
7176 IDirectDrawSurface7 *surface;
7177 ULONG ref;
7179 window = create_window();
7180 ddraw = create_ddraw();
7181 ok(!!ddraw, "Failed to create a ddraw object.\n");
7182 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7183 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7185 reset_ddsd(&ddsd);
7186 ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
7187 ddsd.dwWidth = 16;
7188 ddsd.dwHeight = 16;
7189 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OVERLAY;
7190 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
7191 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
7192 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
7193 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7194 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7195 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7196 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
7197 ok(hr == DDERR_NOOVERLAYHW, "Got unexpected hr %#x.\n", hr);
7199 ref = IDirectDraw7_Release(ddraw);
7200 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
7201 DestroyWindow(window);
7204 static void test_primary_palette(void)
7206 DDSCAPS2 surface_caps = {DDSCAPS_FLIP, 0, 0, {0}};
7207 IDirectDrawSurface7 *primary, *backbuffer;
7208 PALETTEENTRY palette_entries[256];
7209 IDirectDrawPalette *palette, *tmp;
7210 DDSURFACEDESC2 surface_desc;
7211 IDirectDraw7 *ddraw;
7212 DWORD palette_caps;
7213 ULONG refcount;
7214 HWND window;
7215 HRESULT hr;
7217 window = create_window();
7218 ddraw = create_ddraw();
7219 ok(!!ddraw, "Failed to create a ddraw object.\n");
7220 if (FAILED(IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
7222 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
7223 IDirectDraw7_Release(ddraw);
7224 DestroyWindow(window);
7225 return;
7227 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7228 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7230 memset(&surface_desc, 0, sizeof(surface_desc));
7231 surface_desc.dwSize = sizeof(surface_desc);
7232 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
7233 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
7234 U5(surface_desc).dwBackBufferCount = 1;
7235 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
7236 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7237 hr = IDirectDrawSurface7_GetAttachedSurface(primary, &surface_caps, &backbuffer);
7238 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
7240 memset(palette_entries, 0, sizeof(palette_entries));
7241 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_entries, &palette, NULL);
7242 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7243 refcount = get_refcount((IUnknown *)palette);
7244 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7246 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
7247 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
7248 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
7250 hr = IDirectDrawSurface7_SetPalette(primary, palette);
7251 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7253 /* The Windows 8 testbot attaches the palette to the backbuffer as well,
7254 * and is generally somewhat broken with respect to 8 bpp / palette
7255 * handling. */
7256 if (SUCCEEDED(IDirectDrawSurface7_GetPalette(backbuffer, &tmp)))
7258 win_skip("Broken palette handling detected, skipping tests.\n");
7259 IDirectDrawPalette_Release(tmp);
7260 IDirectDrawPalette_Release(palette);
7261 /* The Windows 8 testbot keeps extra references to the primary and
7262 * backbuffer while in 8 bpp mode. */
7263 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
7264 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
7265 goto done;
7268 refcount = get_refcount((IUnknown *)palette);
7269 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
7271 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
7272 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
7273 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE | DDPCAPS_ALLOW256),
7274 "Got unexpected palette caps %#x.\n", palette_caps);
7276 hr = IDirectDrawSurface7_SetPalette(primary, NULL);
7277 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7278 refcount = get_refcount((IUnknown *)palette);
7279 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7281 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
7282 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
7283 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
7285 hr = IDirectDrawSurface7_SetPalette(primary, palette);
7286 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7287 refcount = get_refcount((IUnknown *)palette);
7288 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
7290 hr = IDirectDrawSurface7_GetPalette(primary, &tmp);
7291 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
7292 ok(tmp == palette, "Got unexpected palette %p, expected %p.\n", tmp, palette);
7293 IDirectDrawPalette_Release(tmp);
7294 hr = IDirectDrawSurface7_GetPalette(backbuffer, &tmp);
7295 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
7297 refcount = IDirectDrawPalette_Release(palette);
7298 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7299 refcount = IDirectDrawPalette_Release(palette);
7300 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7302 /* Note that this only seems to work when the palette is attached to the
7303 * primary surface. When attached to a regular surface, attempting to get
7304 * the palette here will cause an access violation. */
7305 hr = IDirectDrawSurface7_GetPalette(primary, &tmp);
7306 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
7308 hr = IDirectDrawSurface7_IsLost(primary);
7309 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7311 memset(&surface_desc, 0, sizeof(surface_desc));
7312 surface_desc.dwSize = sizeof(surface_desc);
7313 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &surface_desc);
7314 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7315 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
7316 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
7317 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 8, "Got unexpected bit count %u.\n",
7318 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
7320 hr = set_display_mode(ddraw, 640, 480);
7321 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
7323 memset(&surface_desc, 0, sizeof(surface_desc));
7324 surface_desc.dwSize = sizeof(surface_desc);
7325 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &surface_desc);
7326 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7327 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
7328 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
7329 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 32
7330 || U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 24,
7331 "Got unexpected bit count %u.\n", U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
7333 hr = IDirectDrawSurface7_IsLost(primary);
7334 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7335 hr = IDirectDrawSurface7_Restore(primary);
7336 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
7337 hr = IDirectDrawSurface7_IsLost(primary);
7338 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7340 memset(&surface_desc, 0, sizeof(surface_desc));
7341 surface_desc.dwSize = sizeof(surface_desc);
7342 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &surface_desc);
7343 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7344 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
7345 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
7346 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 32
7347 || U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 24,
7348 "Got unexpected bit count %u.\n", U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
7350 done:
7351 refcount = IDirectDrawSurface7_Release(backbuffer);
7352 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7353 refcount = IDirectDrawSurface7_Release(primary);
7354 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7355 refcount = IDirectDraw7_Release(ddraw);
7356 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7357 DestroyWindow(window);
7360 static HRESULT WINAPI surface_counter(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
7362 UINT *surface_count = context;
7364 ++(*surface_count);
7365 IDirectDrawSurface_Release(surface);
7367 return DDENUMRET_OK;
7370 static void test_surface_attachment(void)
7372 IDirectDrawSurface7 *surface1, *surface2, *surface3, *surface4;
7373 IDirectDrawSurface *surface1v1, *surface2v1;
7374 DDSCAPS2 caps = {DDSCAPS_TEXTURE, 0, 0, {0}};
7375 DDSURFACEDESC2 surface_desc;
7376 IDirectDraw7 *ddraw;
7377 UINT surface_count;
7378 ULONG refcount;
7379 HWND window;
7380 HRESULT hr;
7382 window = create_window();
7383 ddraw = create_ddraw();
7384 ok(!!ddraw, "Failed to create a ddraw object.\n");
7385 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7386 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
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 | DDSD_MIPMAPCOUNT;
7391 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7392 U2(surface_desc).dwMipMapCount = 3;
7393 surface_desc.dwWidth = 128;
7394 surface_desc.dwHeight = 128;
7395 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL)))
7397 skip("Failed to create a texture, skipping tests.\n");
7398 IDirectDraw7_Release(ddraw);
7399 DestroyWindow(window);
7400 return;
7403 hr = IDirectDrawSurface7_GetAttachedSurface(surface1, &caps, &surface2);
7404 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
7405 hr = IDirectDrawSurface7_GetAttachedSurface(surface2, &caps, &surface3);
7406 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
7407 hr = IDirectDrawSurface7_GetAttachedSurface(surface3, &caps, &surface4);
7408 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7410 surface_count = 0;
7411 IDirectDrawSurface7_EnumAttachedSurfaces(surface1, &surface_count, surface_counter);
7412 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
7413 surface_count = 0;
7414 IDirectDrawSurface7_EnumAttachedSurfaces(surface2, &surface_count, surface_counter);
7415 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
7416 surface_count = 0;
7417 IDirectDrawSurface7_EnumAttachedSurfaces(surface3, &surface_count, surface_counter);
7418 ok(!surface_count, "Got unexpected surface_count %u.\n", surface_count);
7420 memset(&surface_desc, 0, sizeof(surface_desc));
7421 surface_desc.dwSize = sizeof(surface_desc);
7422 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7423 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
7424 surface_desc.dwWidth = 16;
7425 surface_desc.dwHeight = 16;
7426 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
7427 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7429 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
7430 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7431 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
7432 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7433 hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface4);
7434 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7435 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface3);
7436 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7437 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface4);
7438 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7439 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface2);
7440 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7442 IDirectDrawSurface7_Release(surface4);
7444 memset(&surface_desc, 0, sizeof(surface_desc));
7445 surface_desc.dwSize = sizeof(surface_desc);
7446 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7447 surface_desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
7448 surface_desc.dwWidth = 16;
7449 surface_desc.dwHeight = 16;
7450 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
7451 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7453 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
7454 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7455 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
7456 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7457 hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface4);
7458 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7459 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface3);
7460 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7461 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface4);
7462 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7463 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface2);
7464 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7466 IDirectDrawSurface7_Release(surface4);
7467 IDirectDrawSurface7_Release(surface3);
7468 IDirectDrawSurface7_Release(surface2);
7469 IDirectDrawSurface7_Release(surface1);
7471 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7472 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7474 /* Try a single primary and two offscreen plain surfaces. */
7475 memset(&surface_desc, 0, sizeof(surface_desc));
7476 surface_desc.dwSize = sizeof(surface_desc);
7477 surface_desc.dwFlags = DDSD_CAPS;
7478 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7479 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7480 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7482 memset(&surface_desc, 0, sizeof(surface_desc));
7483 surface_desc.dwSize = sizeof(surface_desc);
7484 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7485 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7486 surface_desc.dwWidth = registry_mode.dmPelsWidth;
7487 surface_desc.dwHeight = registry_mode.dmPelsHeight;
7488 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
7489 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7491 memset(&surface_desc, 0, sizeof(surface_desc));
7492 surface_desc.dwSize = sizeof(surface_desc);
7493 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7494 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7495 surface_desc.dwWidth = registry_mode.dmPelsWidth;
7496 surface_desc.dwHeight = registry_mode.dmPelsHeight;
7497 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
7498 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7500 /* This one has a different size. */
7501 memset(&surface_desc, 0, sizeof(surface_desc));
7502 surface_desc.dwSize = sizeof(surface_desc);
7503 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7504 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7505 surface_desc.dwWidth = 128;
7506 surface_desc.dwHeight = 128;
7507 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
7508 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7510 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
7511 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7512 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface1);
7513 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7514 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface3);
7515 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7516 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
7517 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7518 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
7519 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7521 IDirectDrawSurface7_Release(surface4);
7522 IDirectDrawSurface7_Release(surface3);
7523 IDirectDrawSurface7_Release(surface2);
7524 IDirectDrawSurface7_Release(surface1);
7526 /* Test depth surfaces of different sizes. */
7527 memset(&surface_desc, 0, sizeof(surface_desc));
7528 surface_desc.dwSize = sizeof(surface_desc);
7529 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7530 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
7531 surface_desc.dwWidth = 64;
7532 surface_desc.dwHeight = 64;
7533 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7534 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
7536 memset(&surface_desc, 0, sizeof(surface_desc));
7537 surface_desc.dwSize = sizeof(surface_desc);
7538 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
7539 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
7540 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7541 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
7542 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = 16;
7543 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = 0x0000ffff;
7544 surface_desc.dwWidth = 32;
7545 surface_desc.dwHeight = 32;
7546 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
7547 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
7548 surface_desc.dwWidth = 64;
7549 surface_desc.dwHeight = 64;
7550 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
7551 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
7552 surface_desc.dwWidth = 128;
7553 surface_desc.dwHeight = 128;
7554 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
7555 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
7557 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
7558 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7559 if (SUCCEEDED(hr))
7560 IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface2);
7561 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface3);
7562 ok(hr == D3D_OK, "Failed to attach depth buffer, hr %#x.\n", hr);
7563 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface3);
7564 ok(hr == D3D_OK, "Failed to detach depth buffer, hr %#x.\n", hr);
7565 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
7566 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7568 IDirectDrawSurface7_Release(surface4);
7569 IDirectDrawSurface7_Release(surface3);
7570 IDirectDrawSurface7_Release(surface2);
7571 IDirectDrawSurface7_Release(surface1);
7573 /* Test DeleteAttachedSurface() and automatic detachment of attached surfaces on release. */
7574 memset(&surface_desc, 0, sizeof(surface_desc));
7575 surface_desc.dwSize = sizeof(surface_desc);
7576 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7577 surface_desc.dwWidth = 64;
7578 surface_desc.dwHeight = 64;
7579 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
7580 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7581 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
7582 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
7583 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
7584 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
7585 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
7586 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7587 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7588 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
7589 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7591 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
7592 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
7593 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = 16;
7594 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = 0x0000ffff;
7595 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
7596 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7598 hr = IDirectDrawSurface7_QueryInterface(surface1, &IID_IDirectDrawSurface, (void **)&surface1v1);
7599 ok(SUCCEEDED(hr), "Failed to get interface, hr %#x.\n", hr);
7600 hr = IDirectDrawSurface7_QueryInterface(surface2, &IID_IDirectDrawSurface, (void **)&surface2v1);
7601 ok(SUCCEEDED(hr), "Failed to get interface, hr %#x.\n", hr);
7603 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
7604 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7605 refcount = get_refcount((IUnknown *)surface2);
7606 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
7607 refcount = get_refcount((IUnknown *)surface2v1);
7608 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7609 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
7610 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
7611 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
7612 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7613 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
7614 ok(hr == DDERR_SURFACENOTATTACHED, "Got unexpected hr %#x.\n", hr);
7616 /* Attaching while already attached to other surface. */
7617 hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface2);
7618 todo_wine ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7619 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface3, 0, surface2);
7620 todo_wine ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7621 IDirectDrawSurface7_Release(surface3);
7623 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface2);
7624 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7625 refcount = get_refcount((IUnknown *)surface2);
7626 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7627 refcount = get_refcount((IUnknown *)surface2v1);
7628 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7630 /* DeleteAttachedSurface() when attaching via IDirectDrawSurface. */
7631 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
7632 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7633 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface2);
7634 ok(hr == DDERR_SURFACENOTATTACHED, "Got unexpected hr %#x.\n", hr);
7635 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
7636 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7637 refcount = IDirectDrawSurface7_Release(surface2);
7638 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7639 refcount = IDirectDrawSurface7_Release(surface1);
7640 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7642 /* Automatic detachment on release. */
7643 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
7644 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7645 refcount = get_refcount((IUnknown *)surface2v1);
7646 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
7647 refcount = IDirectDrawSurface_Release(surface1v1);
7648 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7649 refcount = IDirectDrawSurface_Release(surface2v1);
7650 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7651 refcount = IDirectDraw7_Release(ddraw);
7652 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7653 DestroyWindow(window);
7656 static void test_private_data(void)
7658 IDirectDraw7 *ddraw;
7659 IDirectDrawSurface7 *surface, *surface2;
7660 DDSURFACEDESC2 surface_desc;
7661 ULONG refcount, refcount2, refcount3;
7662 IUnknown *ptr;
7663 DWORD size = sizeof(ptr);
7664 HRESULT hr;
7665 HWND window;
7666 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
7667 DWORD data[] = {1, 2, 3, 4};
7668 DDCAPS hal_caps;
7669 static const GUID ddraw_private_data_test_guid =
7671 0xfdb37466,
7672 0x428f,
7673 0x4edf,
7674 {0xa3,0x7f,0x9b,0x1d,0xf4,0x88,0xc5,0xfc}
7676 static const GUID ddraw_private_data_test_guid2 =
7678 0x2e5afac2,
7679 0x87b5,
7680 0x4c10,
7681 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
7684 window = create_window();
7685 ddraw = create_ddraw();
7686 ok(!!ddraw, "Failed to create a ddraw object.\n");
7687 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7688 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7690 reset_ddsd(&surface_desc);
7691 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
7692 surface_desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
7693 surface_desc.dwHeight = 4;
7694 surface_desc.dwWidth = 4;
7695 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7696 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7698 /* NULL pointers are not valid, but don't cause a crash. */
7699 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL,
7700 sizeof(IUnknown *), DDSPD_IUNKNOWNPOINTER);
7701 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7702 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL, 0, 0);
7703 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7704 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL, 1, 0);
7705 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7707 /* DDSPD_IUNKNOWNPOINTER needs sizeof(IUnknown *) bytes of data. */
7708 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7709 0, DDSPD_IUNKNOWNPOINTER);
7710 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7711 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7712 5, DDSPD_IUNKNOWNPOINTER);
7713 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7714 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7715 sizeof(ddraw) * 2, DDSPD_IUNKNOWNPOINTER);
7716 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7718 /* Note that with a size != 0 and size != sizeof(IUnknown *) and
7719 * DDSPD_IUNKNOWNPOINTER set SetPrivateData in ddraw4 and ddraw7
7720 * erases the old content and returns an error. This behavior has
7721 * been fixed in d3d8 and d3d9. Unless an application is found
7722 * that depends on this we don't care about this behavior. */
7723 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7724 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7725 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7726 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7727 0, DDSPD_IUNKNOWNPOINTER);
7728 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7729 size = sizeof(ptr);
7730 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
7731 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7732 hr = IDirectDrawSurface7_FreePrivateData(surface, &ddraw_private_data_test_guid);
7733 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7735 refcount = get_refcount((IUnknown *)ddraw);
7736 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7737 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7738 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7739 refcount2 = get_refcount((IUnknown *)ddraw);
7740 ok(refcount2 == refcount + 1, "Got unexpected refcount %u.\n", refcount2);
7742 hr = IDirectDrawSurface7_FreePrivateData(surface, &ddraw_private_data_test_guid);
7743 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7744 refcount2 = get_refcount((IUnknown *)ddraw);
7745 ok(refcount2 == refcount, "Got unexpected refcount %u.\n", refcount2);
7747 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7748 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7749 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7750 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, surface,
7751 sizeof(surface), DDSPD_IUNKNOWNPOINTER);
7752 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7753 refcount2 = get_refcount((IUnknown *)ddraw);
7754 ok(refcount2 == refcount, "Got unexpected refcount %u.\n", refcount2);
7756 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7757 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7758 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7759 size = 2 * sizeof(ptr);
7760 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
7761 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7762 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
7763 refcount2 = get_refcount(ptr);
7764 /* Object is NOT addref'ed by the getter. */
7765 ok(ptr == (IUnknown *)ddraw, "Returned interface pointer is %p, expected %p.\n", ptr, ddraw);
7766 ok(refcount2 == refcount + 1, "Got unexpected refcount %u.\n", refcount2);
7768 ptr = (IUnknown *)0xdeadbeef;
7769 size = 1;
7770 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, &size);
7771 ok(hr == DDERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
7772 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
7773 size = 2 * sizeof(ptr);
7774 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, &size);
7775 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7776 ok(size == 2 * sizeof(ptr), "Got unexpected size %u.\n", size);
7777 size = 1;
7778 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
7779 ok(hr == DDERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
7780 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
7781 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7782 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid2, NULL, NULL);
7783 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7784 size = 0xdeadbabe;
7785 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid2, &ptr, &size);
7786 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7787 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7788 ok(size == 0xdeadbabe, "Got unexpected size %u.\n", size);
7789 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, NULL);
7790 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7792 refcount3 = IDirectDrawSurface7_Release(surface);
7793 ok(!refcount3, "Got unexpected refcount %u.\n", refcount3);
7795 /* Destroying the surface frees the reference held on the private data. It also frees
7796 * the reference the surface is holding on its creating object. */
7797 refcount2 = get_refcount((IUnknown *)ddraw);
7798 ok(refcount2 == refcount - 1, "Got unexpected refcount %u.\n", refcount2);
7800 memset(&hal_caps, 0, sizeof(hal_caps));
7801 hal_caps.dwSize = sizeof(hal_caps);
7802 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
7803 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7804 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) == (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)
7805 && !is_ddraw64)
7807 reset_ddsd(&surface_desc);
7808 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_MIPMAPCOUNT;
7809 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7810 surface_desc.dwHeight = 4;
7811 surface_desc.dwWidth = 4;
7812 U2(surface_desc).dwMipMapCount = 2;
7813 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7814 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7815 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &surface2);
7816 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
7818 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, data, sizeof(data), 0);
7819 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7820 hr = IDirectDrawSurface7_GetPrivateData(surface2, &ddraw_private_data_test_guid, NULL, NULL);
7821 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7823 IDirectDrawSurface7_Release(surface2);
7824 IDirectDrawSurface7_Release(surface);
7826 else
7827 skip("Mipmapped textures not supported, skipping mipmap private data test.\n");
7829 refcount = IDirectDraw7_Release(ddraw);
7830 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7831 DestroyWindow(window);
7834 static void test_pixel_format(void)
7836 HWND window, window2 = NULL;
7837 HDC hdc, hdc2 = NULL;
7838 HMODULE gl = NULL;
7839 int format, test_format;
7840 PIXELFORMATDESCRIPTOR pfd;
7841 IDirectDraw7 *ddraw = NULL;
7842 IDirectDrawClipper *clipper = NULL;
7843 DDSURFACEDESC2 ddsd;
7844 IDirectDrawSurface7 *primary = NULL, *offscreen;
7845 DDBLTFX fx;
7846 HRESULT hr;
7848 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
7849 100, 100, 160, 160, NULL, NULL, NULL, NULL);
7850 if (!window)
7852 skip("Failed to create window\n");
7853 return;
7856 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
7857 100, 100, 160, 160, NULL, NULL, NULL, NULL);
7859 hdc = GetDC(window);
7860 if (!hdc)
7862 skip("Failed to get DC\n");
7863 goto cleanup;
7866 if (window2)
7867 hdc2 = GetDC(window2);
7869 gl = LoadLibraryA("opengl32.dll");
7870 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
7872 format = GetPixelFormat(hdc);
7873 ok(format == 0, "new window has pixel format %d\n", format);
7875 ZeroMemory(&pfd, sizeof(pfd));
7876 pfd.nSize = sizeof(pfd);
7877 pfd.nVersion = 1;
7878 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
7879 pfd.iPixelType = PFD_TYPE_RGBA;
7880 pfd.iLayerType = PFD_MAIN_PLANE;
7881 format = ChoosePixelFormat(hdc, &pfd);
7882 if (format <= 0)
7884 skip("no pixel format available\n");
7885 goto cleanup;
7888 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
7890 skip("failed to set pixel format\n");
7891 goto cleanup;
7894 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
7896 skip("failed to set pixel format on second window\n");
7897 if (hdc2)
7899 ReleaseDC(window2, hdc2);
7900 hdc2 = NULL;
7904 ddraw = create_ddraw();
7905 ok(!!ddraw, "Failed to create a ddraw object.\n");
7907 test_format = GetPixelFormat(hdc);
7908 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7910 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7911 if (FAILED(hr))
7913 skip("Failed to set cooperative level, hr %#x.\n", hr);
7914 goto cleanup;
7917 test_format = GetPixelFormat(hdc);
7918 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7920 if (hdc2)
7922 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
7923 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
7924 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window2);
7925 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
7927 test_format = GetPixelFormat(hdc);
7928 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7930 test_format = GetPixelFormat(hdc2);
7931 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7934 memset(&ddsd, 0, sizeof(ddsd));
7935 ddsd.dwSize = sizeof(ddsd);
7936 ddsd.dwFlags = DDSD_CAPS;
7937 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7939 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
7940 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
7942 test_format = GetPixelFormat(hdc);
7943 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7945 if (hdc2)
7947 test_format = GetPixelFormat(hdc2);
7948 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7951 if (clipper)
7953 hr = IDirectDrawSurface7_SetClipper(primary, clipper);
7954 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
7956 test_format = GetPixelFormat(hdc);
7957 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7959 test_format = GetPixelFormat(hdc2);
7960 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7963 memset(&ddsd, 0, sizeof(ddsd));
7964 ddsd.dwSize = sizeof(ddsd);
7965 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7966 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7967 ddsd.dwWidth = ddsd.dwHeight = 64;
7968 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &offscreen, NULL);
7969 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
7971 memset(&fx, 0, sizeof(fx));
7972 fx.dwSize = sizeof(fx);
7973 hr = IDirectDrawSurface7_Blt(offscreen, NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &fx);
7974 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
7976 test_format = GetPixelFormat(hdc);
7977 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7979 hr = IDirectDrawSurface7_Blt(primary, NULL, offscreen, NULL, DDBLT_WAIT, NULL);
7980 ok(SUCCEEDED(hr), "Failed to blit to primary surface, hr %#x.\n", hr);
7982 test_format = GetPixelFormat(hdc);
7983 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7985 if (hdc2)
7987 test_format = GetPixelFormat(hdc2);
7988 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7991 IDirectDrawSurface7_Release(offscreen);
7993 cleanup:
7994 if (primary) IDirectDrawSurface7_Release(primary);
7995 if (clipper) IDirectDrawClipper_Release(clipper);
7996 if (ddraw) IDirectDraw7_Release(ddraw);
7997 if (gl) FreeLibrary(gl);
7998 if (hdc) ReleaseDC(window, hdc);
7999 if (hdc2) ReleaseDC(window2, hdc2);
8000 DestroyWindow(window);
8001 if (window2) DestroyWindow(window2);
8004 static void test_create_surface_pitch(void)
8006 IDirectDrawSurface7 *surface;
8007 DDSURFACEDESC2 surface_desc;
8008 IDirectDraw7 *ddraw;
8009 unsigned int i;
8010 ULONG refcount;
8011 HWND window;
8012 HRESULT hr;
8013 void *mem;
8015 static const struct
8017 DWORD caps;
8018 DWORD flags_in;
8019 DWORD pitch_in;
8020 HRESULT hr;
8021 DWORD flags_out;
8022 DWORD pitch_out32;
8023 DWORD pitch_out64;
8025 test_data[] =
8027 /* 0 */
8028 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
8029 0, 0, DD_OK,
8030 DDSD_PITCH, 0x100, 0x100},
8031 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
8032 DDSD_PITCH, 0x104, DD_OK,
8033 DDSD_PITCH, 0x100, 0x100},
8034 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
8035 DDSD_PITCH, 0x0f8, DD_OK,
8036 DDSD_PITCH, 0x100, 0x100},
8037 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
8038 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
8039 0, 0, 0 },
8040 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8041 0, 0, DD_OK,
8042 DDSD_PITCH, 0x100, 0x0fc},
8043 /* 5 */
8044 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8045 DDSD_PITCH, 0x104, DD_OK,
8046 DDSD_PITCH, 0x100, 0x0fc},
8047 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8048 DDSD_PITCH, 0x0f8, DD_OK,
8049 DDSD_PITCH, 0x100, 0x0fc},
8050 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8051 DDSD_PITCH | DDSD_LINEARSIZE, 0, DD_OK,
8052 DDSD_PITCH, 0x100, 0x0fc},
8053 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8054 DDSD_LPSURFACE, 0, DDERR_INVALIDPARAMS,
8055 0, 0, 0 },
8056 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8057 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DD_OK,
8058 DDSD_PITCH, 0x100, 0x100},
8059 /* 10 */
8060 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8061 DDSD_LPSURFACE | DDSD_PITCH, 0x0fe, DDERR_INVALIDPARAMS,
8062 0, 0, 0 },
8063 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8064 DDSD_LPSURFACE | DDSD_PITCH, 0x0fc, DD_OK,
8065 DDSD_PITCH, 0x0fc, 0x0fc},
8066 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8067 DDSD_LPSURFACE | DDSD_PITCH, 0x0f8, DDERR_INVALIDPARAMS,
8068 0, 0, 0 },
8069 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8070 DDSD_LPSURFACE | DDSD_LINEARSIZE, 0x100, DDERR_INVALIDPARAMS,
8071 0, 0, 0 },
8072 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8073 DDSD_LPSURFACE | DDSD_LINEARSIZE, 0x3f00, DDERR_INVALIDPARAMS,
8074 0, 0, 0 },
8075 /* 15 */
8076 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8077 DDSD_LPSURFACE | DDSD_PITCH | DDSD_LINEARSIZE, 0x100, DD_OK,
8078 DDSD_PITCH, 0x100, 0x100},
8079 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
8080 0, 0, DDERR_INVALIDCAPS,
8081 0, 0, 0 },
8082 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
8083 0, 0, DD_OK,
8084 DDSD_PITCH, 0x100, 0 },
8085 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
8086 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
8087 0, 0, 0 },
8088 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
8089 0, 0, DDERR_INVALIDCAPS,
8090 0, 0, 0 },
8091 /* 20 */
8092 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
8093 0, 0, DD_OK,
8094 DDSD_PITCH, 0x100, 0 },
8095 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
8096 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DD_OK,
8097 DDSD_PITCH, 0x100, 0 },
8099 DWORD flags_mask = DDSD_PITCH | DDSD_LPSURFACE | DDSD_LINEARSIZE;
8101 window = create_window();
8102 ddraw = create_ddraw();
8103 ok(!!ddraw, "Failed to create a ddraw object.\n");
8104 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8105 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8107 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((63 * 4) + 8) * 63);
8109 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
8111 memset(&surface_desc, 0, sizeof(surface_desc));
8112 surface_desc.dwSize = sizeof(surface_desc);
8113 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | test_data[i].flags_in;
8114 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
8115 surface_desc.dwWidth = 63;
8116 surface_desc.dwHeight = 63;
8117 U1(surface_desc).lPitch = test_data[i].pitch_in;
8118 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8119 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
8120 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
8121 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8122 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8123 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
8124 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8125 if (test_data[i].flags_in & DDSD_LPSURFACE)
8127 HRESULT expected_hr = SUCCEEDED(test_data[i].hr) ? DDERR_INVALIDPARAMS : test_data[i].hr;
8128 ok(hr == expected_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, expected_hr);
8129 surface_desc.lpSurface = mem;
8130 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8132 if ((test_data[i].caps & DDSCAPS_VIDEOMEMORY) && hr == DDERR_NODIRECTDRAWHW)
8133 continue;
8134 if (is_ddraw64 && (test_data[i].caps & DDSCAPS_TEXTURE) && SUCCEEDED(test_data[i].hr))
8135 todo_wine ok(hr == E_NOINTERFACE, "Test %u: Got unexpected hr %#x.\n", i, hr);
8136 else
8137 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
8138 if (FAILED(hr))
8139 continue;
8141 memset(&surface_desc, 0, sizeof(surface_desc));
8142 surface_desc.dwSize = sizeof(surface_desc);
8143 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
8144 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
8145 ok((surface_desc.dwFlags & flags_mask) == test_data[i].flags_out,
8146 "Test %u: Got unexpected flags %#x, expected %#x.\n",
8147 i, surface_desc.dwFlags & flags_mask, test_data[i].flags_out);
8148 /* The pitch for textures seems to be implementation specific. */
8149 if (!(test_data[i].caps & DDSCAPS_TEXTURE))
8151 if (is_ddraw64 && test_data[i].pitch_out32 != test_data[i].pitch_out64)
8152 todo_wine ok(U1(surface_desc).lPitch == test_data[i].pitch_out64,
8153 "Test %u: Got unexpected pitch %u, expected %u.\n",
8154 i, U1(surface_desc).lPitch, test_data[i].pitch_out64);
8155 else
8156 ok(U1(surface_desc).lPitch == test_data[i].pitch_out32,
8157 "Test %u: Got unexpected pitch %u, expected %u.\n",
8158 i, U1(surface_desc).lPitch, test_data[i].pitch_out32);
8160 ok(!surface_desc.lpSurface, "Test %u: Got unexpected lpSurface %p.\n", i, surface_desc.lpSurface);
8162 IDirectDrawSurface7_Release(surface);
8165 HeapFree(GetProcessHeap(), 0, mem);
8166 refcount = IDirectDraw7_Release(ddraw);
8167 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8168 DestroyWindow(window);
8171 static void test_mipmap(void)
8173 IDirectDrawSurface7 *surface, *surface_base, *surface_mip;
8174 unsigned int i, mipmap_count;
8175 DDSURFACEDESC2 surface_desc;
8176 IDirectDraw7 *ddraw;
8177 ULONG refcount;
8178 HWND window;
8179 HRESULT hr;
8180 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
8181 DDCAPS hal_caps;
8183 static const struct
8185 DWORD flags;
8186 DWORD caps;
8187 DWORD width;
8188 DWORD height;
8189 DWORD mipmap_count_in;
8190 HRESULT hr;
8191 DWORD mipmap_count_out;
8193 tests[] =
8195 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 3, DD_OK, 3},
8196 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDPARAMS, 0},
8197 {0, DDSCAPS_TEXTURE | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 1},
8198 {0, DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDCAPS, 0},
8199 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 8},
8200 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 32, 64, 0, DD_OK, 7},
8203 window = create_window();
8204 ddraw = create_ddraw();
8205 ok(!!ddraw, "Failed to create a ddraw object.\n");
8206 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8207 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8209 memset(&hal_caps, 0, sizeof(hal_caps));
8210 hal_caps.dwSize = sizeof(hal_caps);
8211 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
8212 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8213 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)
8214 || is_ddraw64)
8216 skip("Mipmapped textures not supported, skipping tests.\n");
8217 IDirectDraw7_Release(ddraw);
8218 DestroyWindow(window);
8219 return;
8222 for (i = 0; i < ARRAY_SIZE(tests); ++i)
8224 memset(&surface_desc, 0, sizeof(surface_desc));
8225 surface_desc.dwSize = sizeof(surface_desc);
8226 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | tests[i].flags;
8227 surface_desc.ddsCaps.dwCaps = tests[i].caps;
8228 surface_desc.dwWidth = tests[i].width;
8229 surface_desc.dwHeight = tests[i].height;
8230 if (tests[i].flags & DDSD_MIPMAPCOUNT)
8231 U2(surface_desc).dwMipMapCount = tests[i].mipmap_count_in;
8232 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8233 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x.\n", i, hr);
8234 if (FAILED(hr))
8235 continue;
8237 memset(&surface_desc, 0, sizeof(surface_desc));
8238 surface_desc.dwSize = sizeof(surface_desc);
8239 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
8240 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
8241 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
8242 "Test %u: Got unexpected flags %#x.\n", i, surface_desc.dwFlags);
8243 ok(U2(surface_desc).dwMipMapCount == tests[i].mipmap_count_out,
8244 "Test %u: Got unexpected mipmap count %u.\n", i, U2(surface_desc).dwMipMapCount);
8246 surface_base = surface;
8247 IDirectDrawSurface7_AddRef(surface_base);
8248 mipmap_count = U2(surface_desc).dwMipMapCount;
8249 while (mipmap_count > 1)
8251 hr = IDirectDrawSurface7_GetAttachedSurface(surface_base, &caps, &surface_mip);
8252 ok(SUCCEEDED(hr), "Test %u, %u: Failed to get attached surface, hr %#x.\n", i, mipmap_count, hr);
8254 memset(&surface_desc, 0, sizeof(surface_desc));
8255 surface_desc.dwSize = sizeof(surface_desc);
8256 hr = IDirectDrawSurface7_GetSurfaceDesc(surface_base, &surface_desc);
8257 ok(SUCCEEDED(hr), "Test %u, %u: Failed to get surface desc, hr %#x.\n", i, mipmap_count, hr);
8258 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
8259 "Test %u, %u: Got unexpected flags %#x.\n", i, mipmap_count, surface_desc.dwFlags);
8260 ok(U2(surface_desc).dwMipMapCount == mipmap_count,
8261 "Test %u, %u: Got unexpected mipmap count %u.\n",
8262 i, mipmap_count, U2(surface_desc).dwMipMapCount);
8264 memset(&surface_desc, 0, sizeof(surface_desc));
8265 surface_desc.dwSize = sizeof(surface_desc);
8266 hr = IDirectDrawSurface7_Lock(surface_base, NULL, &surface_desc, 0, NULL);
8267 ok(SUCCEEDED(hr), "Test %u, %u: Failed to lock surface, hr %#x.\n", i, mipmap_count, hr);
8268 ok(surface_desc.dwMipMapCount == mipmap_count,
8269 "Test %u, %u: unexpected change of mipmap count %u.\n",
8270 i, mipmap_count, surface_desc.dwMipMapCount);
8271 memset(&surface_desc, 0, sizeof(surface_desc));
8272 surface_desc.dwSize = sizeof(surface_desc);
8273 hr = IDirectDrawSurface7_Lock(surface_mip, NULL, &surface_desc, 0, NULL);
8274 ok(SUCCEEDED(hr), "Test %u, %u: Failed to lock surface, hr %#x.\n", i, mipmap_count, hr);
8275 ok(surface_desc.dwMipMapCount == mipmap_count - 1,
8276 "Test %u, %u: Child mipmap count unexpected %u\n", i, mipmap_count, surface_desc.dwMipMapCount);
8277 IDirectDrawSurface7_Unlock(surface_mip, NULL);
8278 IDirectDrawSurface7_Unlock(surface_base, NULL);
8280 IDirectDrawSurface7_Release(surface_base);
8281 surface_base = surface_mip;
8282 --mipmap_count;
8284 IDirectDrawSurface7_Release(surface_base);
8286 IDirectDrawSurface7_Release(surface);
8289 refcount = IDirectDraw7_Release(ddraw);
8290 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8291 DestroyWindow(window);
8294 static void test_palette_complex(void)
8296 IDirectDrawSurface7 *surface, *mipmap, *tmp;
8297 DDSURFACEDESC2 surface_desc;
8298 IDirectDraw7 *ddraw;
8299 IDirectDrawPalette *palette, *palette2;
8300 ULONG refcount;
8301 HWND window;
8302 HRESULT hr;
8303 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
8304 DDCAPS hal_caps;
8305 PALETTEENTRY palette_entries[256];
8306 unsigned int i;
8308 window = create_window();
8309 ddraw = create_ddraw();
8310 ok(!!ddraw, "Failed to create a ddraw object.\n");
8311 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8312 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8314 memset(&hal_caps, 0, sizeof(hal_caps));
8315 hal_caps.dwSize = sizeof(hal_caps);
8316 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
8317 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8318 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)
8319 || is_ddraw64)
8321 skip("Mipmapped textures not supported, skipping mipmap palette test.\n");
8322 IDirectDraw7_Release(ddraw);
8323 DestroyWindow(window);
8324 return;
8327 memset(&surface_desc, 0, sizeof(surface_desc));
8328 surface_desc.dwSize = sizeof(surface_desc);
8329 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8330 surface_desc.dwWidth = 128;
8331 surface_desc.dwHeight = 128;
8332 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
8333 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8334 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
8335 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
8336 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8337 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8339 memset(palette_entries, 0, sizeof(palette_entries));
8340 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8341 palette_entries, &palette, NULL);
8342 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8344 palette2 = (void *)0xdeadbeef;
8345 hr = IDirectDrawSurface7_GetPalette(surface, &palette2);
8346 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
8347 ok(!palette2, "Got unexpected palette %p.\n", palette2);
8348 hr = IDirectDrawSurface7_SetPalette(surface, palette);
8349 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8350 hr = IDirectDrawSurface7_GetPalette(surface, &palette2);
8351 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
8352 ok(palette == palette2, "Got unexpected palette %p.\n", palette2);
8353 IDirectDrawPalette_Release(palette2);
8355 mipmap = surface;
8356 IDirectDrawSurface7_AddRef(mipmap);
8357 for (i = 0; i < 7; ++i)
8359 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
8360 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
8361 palette2 = (void *)0xdeadbeef;
8362 hr = IDirectDrawSurface7_GetPalette(tmp, &palette2);
8363 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x, i %u.\n", hr, i);
8364 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
8366 hr = IDirectDrawSurface7_SetPalette(tmp, palette);
8367 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x, i %u.\n", hr, i);
8369 hr = IDirectDrawSurface7_GetPalette(tmp, &palette2);
8370 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x, i %u.\n", hr, i);
8371 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
8373 /* Ddraw7 uses the palette of the mipmap for GetDC, just like previous
8374 * ddraw versions. Combined with the test results above this means no
8375 * palette is available. So depending on the driver either GetDC fails
8376 * or the DIB color table contains random data. */
8378 IDirectDrawSurface7_Release(mipmap);
8379 mipmap = tmp;
8382 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
8383 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
8384 IDirectDrawSurface7_Release(mipmap);
8385 refcount = IDirectDrawSurface7_Release(surface);
8386 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8388 /* Test DDERR_INVALIDPIXELFORMAT vs DDERR_NOTONMIPMAPSUBLEVEL. */
8389 memset(&surface_desc, 0, sizeof(surface_desc));
8390 surface_desc.dwSize = sizeof(surface_desc);
8391 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8392 surface_desc.dwWidth = 128;
8393 surface_desc.dwHeight = 128;
8394 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
8395 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8396 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
8397 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
8398 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8399 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8400 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
8401 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8402 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8404 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
8405 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
8406 hr = IDirectDrawSurface7_SetPalette(mipmap, palette);
8407 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x.\n", hr);
8409 IDirectDrawSurface7_Release(mipmap);
8410 refcount = IDirectDrawSurface7_Release(surface);
8411 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8412 refcount = IDirectDrawPalette_Release(palette);
8413 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8415 refcount = IDirectDraw7_Release(ddraw);
8416 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8417 DestroyWindow(window);
8420 static void test_p8_blit(void)
8422 IDirectDrawSurface7 *src, *dst, *dst_p8;
8423 DDSURFACEDESC2 surface_desc;
8424 IDirectDraw7 *ddraw;
8425 IDirectDrawPalette *palette, *palette2;
8426 ULONG refcount;
8427 HWND window;
8428 HRESULT hr;
8429 PALETTEENTRY palette_entries[256];
8430 unsigned int x;
8431 DDBLTFX fx;
8432 BOOL is_warp;
8433 static const BYTE src_data[] = {0x10, 0x1, 0x2, 0x3, 0x4, 0x5, 0xff, 0x80};
8434 static const BYTE src_data2[] = {0x10, 0x5, 0x4, 0x3, 0x2, 0x1, 0xff, 0x80};
8435 static const BYTE expected_p8[] = {0x10, 0x1, 0x4, 0x3, 0x4, 0x5, 0xff, 0x80};
8436 static const D3DCOLOR expected[] =
8438 0x00101010, 0x00010101, 0x00020202, 0x00030303,
8439 0x00040404, 0x00050505, 0x00ffffff, 0x00808080,
8441 D3DCOLOR color;
8443 window = create_window();
8444 ddraw = create_ddraw();
8445 ok(!!ddraw, "Failed to create a ddraw object.\n");
8446 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8447 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8448 is_warp = ddraw_is_warp(ddraw);
8450 memset(palette_entries, 0, sizeof(palette_entries));
8451 palette_entries[1].peGreen = 0xff;
8452 palette_entries[2].peBlue = 0xff;
8453 palette_entries[3].peFlags = 0xff;
8454 palette_entries[4].peRed = 0xff;
8455 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8456 palette_entries, &palette, NULL);
8457 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8458 palette_entries[1].peBlue = 0xff;
8459 palette_entries[2].peGreen = 0xff;
8460 palette_entries[3].peRed = 0xff;
8461 palette_entries[4].peFlags = 0x0;
8462 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8463 palette_entries, &palette2, NULL);
8464 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8466 memset(&surface_desc, 0, sizeof(surface_desc));
8467 surface_desc.dwSize = sizeof(surface_desc);
8468 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8469 surface_desc.dwWidth = 8;
8470 surface_desc.dwHeight = 1;
8471 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8472 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8473 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
8474 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
8475 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
8476 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8477 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_p8, NULL);
8478 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8479 hr = IDirectDrawSurface7_SetPalette(dst_p8, palette2);
8480 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8482 memset(&surface_desc, 0, sizeof(surface_desc));
8483 surface_desc.dwSize = sizeof(surface_desc);
8484 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8485 surface_desc.dwWidth = 8;
8486 surface_desc.dwHeight = 1;
8487 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8488 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8489 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
8490 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
8491 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8492 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8493 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
8494 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
8495 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
8496 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8498 memset(&surface_desc, 0, sizeof(surface_desc));
8499 surface_desc.dwSize = sizeof(surface_desc);
8500 hr = IDirectDrawSurface7_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
8501 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
8502 memcpy(surface_desc.lpSurface, src_data, sizeof(src_data));
8503 hr = IDirectDrawSurface7_Unlock(src, NULL);
8504 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
8506 hr = IDirectDrawSurface7_Lock(dst_p8, NULL, &surface_desc, DDLOCK_WAIT, NULL);
8507 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#x.\n", hr);
8508 memcpy(surface_desc.lpSurface, src_data2, sizeof(src_data2));
8509 hr = IDirectDrawSurface7_Unlock(dst_p8, NULL);
8510 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#x.\n", hr);
8512 hr = IDirectDrawSurface7_SetPalette(src, palette);
8513 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8514 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_WAIT, NULL);
8515 /* The r500 Windows 7 driver returns E_NOTIMPL. r200 on Windows XP works.
8516 * The Geforce 7 driver on Windows Vista returns E_FAIL. Newer Nvidia GPUs work. */
8517 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL) || broken(hr == E_FAIL),
8518 "Failed to blit, hr %#x.\n", hr);
8520 if (SUCCEEDED(hr))
8522 for (x = 0; x < ARRAY_SIZE(expected); ++x)
8524 color = get_surface_color(dst, x, 0);
8525 todo_wine ok(compare_color(color, expected[x], 0),
8526 "Pixel %u: Got color %#x, expected %#x.\n",
8527 x, color, expected[x]);
8531 memset(&fx, 0, sizeof(fx));
8532 fx.dwSize = sizeof(fx);
8533 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x2;
8534 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x2;
8535 hr = IDirectDrawSurface7_Blt(dst_p8, NULL, src, NULL, DDBLT_WAIT | DDBLT_KEYSRCOVERRIDE, &fx);
8536 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
8538 hr = IDirectDrawSurface7_Lock(dst_p8, NULL, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
8539 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#x.\n", hr);
8540 /* A color keyed P8 blit doesn't do anything on WARP - it just leaves the data in the destination
8541 * surface untouched. P8 blits without color keys work. Error checking (DDBLT_KEYSRC without a key
8542 * for example) also works as expected.
8544 * Using DDBLT_KEYSRC instead of DDBLT_KEYSRCOVERRIDE doesn't change this. Doing this blit with
8545 * the display mode set to P8 doesn't help either. */
8546 ok(!memcmp(surface_desc.lpSurface, expected_p8, sizeof(expected_p8))
8547 || broken(is_warp && !memcmp(surface_desc.lpSurface, src_data2, sizeof(src_data2))),
8548 "Got unexpected P8 color key blit result.\n");
8549 hr = IDirectDrawSurface7_Unlock(dst_p8, NULL);
8550 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#x.\n", hr);
8552 IDirectDrawSurface7_Release(src);
8553 IDirectDrawSurface7_Release(dst);
8554 IDirectDrawSurface7_Release(dst_p8);
8555 IDirectDrawPalette_Release(palette);
8556 IDirectDrawPalette_Release(palette2);
8558 refcount = IDirectDraw7_Release(ddraw);
8559 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8560 DestroyWindow(window);
8563 static void test_material(void)
8565 static const D3DCOLORVALUE null_color;
8566 IDirect3DDevice7 *device;
8567 D3DMATERIAL7 material;
8568 ULONG refcount;
8569 HWND window;
8570 HRESULT hr;
8572 window = create_window();
8573 if (!(device = create_device(window, DDSCL_NORMAL)))
8575 skip("Failed to create a 3D device, skipping test.\n");
8576 DestroyWindow(window);
8577 return;
8580 hr = IDirect3DDevice7_GetMaterial(device, &material);
8581 ok(SUCCEEDED(hr), "Failed to get material, hr %#x.\n", hr);
8582 ok(!memcmp(&U(material).diffuse, &null_color, sizeof(null_color)),
8583 "Got unexpected diffuse color {%.8e, %.8e, %.8e, %.8e}.\n",
8584 U1(U(material).diffuse).r, U2(U(material).diffuse).g,
8585 U3(U(material).diffuse).b, U4(U(material).diffuse).a);
8586 ok(!memcmp(&U1(material).ambient, &null_color, sizeof(null_color)),
8587 "Got unexpected ambient color {%.8e, %.8e, %.8e, %.8e}.\n",
8588 U1(U1(material).ambient).r, U2(U1(material).ambient).g,
8589 U3(U1(material).ambient).b, U4(U1(material).ambient).a);
8590 ok(!memcmp(&U2(material).specular, &null_color, sizeof(null_color)),
8591 "Got unexpected specular color {%.8e, %.8e, %.8e, %.8e}.\n",
8592 U1(U2(material).specular).r, U2(U2(material).specular).g,
8593 U3(U2(material).specular).b, U4(U2(material).specular).a);
8594 ok(!memcmp(&U3(material).emissive, &null_color, sizeof(null_color)),
8595 "Got unexpected emissive color {%.8e, %.8e, %.8e, %.8e}.\n",
8596 U1(U3(material).emissive).r, U2(U3(material).emissive).g,
8597 U3(U3(material).emissive).b, U4(U3(material).emissive).a);
8598 ok(U4(material).power == 0.0f, "Got unexpected power %.8e.\n", U4(material).power);
8600 refcount = IDirect3DDevice7_Release(device);
8601 ok(!refcount, "Device has %u references left.\n", refcount);
8602 DestroyWindow(window);
8605 static void test_palette_gdi(void)
8607 IDirectDrawSurface7 *surface, *primary;
8608 DDSURFACEDESC2 surface_desc;
8609 IDirectDraw7 *ddraw;
8610 IDirectDrawPalette *palette, *palette2;
8611 ULONG refcount;
8612 HWND window;
8613 HRESULT hr;
8614 PALETTEENTRY palette_entries[256];
8615 UINT i;
8616 HDC dc;
8617 DDBLTFX fx;
8618 RECT r;
8619 COLORREF color;
8620 /* On the Windows 8 testbot palette index 0 of the onscreen palette is forced to
8621 * r = 0, g = 0, b = 0. Do not attempt to set it to something else as this is
8622 * not the point of this test. */
8623 static const RGBQUAD expected1[] =
8625 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
8626 {0x03, 0x00, 0x00, 0x00}, {0x15, 0x14, 0x13, 0x00},
8628 static const RGBQUAD expected2[] =
8630 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
8631 {0x03, 0x00, 0x00, 0x00}, {0x25, 0x24, 0x23, 0x00},
8633 static const RGBQUAD expected3[] =
8635 {0x00, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x40, 0x00},
8636 {0x00, 0x40, 0x00, 0x00}, {0x56, 0x34, 0x12, 0x00},
8638 HPALETTE ddraw_palette_handle;
8639 /* Similar to index 0, index 255 is r = 0xff, g = 0xff, b = 0xff on the Win8 VMs. */
8640 RGBQUAD rgbquad[255];
8641 static const RGBQUAD rgb_zero = {0, 0, 0, 0};
8643 window = create_window();
8644 ddraw = create_ddraw();
8645 ok(!!ddraw, "Failed to create a ddraw object.\n");
8646 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8647 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8649 memset(&surface_desc, 0, sizeof(surface_desc));
8650 surface_desc.dwSize = sizeof(surface_desc);
8651 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8652 surface_desc.dwWidth = 16;
8653 surface_desc.dwHeight = 16;
8654 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8655 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8656 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
8657 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
8658 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8659 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8661 /* Avoid colors from the Windows default palette. */
8662 memset(palette_entries, 0, sizeof(palette_entries));
8663 palette_entries[1].peRed = 0x01;
8664 palette_entries[2].peGreen = 0x02;
8665 palette_entries[3].peBlue = 0x03;
8666 palette_entries[4].peRed = 0x13;
8667 palette_entries[4].peGreen = 0x14;
8668 palette_entries[4].peBlue = 0x15;
8669 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8670 palette_entries, &palette, NULL);
8671 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8673 /* If there is no palette assigned and the display mode is not 8 bpp, some
8674 * drivers refuse to create a DC while others allow it. If a DC is created,
8675 * the DIB color table is uninitialized and contains random colors. No error
8676 * is generated when trying to read pixels and random garbage is returned.
8678 * The most likely explanation is that if the driver creates a DC, it (or
8679 * the higher-level runtime) uses GetSystemPaletteEntries to find the
8680 * palette, but GetSystemPaletteEntries fails when bpp > 8 and the palette
8681 * contains uninitialized garbage. See comments below for the P8 case. */
8683 hr = IDirectDrawSurface7_SetPalette(surface, palette);
8684 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8685 hr = IDirectDrawSurface7_GetDC(surface, &dc);
8686 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8687 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
8688 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
8689 "Got unexpected palette %p, expected %p.\n",
8690 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
8692 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8693 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8694 for (i = 0; i < ARRAY_SIZE(expected1); ++i)
8696 ok(!memcmp(&rgbquad[i], &expected1[i], sizeof(rgbquad[i])),
8697 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8698 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8699 expected1[i].rgbRed, expected1[i].rgbGreen, expected1[i].rgbBlue);
8701 for (; i < ARRAY_SIZE(rgbquad); ++i)
8703 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8704 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8705 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8708 /* Update the palette while the DC is in use. This does not modify the DC. */
8709 palette_entries[4].peRed = 0x23;
8710 palette_entries[4].peGreen = 0x24;
8711 palette_entries[4].peBlue = 0x25;
8712 hr = IDirectDrawPalette_SetEntries(palette, 0, 4, 1, &palette_entries[4]);
8713 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
8715 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
8716 ok(i == 1, "Expected count 1, got %u.\n", i);
8717 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
8718 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8719 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
8720 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
8722 /* Neither does re-setting the palette. */
8723 hr = IDirectDrawSurface7_SetPalette(surface, NULL);
8724 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8725 hr = IDirectDrawSurface7_SetPalette(surface, palette);
8726 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8728 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
8729 ok(i == 1, "Expected count 1, got %u.\n", i);
8730 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
8731 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8732 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
8733 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
8735 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
8736 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8738 /* Refresh the DC. This updates the palette. */
8739 hr = IDirectDrawSurface7_GetDC(surface, &dc);
8740 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8741 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8742 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8743 for (i = 0; i < ARRAY_SIZE(expected2); ++i)
8745 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8746 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8747 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8748 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8750 for (; i < ARRAY_SIZE(rgbquad); ++i)
8752 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8753 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8754 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8756 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
8757 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8759 refcount = IDirectDrawSurface7_Release(surface);
8760 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8762 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
8763 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8764 if (FAILED(IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
8766 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
8767 IDirectDrawPalette_Release(palette);
8768 IDirectDraw7_Release(ddraw);
8769 DestroyWindow(window);
8770 return;
8772 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
8774 memset(&surface_desc, 0, sizeof(surface_desc));
8775 surface_desc.dwSize = sizeof(surface_desc);
8776 surface_desc.dwFlags = DDSD_CAPS;
8777 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8778 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
8779 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8781 memset(&fx, 0, sizeof(fx));
8782 fx.dwSize = sizeof(fx);
8783 U5(fx).dwFillColor = 3;
8784 SetRect(&r, 0, 0, 319, 479);
8785 hr = IDirectDrawSurface7_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8786 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#x.\n", hr);
8787 SetRect(&r, 320, 0, 639, 479);
8788 U5(fx).dwFillColor = 4;
8789 hr = IDirectDrawSurface7_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8790 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#x.\n", hr);
8792 hr = IDirectDrawSurface7_SetPalette(primary, palette);
8793 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8794 hr = IDirectDrawSurface7_GetDC(primary, &dc);
8795 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8797 color = GetPixel(dc, 160, 240);
8798 ok(color == 0x00030000, "Clear index 3: Got unexpected color 0x%08x.\n", color);
8799 color = GetPixel(dc, 480, 240);
8800 ok(color == 0x00252423, "Clear index 4: Got unexpected color 0x%08x.\n", color);
8802 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
8803 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
8804 "Got unexpected palette %p, expected %p.\n",
8805 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
8806 SelectPalette(dc, ddraw_palette_handle, FALSE);
8808 /* The primary uses the system palette. In exclusive mode, the system palette matches
8809 * the ddraw palette attached to the primary, so the result is what you would expect
8810 * from a regular surface. Tests for the interaction between the ddraw palette and
8811 * the system palette are not included pending an application that depends on this.
8812 * The relation between those causes problems on Windows Vista and newer for games
8813 * like Age of Empires or StarcCaft. Don't emulate it without a real need. */
8814 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8815 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8816 for (i = 0; i < ARRAY_SIZE(expected2); ++i)
8818 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8819 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8820 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8821 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8823 for (; i < ARRAY_SIZE(rgbquad); ++i)
8825 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8826 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8827 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8829 hr = IDirectDrawSurface7_ReleaseDC(primary, dc);
8830 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8832 memset(&surface_desc, 0, sizeof(surface_desc));
8833 surface_desc.dwSize = sizeof(surface_desc);
8834 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8835 surface_desc.dwWidth = 16;
8836 surface_desc.dwHeight = 16;
8837 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8838 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8839 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8841 /* Here the offscreen surface appears to use the primary's palette,
8842 * but in all likelihood it is actually the system palette. */
8843 hr = IDirectDrawSurface7_GetDC(surface, &dc);
8844 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8845 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8846 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8847 for (i = 0; i < ARRAY_SIZE(expected2); ++i)
8849 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8850 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8851 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8852 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8854 for (; i < ARRAY_SIZE(rgbquad); ++i)
8856 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8857 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8858 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8860 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
8861 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8863 /* On real hardware a change to the primary surface's palette applies immediately,
8864 * even on device contexts from offscreen surfaces that do not have their own
8865 * palette. On the testbot VMs this is not the case. Don't test this until we
8866 * know of an application that depends on this. */
8868 memset(palette_entries, 0, sizeof(palette_entries));
8869 palette_entries[1].peBlue = 0x40;
8870 palette_entries[2].peRed = 0x40;
8871 palette_entries[3].peGreen = 0x40;
8872 palette_entries[4].peRed = 0x12;
8873 palette_entries[4].peGreen = 0x34;
8874 palette_entries[4].peBlue = 0x56;
8875 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8876 palette_entries, &palette2, NULL);
8877 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8878 hr = IDirectDrawSurface7_SetPalette(surface, palette2);
8879 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8881 /* A palette assigned to the offscreen surface overrides the primary / system
8882 * palette. */
8883 hr = IDirectDrawSurface7_GetDC(surface, &dc);
8884 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8885 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8886 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8887 for (i = 0; i < ARRAY_SIZE(expected3); ++i)
8889 ok(!memcmp(&rgbquad[i], &expected3[i], sizeof(rgbquad[i])),
8890 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8891 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8892 expected3[i].rgbRed, expected3[i].rgbGreen, expected3[i].rgbBlue);
8894 for (; i < ARRAY_SIZE(rgbquad); ++i)
8896 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8897 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8898 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8900 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
8901 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8903 refcount = IDirectDrawSurface7_Release(surface);
8904 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8906 /* The Windows 8 testbot keeps extra references to the primary and
8907 * backbuffer while in 8 bpp mode. */
8908 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
8909 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
8911 refcount = IDirectDrawSurface7_Release(primary);
8912 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8913 refcount = IDirectDrawPalette_Release(palette2);
8914 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8915 refcount = IDirectDrawPalette_Release(palette);
8916 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8917 refcount = IDirectDraw7_Release(ddraw);
8918 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8919 DestroyWindow(window);
8922 static void test_palette_alpha(void)
8924 IDirectDrawSurface7 *surface;
8925 DDSURFACEDESC2 surface_desc;
8926 IDirectDraw7 *ddraw;
8927 IDirectDrawPalette *palette;
8928 ULONG refcount;
8929 HWND window;
8930 HRESULT hr;
8931 PALETTEENTRY palette_entries[256];
8932 unsigned int i;
8933 static const struct
8935 DWORD caps, flags;
8936 BOOL attach_allowed;
8937 const char *name;
8939 test_data[] =
8941 {DDSCAPS_OFFSCREENPLAIN, DDSD_WIDTH | DDSD_HEIGHT, FALSE, "offscreenplain"},
8942 {DDSCAPS_TEXTURE, DDSD_WIDTH | DDSD_HEIGHT, TRUE, "texture"},
8943 {DDSCAPS_PRIMARYSURFACE, 0, FALSE, "primary"}
8946 window = create_window();
8947 ddraw = create_ddraw();
8948 ok(!!ddraw, "Failed to create a ddraw object.\n");
8949 if (FAILED(IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
8951 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
8952 IDirectDraw7_Release(ddraw);
8953 DestroyWindow(window);
8954 return;
8956 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8957 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8959 memset(palette_entries, 0, sizeof(palette_entries));
8960 palette_entries[1].peFlags = 0x42;
8961 palette_entries[2].peFlags = 0xff;
8962 palette_entries[3].peFlags = 0x80;
8963 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
8964 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8966 memset(palette_entries, 0x66, sizeof(palette_entries));
8967 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
8968 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
8969 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8970 palette_entries[0].peFlags);
8971 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8972 palette_entries[1].peFlags);
8973 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
8974 palette_entries[2].peFlags);
8975 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
8976 palette_entries[3].peFlags);
8978 IDirectDrawPalette_Release(palette);
8980 memset(palette_entries, 0, sizeof(palette_entries));
8981 palette_entries[1].peFlags = 0x42;
8982 palette_entries[1].peRed = 0xff;
8983 palette_entries[2].peFlags = 0xff;
8984 palette_entries[3].peFlags = 0x80;
8985 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT | DDPCAPS_ALPHA,
8986 palette_entries, &palette, NULL);
8987 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8989 memset(palette_entries, 0x66, sizeof(palette_entries));
8990 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
8991 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
8992 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8993 palette_entries[0].peFlags);
8994 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
8995 palette_entries[1].peFlags);
8996 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
8997 palette_entries[2].peFlags);
8998 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
8999 palette_entries[3].peFlags);
9001 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
9003 memset(&surface_desc, 0, sizeof(surface_desc));
9004 surface_desc.dwSize = sizeof(surface_desc);
9005 surface_desc.dwFlags = DDSD_CAPS | test_data[i].flags;
9006 surface_desc.dwWidth = 128;
9007 surface_desc.dwHeight = 128;
9008 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
9009 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9010 if (is_ddraw64 && test_data[i].caps & DDSCAPS_TEXTURE)
9011 todo_wine ok(hr == E_NOINTERFACE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
9012 else
9013 ok(hr == DD_OK, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
9014 if (FAILED(hr))
9015 continue;
9017 hr = IDirectDrawSurface7_SetPalette(surface, palette);
9018 if (test_data[i].attach_allowed)
9019 ok(SUCCEEDED(hr), "Failed to attach palette to %s surface, hr %#x.\n", test_data[i].name, hr);
9020 else
9021 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x, %s surface.\n", hr, test_data[i].name);
9023 if (SUCCEEDED(hr))
9025 HDC dc;
9026 RGBQUAD rgbquad;
9027 UINT retval;
9029 hr = IDirectDrawSurface7_GetDC(surface, &dc);
9030 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x, %s surface.\n", hr, test_data[i].name);
9031 retval = GetDIBColorTable(dc, 1, 1, &rgbquad);
9032 ok(retval == 1, "GetDIBColorTable returned unexpected result %u.\n", retval);
9033 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x, %s surface.\n",
9034 rgbquad.rgbRed, test_data[i].name);
9035 ok(rgbquad.rgbGreen == 0, "Expected rgbGreen = 0, got %#x, %s surface.\n",
9036 rgbquad.rgbGreen, test_data[i].name);
9037 ok(rgbquad.rgbBlue == 0, "Expected rgbBlue = 0, got %#x, %s surface.\n",
9038 rgbquad.rgbBlue, test_data[i].name);
9039 ok(rgbquad.rgbReserved == 0, "Expected rgbReserved = 0, got %u, %s surface.\n",
9040 rgbquad.rgbReserved, test_data[i].name);
9041 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
9042 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
9044 IDirectDrawSurface7_Release(surface);
9047 /* Test INVALIDSURFACETYPE vs INVALIDPIXELFORMAT. */
9048 memset(&surface_desc, 0, sizeof(surface_desc));
9049 surface_desc.dwSize = sizeof(surface_desc);
9050 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9051 surface_desc.dwWidth = 128;
9052 surface_desc.dwHeight = 128;
9053 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9054 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9055 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
9056 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
9057 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9058 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9059 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
9060 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9061 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9062 hr = IDirectDrawSurface7_SetPalette(surface, palette);
9063 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x.\n", hr);
9064 IDirectDrawSurface7_Release(surface);
9066 /* The Windows 8 testbot keeps extra references to the primary
9067 * while in 8 bpp mode. */
9068 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
9069 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
9071 refcount = IDirectDrawPalette_Release(palette);
9072 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9073 refcount = IDirectDraw7_Release(ddraw);
9074 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9075 DestroyWindow(window);
9078 static void test_vb_writeonly(void)
9080 IDirect3DDevice7 *device;
9081 IDirect3D7 *d3d;
9082 IDirect3DVertexBuffer7 *buffer;
9083 HWND window;
9084 HRESULT hr;
9085 D3DVERTEXBUFFERDESC desc;
9086 void *ptr;
9087 static const struct vec4 quad[] =
9089 { 0.0f, 480.0f, 0.0f, 1.0f},
9090 { 0.0f, 0.0f, 0.0f, 1.0f},
9091 {640.0f, 480.0f, 0.0f, 1.0f},
9092 {640.0f, 0.0f, 0.0f, 1.0f},
9095 window = create_window();
9096 if (!(device = create_device(window, DDSCL_NORMAL)))
9098 skip("Failed to create a 3D device, skipping test.\n");
9099 DestroyWindow(window);
9100 return;
9103 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
9104 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
9106 memset(&desc, 0, sizeof(desc));
9107 desc.dwSize = sizeof(desc);
9108 desc.dwCaps = D3DVBCAPS_WRITEONLY;
9109 desc.dwFVF = D3DFVF_XYZRHW;
9110 desc.dwNumVertices = ARRAY_SIZE(quad);
9111 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &buffer, 0);
9112 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
9114 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, &ptr, NULL);
9115 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
9116 memcpy(ptr, quad, sizeof(quad));
9117 hr = IDirect3DVertexBuffer7_Unlock(buffer);
9118 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
9120 hr = IDirect3DDevice7_BeginScene(device);
9121 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9122 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
9123 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9124 hr = IDirect3DDevice7_EndScene(device);
9125 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9127 hr = IDirect3DVertexBuffer7_Lock(buffer, 0, &ptr, NULL);
9128 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
9129 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
9130 hr = IDirect3DVertexBuffer7_Unlock(buffer);
9131 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
9133 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_READONLY, &ptr, NULL);
9134 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
9135 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
9136 hr = IDirect3DVertexBuffer7_Unlock(buffer);
9137 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
9139 IDirect3DVertexBuffer7_Release(buffer);
9140 IDirect3D7_Release(d3d);
9141 IDirect3DDevice7_Release(device);
9142 DestroyWindow(window);
9145 static void test_lost_device(void)
9147 IDirectDrawSurface7 *surface, *back_buffer;
9148 DDSURFACEDESC2 surface_desc;
9149 HWND window1, window2;
9150 IDirectDraw7 *ddraw;
9151 ULONG refcount;
9152 DDSCAPS2 caps;
9153 HRESULT hr;
9154 BOOL ret;
9156 window1 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9157 0, 0, 640, 480, 0, 0, 0, 0);
9158 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9159 0, 0, 640, 480, 0, 0, 0, 0);
9160 ddraw = create_ddraw();
9161 ok(!!ddraw, "Failed to create a ddraw object.\n");
9162 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
9163 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9165 memset(&surface_desc, 0, sizeof(surface_desc));
9166 surface_desc.dwSize = sizeof(surface_desc);
9167 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
9168 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
9169 U5(surface_desc).dwBackBufferCount = 1;
9170 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9171 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9173 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9174 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9175 hr = IDirectDrawSurface7_IsLost(surface);
9176 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9177 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9178 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9180 ret = SetForegroundWindow(GetDesktopWindow());
9181 ok(ret, "Failed to set foreground window.\n");
9182 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9183 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
9184 hr = IDirectDrawSurface7_IsLost(surface);
9185 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9186 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9187 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9189 ret = SetForegroundWindow(window1);
9190 ok(ret, "Failed to set foreground window.\n");
9191 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9192 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9193 hr = IDirectDrawSurface7_IsLost(surface);
9194 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9195 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9196 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9198 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
9199 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9200 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9201 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9202 hr = IDirectDrawSurface7_IsLost(surface);
9203 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9204 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9205 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9207 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
9208 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9209 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9210 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9211 hr = IDirectDrawSurface7_IsLost(surface);
9212 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9213 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9214 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9216 /* Trying to restore the primary will crash, probably because flippable
9217 * surfaces can't exist in DDSCL_NORMAL. */
9218 IDirectDrawSurface7_Release(surface);
9219 memset(&surface_desc, 0, sizeof(surface_desc));
9220 surface_desc.dwSize = sizeof(surface_desc);
9221 surface_desc.dwFlags = DDSD_CAPS;
9222 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
9223 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9224 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9226 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9227 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9228 hr = IDirectDrawSurface7_IsLost(surface);
9229 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9231 ret = SetForegroundWindow(GetDesktopWindow());
9232 ok(ret, "Failed to set foreground window.\n");
9233 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9234 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9235 hr = IDirectDrawSurface7_IsLost(surface);
9236 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9238 ret = SetForegroundWindow(window1);
9239 ok(ret, "Failed to set foreground window.\n");
9240 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9241 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9242 hr = IDirectDrawSurface7_IsLost(surface);
9243 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9245 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
9246 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9247 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9248 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9249 hr = IDirectDrawSurface7_IsLost(surface);
9250 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9252 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
9253 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9254 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9255 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9256 hr = IDirectDrawSurface7_IsLost(surface);
9257 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9259 IDirectDrawSurface7_Release(surface);
9260 memset(&surface_desc, 0, sizeof(surface_desc));
9261 surface_desc.dwSize = sizeof(surface_desc);
9262 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
9263 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
9264 U5(surface_desc).dwBackBufferCount = 1;
9265 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9266 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9268 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
9269 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9270 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9271 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9272 hr = IDirectDrawSurface7_IsLost(surface);
9273 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9274 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9275 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9277 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL | DDSCL_FULLSCREEN);
9278 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9279 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9280 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9281 hr = IDirectDrawSurface7_IsLost(surface);
9282 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9283 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9284 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
9286 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
9287 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9288 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9289 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9290 hr = IDirectDrawSurface7_IsLost(surface);
9291 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9292 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9293 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
9295 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
9296 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9297 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9298 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9299 hr = IDirectDrawSurface7_IsLost(surface);
9300 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9301 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9302 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
9304 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL | DDSCL_FULLSCREEN);
9305 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9306 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9307 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9308 hr = IDirectDrawSurface7_IsLost(surface);
9309 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9310 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9311 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
9313 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
9314 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9315 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9316 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9317 hr = IDirectDrawSurface7_IsLost(surface);
9318 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9319 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9320 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9322 memset(&caps, 0, sizeof(caps));
9323 caps.dwCaps = DDSCAPS_FLIP;
9325 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &back_buffer);
9326 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9327 hr = IDirectDrawSurface7_Restore(surface);
9328 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9329 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &back_buffer);
9330 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9331 hr = IDirectDrawSurface7_IsLost(back_buffer);
9332 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9333 IDirectDrawSurface7_Release(back_buffer);
9335 IDirectDrawSurface7_Release(surface);
9336 refcount = IDirectDraw7_Release(ddraw);
9337 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9338 DestroyWindow(window2);
9339 DestroyWindow(window1);
9342 static void test_resource_priority(void)
9344 IDirectDrawSurface7 *surface, *mipmap;
9345 DDSURFACEDESC2 surface_desc;
9346 IDirectDraw7 *ddraw;
9347 ULONG refcount;
9348 HWND window;
9349 HRESULT hr;
9350 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
9351 DDCAPS hal_caps;
9352 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_MIPMAP;
9353 unsigned int i;
9354 DWORD priority;
9355 static const struct
9357 DWORD caps, caps2;
9358 const char *name;
9359 HRESULT hr;
9360 /* SetPriority on offscreenplain surfaces crashes on AMD GPUs on Win7. */
9361 BOOL crash;
9363 test_data[] =
9365 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, "vidmem texture", DDERR_INVALIDPARAMS, FALSE},
9366 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, "sysmem texture", DDERR_INVALIDPARAMS, FALSE},
9367 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, "managed texture", DD_OK, FALSE},
9368 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, "managed texture", DD_OK, FALSE},
9369 {DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP,
9370 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_TEXTUREMANAGE,
9371 "cubemap", DD_OK, FALSE},
9372 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, "vidmem offscreenplain", DDERR_INVALIDOBJECT, TRUE},
9373 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, "sysmem offscreenplain", DDERR_INVALIDOBJECT, TRUE},
9376 window = create_window();
9377 ddraw = create_ddraw();
9378 ok(!!ddraw, "Failed to create a ddraw object.\n");
9379 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9380 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9382 memset(&hal_caps, 0, sizeof(hal_caps));
9383 hal_caps.dwSize = sizeof(hal_caps);
9384 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
9385 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9386 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps
9387 || !(hal_caps.ddsCaps.dwCaps & DDSCAPS2_TEXTUREMANAGE))
9389 skip("Required surface types not supported, skipping test.\n");
9390 goto done;
9393 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
9395 memset(&surface_desc, 0, sizeof(surface_desc));
9396 surface_desc.dwSize = sizeof(surface_desc);
9397 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
9398 surface_desc.dwWidth = 32;
9399 surface_desc.dwHeight = 32;
9400 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
9401 surface_desc.ddsCaps.dwCaps2 = test_data[i].caps2;
9402 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9403 if (is_ddraw64 && (test_data[i].caps & DDSCAPS_TEXTURE))
9405 todo_wine ok(hr == E_NOINTERFACE, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
9406 if (SUCCEEDED(hr))
9407 IDirectDrawSurface7_Release(surface);
9408 continue;
9410 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n", hr, test_data[i].name);
9412 /* Priority == NULL segfaults. */
9413 priority = 0xdeadbeef;
9414 hr = IDirectDrawSurface7_GetPriority(surface, &priority);
9415 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
9416 if (SUCCEEDED(test_data[i].hr))
9417 ok(priority == 0, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
9418 else
9419 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
9421 if (!test_data[i].crash)
9423 hr = IDirectDrawSurface7_SetPriority(surface, 1);
9424 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
9425 hr = IDirectDrawSurface7_GetPriority(surface, &priority);
9426 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
9427 if (SUCCEEDED(test_data[i].hr))
9429 ok(priority == 1, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
9430 hr = IDirectDrawSurface7_SetPriority(surface, 2);
9431 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
9433 else
9434 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
9437 if (test_data[i].caps2 & DDSCAPS2_CUBEMAP)
9439 caps.dwCaps2 = DDSCAPS2_CUBEMAP_NEGATIVEZ;
9440 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
9441 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
9442 /* IDirectDrawSurface7_SetPriority crashes when called on non-positive X surfaces on Windows */
9443 priority = 0xdeadbeef;
9444 hr = IDirectDrawSurface7_GetPriority(mipmap, &priority);
9445 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
9446 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
9448 IDirectDrawSurface7_Release(mipmap);
9451 IDirectDrawSurface7_Release(surface);
9454 if (is_ddraw64)
9455 goto done;
9457 memset(&surface_desc, 0, sizeof(surface_desc));
9458 surface_desc.dwSize = sizeof(surface_desc);
9459 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_MIPMAPCOUNT;
9460 surface_desc.dwWidth = 32;
9461 surface_desc.dwHeight = 32;
9462 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
9463 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
9464 U2(surface_desc).dwMipMapCount = 2;
9465 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9466 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9467 caps.dwCaps2 = 0;
9468 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
9469 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
9471 priority = 0xdeadbeef;
9472 hr = IDirectDrawSurface7_GetPriority(mipmap, &priority);
9473 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type managed mipmap.\n", hr);
9474 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type managed mipmap.\n", priority);
9475 /* SetPriority on the mipmap surface crashes. */
9476 hr = IDirectDrawSurface7_GetPriority(surface, &priority);
9477 ok(SUCCEEDED(hr), "Failed to get priority, hr %#x.\n", hr);
9478 ok(priority == 0, "Got unexpected priority %u, type managed mipmap.\n", priority);
9480 IDirectDrawSurface7_Release(mipmap);
9481 refcount = IDirectDrawSurface7_Release(surface);
9482 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9484 done:
9485 refcount = IDirectDraw7_Release(ddraw);
9486 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9487 DestroyWindow(window);
9490 static void test_surface_desc_lock(void)
9492 IDirectDrawSurface7 *surface;
9493 DDSURFACEDESC2 surface_desc;
9494 IDirectDraw7 *ddraw;
9495 ULONG refcount;
9496 HWND window;
9497 HRESULT hr;
9499 window = create_window();
9500 ddraw = create_ddraw();
9501 ok(!!ddraw, "Failed to create a ddraw object.\n");
9502 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9503 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9505 memset(&surface_desc, 0, sizeof(surface_desc));
9506 surface_desc.dwSize = sizeof(surface_desc);
9507 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
9508 surface_desc.dwWidth = 16;
9509 surface_desc.dwHeight = 16;
9510 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9511 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9512 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9514 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9515 surface_desc.dwSize = sizeof(surface_desc);
9516 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
9517 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
9518 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9520 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9521 surface_desc.dwSize = sizeof(surface_desc);
9522 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, 0, NULL);
9523 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
9524 ok(surface_desc.lpSurface != NULL, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9525 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9526 surface_desc.dwSize = sizeof(surface_desc);
9527 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
9528 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
9529 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9530 hr = IDirectDrawSurface7_Unlock(surface, NULL);
9531 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9533 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9534 surface_desc.dwSize = sizeof(surface_desc);
9535 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
9536 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
9537 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9539 IDirectDrawSurface7_Release(surface);
9540 refcount = IDirectDraw7_Release(ddraw);
9541 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9542 DestroyWindow(window);
9545 static void test_fog_interpolation(void)
9547 HRESULT hr;
9548 IDirect3DDevice7 *device;
9549 IDirectDrawSurface7 *rt;
9550 ULONG refcount;
9551 HWND window;
9552 D3DCOLOR color;
9553 static struct
9555 struct vec3 position;
9556 D3DCOLOR diffuse;
9557 D3DCOLOR specular;
9559 quad[] =
9561 {{-1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff000000},
9562 {{-1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff000000},
9563 {{ 1.0f, -1.0f, 1.0f}, 0xffff0000, 0x00000000},
9564 {{ 1.0f, 1.0f, 1.0f}, 0xffff0000, 0x00000000},
9566 union
9568 DWORD d;
9569 float f;
9570 } conv;
9571 unsigned int i;
9572 static const struct
9574 D3DFOGMODE vfog, tfog;
9575 D3DSHADEMODE shade;
9576 D3DCOLOR middle_color;
9577 BOOL todo;
9579 tests[] =
9581 {D3DFOG_NONE, D3DFOG_NONE, D3DSHADE_FLAT, 0x00007f80, FALSE},
9582 {D3DFOG_NONE, D3DFOG_NONE, D3DSHADE_GOURAUD, 0x00007f80, FALSE},
9583 {D3DFOG_EXP, D3DFOG_NONE, D3DSHADE_FLAT, 0x00007f80, TRUE},
9584 {D3DFOG_EXP, D3DFOG_NONE, D3DSHADE_GOURAUD, 0x00007f80, TRUE},
9585 {D3DFOG_NONE, D3DFOG_EXP, D3DSHADE_FLAT, 0x0000ea15, FALSE},
9586 {D3DFOG_NONE, D3DFOG_EXP, D3DSHADE_GOURAUD, 0x0000ea15, FALSE},
9587 {D3DFOG_EXP, D3DFOG_EXP, D3DSHADE_FLAT, 0x0000ea15, FALSE},
9588 {D3DFOG_EXP, D3DFOG_EXP, D3DSHADE_GOURAUD, 0x0000ea15, FALSE},
9590 D3DDEVICEDESC7 caps;
9592 window = create_window();
9593 if (!(device = create_device(window, DDSCL_NORMAL)))
9595 skip("Failed to create a 3D device, skipping test.\n");
9596 DestroyWindow(window);
9597 return;
9600 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
9601 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9602 hr = IDirect3DDevice7_GetCaps(device, &caps);
9603 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
9604 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE))
9605 skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping some fog tests\n");
9607 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
9608 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9609 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
9610 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9611 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
9612 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9613 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x0000ff00);
9614 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9615 conv.f = 5.0;
9616 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGDENSITY, conv.d);
9617 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9619 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
9620 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
9621 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
9622 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
9623 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x000000ff);
9624 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9626 for (i = 0; i < ARRAY_SIZE(tests); ++i)
9628 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE) && tests[i].tfog)
9629 continue;
9631 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00808080, 0.0f, 0);
9632 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
9634 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SHADEMODE, tests[i].shade);
9635 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9636 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, tests[i].vfog);
9637 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9638 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, tests[i].tfog);
9639 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9640 hr = IDirect3DDevice7_BeginScene(device);
9641 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9642 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9643 D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR, quad, 4, 0);
9644 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9645 hr = IDirect3DDevice7_EndScene(device);
9646 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9648 color = get_surface_color(rt, 0, 240);
9649 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x, case %u.\n", color, i);
9650 color = get_surface_color(rt, 320, 240);
9651 todo_wine_if (tests[i].todo)
9652 ok(compare_color(color, tests[i].middle_color, 2),
9653 "Got unexpected color 0x%08x, case %u.\n", color, i);
9654 color = get_surface_color(rt, 639, 240);
9655 ok(compare_color(color, 0x0000fd02, 2), "Got unexpected color 0x%08x, case %u.\n", color, i);
9658 IDirectDrawSurface7_Release(rt);
9659 refcount = IDirect3DDevice7_Release(device);
9660 ok(!refcount, "Device has %u references left.\n", refcount);
9661 DestroyWindow(window);
9664 static void test_fog_process_vertices(void)
9666 static D3DMATRIX view_matrix =
9668 1.0f, 0.0f, 0.0f, 0.0f,
9669 0.0f, 1.0f, 0.0f, 0.0f,
9670 0.0f, 0.0f, 0.5f, 0.0f,
9671 0.0f, 0.0f, 0.0f, 1.0f
9673 static D3DMATRIX model_matrix =
9675 1.0f, 0.0f, 0.0f, 0.0f,
9676 0.0f, 1.0f, 0.0f, 0.0f,
9677 0.0f, 0.0f, 0.75f, 0.0f,
9678 0.0f, 0.0f, 0.0f, 1.0f
9680 static D3DMATRIX identity_matrix =
9682 1.0f, 0.0f, 0.0f, 0.0f,
9683 0.0f, 1.0f, 0.0f, 0.0f,
9684 0.0f, 0.0f, 1.0f, 0.0f,
9685 0.0f, 0.0f, 0.0f, 1.0f
9688 static D3DLIGHT7 directional_light =
9690 D3DLIGHT_DIRECTIONAL,
9691 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
9692 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
9693 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
9694 {{0.0f}, {0.0f}, {0.0f}},
9695 {{0.0f}, {0.0f}, {1.0f}},
9698 struct vertex
9700 struct vec3 position;
9701 struct vec3 normal;
9703 static const struct
9705 struct vertex vertex;
9706 D3DFOGMODE fog_vertex_mode, fog_table_mode;
9707 BOOL range_fog;
9708 D3DCOLOR expected_color, expected_broken;
9710 tests[] =
9712 /* Some drivers ignore ranged fog state without an obvious reason, even with D3DPRASTERCAPS_FOGRANGE
9713 * set, while some others (including WARP driver on Windows 10) favour it.
9714 * Vertex fog result does not depend on table fog settings. */
9715 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_NONE, D3DFOG_NONE, FALSE, 0x8000ff00},
9716 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_NONE, D3DFOG_LINEAR, FALSE, 0x8000ff00},
9717 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_EXP, D3DFOG_NONE, FALSE, 0xaf00ff00},
9718 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_EXP2, D3DFOG_NONE, FALSE, 0xde00ff00},
9719 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_LINEAR, D3DFOG_NONE, FALSE, 0x9f00ff00},
9720 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_LINEAR, D3DFOG_LINEAR, FALSE, 0x9f00ff00},
9721 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_NONE, D3DFOG_NONE, TRUE, 0x8000ff00},
9722 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_EXP, D3DFOG_NONE, TRUE, 0x8800ff00, 0xaf00ff00},
9723 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_EXP2, D3DFOG_NONE, TRUE, 0xad00ff00, 0xde00ff00},
9724 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_LINEAR, D3DFOG_NONE, TRUE, 0x6000ff00, 0x9f00ff00},
9725 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_LINEAR, D3DFOG_EXP, TRUE, 0x6000ff00, 0x9f00ff00},
9726 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_EXP, D3DFOG_LINEAR, TRUE, 0x8800ff00, 0xaf00ff00},
9729 struct
9731 struct vec4 position;
9732 D3DCOLOR diffuse, specular;
9734 *dst_data;
9736 IDirect3DVertexBuffer7 *src_vb, *dst_vb;
9737 D3DVERTEXBUFFERDESC vb_desc;
9738 IDirect3DDevice7 *device;
9739 struct vertex *src_data;
9740 D3DMATERIAL7 material;
9741 IDirect3D7 *d3d;
9742 ULONG refcount;
9743 unsigned int i;
9744 HWND window;
9745 HRESULT hr;
9747 window = create_window();
9748 if (!(device = create_device(window, DDSCL_NORMAL)))
9750 skip("Failed to create a 3D device, skipping test.\n");
9751 DestroyWindow(window);
9752 return;
9754 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
9755 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9757 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &model_matrix);
9758 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9759 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &view_matrix);
9760 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9761 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &identity_matrix);
9762 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9764 memset(&vb_desc, 0, sizeof(vb_desc));
9765 vb_desc.dwSize = sizeof(vb_desc);
9766 vb_desc.dwFVF = D3DFVF_XYZ | D3DFVF_NORMAL;
9767 vb_desc.dwNumVertices = 1;
9768 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &src_vb, 0);
9769 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9771 memset(&vb_desc, 0, sizeof(vb_desc));
9772 vb_desc.dwSize = sizeof(vb_desc);
9773 vb_desc.dwFVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR;
9774 vb_desc.dwNumVertices = 1;
9775 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &dst_vb, 0);
9776 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9778 hr = IDirect3DDevice7_LightEnable(device, 0, TRUE);
9779 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9780 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, TRUE);
9781 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9782 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
9783 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9784 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
9785 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9786 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
9787 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9789 hr = IDirect3DDevice7_SetLight(device, 0, &directional_light);
9790 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9792 memset(&material, 0, sizeof(material));
9793 U1(U2(material).specular).r = 0.0f;
9794 U2(U2(material).specular).g = 1.0f;
9795 U3(U2(material).specular).b = 0.0f;
9796 U4(U2(material).specular).a = 0.5f;
9797 U4(material).power = 5.0f;
9798 hr = IDirect3DDevice7_SetMaterial(device, &material);
9799 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9801 for (i = 0; i < ARRAY_SIZE(tests); ++i)
9803 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE,
9804 tests[i].fog_vertex_mode);
9805 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE,
9806 tests[i].fog_table_mode);
9807 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9808 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_RANGEFOGENABLE, tests[i].range_fog);
9809 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9811 hr = IDirect3DVertexBuffer7_Lock(src_vb, 0, (void **)&src_data, NULL);
9812 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9813 *src_data = tests[i].vertex;
9814 hr = IDirect3DVertexBuffer7_Unlock(src_vb);
9815 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9817 hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL);
9818 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9819 memset(dst_data, 0, sizeof(*dst_data));
9820 hr = IDirect3DVertexBuffer7_Unlock(dst_vb);
9821 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9822 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 0,
9823 1, src_vb, 0, device, 0);
9824 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9826 hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL);
9827 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9829 ok(compare_color(dst_data->specular, tests[i].expected_color, 1)
9830 || broken(tests[i].expected_broken
9831 && compare_color(dst_data->specular, tests[i].expected_broken, 1)),
9832 "Expected color 0x%08x, got 0x%08x, test %u.\n",
9833 tests[i].expected_color, dst_data->specular, i);
9835 hr = IDirect3DVertexBuffer7_Unlock(dst_vb);
9836 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9839 IDirect3DVertexBuffer7_Release(dst_vb);
9840 IDirect3DVertexBuffer7_Release(src_vb);
9841 IDirect3D7_Release(d3d);
9842 refcount = IDirect3DDevice7_Release(device);
9843 ok(!refcount, "Device has %u references left.\n", refcount);
9844 DestroyWindow(window);
9847 static void test_negative_fixedfunction_fog(void)
9849 HRESULT hr;
9850 IDirect3DDevice7 *device;
9851 IDirectDrawSurface7 *rt;
9852 ULONG refcount;
9853 HWND window;
9854 D3DCOLOR color;
9855 static struct
9857 struct vec3 position;
9858 D3DCOLOR diffuse;
9860 quad[] =
9862 {{-1.0f, -1.0f, -0.5f}, 0xffff0000},
9863 {{-1.0f, 1.0f, -0.5f}, 0xffff0000},
9864 {{ 1.0f, -1.0f, -0.5f}, 0xffff0000},
9865 {{ 1.0f, 1.0f, -0.5f}, 0xffff0000},
9867 static struct
9869 struct vec4 position;
9870 D3DCOLOR diffuse;
9872 tquad[] =
9874 {{ 0.0f, 0.0f, -0.5f, 1.0f}, 0xffff0000},
9875 {{640.0f, 0.0f, -0.5f, 1.0f}, 0xffff0000},
9876 {{ 0.0f, 480.0f, -0.5f, 1.0f}, 0xffff0000},
9877 {{640.0f, 480.0f, -0.5f, 1.0f}, 0xffff0000},
9879 unsigned int i;
9880 static D3DMATRIX zero =
9882 1.0f, 0.0f, 0.0f, 0.0f,
9883 0.0f, 1.0f, 0.0f, 0.0f,
9884 0.0f, 0.0f, 0.0f, 0.0f,
9885 0.0f, 0.0f, 0.0f, 1.0f
9887 static D3DMATRIX identity =
9889 1.0f, 0.0f, 0.0f, 0.0f,
9890 0.0f, 1.0f, 0.0f, 0.0f,
9891 0.0f, 0.0f, 1.0f, 0.0f,
9892 0.0f, 0.0f, 0.0f, 1.0f
9894 static const struct
9896 DWORD pos_type;
9897 void *quad;
9898 D3DMATRIX *matrix;
9899 union
9901 float f;
9902 DWORD d;
9903 } start, end;
9904 D3DFOGMODE vfog, tfog;
9905 DWORD color, color_broken, color_broken2;
9907 tests[] =
9909 /* Run the XYZRHW tests first. Depth clamping is broken after RHW draws on the testbot.
9911 * Geforce8+ GPUs on Windows abs() table fog, everything else does not. */
9912 {D3DFVF_XYZRHW, tquad, &identity, { 0.0f}, {1.0f}, D3DFOG_NONE, D3DFOG_LINEAR,
9913 0x00ff0000, 0x00808000, 0x00808000},
9914 /* r200 GPUs and presumably all d3d8 and older HW clamp the fog
9915 * parameters to 0.0 and 1.0 in the table fog case. */
9916 {D3DFVF_XYZRHW, tquad, &identity, {-1.0f}, {0.0f}, D3DFOG_NONE, D3DFOG_LINEAR,
9917 0x00808000, 0x00ff0000, 0x0000ff00},
9918 /* test_fog_interpolation shows that vertex fog evaluates the fog
9919 * equation in the vertex pipeline. Start = -1.0 && end = 0.0 shows
9920 * that the abs happens before the fog equation is evaluated.
9922 * Vertex fog abs() behavior is the same on all GPUs. */
9923 {D3DFVF_XYZ, quad, &zero, { 0.0f}, {1.0f}, D3DFOG_LINEAR, D3DFOG_NONE,
9924 0x00808000, 0x00808000, 0x00808000},
9925 {D3DFVF_XYZ, quad, &zero, {-1.0f}, {0.0f}, D3DFOG_LINEAR, D3DFOG_NONE,
9926 0x0000ff00, 0x0000ff00, 0x0000ff00},
9927 {D3DFVF_XYZ, quad, &zero, { 0.0f}, {1.0f}, D3DFOG_EXP, D3DFOG_NONE,
9928 0x009b6400, 0x009b6400, 0x009b6400},
9930 D3DDEVICEDESC7 caps;
9932 window = create_window();
9933 if (!(device = create_device(window, DDSCL_NORMAL)))
9935 skip("Failed to create a 3D device, skipping test.\n");
9936 DestroyWindow(window);
9937 return;
9940 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
9941 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9942 hr = IDirect3DDevice7_GetCaps(device, &caps);
9943 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
9944 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE))
9945 skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping some fog tests.\n");
9947 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
9948 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9949 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
9950 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9951 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
9952 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9953 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x0000ff00);
9954 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9955 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
9956 ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
9958 for (i = 0; i < ARRAY_SIZE(tests); ++i)
9960 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE) && tests[i].tfog)
9961 continue;
9963 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0);
9964 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
9966 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, tests[i].matrix);
9967 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
9968 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGSTART, tests[i].start.d);
9969 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9970 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGEND, tests[i].end.d);
9971 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9972 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, tests[i].vfog);
9973 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9974 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, tests[i].tfog);
9975 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9977 hr = IDirect3DDevice7_BeginScene(device);
9978 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9979 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9980 tests[i].pos_type | D3DFVF_DIFFUSE, tests[i].quad, 4, 0);
9981 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9982 hr = IDirect3DDevice7_EndScene(device);
9983 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9985 color = get_surface_color(rt, 0, 240);
9986 ok(compare_color(color, tests[i].color, 2) || broken(compare_color(color, tests[i].color_broken, 2))
9987 || broken(compare_color(color, tests[i].color_broken2, 2)),
9988 "Got unexpected color 0x%08x, case %u.\n", color, i);
9991 IDirectDrawSurface7_Release(rt);
9992 refcount = IDirect3DDevice7_Release(device);
9993 ok(!refcount, "Device has %u references left.\n", refcount);
9994 DestroyWindow(window);
9997 static void test_table_fog_zw(void)
9999 HRESULT hr;
10000 IDirect3DDevice7 *device;
10001 IDirectDrawSurface7 *rt;
10002 ULONG refcount;
10003 HWND window;
10004 D3DCOLOR color;
10005 static struct
10007 struct vec4 position;
10008 D3DCOLOR diffuse;
10010 quad[] =
10012 {{ 0.0f, 0.0f, 0.0f, 0.0f}, 0xffff0000},
10013 {{640.0f, 0.0f, 0.0f, 0.0f}, 0xffff0000},
10014 {{ 0.0f, 480.0f, 0.0f, 0.0f}, 0xffff0000},
10015 {{640.0f, 480.0f, 0.0f, 0.0f}, 0xffff0000},
10017 static D3DMATRIX identity =
10019 1.0f, 0.0f, 0.0f, 0.0f,
10020 0.0f, 1.0f, 0.0f, 0.0f,
10021 0.0f, 0.0f, 1.0f, 0.0f,
10022 0.0f, 0.0f, 0.0f, 1.0f
10024 D3DDEVICEDESC7 caps;
10025 static const struct
10027 float z, w;
10028 D3DZBUFFERTYPE z_test;
10029 D3DCOLOR color;
10031 tests[] =
10033 {0.7f, 0.0f, D3DZB_TRUE, 0x004cb200},
10034 {0.7f, 0.0f, D3DZB_FALSE, 0x004cb200},
10035 {0.7f, 0.3f, D3DZB_TRUE, 0x004cb200},
10036 {0.7f, 0.3f, D3DZB_FALSE, 0x004cb200},
10037 {0.7f, 3.0f, D3DZB_TRUE, 0x004cb200},
10038 {0.7f, 3.0f, D3DZB_FALSE, 0x004cb200},
10039 {0.3f, 0.0f, D3DZB_TRUE, 0x00b24c00},
10040 {0.3f, 0.0f, D3DZB_FALSE, 0x00b24c00},
10042 unsigned int i;
10044 window = create_window();
10045 if (!(device = create_device(window, DDSCL_NORMAL)))
10047 skip("Failed to create a 3D device, skipping test.\n");
10048 DestroyWindow(window);
10049 return;
10052 hr = IDirect3DDevice7_GetCaps(device, &caps);
10053 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10054 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE))
10056 skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping POSITIONT table fog test.\n");
10057 goto done;
10059 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
10060 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10062 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
10063 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10064 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
10065 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10066 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x0000ff00);
10067 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10068 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
10069 ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10070 /* Work around an AMD Windows driver bug. Needs a proj matrix applied redundantly. */
10071 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &identity);
10072 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
10073 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_LINEAR);
10074 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10076 for (i = 0; i < ARRAY_SIZE(tests); ++i)
10078 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x000000ff, 1.0f, 0);
10079 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10081 quad[0].position.z = tests[i].z;
10082 quad[1].position.z = tests[i].z;
10083 quad[2].position.z = tests[i].z;
10084 quad[3].position.z = tests[i].z;
10085 quad[0].position.w = tests[i].w;
10086 quad[1].position.w = tests[i].w;
10087 quad[2].position.w = tests[i].w;
10088 quad[3].position.w = tests[i].w;
10089 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, tests[i].z_test);
10090 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10092 hr = IDirect3DDevice7_BeginScene(device);
10093 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10094 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
10095 D3DFVF_XYZRHW | D3DFVF_DIFFUSE, quad, 4, 0);
10096 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10097 hr = IDirect3DDevice7_EndScene(device);
10098 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10100 color = get_surface_color(rt, 0, 240);
10101 ok(compare_color(color, tests[i].color, 2),
10102 "Got unexpected color 0x%08x, expected 0x%8x, case %u.\n", color, tests[i].color, i);
10105 IDirectDrawSurface7_Release(rt);
10106 done:
10107 refcount = IDirect3DDevice7_Release(device);
10108 ok(!refcount, "Device has %u references left.\n", refcount);
10109 DestroyWindow(window);
10112 static void test_signed_formats(void)
10114 HRESULT hr;
10115 IDirect3DDevice7 *device;
10116 IDirect3D7 *d3d;
10117 IDirectDraw7 *ddraw;
10118 IDirectDrawSurface7 *surface, *rt;
10119 DDSURFACEDESC2 surface_desc;
10120 ULONG refcount;
10121 HWND window;
10122 D3DCOLOR color, expected_color;
10123 static struct
10125 struct vec3 position;
10126 struct vec2 texcoord;
10128 quad[] =
10130 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
10131 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
10132 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
10133 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
10135 /* See test_signed_formats() in dlls/d3d9/tests/visual.c for an explanation
10136 * of these values. */
10137 static const USHORT content_v8u8[4][4] =
10139 {0x0000, 0x7f7f, 0x8880, 0x0000},
10140 {0x0080, 0x8000, 0x7f00, 0x007f},
10141 {0x193b, 0xe8c8, 0x0808, 0xf8f8},
10142 {0x4444, 0xc0c0, 0xa066, 0x22e0},
10144 static const DWORD content_x8l8v8u8[4][4] =
10146 {0x00000000, 0x00ff7f7f, 0x00008880, 0x00ff0000},
10147 {0x00000080, 0x00008000, 0x00007f00, 0x0000007f},
10148 {0x0041193b, 0x0051e8c8, 0x00040808, 0x00fff8f8},
10149 {0x00824444, 0x0000c0c0, 0x00c2a066, 0x009222e0},
10151 static const USHORT content_l6v5u5[4][4] =
10153 {0x0000, 0xfdef, 0x0230, 0xfc00},
10154 {0x0010, 0x0200, 0x01e0, 0x000f},
10155 {0x4067, 0x53b9, 0x0421, 0xffff},
10156 {0x8108, 0x0318, 0xc28c, 0x909c},
10158 static const struct
10160 const char *name;
10161 const void *content;
10162 SIZE_T pixel_size;
10163 BOOL blue;
10164 unsigned int slop, slop_broken;
10165 DDPIXELFORMAT format;
10167 formats[] =
10170 "D3DFMT_V8U8", content_v8u8, sizeof(WORD), FALSE, 1, 0,
10172 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV, 0,
10173 {16}, {0x000000ff}, {0x0000ff00}, {0x00000000}, {0x00000000}
10177 "D3DFMT_X8L8V8U8", content_x8l8v8u8, sizeof(DWORD), TRUE, 1, 0,
10179 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE, 0,
10180 {32}, {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}
10184 "D3DFMT_L6V5U5", content_l6v5u5, sizeof(WORD), TRUE, 4, 7,
10186 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE, 0,
10187 {16}, {0x0000001f}, {0x000003e0}, {0x0000fc00}, {0x00000000}
10191 /* No V16U16 or Q8W8V8U8 support in ddraw. */
10193 static const D3DCOLOR expected_colors[4][4] =
10195 {0x00808080, 0x00fefeff, 0x00010780, 0x008080ff},
10196 {0x00018080, 0x00800180, 0x0080fe80, 0x00fe8080},
10197 {0x00ba98a0, 0x004767a8, 0x00888881, 0x007878ff},
10198 {0x00c3c3c0, 0x003f3f80, 0x00e51fe1, 0x005fa2c8},
10200 unsigned int i, width, x, y;
10201 D3DDEVICEDESC7 device_desc;
10203 window = create_window();
10204 if (!(device = create_device(window, DDSCL_NORMAL)))
10206 skip("Failed to create a 3D device, skipping test.\n");
10207 DestroyWindow(window);
10208 return;
10211 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
10212 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10213 if (!(device_desc.dwTextureOpCaps & D3DTEXOPCAPS_BLENDFACTORALPHA))
10215 skip("D3DTOP_BLENDFACTORALPHA not supported, skipping bumpmap format tests.\n");
10216 goto done;
10219 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
10220 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
10221 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
10222 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
10223 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
10224 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10226 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
10227 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10229 /* dst = tex * 0.5 + 1.0 * (1.0 - 0.5) = tex * 0.5 + 0.5 */
10230 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x80ffffff);
10231 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10232 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_BLENDFACTORALPHA);
10233 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
10234 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
10235 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
10236 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
10237 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
10239 for (i = 0; i < ARRAY_SIZE(formats); ++i)
10241 for (width = 1; width < 5; width += 3)
10243 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
10244 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
10246 memset(&surface_desc, 0, sizeof(surface_desc));
10247 surface_desc.dwSize = sizeof(surface_desc);
10248 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
10249 surface_desc.dwWidth = width;
10250 surface_desc.dwHeight = 4;
10251 U4(surface_desc).ddpfPixelFormat = formats[i].format;
10252 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
10253 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10254 if (FAILED(hr))
10256 skip("%s textures not supported, skipping.\n", formats[i].name);
10257 continue;
10259 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, format %s.\n", hr, formats[i].name);
10260 hr = IDirect3DDevice7_SetTexture(device, 0, surface);
10261 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x, format %s.\n", hr, formats[i].name);
10263 memset(&surface_desc, 0, sizeof(surface_desc));
10264 surface_desc.dwSize = sizeof(surface_desc);
10265 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, 0, NULL);
10266 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, format %s.\n", hr, formats[i].name);
10267 for (y = 0; y < 4; y++)
10269 memcpy((char *)surface_desc.lpSurface + y * U1(surface_desc).lPitch,
10270 (char *)formats[i].content + y * 4 * formats[i].pixel_size,
10271 width * formats[i].pixel_size);
10273 hr = IDirectDrawSurface7_Unlock(surface, NULL);
10274 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, format %s.\n", hr, formats[i].name);
10276 hr = IDirect3DDevice7_BeginScene(device);
10277 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10278 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
10279 D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
10280 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10281 hr = IDirect3DDevice7_EndScene(device);
10282 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10284 for (y = 0; y < 4; y++)
10286 for (x = 0; x < width; x++)
10288 expected_color = expected_colors[y][x];
10289 if (!formats[i].blue)
10290 expected_color |= 0x000000ff;
10292 color = get_surface_color(rt, 80 + 160 * x, 60 + 120 * y);
10293 ok(compare_color(color, expected_color, formats[i].slop)
10294 || broken(compare_color(color, expected_color, formats[i].slop_broken)),
10295 "Expected color 0x%08x, got 0x%08x, format %s, location %ux%u.\n",
10296 expected_color, color, formats[i].name, x, y);
10300 IDirectDrawSurface7_Release(surface);
10305 IDirectDrawSurface7_Release(rt);
10306 IDirectDraw7_Release(ddraw);
10307 IDirect3D7_Release(d3d);
10309 done:
10310 refcount = IDirect3DDevice7_Release(device);
10311 ok(!refcount, "Device has %u references left.\n", refcount);
10312 DestroyWindow(window);
10315 static void test_color_fill(void)
10317 HRESULT hr;
10318 IDirect3DDevice7 *device;
10319 IDirect3D7 *d3d;
10320 IDirectDraw7 *ddraw;
10321 IDirectDrawSurface7 *surface, *surface2;
10322 DDSURFACEDESC2 surface_desc;
10323 DDPIXELFORMAT z_fmt;
10324 ULONG refcount;
10325 HWND window;
10326 unsigned int i;
10327 DDBLTFX fx;
10328 RECT rect = {5, 5, 7, 7};
10329 DWORD *color;
10330 DWORD supported_fmts = 0, num_fourcc_codes, *fourcc_codes;
10331 DDCAPS hal_caps;
10332 static const struct
10334 DWORD caps, caps2;
10335 HRESULT colorfill_hr, depthfill_hr;
10336 BOOL rop_success;
10337 const char *name;
10338 DWORD result;
10339 BOOL check_result;
10340 DDPIXELFORMAT format;
10342 tests[] =
10345 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
10346 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain RGB", 0xdeadbeef, TRUE,
10348 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
10349 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
10353 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0,
10354 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain RGB", 0xdeadbeef, TRUE,
10356 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
10357 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
10361 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0,
10362 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem texture RGB", 0xdeadbeef, TRUE,
10364 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
10365 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
10369 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0,
10370 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem texture RGB", 0xdeadbeef, TRUE,
10372 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
10373 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
10377 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
10378 DD_OK, DDERR_INVALIDPARAMS, TRUE, "managed texture RGB", 0xdeadbeef, TRUE,
10380 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
10381 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
10385 DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY, 0,
10386 DDERR_INVALIDPARAMS, DD_OK, TRUE, "vidmem zbuffer", 0xdeadbeef, TRUE,
10387 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
10390 DDSCAPS_ZBUFFER | DDSCAPS_SYSTEMMEMORY, 0,
10391 DDERR_INVALIDPARAMS, DD_OK, TRUE, "sysmem zbuffer", 0xdeadbeef, TRUE,
10392 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
10395 /* Colorfill on YUV surfaces always returns DD_OK, but the content is
10396 * different afterwards. DX9+ GPUs set one of the two luminance values
10397 * in each block, but AMD and Nvidia GPUs disagree on which luminance
10398 * value they set. r200 (dx8) just sets the entire block to the clear
10399 * value. */
10400 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
10401 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain YUY2", 0, FALSE,
10403 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
10404 {0}, {0}, {0}, {0}, {0}
10408 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
10409 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain UYVY", 0, FALSE,
10411 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
10412 {0}, {0}, {0}, {0}, {0}
10416 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY, 0,
10417 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay YUY2", 0, FALSE,
10419 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
10420 {0}, {0}, {0}, {0}, {0}
10424 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY, 0,
10425 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay UYVY", 0, FALSE,
10427 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
10428 {0}, {0}, {0}, {0}, {0}
10432 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0,
10433 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "vidmem texture DXT1", 0, FALSE,
10435 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
10436 {0}, {0}, {0}, {0}, {0}
10440 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0,
10441 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "sysmem texture DXT1", 0, FALSE,
10443 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
10444 {0}, {0}, {0}, {0}, {0}
10448 /* The testbot fills this with 0x00 instead of the blue channel. The sysmem
10449 * surface works, presumably because it is handled by the runtime instead of
10450 * the driver. */
10451 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
10452 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain P8", 0xefefefef, FALSE,
10454 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
10455 {8}, {0}, {0}, {0}, {0}
10459 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0,
10460 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain P8", 0xefefefef, TRUE,
10462 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
10463 {8}, {0}, {0}, {0}, {0}
10467 static const struct
10469 DWORD rop;
10470 const char *name;
10471 HRESULT hr;
10473 rops[] =
10475 {SRCCOPY, "SRCCOPY", DD_OK},
10476 {SRCPAINT, "SRCPAINT", DDERR_NORASTEROPHW},
10477 {SRCAND, "SRCAND", DDERR_NORASTEROPHW},
10478 {SRCINVERT, "SRCINVERT", DDERR_NORASTEROPHW},
10479 {SRCERASE, "SRCERASE", DDERR_NORASTEROPHW},
10480 {NOTSRCCOPY, "NOTSRCCOPY", DDERR_NORASTEROPHW},
10481 {NOTSRCERASE, "NOTSRCERASE", DDERR_NORASTEROPHW},
10482 {MERGECOPY, "MERGECOPY", DDERR_NORASTEROPHW},
10483 {MERGEPAINT, "MERGEPAINT", DDERR_NORASTEROPHW},
10484 {PATCOPY, "PATCOPY", DDERR_NORASTEROPHW},
10485 {PATPAINT, "PATPAINT", DDERR_NORASTEROPHW},
10486 {PATINVERT, "PATINVERT", DDERR_NORASTEROPHW},
10487 {DSTINVERT, "DSTINVERT", DDERR_NORASTEROPHW},
10488 {BLACKNESS, "BLACKNESS", DD_OK},
10489 {WHITENESS, "WHITENESS", DD_OK},
10490 {0xaa0029, "0xaa0029", DDERR_NORASTEROPHW} /* noop */
10493 window = create_window();
10494 if (!(device = create_device(window, DDSCL_NORMAL)))
10496 skip("Failed to create a 3D device, skipping test.\n");
10497 DestroyWindow(window);
10498 return;
10501 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
10502 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
10503 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
10504 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
10506 memset(&z_fmt, 0, sizeof(z_fmt));
10507 IDirect3D7_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
10508 if (!z_fmt.dwSize)
10509 skip("No Z buffer formats supported, skipping Z buffer colorfill test.\n");
10511 IDirect3DDevice7_EnumTextureFormats(device, test_block_formats_creation_cb, &supported_fmts);
10512 if (!(supported_fmts & SUPPORT_DXT1))
10513 skip("DXT1 textures not supported, skipping DXT1 colorfill test.\n");
10515 IDirect3D7_Release(d3d);
10517 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
10518 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
10519 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
10520 num_fourcc_codes * sizeof(*fourcc_codes));
10521 if (!fourcc_codes)
10522 goto done;
10523 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
10524 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
10525 for (i = 0; i < num_fourcc_codes; i++)
10527 if (fourcc_codes[i] == MAKEFOURCC('Y', 'U', 'Y', '2'))
10528 supported_fmts |= SUPPORT_YUY2;
10529 else if (fourcc_codes[i] == MAKEFOURCC('U', 'Y', 'V', 'Y'))
10530 supported_fmts |= SUPPORT_UYVY;
10532 HeapFree(GetProcessHeap(), 0, fourcc_codes);
10534 memset(&hal_caps, 0, sizeof(hal_caps));
10535 hal_caps.dwSize = sizeof(hal_caps);
10536 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
10537 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
10539 if (!(supported_fmts & (SUPPORT_YUY2 | SUPPORT_UYVY)) || !(hal_caps.dwCaps & DDCAPS_OVERLAY))
10540 skip("Overlays or some YUV formats not supported, skipping YUV colorfill tests.\n");
10542 for (i = 0; i < ARRAY_SIZE(tests); ++i)
10544 DWORD expected_broken = tests[i].result;
10546 /* Some Windows drivers modify dwFillColor when it is used on P8 or FourCC formats. */
10547 memset(&fx, 0, sizeof(fx));
10548 fx.dwSize = sizeof(fx);
10549 U5(fx).dwFillColor = 0xdeadbeef;
10551 memset(&surface_desc, 0, sizeof(surface_desc));
10552 surface_desc.dwSize = sizeof(surface_desc);
10553 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10554 surface_desc.dwWidth = 64;
10555 surface_desc.dwHeight = 64;
10556 U4(surface_desc).ddpfPixelFormat = tests[i].format;
10557 surface_desc.ddsCaps.dwCaps = tests[i].caps;
10558 surface_desc.ddsCaps.dwCaps2 = tests[i].caps2;
10560 if (tests[i].format.dwFourCC == MAKEFOURCC('D','X','T','1') && !(supported_fmts & SUPPORT_DXT1))
10561 continue;
10562 if (tests[i].format.dwFourCC == MAKEFOURCC('Y','U','Y','2') && !(supported_fmts & SUPPORT_YUY2))
10563 continue;
10564 if (tests[i].format.dwFourCC == MAKEFOURCC('U','Y','V','Y') && !(supported_fmts & SUPPORT_UYVY))
10565 continue;
10566 if (tests[i].caps & DDSCAPS_OVERLAY && !(hal_caps.dwCaps & DDCAPS_OVERLAY))
10567 continue;
10569 if (tests[i].caps & DDSCAPS_ZBUFFER)
10571 if (!z_fmt.dwSize)
10572 continue;
10574 U4(surface_desc).ddpfPixelFormat = z_fmt;
10575 /* Some drivers seem to convert depth values incorrectly or not at
10576 * all. Affects at least AMD PALM, 8.17.10.1247. */
10577 if (tests[i].caps & DDSCAPS_VIDEOMEMORY)
10579 DWORD expected;
10580 float f, g;
10582 expected = tests[i].result & U3(z_fmt).dwZBitMask;
10583 f = ceilf(logf(expected + 1.0f) / logf(2.0f));
10584 g = (f + 1.0f) / 2.0f;
10585 g -= (int)g;
10586 expected_broken = (expected / exp2f(f) - g) * 256;
10587 expected_broken *= 0x01010101;
10591 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10592 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, surface %s.\n", hr, tests[i].name);
10594 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10595 todo_wine_if (tests[i].format.dwFourCC)
10596 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
10597 hr, tests[i].colorfill_hr, tests[i].name);
10599 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10600 todo_wine_if (tests[i].format.dwFourCC)
10601 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
10602 hr, tests[i].colorfill_hr, tests[i].name);
10604 if (SUCCEEDED(hr) && tests[i].check_result)
10606 memset(&surface_desc, 0, sizeof(surface_desc));
10607 surface_desc.dwSize = sizeof(surface_desc);
10608 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
10609 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10610 color = surface_desc.lpSurface;
10611 ok(*color == tests[i].result, "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
10612 *color, tests[i].result, tests[i].name);
10613 hr = IDirectDrawSurface7_Unlock(surface, NULL);
10614 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10617 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10618 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
10619 hr, tests[i].depthfill_hr, tests[i].name);
10620 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10621 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
10622 hr, tests[i].depthfill_hr, tests[i].name);
10624 if (SUCCEEDED(hr) && tests[i].check_result)
10626 memset(&surface_desc, 0, sizeof(surface_desc));
10627 surface_desc.dwSize = sizeof(surface_desc);
10628 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
10629 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10630 color = surface_desc.lpSurface;
10631 ok((*color & U3(z_fmt).dwZBitMask) == (tests[i].result & U3(z_fmt).dwZBitMask)
10632 || broken((*color & U3(z_fmt).dwZBitMask) == (expected_broken & U3(z_fmt).dwZBitMask)),
10633 "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
10634 *color & U3(z_fmt).dwZBitMask, tests[i].result & U3(z_fmt).dwZBitMask, tests[i].name);
10635 hr = IDirectDrawSurface7_Unlock(surface, NULL);
10636 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10639 U5(fx).dwFillColor = 0xdeadbeef;
10640 fx.dwROP = BLACKNESS;
10641 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
10642 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
10643 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
10644 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
10645 U5(fx).dwFillColor, tests[i].name);
10647 if (SUCCEEDED(hr) && tests[i].check_result)
10649 memset(&surface_desc, 0, sizeof(surface_desc));
10650 surface_desc.dwSize = sizeof(surface_desc);
10651 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
10652 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10653 color = surface_desc.lpSurface;
10654 ok(*color == 0, "Got clear result 0x%08x, expected 0x00000000, surface %s.\n",
10655 *color, tests[i].name);
10656 hr = IDirectDrawSurface7_Unlock(surface, NULL);
10657 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10660 fx.dwROP = WHITENESS;
10661 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
10662 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
10663 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
10664 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
10665 U5(fx).dwFillColor, tests[i].name);
10667 if (SUCCEEDED(hr) && tests[i].check_result)
10669 memset(&surface_desc, 0, sizeof(surface_desc));
10670 surface_desc.dwSize = sizeof(surface_desc);
10671 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
10672 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10673 color = surface_desc.lpSurface;
10674 /* WHITENESS sets the alpha channel to 0x00. Ignore this for now. */
10675 ok((*color & 0x00ffffff) == 0x00ffffff, "Got clear result 0x%08x, expected 0xffffffff, surface %s.\n",
10676 *color, tests[i].name);
10677 hr = IDirectDrawSurface7_Unlock(surface, NULL);
10678 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10681 IDirectDrawSurface7_Release(surface);
10684 memset(&fx, 0, sizeof(fx));
10685 fx.dwSize = sizeof(fx);
10686 U5(fx).dwFillColor = 0xdeadbeef;
10687 fx.dwROP = WHITENESS;
10689 memset(&surface_desc, 0, sizeof(surface_desc));
10690 surface_desc.dwSize = sizeof(surface_desc);
10691 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10692 surface_desc.dwWidth = 64;
10693 surface_desc.dwHeight = 64;
10694 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
10695 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
10696 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
10697 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
10698 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
10699 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
10700 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
10701 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10702 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10703 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
10704 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10706 /* No DDBLTFX. */
10707 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, NULL);
10708 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10709 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, NULL);
10710 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10712 /* Unused source rectangle. */
10713 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10714 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10715 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10716 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10718 /* Unused source surface. */
10719 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10720 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10721 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
10722 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10723 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10724 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10725 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10726 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10728 /* Inverted destination or source rectangle. */
10729 SetRect(&rect, 5, 7, 7, 5);
10730 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10731 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10732 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10733 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10734 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10735 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10736 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10737 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10738 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10739 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10741 /* Negative rectangle. */
10742 SetRect(&rect, -1, -1, 5, 5);
10743 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10744 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10745 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10746 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10747 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10748 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10749 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10750 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10751 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10752 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10754 /* Out of bounds rectangle. */
10755 SetRect(&rect, 0, 0, 65, 65);
10756 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10757 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10758 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10759 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10761 /* Combine multiple flags. */
10762 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10763 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10764 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
10765 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10766 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
10767 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10769 for (i = 0; i < ARRAY_SIZE(rops); ++i)
10771 fx.dwROP = rops[i].rop;
10772 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
10773 ok(hr == rops[i].hr, "Got unexpected hr %#x for rop %s.\n", hr, rops[i].name);
10776 IDirectDrawSurface7_Release(surface2);
10777 IDirectDrawSurface7_Release(surface);
10779 if (!z_fmt.dwSize)
10780 goto done;
10782 memset(&surface_desc, 0, sizeof(surface_desc));
10783 surface_desc.dwSize = sizeof(surface_desc);
10784 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10785 surface_desc.dwWidth = 64;
10786 surface_desc.dwHeight = 64;
10787 U4(surface_desc).ddpfPixelFormat = z_fmt;
10788 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
10789 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10790 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10791 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
10792 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10794 /* No DDBLTFX. */
10795 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, NULL);
10796 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10798 /* Unused source rectangle. */
10799 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10800 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10802 /* Unused source surface. */
10803 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10804 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10805 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10806 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10808 /* Inverted destination or source rectangle. */
10809 SetRect(&rect, 5, 7, 7, 5);
10810 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10811 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10812 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10813 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10814 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10815 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10816 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10817 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10819 /* Negative rectangle. */
10820 SetRect(&rect, -1, -1, 5, 5);
10821 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10822 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10823 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10824 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10825 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10826 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10827 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10828 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10830 /* Out of bounds rectangle. */
10831 SetRect(&rect, 0, 0, 65, 65);
10832 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10833 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10835 /* Combine multiple flags. */
10836 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10837 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10839 IDirectDrawSurface7_Release(surface2);
10840 IDirectDrawSurface7_Release(surface);
10842 done:
10843 IDirectDraw7_Release(ddraw);
10844 refcount = IDirect3DDevice7_Release(device);
10845 ok(!refcount, "Device has %u references left.\n", refcount);
10846 DestroyWindow(window);
10849 static void test_texcoordindex(void)
10851 static D3DMATRIX mat =
10853 1.0f, 0.0f, 0.0f, 0.0f,
10854 0.0f, 0.0f, 0.0f, 0.0f,
10855 0.0f, 0.0f, 0.0f, 0.0f,
10856 0.0f, 0.0f, 0.0f, 0.0f,
10858 static struct
10860 struct vec3 pos;
10861 struct vec2 texcoord1;
10862 struct vec2 texcoord2;
10863 struct vec2 texcoord3;
10865 quad[] =
10867 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f}},
10868 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 0.0f}},
10869 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}},
10870 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}},
10872 static const DWORD fvf = D3DFVF_XYZ | D3DFVF_TEX3;
10873 IDirect3DDevice7 *device;
10874 IDirect3D7 *d3d;
10875 IDirectDraw7 *ddraw;
10876 IDirectDrawSurface7 *rt;
10877 HWND window;
10878 HRESULT hr;
10879 IDirectDrawSurface7 *texture1, *texture2;
10880 DDSURFACEDESC2 surface_desc;
10881 ULONG refcount;
10882 D3DCOLOR color;
10883 DWORD *ptr;
10885 window = create_window();
10886 if (!(device = create_device(window, DDSCL_NORMAL)))
10888 skip("Failed to create a 3D device, skipping test.\n");
10889 DestroyWindow(window);
10890 return;
10893 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
10894 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
10895 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
10896 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
10897 IDirect3D7_Release(d3d);
10899 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
10900 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10902 memset(&surface_desc, 0, sizeof(surface_desc));
10903 surface_desc.dwSize = sizeof(surface_desc);
10904 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10905 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
10906 surface_desc.dwWidth = 2;
10907 surface_desc.dwHeight = 2;
10908 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
10909 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
10910 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
10911 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
10912 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
10913 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
10914 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
10915 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture1, NULL);
10916 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10917 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture2, NULL);
10918 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10920 memset(&surface_desc, 0, sizeof(surface_desc));
10921 surface_desc.dwSize = sizeof(surface_desc);
10922 hr = IDirectDrawSurface7_Lock(texture1, 0, &surface_desc, 0, NULL);
10923 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10924 ptr = surface_desc.lpSurface;
10925 ptr[0] = 0xff000000;
10926 ptr[1] = 0xff00ff00;
10927 ptr += U1(surface_desc).lPitch / sizeof(*ptr);
10928 ptr[0] = 0xff0000ff;
10929 ptr[1] = 0xff00ffff;
10930 hr = IDirectDrawSurface7_Unlock(texture1, NULL);
10931 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10933 memset(&surface_desc, 0, sizeof(surface_desc));
10934 surface_desc.dwSize = sizeof(surface_desc);
10935 hr = IDirectDrawSurface7_Lock(texture2, 0, &surface_desc, 0, NULL);
10936 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10937 ptr = surface_desc.lpSurface;
10938 ptr[0] = 0xff000000;
10939 ptr[1] = 0xff0000ff;
10940 ptr += U1(surface_desc).lPitch / sizeof(*ptr);
10941 ptr[0] = 0xffff0000;
10942 ptr[1] = 0xffff00ff;
10943 hr = IDirectDrawSurface7_Unlock(texture2, 0);
10944 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10946 hr = IDirect3DDevice7_SetTexture(device, 0, texture1);
10947 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
10948 hr = IDirect3DDevice7_SetTexture(device, 1, texture2);
10949 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
10950 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
10951 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
10952 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
10953 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
10954 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
10955 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10956 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_ADD);
10957 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
10958 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
10959 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10960 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
10961 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
10962 hr = IDirect3DDevice7_SetTextureStageState(device, 2, D3DTSS_COLOROP, D3DTOP_DISABLE);
10963 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
10965 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_TEXCOORDINDEX, 1);
10966 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
10967 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXCOORDINDEX, 0);
10968 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
10970 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
10971 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
10973 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
10974 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10976 hr = IDirect3DDevice7_BeginScene(device);
10977 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10978 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
10979 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10980 hr = IDirect3DDevice7_EndScene(device);
10981 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10983 color = get_surface_color(rt, 160, 120);
10984 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
10985 color = get_surface_color(rt, 480, 120);
10986 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
10987 color = get_surface_color(rt, 160, 360);
10988 ok(compare_color(color, 0x00ff0000, 2), "Got unexpected color 0x%08x.\n", color);
10989 color = get_surface_color(rt, 480, 360);
10990 ok(compare_color(color, 0x00ffffff, 2), "Got unexpected color 0x%08x.\n", color);
10992 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
10993 ok(SUCCEEDED(hr), "Failed to set texture transform flags, hr %#x.\n", hr);
10994 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_TEXTURE1, &mat);
10995 ok(SUCCEEDED(hr), "Failed to set transformation matrix, hr %#x.\n", hr);
10997 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
10998 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
11000 hr = IDirect3DDevice7_BeginScene(device);
11001 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11002 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
11003 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11004 hr = IDirect3DDevice7_EndScene(device);
11005 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11007 color = get_surface_color(rt, 160, 120);
11008 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
11009 color = get_surface_color(rt, 480, 120);
11010 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
11011 color = get_surface_color(rt, 160, 360);
11012 ok(compare_color(color, 0x00000000, 2), "Got unexpected color 0x%08x.\n", color);
11013 color = get_surface_color(rt, 480, 360);
11014 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
11016 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
11017 ok(SUCCEEDED(hr), "Failed to set texture transform flags, hr %#x.\n", hr);
11018 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXCOORDINDEX, 2);
11019 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
11021 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
11022 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
11024 hr = IDirect3DDevice7_BeginScene(device);
11025 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11026 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
11027 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11028 hr = IDirect3DDevice7_EndScene(device);
11029 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11031 color = get_surface_color(rt, 160, 120);
11032 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
11033 color = get_surface_color(rt, 480, 120);
11034 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
11035 color = get_surface_color(rt, 160, 360);
11036 ok(compare_color(color, 0x00ff00ff, 2), "Got unexpected color 0x%08x.\n", color);
11037 color = get_surface_color(rt, 480, 360);
11038 ok(compare_color(color, 0x00ffff00, 2), "Got unexpected color 0x%08x.\n", color);
11040 IDirectDrawSurface7_Release(texture1);
11041 IDirectDrawSurface7_Release(texture2);
11043 IDirectDrawSurface7_Release(rt);
11044 IDirectDraw_Release(ddraw);
11045 refcount = IDirect3DDevice7_Release(device);
11046 ok(!refcount, "Device has %u references left.\n", refcount);
11047 DestroyWindow(window);
11050 static void test_colorkey_precision(void)
11052 static struct
11054 struct vec3 pos;
11055 struct vec2 texcoord;
11057 quad[] =
11059 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
11060 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
11061 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
11062 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
11065 static const struct
11067 unsigned int max, shift, bpp, clear;
11068 const char *name;
11069 BOOL skip_nv;
11070 DDPIXELFORMAT fmt;
11072 tests[] =
11075 255, 0, 4, 0x00345678, "D3DFMT_X8R8G8B8", FALSE,
11077 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
11078 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
11083 63, 5, 2, 0x5678, "D3DFMT_R5G6B5, G channel", FALSE,
11085 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
11086 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
11091 31, 0, 2, 0x5678, "D3DFMT_R5G6B5, B channel", FALSE,
11093 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
11094 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
11099 15, 0, 2, 0x0678, "D3DFMT_A4R4G4B4", TRUE,
11101 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
11102 {16}, {0x0f00}, {0x00f0}, {0x000f}, {0xf000}
11107 IDirectDrawSurface7 *src, *dst, *texture;
11108 DDSURFACEDESC2 surface_desc, lock_desc;
11109 DWORD data[4] = {0}, color_mask;
11110 IDirect3DDevice7 *device;
11111 IDirectDrawSurface7 *rt;
11112 IDirectDraw7 *ddraw;
11113 unsigned int t, c;
11114 DDCOLORKEY ckey;
11115 IDirect3D7 *d3d;
11116 BOOL is_nvidia;
11117 ULONG refcount;
11118 D3DCOLOR color;
11119 HWND window;
11120 HRESULT hr;
11121 DDBLTFX fx;
11123 window = create_window();
11124 if (!(device = create_device(window, DDSCL_NORMAL)))
11126 skip("Failed to create a 3D device, skipping test.\n");
11127 DestroyWindow(window);
11128 return;
11131 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
11132 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11133 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
11134 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11135 IDirect3D7_Release(d3d);
11136 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
11137 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11139 is_nvidia = ddraw_is_nvidia(ddraw);
11140 /* The Windows 8 WARP driver has plenty of false negatives in X8R8G8B8
11141 * (color key doesn't match although the values are equal), and a false
11142 * positive when the color key is 0 and the texture contains the value 1.
11143 * Also on random occasions 254 == 255 and 255 != 255.
11144 * Crashes on Windows 10 WARP. */
11145 if (ddraw_is_warp(ddraw))
11147 win_skip("Skipping test on WARP driver.\n");
11148 goto done;
11151 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
11152 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11153 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
11154 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11155 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
11156 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11157 /* Multiply the texture read result with 0, that way the result color if the key doesn't
11158 * match is constant. In theory color keying works without reading the texture result
11159 * (meaning we could just op=arg1, arg1=tfactor), but the Geforce7 Windows driver begs
11160 * to differ. */
11161 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
11162 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11163 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
11164 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11165 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
11166 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11167 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x00000000);
11168 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11170 memset(&fx, 0, sizeof(fx));
11171 fx.dwSize = sizeof(fx);
11172 memset(&lock_desc, 0, sizeof(lock_desc));
11173 lock_desc.dwSize = sizeof(lock_desc);
11175 for (t = 0; t < ARRAY_SIZE(tests); ++t)
11177 if (is_nvidia && tests[t].skip_nv)
11179 win_skip("Skipping test %s on Nvidia Windows drivers.\n", tests[t].name);
11180 continue;
11183 memset(&surface_desc, 0, sizeof(surface_desc));
11184 surface_desc.dwSize = sizeof(surface_desc);
11185 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
11186 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11187 surface_desc.dwWidth = 4;
11188 surface_desc.dwHeight = 1;
11189 U4(surface_desc).ddpfPixelFormat = tests[t].fmt;
11190 /* Windows XP (at least with the r200 driver, other drivers untested) produces
11191 * garbage when doing color keyed texture->texture blits. */
11192 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
11193 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11194 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
11195 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11197 U5(fx).dwFillColor = tests[t].clear;
11198 /* On the w8 testbot (WARP driver) the blit result has different values in the
11199 * X channel. */
11200 color_mask = U2(tests[t].fmt).dwRBitMask
11201 | U3(tests[t].fmt).dwGBitMask
11202 | U4(tests[t].fmt).dwBBitMask;
11204 for (c = 0; c <= tests[t].max; ++c)
11206 /* The idiotic Nvidia Windows driver can't change the color key on a d3d
11207 * texture after it has been set once... */
11208 surface_desc.dwFlags |= DDSD_CKSRCBLT;
11209 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
11210 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = c << tests[t].shift;
11211 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = c << tests[t].shift;
11212 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
11213 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11214 hr = IDirect3DDevice7_SetTexture(device, 0, texture);
11215 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11217 hr = IDirectDrawSurface7_Blt(dst, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11218 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11220 hr = IDirectDrawSurface7_Lock(src, NULL, &lock_desc, DDLOCK_WAIT, NULL);
11221 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11222 switch (tests[t].bpp)
11224 case 4:
11225 ((DWORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
11226 ((DWORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
11227 ((DWORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
11228 ((DWORD *)lock_desc.lpSurface)[3] = 0xffffffff;
11229 break;
11231 case 2:
11232 ((WORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
11233 ((WORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
11234 ((WORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
11235 ((WORD *)lock_desc.lpSurface)[3] = 0xffff;
11236 break;
11238 hr = IDirectDrawSurface7_Unlock(src, 0);
11239 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11240 hr = IDirectDrawSurface7_Blt(texture, NULL, src, NULL, DDBLT_WAIT, NULL);
11241 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11243 ckey.dwColorSpaceLowValue = c << tests[t].shift;
11244 ckey.dwColorSpaceHighValue = c << tests[t].shift;
11245 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
11246 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11248 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_WAIT, NULL);
11249 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11251 /* Don't make this read only, it somehow breaks the detection of the Nvidia bug below. */
11252 hr = IDirectDrawSurface7_Lock(dst, NULL, &lock_desc, DDLOCK_WAIT, NULL);
11253 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11254 switch (tests[t].bpp)
11256 case 4:
11257 data[0] = ((DWORD *)lock_desc.lpSurface)[0] & color_mask;
11258 data[1] = ((DWORD *)lock_desc.lpSurface)[1] & color_mask;
11259 data[2] = ((DWORD *)lock_desc.lpSurface)[2] & color_mask;
11260 data[3] = ((DWORD *)lock_desc.lpSurface)[3] & color_mask;
11261 break;
11263 case 2:
11264 data[0] = ((WORD *)lock_desc.lpSurface)[0] & color_mask;
11265 data[1] = ((WORD *)lock_desc.lpSurface)[1] & color_mask;
11266 data[2] = ((WORD *)lock_desc.lpSurface)[2] & color_mask;
11267 data[3] = ((WORD *)lock_desc.lpSurface)[3] & color_mask;
11268 break;
11270 hr = IDirectDrawSurface7_Unlock(dst, 0);
11271 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11273 if (!c)
11275 ok(data[0] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
11276 tests[t].clear, data[0], tests[t].name, c);
11278 if (data[3] == tests[t].clear)
11280 /* My Geforce GTX 460 on Windows 7 misbehaves when A4R4G4B4 is blitted with color
11281 * keying: The blit takes ~0.5 seconds, and subsequent color keying draws are broken,
11282 * even when a different surface is used. The blit itself doesn't draw anything,
11283 * so we can detect the bug by looking at the otherwise unused 4th texel. It should
11284 * never be masked out by the key.
11286 * On Windows 10 the problem is worse, Blt just hangs. For this reason the ARGB4444
11287 * test is disabled on Nvidia.
11289 * Also appears to affect the testbot in some way with R5G6B5. Color keying is
11290 * terrible on WARP. */
11291 skip("Nvidia A4R4G4B4 color keying blit bug detected, skipping.\n");
11292 IDirectDrawSurface7_Release(texture);
11293 IDirectDrawSurface7_Release(src);
11294 IDirectDrawSurface7_Release(dst);
11295 goto done;
11298 else
11299 ok(data[0] == (c - 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
11300 (c - 1) << tests[t].shift, data[0], tests[t].name, c);
11302 ok(data[1] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
11303 tests[t].clear, data[1], tests[t].name, c);
11305 if (c == tests[t].max)
11306 ok(data[2] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
11307 tests[t].clear, data[2], tests[t].name, c);
11308 else
11309 ok(data[2] == (c + 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
11310 (c + 1) << tests[t].shift, data[2], tests[t].name, c);
11312 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x0000ff00, 1.0f, 0);
11313 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11315 hr = IDirect3DDevice7_BeginScene(device);
11316 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11317 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
11318 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11319 hr = IDirect3DDevice7_EndScene(device);
11320 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11322 color = get_surface_color(rt, 80, 240);
11324 if (!c)
11325 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x, format %s, c=%u.\n",
11326 color, tests[t].name, c);
11327 else
11328 ok(compare_color(color, 0x00000000, 1), "Got unexpected color 0x%08x, format %s, c=%u.\n",
11329 color, tests[t].name, c);
11331 color = get_surface_color(rt, 240, 240);
11332 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x, format %s, c=%u.\n",
11333 color, tests[t].name, c);
11335 color = get_surface_color(rt, 400, 240);
11336 if (c == tests[t].max)
11337 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x, format %s, c=%u.\n",
11338 color, tests[t].name, c);
11339 else
11340 ok(compare_color(color, 0x00000000, 1), "Got unexpected color 0x%08x, format %s, c=%u.\n",
11341 color, tests[t].name, c);
11343 IDirectDrawSurface7_Release(texture);
11345 IDirectDrawSurface7_Release(src);
11346 IDirectDrawSurface7_Release(dst);
11348 done:
11350 IDirectDrawSurface7_Release(rt);
11351 IDirectDraw7_Release(ddraw);
11352 refcount = IDirect3DDevice7_Release(device);
11353 ok(!refcount, "Device has %u references left.\n", refcount);
11354 DestroyWindow(window);
11357 static void test_range_colorkey(void)
11359 IDirectDraw7 *ddraw;
11360 HWND window;
11361 HRESULT hr;
11362 IDirectDrawSurface7 *surface;
11363 DDSURFACEDESC2 surface_desc;
11364 ULONG refcount;
11365 DDCOLORKEY ckey;
11367 window = create_window();
11368 ddraw = create_ddraw();
11369 ok(!!ddraw, "Failed to create a ddraw object.\n");
11370 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11371 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11373 memset(&surface_desc, 0, sizeof(surface_desc));
11374 surface_desc.dwSize = sizeof(surface_desc);
11375 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
11376 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
11377 surface_desc.dwWidth = 1;
11378 surface_desc.dwHeight = 1;
11379 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
11380 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
11381 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
11382 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
11383 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
11384 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0x00000000;
11386 /* Creating a surface with a range color key fails with DDERR_NOCOLORKEY. */
11387 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
11388 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
11389 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11390 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11392 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
11393 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
11394 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11395 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11397 /* Same for DDSCAPS_OFFSCREENPLAIN. */
11398 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11399 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
11400 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
11401 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11402 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11404 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
11405 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
11406 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11407 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11409 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
11410 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
11411 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11412 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11414 /* Setting a range color key without DDCKEY_COLORSPACE collapses the key. */
11415 ckey.dwColorSpaceLowValue = 0x00000000;
11416 ckey.dwColorSpaceHighValue = 0x00000001;
11417 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
11418 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
11420 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
11421 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
11422 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
11423 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
11425 ckey.dwColorSpaceLowValue = 0x00000001;
11426 ckey.dwColorSpaceHighValue = 0x00000000;
11427 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
11428 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
11430 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
11431 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
11432 ok(ckey.dwColorSpaceLowValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
11433 ok(ckey.dwColorSpaceHighValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
11435 /* DDCKEY_COLORSPACE is ignored if the key is a single value. */
11436 ckey.dwColorSpaceLowValue = 0x00000000;
11437 ckey.dwColorSpaceHighValue = 0x00000000;
11438 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
11439 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
11441 /* Using it with a range key results in DDERR_NOCOLORKEYHW. */
11442 ckey.dwColorSpaceLowValue = 0x00000001;
11443 ckey.dwColorSpaceHighValue = 0x00000000;
11444 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
11445 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11446 ckey.dwColorSpaceLowValue = 0x00000000;
11447 ckey.dwColorSpaceHighValue = 0x00000001;
11448 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
11449 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11450 /* Range destination keys don't work either. */
11451 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_DESTBLT | DDCKEY_COLORSPACE, &ckey);
11452 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11454 /* Just to show it's not because of A, R, and G having equal values. */
11455 ckey.dwColorSpaceLowValue = 0x00000000;
11456 ckey.dwColorSpaceHighValue = 0x01010101;
11457 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
11458 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11460 /* None of these operations modified the key. */
11461 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
11462 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
11463 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
11464 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
11466 IDirectDrawSurface7_Release(surface);
11467 refcount = IDirectDraw7_Release(ddraw);
11468 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
11469 DestroyWindow(window);
11472 static void test_shademode(void)
11474 IDirect3DVertexBuffer7 *vb_strip, *vb_list, *buffer;
11475 IDirect3DDevice7 *device;
11476 D3DVERTEXBUFFERDESC desc;
11477 IDirectDrawSurface7 *rt;
11478 DWORD color0, color1;
11479 void *data = NULL;
11480 IDirect3D7 *d3d;
11481 ULONG refcount;
11482 UINT i, count;
11483 HWND window;
11484 HRESULT hr;
11485 static const struct
11487 struct vec3 position;
11488 DWORD diffuse;
11490 quad_strip[] =
11492 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
11493 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
11494 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
11495 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
11497 quad_list[] =
11499 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
11500 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
11501 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
11503 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
11504 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
11505 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
11507 static const struct
11509 DWORD primtype;
11510 DWORD shademode;
11511 DWORD color0, color1;
11513 tests[] =
11515 {D3DPT_TRIANGLESTRIP, D3DSHADE_FLAT, 0x00ff0000, 0x0000ff00},
11516 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
11517 {D3DPT_TRIANGLESTRIP, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
11518 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
11519 {D3DPT_TRIANGLELIST, D3DSHADE_FLAT, 0x00ff0000, 0x000000ff},
11520 {D3DPT_TRIANGLELIST, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
11523 window = create_window();
11524 if (!(device = create_device(window, DDSCL_NORMAL)))
11526 skip("Failed to create a 3D device, skipping test.\n");
11527 DestroyWindow(window);
11528 return;
11531 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
11532 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
11533 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
11534 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11536 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
11537 ok(hr == D3D_OK, "Failed to disable lighting, hr %#x.\n", hr);
11538 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
11539 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
11541 memset(&desc, 0, sizeof(desc));
11542 desc.dwSize = sizeof(desc);
11543 desc.dwCaps = D3DVBCAPS_WRITEONLY;
11544 desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
11545 desc.dwNumVertices = ARRAY_SIZE(quad_strip);
11546 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &vb_strip, 0);
11547 ok(hr == D3D_OK, "Failed to create vertex buffer, hr %#x.\n", hr);
11548 hr = IDirect3DVertexBuffer7_Lock(vb_strip, 0, &data, NULL);
11549 ok(hr == D3D_OK, "Failed to lock vertex buffer, hr %#x.\n", hr);
11550 memcpy(data, quad_strip, sizeof(quad_strip));
11551 hr = IDirect3DVertexBuffer7_Unlock(vb_strip);
11552 ok(hr == D3D_OK, "Failed to unlock vertex buffer, hr %#x.\n", hr);
11554 desc.dwNumVertices = ARRAY_SIZE(quad_list);
11555 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &vb_list, 0);
11556 ok(hr == D3D_OK, "Failed to create vertex buffer, hr %#x.\n", hr);
11557 hr = IDirect3DVertexBuffer7_Lock(vb_list, 0, &data, NULL);
11558 ok(hr == D3D_OK, "Failed to lock vertex buffer, hr %#x.\n", hr);
11559 memcpy(data, quad_list, sizeof(quad_list));
11560 hr = IDirect3DVertexBuffer7_Unlock(vb_list);
11561 ok(hr == D3D_OK, "Failed to unlock vertex buffer, hr %#x.\n", hr);
11563 /* Try it first with a TRIANGLESTRIP. Do it with different geometry because
11564 * the color fixups we have to do for FLAT shading will be dependent on that. */
11566 for (i = 0; i < ARRAY_SIZE(tests); ++i)
11568 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
11569 ok(hr == D3D_OK, "Failed to clear, hr %#x.\n", hr);
11571 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SHADEMODE, tests[i].shademode);
11572 ok(hr == D3D_OK, "Failed to set shade mode, hr %#x.\n", hr);
11574 hr = IDirect3DDevice7_BeginScene(device);
11575 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11576 buffer = tests[i].primtype == D3DPT_TRIANGLESTRIP ? vb_strip : vb_list;
11577 count = tests[i].primtype == D3DPT_TRIANGLESTRIP ? 4 : 6;
11578 hr = IDirect3DDevice7_DrawPrimitiveVB(device, tests[i].primtype, buffer, 0, count, 0);
11579 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11580 hr = IDirect3DDevice7_EndScene(device);
11581 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11583 color0 = get_surface_color(rt, 100, 100); /* Inside first triangle */
11584 color1 = get_surface_color(rt, 500, 350); /* Inside second triangle */
11586 /* For D3DSHADE_FLAT it should take the color of the first vertex of
11587 * each triangle. This requires EXT_provoking_vertex or similar
11588 * functionality being available. */
11589 /* PHONG should be the same as GOURAUD, since no hardware implements
11590 * this. */
11591 ok(compare_color(color0, tests[i].color0, 1), "Test %u shading has color0 %08x, expected %08x.\n",
11592 i, color0, tests[i].color0);
11593 ok(compare_color(color1, tests[i].color1, 1), "Test %u shading has color1 %08x, expected %08x.\n",
11594 i, color1, tests[i].color1);
11597 IDirect3DVertexBuffer7_Release(vb_strip);
11598 IDirect3DVertexBuffer7_Release(vb_list);
11599 IDirectDrawSurface7_Release(rt);
11600 IDirect3D7_Release(d3d);
11601 refcount = IDirect3DDevice7_Release(device);
11602 ok(!refcount, "Device has %u references left.\n", refcount);
11603 DestroyWindow(window);
11606 static void test_lockrect_invalid(void)
11608 unsigned int i, r;
11609 IDirectDraw7 *ddraw;
11610 IDirectDrawSurface7 *surface;
11611 HWND window;
11612 HRESULT hr;
11613 DDSURFACEDESC2 surface_desc;
11614 DDSURFACEDESC2 locked_desc;
11615 DDCAPS hal_caps;
11616 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
11617 static RECT valid[] =
11619 {60, 60, 68, 68},
11620 {60, 60, 60, 68},
11621 {60, 60, 68, 60},
11622 {120, 60, 128, 68},
11623 {60, 120, 68, 128},
11625 static RECT invalid[] =
11627 {68, 60, 60, 68}, /* left > right */
11628 {60, 68, 68, 60}, /* top > bottom */
11629 {-8, 60, 0, 68}, /* left < surface */
11630 {60, -8, 68, 0}, /* top < surface */
11631 {-16, 60, -8, 68}, /* right < surface */
11632 {60, -16, 68, -8}, /* bottom < surface */
11633 {60, 60, 136, 68}, /* right > surface */
11634 {60, 60, 68, 136}, /* bottom > surface */
11635 {136, 60, 144, 68}, /* left > surface */
11636 {60, 136, 68, 144}, /* top > surface */
11638 static const struct
11640 DWORD caps, caps2;
11641 const char *name;
11642 BOOL allowed;
11643 HRESULT hr;
11645 resources[] =
11647 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, "sysmem offscreenplain", TRUE, DDERR_INVALIDPARAMS},
11648 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, "vidmem offscreenplain", TRUE, DDERR_INVALIDPARAMS},
11649 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, "sysmem texture", TRUE, DD_OK},
11650 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, "vidmem texture", TRUE, DDERR_INVALIDPARAMS},
11651 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, "managed texture", TRUE, DD_OK},
11653 /* FWIW the SDK header mentions DDSCAPS_WRITEONLY as being a "READ
11654 * ONLY" flag. */
11655 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_WRITEONLY, 0, "sysmem offscreenplain writeonly", FALSE, DDERR_INVALIDPARAMS},
11656 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_WRITEONLY, 0, "vidmem offscreenplain writeonly", FALSE, DDERR_INVALIDPARAMS},
11657 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_WRITEONLY, 0, "sysmem texture writeonly", FALSE, DD_OK},
11658 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_WRITEONLY, 0, "vidmem texture writeonly", FALSE, DDERR_INVALIDPARAMS},
11659 {DDSCAPS_TEXTURE | DDSCAPS_WRITEONLY, DDSCAPS2_TEXTUREMANAGE, "managed texture writeonly", TRUE, DD_OK},
11662 window = create_window();
11663 ddraw = create_ddraw();
11664 ok(!!ddraw, "Failed to create a ddraw object.\n");
11665 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11666 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11668 memset(&hal_caps, 0, sizeof(hal_caps));
11669 hal_caps.dwSize = sizeof(hal_caps);
11670 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
11671 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
11672 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps
11673 || !(hal_caps.ddsCaps.dwCaps & DDSCAPS2_TEXTUREMANAGE))
11675 skip("Required surface types not supported, skipping test.\n");
11676 goto done;
11679 for (r = 0; r < ARRAY_SIZE(resources); ++r)
11681 memset(&surface_desc, 0, sizeof(surface_desc));
11682 surface_desc.dwSize = sizeof(surface_desc);
11683 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
11684 surface_desc.ddsCaps.dwCaps = resources[r].caps;
11685 surface_desc.ddsCaps.dwCaps2 = resources[r].caps2;
11686 surface_desc.dwWidth = 128;
11687 surface_desc.dwHeight = 128;
11688 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
11689 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
11690 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
11691 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xff0000;
11692 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x00ff00;
11693 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x0000ff;
11695 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11696 if (!resources[r].allowed)
11698 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
11699 continue;
11701 if (is_ddraw64 && (resources[r].caps & DDSCAPS_TEXTURE))
11703 todo_wine ok(hr == E_NOINTERFACE, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
11704 if (SUCCEEDED(hr))
11705 IDirectDrawSurface7_Release(surface);
11706 continue;
11708 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n", hr, resources[r].name);
11710 /* Crashes in ddraw7
11711 hr = IDirectDrawSurface7_Lock(surface, NULL, NULL, DDLOCK_WAIT, NULL);
11712 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
11715 for (i = 0; i < ARRAY_SIZE(valid); ++i)
11717 RECT *rect = &valid[i];
11719 memset(&locked_desc, 0, sizeof(locked_desc));
11720 locked_desc.dwSize = sizeof(locked_desc);
11722 hr = IDirectDrawSurface7_Lock(surface, rect, &locked_desc, DDLOCK_WAIT, NULL);
11723 ok(SUCCEEDED(hr), "Lock failed (%#x) for rect %s, type %s.\n",
11724 hr, wine_dbgstr_rect(rect), resources[r].name);
11726 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11727 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11730 for (i = 0; i < ARRAY_SIZE(invalid); ++i)
11732 RECT *rect = &invalid[i];
11734 memset(&locked_desc, 1, sizeof(locked_desc));
11735 locked_desc.dwSize = sizeof(locked_desc);
11737 hr = IDirectDrawSurface7_Lock(surface, rect, &locked_desc, DDLOCK_WAIT, NULL);
11738 todo_wine_if (SUCCEEDED(resources[r].hr))
11739 ok(hr == resources[r].hr, "Lock returned %#x for rect %s, type %s.\n",
11740 hr, wine_dbgstr_rect(rect), resources[r].name);
11741 if (SUCCEEDED(hr))
11743 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11744 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11746 else
11747 ok(!locked_desc.lpSurface, "Got unexpected lpSurface %p.\n", locked_desc.lpSurface);
11750 hr = IDirectDrawSurface7_Lock(surface, NULL, &locked_desc, DDLOCK_WAIT, NULL);
11751 ok(SUCCEEDED(hr), "Lock(rect = NULL) failed, hr %#x, type %s.\n",
11752 hr, resources[r].name);
11753 hr = IDirectDrawSurface7_Lock(surface, NULL, &locked_desc, DDLOCK_WAIT, NULL);
11754 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = NULL) returned %#x, type %s.\n",
11755 hr, resources[r].name);
11756 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11757 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11759 hr = IDirectDrawSurface7_Lock(surface, &valid[0], &locked_desc, DDLOCK_WAIT, NULL);
11760 ok(SUCCEEDED(hr), "Lock(rect = %s) failed (%#x).\n", wine_dbgstr_rect(&valid[0]), hr);
11761 hr = IDirectDrawSurface7_Lock(surface, &valid[0], &locked_desc, DDLOCK_WAIT, NULL);
11762 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = %s) failed (%#x).\n",
11763 wine_dbgstr_rect(&valid[0]), hr);
11765 /* Locking a different rectangle returns DD_OK, but it seems to break the surface.
11766 * Afterwards unlocking the surface fails(NULL rectangle or both locked rectangles) */
11768 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11769 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11771 IDirectDrawSurface7_Release(surface);
11774 done:
11775 IDirectDraw7_Release(ddraw);
11776 DestroyWindow(window);
11779 static void test_yv12_overlay(void)
11781 IDirectDrawSurface7 *src_surface, *dst_surface;
11782 RECT rect = {13, 17, 14, 18};
11783 unsigned int offset, y;
11784 DDSURFACEDESC2 desc;
11785 unsigned char *base;
11786 IDirectDraw7 *ddraw;
11787 HWND window;
11788 HRESULT hr;
11790 window = create_window();
11791 ddraw = create_ddraw();
11792 ok(!!ddraw, "Failed to create a ddraw object.\n");
11793 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11794 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11796 if (!(src_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
11798 skip("Failed to create a YV12 overlay, skipping test.\n");
11799 goto done;
11802 memset(&desc, 0, sizeof(desc));
11803 desc.dwSize = sizeof(desc);
11804 hr = IDirectDrawSurface7_Lock(src_surface, NULL, &desc, DDLOCK_WAIT, NULL);
11805 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11807 ok(desc.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH),
11808 "Got unexpected flags %#x.\n", desc.dwFlags);
11809 ok(desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_HWCODEC)
11810 || desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
11811 "Got unexpected caps %#x.\n", desc.ddsCaps.dwCaps);
11812 ok(desc.dwWidth == 256, "Got unexpected width %u.\n", desc.dwWidth);
11813 ok(desc.dwHeight == 256, "Got unexpected height %u.\n", desc.dwHeight);
11814 /* The overlay pitch seems to have 256 byte alignment. */
11815 ok(!(U1(desc).lPitch & 0xff), "Got unexpected pitch %u.\n", U1(desc).lPitch);
11817 /* Fill the surface with some data for the blit test. */
11818 base = desc.lpSurface;
11819 /* Luminance */
11820 for (y = 0; y < desc.dwHeight; ++y)
11822 memset(base + U1(desc).lPitch * y, 0x10, desc.dwWidth);
11824 /* V */
11825 for (; y < desc.dwHeight + desc.dwHeight / 4; ++y)
11827 memset(base + U1(desc).lPitch * y, 0x20, desc.dwWidth);
11829 /* U */
11830 for (; y < desc.dwHeight + desc.dwHeight / 2; ++y)
11832 memset(base + U1(desc).lPitch * y, 0x30, desc.dwWidth);
11835 hr = IDirectDrawSurface7_Unlock(src_surface, NULL);
11836 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11838 /* YV12 uses 2x2 blocks with 6 bytes per block (4*Y, 1*U, 1*V). Unlike
11839 * other block-based formats like DXT the entire Y channel is stored in
11840 * one big chunk of memory, followed by the chroma channels. So partial
11841 * locks do not really make sense. Show that they are allowed nevertheless
11842 * and the offset points into the luminance data. */
11843 hr = IDirectDrawSurface7_Lock(src_surface, &rect, &desc, DDLOCK_WAIT, NULL);
11844 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11845 offset = ((const unsigned char *)desc.lpSurface - base);
11846 ok(offset == rect.top * U1(desc).lPitch + rect.left, "Got unexpected offset %u, expected %u.\n",
11847 offset, rect.top * U1(desc).lPitch + rect.left);
11848 hr = IDirectDrawSurface7_Unlock(src_surface, NULL);
11849 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11851 if (!(dst_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
11853 /* Windows XP with a Radeon X1600 GPU refuses to create a second
11854 * overlay surface, DDERR_NOOVERLAYHW, making the blit tests moot. */
11855 skip("Failed to create a second YV12 surface, skipping blit test.\n");
11856 IDirectDrawSurface7_Release(src_surface);
11857 goto done;
11860 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, src_surface, NULL, DDBLT_WAIT, NULL);
11861 /* VMware rejects YV12 blits. This behavior has not been seen on real
11862 * hardware yet, so mark it broken. */
11863 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL), "Failed to blit, hr %#x.\n", hr);
11865 if (SUCCEEDED(hr))
11867 memset(&desc, 0, sizeof(desc));
11868 desc.dwSize = sizeof(desc);
11869 hr = IDirectDrawSurface7_Lock(dst_surface, NULL, &desc, DDLOCK_WAIT, NULL);
11870 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11872 base = desc.lpSurface;
11873 ok(base[0] == 0x10, "Got unexpected Y data 0x%02x.\n", base[0]);
11874 base += desc.dwHeight * U1(desc).lPitch;
11875 todo_wine ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]);
11876 base += desc.dwHeight / 4 * U1(desc).lPitch;
11877 todo_wine ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]);
11879 hr = IDirectDrawSurface7_Unlock(dst_surface, NULL);
11880 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11883 IDirectDrawSurface7_Release(dst_surface);
11884 IDirectDrawSurface7_Release(src_surface);
11885 done:
11886 IDirectDraw7_Release(ddraw);
11887 DestroyWindow(window);
11890 static BOOL dwm_enabled(void)
11892 BOOL ret = FALSE;
11894 if (!strcmp(winetest_platform, "wine"))
11895 return FALSE;
11896 if (!pDwmIsCompositionEnabled)
11897 return FALSE;
11898 if (FAILED(pDwmIsCompositionEnabled(&ret)))
11899 return FALSE;
11900 return ret;
11903 static void test_offscreen_overlay(void)
11905 IDirectDrawSurface7 *overlay, *offscreen, *primary;
11906 DDSURFACEDESC2 surface_desc;
11907 IDirectDraw7 *ddraw;
11908 HWND window;
11909 HRESULT hr;
11910 HDC dc;
11912 window = create_window();
11913 ddraw = create_ddraw();
11914 ok(!!ddraw, "Failed to create a ddraw object.\n");
11915 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11916 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11918 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
11920 skip("Failed to create a UYVY overlay, skipping test.\n");
11921 goto done;
11924 memset(&surface_desc, 0, sizeof(surface_desc));
11925 surface_desc.dwSize = sizeof(surface_desc);
11926 surface_desc.dwFlags = DDSD_CAPS;
11927 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
11928 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
11929 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
11931 /* On Windows 7, and probably Vista, UpdateOverlay() will return
11932 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
11933 * surface prevents this by disabling the dwm. */
11934 hr = IDirectDrawSurface7_GetDC(primary, &dc);
11935 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
11936 hr = IDirectDrawSurface7_ReleaseDC(primary, dc);
11937 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
11939 /* Try to overlay a NULL surface. */
11940 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_SHOW, NULL);
11941 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11942 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_HIDE, NULL);
11943 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11945 /* Try to overlay an offscreen surface. */
11946 memset(&surface_desc, 0, sizeof(surface_desc));
11947 surface_desc.dwSize = sizeof(surface_desc);
11948 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
11949 surface_desc.dwWidth = 64;
11950 surface_desc.dwHeight = 64;
11951 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11952 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
11953 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
11954 U4(surface_desc).ddpfPixelFormat.dwFourCC = 0;
11955 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
11956 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
11957 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
11958 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
11959 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
11960 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
11962 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, offscreen, NULL, DDOVER_SHOW, NULL);
11963 ok(SUCCEEDED(hr) || broken(hr == DDERR_OUTOFCAPS && dwm_enabled())
11964 || broken(hr == E_NOTIMPL && ddraw_is_vmware(ddraw)),
11965 "Failed to update overlay, hr %#x.\n", hr);
11967 /* Try to overlay the primary with a non-overlay surface. */
11968 hr = IDirectDrawSurface7_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_SHOW, NULL);
11969 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
11970 hr = IDirectDrawSurface7_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_HIDE, NULL);
11971 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
11973 IDirectDrawSurface7_Release(offscreen);
11974 IDirectDrawSurface7_Release(primary);
11975 IDirectDrawSurface7_Release(overlay);
11976 done:
11977 IDirectDraw7_Release(ddraw);
11978 DestroyWindow(window);
11981 static void test_overlay_rect(void)
11983 IDirectDrawSurface7 *overlay, *primary = NULL;
11984 DDSURFACEDESC2 surface_desc;
11985 RECT rect = {0, 0, 64, 64};
11986 IDirectDraw7 *ddraw;
11987 LONG pos_x, pos_y;
11988 HRESULT hr, hr2;
11989 HWND window;
11990 HDC dc;
11992 window = create_window();
11993 ddraw = create_ddraw();
11994 ok(!!ddraw, "Failed to create a ddraw object.\n");
11995 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11996 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11998 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
12000 skip("Failed to create a UYVY overlay, skipping test.\n");
12001 goto done;
12004 memset(&surface_desc, 0, sizeof(surface_desc));
12005 surface_desc.dwSize = sizeof(surface_desc);
12006 surface_desc.dwFlags = DDSD_CAPS;
12007 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
12008 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
12009 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
12011 /* On Windows 7, and probably Vista, UpdateOverlay() will return
12012 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
12013 * surface prevents this by disabling the dwm. */
12014 hr = IDirectDrawSurface7_GetDC(primary, &dc);
12015 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
12016 hr = IDirectDrawSurface7_ReleaseDC(primary, dc);
12017 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
12019 /* On Windows 8 and newer DWM can't be turned off, making overlays unusable. */
12020 if (dwm_enabled())
12022 win_skip("Cannot disable DWM, skipping overlay test.\n");
12023 goto done;
12026 /* The dx sdk sort of implies that rect must be set when DDOVER_SHOW is
12027 * used. This is not true in Windows Vista and earlier, but changed in
12028 * Windows 7. */
12029 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
12030 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
12031 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_HIDE, NULL);
12032 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
12033 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_SHOW, NULL);
12034 ok(hr == DD_OK || hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
12036 /* Show that the overlay position is the (top, left) coordinate of the
12037 * destination rectangle. */
12038 OffsetRect(&rect, 32, 16);
12039 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
12040 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
12041 pos_x = -1; pos_y = -1;
12042 hr = IDirectDrawSurface7_GetOverlayPosition(overlay, &pos_x, &pos_y);
12043 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
12044 ok(pos_x == rect.left, "Got unexpected pos_x %d, expected %d.\n", pos_x, rect.left);
12045 ok(pos_y == rect.top, "Got unexpected pos_y %d, expected %d.\n", pos_y, rect.top);
12047 /* Passing a NULL dest rect sets the position to 0/0. Visually it can be
12048 * seen that the overlay overlays the whole primary(==screen). */
12049 hr2 = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, NULL, 0, NULL);
12050 ok(hr2 == DD_OK || hr2 == DDERR_INVALIDPARAMS || hr2 == DDERR_OUTOFCAPS, "Got unexpected hr %#x.\n", hr2);
12051 hr = IDirectDrawSurface7_GetOverlayPosition(overlay, &pos_x, &pos_y);
12052 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
12053 if (SUCCEEDED(hr2))
12055 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
12056 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
12058 else
12060 ok(pos_x == 32, "Got unexpected pos_x %d.\n", pos_x);
12061 ok(pos_y == 16, "Got unexpected pos_y %d.\n", pos_y);
12064 /* The position cannot be retrieved when the overlay is not shown. */
12065 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_HIDE, NULL);
12066 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
12067 pos_x = -1; pos_y = -1;
12068 hr = IDirectDrawSurface7_GetOverlayPosition(overlay, &pos_x, &pos_y);
12069 ok(hr == DDERR_OVERLAYNOTVISIBLE, "Got unexpected hr %#x.\n", hr);
12070 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
12071 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
12073 done:
12074 if (primary)
12075 IDirectDrawSurface7_Release(primary);
12076 if (overlay)
12077 IDirectDrawSurface7_Release(overlay);
12078 IDirectDraw7_Release(ddraw);
12079 DestroyWindow(window);
12082 static void test_blt(void)
12084 IDirectDrawSurface7 *surface, *rt;
12085 DDSURFACEDESC2 surface_desc;
12086 IDirect3DDevice7 *device;
12087 IDirectDraw7 *ddraw;
12088 IDirect3D7 *d3d;
12089 unsigned int i;
12090 ULONG refcount;
12091 HWND window;
12092 HRESULT hr;
12094 static struct
12096 RECT src_rect;
12097 RECT dst_rect;
12098 HRESULT hr;
12100 test_data[] =
12102 {{160, 0, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit. */
12103 {{160, 480, 640, 0}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, flipped source. */
12104 {{640, 0, 160, 480}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, mirrored source. */
12105 {{160, 0, 480, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched x. */
12106 {{160, 160, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched y. */
12107 {{ 0, 0, 640, 480}, { 0, 0, 640, 480}, DD_OK}, /* Full surface blit. */
12108 {{ 0, 0, 640, 480}, { 0, 480, 640, 0}, DDERR_INVALIDRECT}, /* Full surface, flipped destination. */
12109 {{ 0, 0, 640, 480}, {640, 0, 0, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored destination. */
12110 {{ 0, 480, 640, 0}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, flipped source. */
12111 {{640, 0, 0, 480}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored source. */
12114 window = create_window();
12115 if (!(device = create_device(window, DDSCL_NORMAL)))
12117 skip("Failed to create a 3D device, skipping test.\n");
12118 DestroyWindow(window);
12119 return;
12122 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
12123 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
12124 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
12125 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
12126 IDirect3D7_Release(d3d);
12127 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
12128 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
12130 memset(&surface_desc, 0, sizeof(surface_desc));
12131 surface_desc.dwSize = sizeof(surface_desc);
12132 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
12133 surface_desc.dwWidth = 640;
12134 surface_desc.dwHeight = 480;
12135 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12136 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12137 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12139 hr = IDirectDrawSurface7_Blt(surface, NULL, surface, NULL, 0, NULL);
12140 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12142 hr = IDirectDrawSurface7_Blt(surface, NULL, rt, NULL, 0, NULL);
12143 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12145 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
12147 hr = IDirectDrawSurface7_Blt(surface, &test_data[i].dst_rect,
12148 surface, &test_data[i].src_rect, DDBLT_WAIT, NULL);
12149 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
12151 hr = IDirectDrawSurface7_Blt(surface, &test_data[i].dst_rect,
12152 rt, &test_data[i].src_rect, DDBLT_WAIT, NULL);
12153 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
12155 hr = IDirectDrawSurface7_Blt(surface, &test_data[i].dst_rect,
12156 NULL, &test_data[i].src_rect, DDBLT_WAIT, NULL);
12157 ok(hr == DDERR_INVALIDPARAMS, "Test %u: Got unexpected hr %#x.\n", i, hr);
12159 hr = IDirectDrawSurface7_Blt(surface, &test_data[i].dst_rect, NULL, NULL, DDBLT_WAIT, NULL);
12160 ok(hr == DDERR_INVALIDPARAMS, "Test %u: Got unexpected hr %#x.\n", i, hr);
12163 IDirectDrawSurface7_Release(surface);
12164 IDirectDrawSurface7_Release(rt);
12165 IDirectDraw7_Release(ddraw);
12166 refcount = IDirect3DDevice7_Release(device);
12167 ok(!refcount, "Device has %u references left.\n", refcount);
12168 DestroyWindow(window);
12171 static void test_blt_z_alpha(void)
12173 DWORD blt_flags[] =
12175 /* 0 */
12176 DDBLT_ALPHADEST,
12177 DDBLT_ALPHADESTCONSTOVERRIDE,
12178 DDBLT_ALPHADESTNEG,
12179 DDBLT_ALPHADESTSURFACEOVERRIDE,
12180 DDBLT_ALPHAEDGEBLEND,
12181 /* 5 */
12182 DDBLT_ALPHASRC,
12183 DDBLT_ALPHASRCCONSTOVERRIDE,
12184 DDBLT_ALPHASRCNEG,
12185 DDBLT_ALPHASRCSURFACEOVERRIDE,
12186 DDBLT_ZBUFFER,
12187 /* 10 */
12188 DDBLT_ZBUFFERDESTCONSTOVERRIDE,
12189 DDBLT_ZBUFFERDESTOVERRIDE,
12190 DDBLT_ZBUFFERSRCCONSTOVERRIDE,
12191 DDBLT_ZBUFFERSRCOVERRIDE,
12193 IDirectDrawSurface7 *src_surface, *dst_surface;
12194 DDSURFACEDESC2 surface_desc;
12195 IDirectDraw7 *ddraw;
12196 DDPIXELFORMAT pf;
12197 ULONG refcount;
12198 unsigned int i;
12199 D3DCOLOR color;
12200 HWND window;
12201 HRESULT hr;
12202 DDBLTFX fx;
12204 window = create_window();
12205 ddraw = create_ddraw();
12206 ok(!!ddraw, "Failed to create a ddraw object.\n");
12207 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12208 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12210 memset(&pf, 0, sizeof(pf));
12211 pf.dwSize = sizeof(pf);
12212 pf.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
12213 U1(pf).dwRGBBitCount = 32;
12214 U2(pf).dwRBitMask = 0x00ff0000;
12215 U3(pf).dwGBitMask = 0x0000ff00;
12216 U4(pf).dwBBitMask = 0x000000ff;
12217 U5(pf).dwRGBAlphaBitMask = 0xff000000;
12219 memset(&surface_desc, 0, sizeof(surface_desc));
12220 surface_desc.dwSize = sizeof(surface_desc);
12221 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
12222 surface_desc.dwWidth = 64;
12223 surface_desc.dwHeight = 64;
12224 U4(surface_desc).ddpfPixelFormat = pf;
12225 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12227 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
12228 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
12229 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
12230 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
12232 memset(&fx, 0, sizeof(fx));
12233 fx.dwSize = sizeof(fx);
12234 fx.dwZBufferOpCode = D3DCMP_NEVER;
12235 fx.dwZDestConstBitDepth = 32;
12236 U1(fx).dwZDestConst = 0x11111111;
12237 fx.dwZSrcConstBitDepth = 32;
12238 U2(fx).dwZSrcConst = 0xeeeeeeee;
12239 fx.dwAlphaEdgeBlendBitDepth = 8;
12240 fx.dwAlphaEdgeBlend = 0x7f;
12241 fx.dwAlphaDestConstBitDepth = 8;
12242 U3(fx).dwAlphaDestConst = 0xdd;
12243 fx.dwAlphaSrcConstBitDepth = 8;
12244 U4(fx).dwAlphaSrcConst = 0x22;
12246 for (i = 0; i < ARRAY_SIZE(blt_flags); ++i)
12248 U5(fx).dwFillColor = 0x3300ff00;
12249 hr = IDirectDrawSurface7_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
12250 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
12252 U5(fx).dwFillColor = 0xccff0000;
12253 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
12254 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
12256 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, src_surface, NULL, blt_flags[i] | DDBLT_WAIT, &fx);
12257 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
12259 color = get_surface_color(dst_surface, 32, 32);
12260 ok(compare_color(color, 0x0000ff00, 0), "Test %u: Got unexpected color 0x%08x.\n", i, color);
12263 IDirectDrawSurface7_Release(dst_surface);
12264 IDirectDrawSurface7_Release(src_surface);
12265 refcount = IDirectDraw7_Release(ddraw);
12266 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
12267 DestroyWindow(window);
12270 static void test_cross_device_blt(void)
12272 IDirectDrawSurface7 *surface, *surface2, *sysmem_surface;
12273 IDirect3DDevice7 *device, *device2;
12274 IDirectDraw7 *ddraw, *ddraw2;
12275 DDSURFACEDESC2 surface_desc;
12276 HWND window, window2;
12277 IDirect3D7 *d3d;
12278 ULONG refcount;
12279 D3DCOLOR color;
12280 DDBLTFX fx;
12281 HRESULT hr;
12283 window = create_window();
12284 if (!(device = create_device(window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
12286 skip("Failed to create a 3D device.\n");
12287 DestroyWindow(window);
12288 return;
12291 window2 = create_window();
12292 if (!(device2 = create_device(window2, DDSCL_NORMAL)))
12294 skip("Failed to create a 3D device.\n");
12295 IDirect3DDevice7_Release(device);
12296 DestroyWindow(window);
12297 DestroyWindow(window2);
12298 return;
12301 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
12302 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
12303 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
12304 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
12305 IDirect3D7_Release(d3d);
12307 hr = IDirect3DDevice7_GetDirect3D(device2, &d3d);
12308 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
12309 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw2);
12310 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
12311 IDirect3D7_Release(d3d);
12313 memset(&surface_desc, 0, sizeof(surface_desc));
12314 surface_desc.dwSize = sizeof(surface_desc);
12315 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
12316 surface_desc.dwWidth = 640;
12317 surface_desc.dwHeight = 480;
12318 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
12319 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &sysmem_surface, NULL);
12320 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12322 memset(&surface_desc, 0, sizeof(surface_desc));
12323 surface_desc.dwSize = sizeof(surface_desc);
12324 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
12325 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_VIDEOMEMORY;
12326 U5(surface_desc).dwBackBufferCount = 2;
12327 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12328 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12330 memset(&surface_desc, 0, sizeof(surface_desc));
12331 surface_desc.dwSize = sizeof(surface_desc);
12332 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
12333 surface_desc.dwWidth = 640;
12334 surface_desc.dwHeight = 480;
12335 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
12336 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
12337 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
12338 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
12339 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00007c00;
12340 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x000003e0;
12341 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x0000001f;
12342 hr = IDirectDraw7_CreateSurface(ddraw2, &surface_desc, &surface2, NULL);
12343 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12345 memset(&fx, 0, sizeof(fx));
12346 fx.dwSize = sizeof(fx);
12347 U5(fx).dwFillColor = 0xff0000ff;
12348 hr = IDirectDrawSurface7_Blt(surface2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
12349 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
12351 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
12352 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
12353 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
12354 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12355 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
12356 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
12357 color = get_surface_color(surface, 320, 240);
12358 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
12360 hr = IDirectDrawSurface7_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
12361 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
12362 color = get_surface_color(sysmem_surface, 320, 240);
12363 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
12365 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12366 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12367 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
12368 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
12370 hr = IDirectDrawSurface7_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
12371 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
12372 color = get_surface_color(sysmem_surface, 320, 240);
12373 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
12375 IDirectDrawSurface7_Release(surface2);
12376 memset(&surface_desc, 0, sizeof(surface_desc));
12377 surface_desc.dwSize = sizeof(surface_desc);
12378 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
12379 surface_desc.dwWidth = 640;
12380 surface_desc.dwHeight = 480;
12381 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
12382 hr = IDirectDraw7_CreateSurface(ddraw2, &surface_desc, &surface2, NULL);
12383 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12384 hr = IDirectDrawSurface7_Blt(surface2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
12385 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
12387 hr = IDirectDrawSurface7_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
12388 todo_wine ok(hr == D3D_OK, "Failed to blit, hr %#x.\n", hr);
12389 color = get_surface_color(sysmem_surface, 320, 240);
12390 todo_wine ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
12392 IDirectDrawSurface7_Release(surface);
12393 IDirectDrawSurface7_Release(surface2);
12394 IDirectDrawSurface7_Release(sysmem_surface);
12395 IDirectDraw7_Release(ddraw);
12396 IDirectDraw7_Release(ddraw2);
12397 refcount = IDirect3DDevice7_Release(device);
12398 ok(!refcount, "Device has %u references left.\n", refcount);
12399 refcount = IDirect3DDevice7_Release(device2);
12400 ok(!refcount, "Device has %u references left.\n", refcount);
12401 DestroyWindow(window);
12402 DestroyWindow(window2);
12405 static void test_color_clamping(void)
12407 static D3DMATRIX mat =
12409 1.0f, 0.0f, 0.0f, 0.0f,
12410 0.0f, 1.0f, 0.0f, 0.0f,
12411 0.0f, 0.0f, 1.0f, 0.0f,
12412 0.0f, 0.0f, 0.0f, 1.0f,
12414 static struct vec3 quad[] =
12416 {-1.0f, -1.0f, 0.1f},
12417 {-1.0f, 1.0f, 0.1f},
12418 { 1.0f, -1.0f, 0.1f},
12419 { 1.0f, 1.0f, 0.1f},
12421 IDirect3DDevice7 *device;
12422 IDirectDrawSurface7 *rt;
12423 ULONG refcount;
12424 D3DCOLOR color;
12425 HWND window;
12426 HRESULT hr;
12428 window = create_window();
12429 if (!(device = create_device(window, DDSCL_NORMAL)))
12431 skip("Failed to create a 3D device, skipping test.\n");
12432 DestroyWindow(window);
12433 return;
12436 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
12437 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
12439 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
12440 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
12441 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
12442 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
12443 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
12444 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
12445 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
12446 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
12447 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
12448 ok(SUCCEEDED(hr), "Failed to disable Z test, hr %#x.\n", hr);
12449 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
12450 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
12451 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
12452 ok(SUCCEEDED(hr), "Failed to disable stencil test, hr %#x.\n", hr);
12453 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
12454 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
12455 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
12456 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
12458 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0xff404040);
12459 ok(SUCCEEDED(hr), "Failed to set texture factor, hr %#x.\n", hr);
12460 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_ADD);
12461 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
12462 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
12463 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
12464 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_SPECULAR);
12465 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
12466 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_MODULATE);
12467 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
12468 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TFACTOR);
12469 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
12470 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
12471 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
12473 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
12474 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12476 hr = IDirect3DDevice7_BeginScene(device);
12477 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12479 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
12480 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12482 hr = IDirect3DDevice7_EndScene(device);
12483 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12485 color = get_surface_color(rt, 320, 240);
12486 ok(compare_color(color, 0x00404040, 1), "Got unexpected color 0x%08x.\n", color);
12488 IDirectDrawSurface7_Release(rt);
12489 refcount = IDirect3DDevice7_Release(device);
12490 ok(!refcount, "Device has %u references left.\n", refcount);
12491 DestroyWindow(window);
12494 static void test_getdc(void)
12496 DDSCAPS2 caps = {DDSCAPS_COMPLEX, DDSCAPS2_CUBEMAP_NEGATIVEZ, 0, {0}};
12497 IDirectDrawSurface7 *surface, *surface2, *tmp;
12498 DDSURFACEDESC2 surface_desc, map_desc;
12499 IDirectDraw7 *ddraw;
12500 unsigned int i, screen_bpp;
12501 HWND window;
12502 HDC dc, dc2;
12503 HRESULT hr;
12505 static const struct
12507 const char *name;
12508 DDPIXELFORMAT format;
12509 BOOL getdc_supported;
12510 HRESULT alt_result;
12512 test_data[] =
12514 {"D3DFMT_A8R8G8B8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
12515 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}}, TRUE},
12516 {"D3DFMT_X8R8G8B8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
12517 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}}, TRUE},
12518 {"D3DFMT_R5G6B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
12519 {0x0000f800}, {0x000007e0}, {0x0000001f}, {0x00000000}}, TRUE},
12520 {"D3DFMT_X1R5G5B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
12521 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00000000}}, TRUE},
12522 {"D3DFMT_A1R5G5B5", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
12523 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00008000}}, TRUE},
12524 {"D3DFMT_A4R4G4B4", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
12525 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x0000f000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
12526 {"D3DFMT_X4R4G4B4", {sizeof(test_data->format), DDPF_RGB, 0, {16},
12527 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
12528 {"D3DFMT_A2R10G10B10", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
12529 {0xc0000000}, {0x3ff00000}, {0x000ffc00}, {0x000003ff}}, TRUE},
12530 {"D3DFMT_A8B8G8R8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
12531 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0xff000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
12532 {"D3DFMT_X8B8G8R8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
12533 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
12534 {"D3DFMT_R3G3B2", {sizeof(test_data->format), DDPF_RGB, 0, {8},
12535 {0x000000e0}, {0x0000001c}, {0x00000003}, {0x00000000}}, FALSE},
12536 /* GetDC() on a P8 surface fails unless the display mode is 8 bpp.
12537 * This is not implemented in wine yet, so disable the test for now.
12538 * Succeeding P8 GetDC() calls are tested in the ddraw:visual test.
12539 {"D3DFMT_P8", {sizeof(test_data->format), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0, {8 },
12540 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
12542 {"D3DFMT_L8", {sizeof(test_data->format), DDPF_LUMINANCE, 0, {8},
12543 {0x000000ff}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
12544 {"D3DFMT_A8L8", {sizeof(test_data->format), DDPF_ALPHAPIXELS | DDPF_LUMINANCE, 0, {16},
12545 {0x000000ff}, {0x00000000}, {0x00000000}, {0x0000ff00}}, FALSE},
12546 {"D3DFMT_DXT1", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','1'), {0},
12547 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
12548 {"D3DFMT_DXT2", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','2'), {0},
12549 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
12550 {"D3DFMT_DXT3", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','3'), {0},
12551 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
12552 {"D3DFMT_DXT4", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','4'), {0},
12553 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
12554 {"D3DFMT_DXT5", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','5'), {0},
12555 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
12558 window = create_window();
12559 ddraw = create_ddraw();
12560 ok(!!ddraw, "Failed to create a ddraw object.\n");
12561 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12562 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12564 surface_desc.dwSize = sizeof(surface_desc);
12565 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
12566 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr);
12567 screen_bpp = U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount;
12569 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
12571 memset(&surface_desc, 0, sizeof(surface_desc));
12572 surface_desc.dwSize = sizeof(surface_desc);
12573 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
12574 surface_desc.dwWidth = 64;
12575 surface_desc.dwHeight = 64;
12576 U4(surface_desc).ddpfPixelFormat = test_data[i].format;
12577 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12579 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
12581 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
12582 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
12583 if (FAILED(hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
12585 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", test_data[i].name, hr);
12586 continue;
12590 dc = (void *)0x1234;
12591 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12592 if (test_data[i].getdc_supported)
12593 ok(SUCCEEDED(hr) || broken(hr == test_data[i].alt_result),
12594 "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12595 else
12596 ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12598 if (SUCCEEDED(hr))
12600 unsigned int width_bytes;
12601 DIBSECTION dib;
12602 HBITMAP bitmap;
12603 DWORD type;
12604 int size;
12606 type = GetObjectType(dc);
12607 ok(type == OBJ_MEMDC, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
12608 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
12609 type = GetObjectType(bitmap);
12610 ok(type == OBJ_BITMAP, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
12612 size = GetObjectA(bitmap, sizeof(dib), &dib);
12613 ok(size == sizeof(dib), "Got unexpected size %d for format %s.\n", size, test_data[i].name);
12614 ok(!dib.dsBm.bmType, "Got unexpected type %#x for format %s.\n",
12615 dib.dsBm.bmType, test_data[i].name);
12616 ok(dib.dsBm.bmWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
12617 dib.dsBm.bmWidth, test_data[i].name);
12618 ok(dib.dsBm.bmHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
12619 dib.dsBm.bmHeight, test_data[i].name);
12620 width_bytes = ((dib.dsBm.bmWidth * U1(test_data[i].format).dwRGBBitCount + 31) >> 3) & ~3;
12621 ok(dib.dsBm.bmWidthBytes == width_bytes, "Got unexpected width bytes %d for format %s.\n",
12622 dib.dsBm.bmWidthBytes, test_data[i].name);
12623 ok(dib.dsBm.bmPlanes == 1, "Got unexpected plane count %d for format %s.\n",
12624 dib.dsBm.bmPlanes, test_data[i].name);
12625 ok(dib.dsBm.bmBitsPixel == U1(test_data[i].format).dwRGBBitCount,
12626 "Got unexpected bit count %d for format %s.\n",
12627 dib.dsBm.bmBitsPixel, test_data[i].name);
12628 /* Windows XP sets bmBits == NULL for formats that match the screen at least on my r200 GPU. I
12629 * suspect this applies to all HW accelerated pre-WDDM drivers because they can handle gdi access
12630 * to ddraw surfaces themselves instead of going through a sysmem DIB section. */
12631 ok(!!dib.dsBm.bmBits || broken(!pDwmIsCompositionEnabled && dib.dsBm.bmBitsPixel == screen_bpp),
12632 "Got unexpected bits %p for format %s.\n", dib.dsBm.bmBits, test_data[i].name);
12634 ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "Got unexpected size %u for format %s.\n",
12635 dib.dsBmih.biSize, test_data[i].name);
12636 ok(dib.dsBmih.biWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
12637 dib.dsBmih.biHeight, test_data[i].name);
12638 ok(dib.dsBmih.biHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
12639 dib.dsBmih.biHeight, test_data[i].name);
12640 ok(dib.dsBmih.biPlanes == 1, "Got unexpected plane count %u for format %s.\n",
12641 dib.dsBmih.biPlanes, test_data[i].name);
12642 ok(dib.dsBmih.biBitCount == U1(test_data[i].format).dwRGBBitCount,
12643 "Got unexpected bit count %u for format %s.\n",
12644 dib.dsBmih.biBitCount, test_data[i].name);
12645 ok(dib.dsBmih.biCompression == (U1(test_data[i].format).dwRGBBitCount == 16 ? BI_BITFIELDS : BI_RGB)
12646 || broken(U1(test_data[i].format).dwRGBBitCount == 32 && dib.dsBmih.biCompression == BI_BITFIELDS),
12647 "Got unexpected compression %#x for format %s.\n",
12648 dib.dsBmih.biCompression, test_data[i].name);
12649 ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
12650 dib.dsBmih.biSizeImage, test_data[i].name);
12651 ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n",
12652 dib.dsBmih.biXPelsPerMeter, test_data[i].name);
12653 ok(!dib.dsBmih.biYPelsPerMeter, "Got unexpected vertical resolution %d for format %s.\n",
12654 dib.dsBmih.biYPelsPerMeter, test_data[i].name);
12655 ok(!dib.dsBmih.biClrUsed, "Got unexpected used colour count %u for format %s.\n",
12656 dib.dsBmih.biClrUsed, test_data[i].name);
12657 ok(!dib.dsBmih.biClrImportant, "Got unexpected important colour count %u for format %s.\n",
12658 dib.dsBmih.biClrImportant, test_data[i].name);
12660 if (dib.dsBmih.biCompression == BI_BITFIELDS)
12662 ok((dib.dsBitfields[0] == U2(test_data[i].format).dwRBitMask
12663 && dib.dsBitfields[1] == U3(test_data[i].format).dwGBitMask
12664 && dib.dsBitfields[2] == U4(test_data[i].format).dwBBitMask)
12665 || broken(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2]),
12666 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
12667 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
12669 else
12671 ok(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2],
12672 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
12673 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
12675 ok(!dib.dshSection, "Got unexpected section %p for format %s.\n", dib.dshSection, test_data[i].name);
12676 ok(!dib.dsOffset, "Got unexpected offset %u for format %s.\n", dib.dsOffset, test_data[i].name);
12678 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12679 ok(hr == DD_OK, "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12681 else
12683 ok(!dc, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
12686 IDirectDrawSurface7_Release(surface);
12688 if (FAILED(hr))
12689 continue;
12691 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
12692 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_TEXTUREMANAGE;
12693 if (FAILED(hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
12695 skip("Failed to create cube texture for format %s (hr %#x), skipping tests.\n", test_data[i].name, hr);
12696 continue;
12699 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &surface2);
12700 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
12701 hr = IDirectDrawSurface7_GetAttachedSurface(surface2, &caps, &tmp);
12702 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
12703 IDirectDrawSurface7_Release(surface2);
12704 hr = IDirectDrawSurface7_GetAttachedSurface(tmp, &caps, &surface2);
12705 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
12706 IDirectDrawSurface7_Release(tmp);
12708 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12709 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12710 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12711 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12712 hr = IDirectDrawSurface7_GetDC(surface2, &dc);
12713 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12714 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc);
12715 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12717 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12718 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12719 dc2 = (void *)0x1234;
12720 hr = IDirectDrawSurface7_GetDC(surface, &dc2);
12721 ok(hr == DDERR_DCALREADYCREATED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12722 ok(dc2 == (void *)0x1234, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
12723 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12724 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12725 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12726 ok(hr == DDERR_NODC, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12728 map_desc.dwSize = sizeof(map_desc);
12729 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12730 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12731 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12732 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12733 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12734 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12735 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12736 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12738 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12739 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12740 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12741 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12742 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12743 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12745 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12746 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12747 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12748 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12749 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12750 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12751 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12752 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12754 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12755 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12756 hr = IDirectDrawSurface7_GetDC(surface2, &dc2);
12757 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12758 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc2);
12759 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12760 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12761 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12763 hr = IDirectDrawSurface7_GetDC(surface2, &dc);
12764 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12765 hr = IDirectDrawSurface7_GetDC(surface, &dc2);
12766 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12767 hr = IDirectDrawSurface7_ReleaseDC(surface, dc2);
12768 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12769 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc);
12770 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12772 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12773 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12774 hr = IDirectDrawSurface7_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12775 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12776 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
12777 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12778 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12779 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12781 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12782 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12783 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12784 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12785 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12786 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12787 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12788 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12790 hr = IDirectDrawSurface7_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12791 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12792 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12793 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12794 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12795 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12796 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
12797 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12799 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12800 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12801 hr = IDirectDrawSurface7_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12802 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12803 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
12804 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12805 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12806 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12808 hr = IDirectDrawSurface7_GetDC(surface2, &dc);
12809 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12810 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12811 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12812 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12813 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12814 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc);
12815 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12817 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12818 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12819 hr = IDirectDrawSurface7_GetDC(surface2, &dc);
12820 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12821 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12822 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12823 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc);
12824 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12825 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12826 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12828 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
12829 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12830 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12831 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12832 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
12833 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12834 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12835 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12836 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
12837 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12839 IDirectDrawSurface7_Release(surface2);
12840 IDirectDrawSurface7_Release(surface);
12843 IDirectDraw7_Release(ddraw);
12844 DestroyWindow(window);
12847 static void test_draw_primitive(void)
12849 static WORD indices[] = {0, 1, 2, 3};
12850 static struct vec3 quad[] =
12852 {-1.0f, -1.0f, 0.0f},
12853 {-1.0f, 1.0f, 0.0f},
12854 { 1.0f, -1.0f, 0.0f},
12855 { 1.0f, 1.0f, 0.0f},
12857 D3DDRAWPRIMITIVESTRIDEDDATA strided;
12858 D3DVERTEXBUFFERDESC vb_desc;
12859 IDirect3DVertexBuffer7 *vb;
12860 IDirect3DDevice7 *device;
12861 IDirect3D7 *d3d;
12862 IDirectDraw7 *ddraw;
12863 ULONG refcount;
12864 HWND window;
12865 HRESULT hr;
12866 void *data;
12868 window = create_window();
12869 if (!(device = create_device(window, DDSCL_NORMAL)))
12871 skip("Failed to create a 3D device, skipping test.\n");
12872 DestroyWindow(window);
12873 return;
12876 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
12877 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
12878 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
12879 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
12881 memset(&vb_desc, 0, sizeof(vb_desc));
12882 vb_desc.dwSize = sizeof(vb_desc);
12883 vb_desc.dwFVF = D3DFVF_XYZ;
12884 vb_desc.dwNumVertices = 4;
12885 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &vb, 0);
12886 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
12888 IDirect3D7_Release(d3d);
12890 memset(&strided, 0, sizeof(strided));
12892 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, NULL, 0, 0);
12893 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12894 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device,
12895 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, NULL, 0, 0);
12896 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12897 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, NULL, 0, 0);
12898 todo_wine ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
12899 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, NULL, 0, 0);
12900 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12901 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, 0);
12902 /* r200 rejects 0 vertices */
12903 ok(SUCCEEDED(hr) || broken(ddraw_is_amd(ddraw) && hr == E_FAIL), "Failed to draw, hr %#x.\n", hr);
12904 hr = IDirect3DDevice7_DrawPrimitiveStrided(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, 0);
12905 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12906 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, 0);
12907 ok(SUCCEEDED(hr) || broken(ddraw_is_amd(ddraw) && hr == E_FAIL), "Failed to draw, hr %#x.\n", hr);
12909 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, indices, 4, 0);
12910 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12911 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device,
12912 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, indices, 4, 0);
12913 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12914 /* Interestingly r200 rejects this, but not the call with a NULL index buffer and 0 indices. */
12915 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, indices, 4, 0);
12916 ok(SUCCEEDED(hr) || broken(ddraw_is_amd(ddraw) && hr == E_FAIL), "Failed to draw, hr %#x.\n", hr);
12918 strided.position.lpvData = quad;
12919 strided.position.dwStride = sizeof(*quad);
12920 hr = IDirect3DVertexBuffer7_Lock(vb, 0, &data, NULL);
12921 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
12922 memcpy(data, quad, sizeof(quad));
12923 hr = IDirect3DVertexBuffer7_Unlock(vb);
12924 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
12926 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, NULL, 0, 0);
12927 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12928 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device,
12929 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, NULL, 0, 0);
12930 /* r200 again fails this, this time with E_OUTOFMEMORY. */
12931 ok(SUCCEEDED(hr) || broken(ddraw_is_amd(ddraw) && hr == E_OUTOFMEMORY), "Failed to draw, hr %#x.\n", hr);
12932 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, NULL, 0, 0);
12933 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12934 /* Now this draw should work, but r200 rejects it too - presumably earlier tests broke
12935 * driver internal state. */
12936 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
12937 ok(SUCCEEDED(hr) || broken(ddraw_is_amd(ddraw) && hr == E_FAIL), "Failed to draw, hr %#x.\n", hr);
12938 hr = IDirect3DDevice7_DrawPrimitiveStrided(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, 0);
12939 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12940 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, 0);
12941 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12943 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, indices, 4, 0);
12944 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12945 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device,
12946 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, indices, 4, 0);
12947 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12948 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, indices, 4, 0);
12949 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12951 IDirect3DVertexBuffer7_Release(vb);
12952 IDirectDraw7_Release(ddraw);
12953 refcount = IDirect3DDevice7_Release(device);
12954 ok(!refcount, "Device has %u references left.\n", refcount);
12955 DestroyWindow(window);
12958 static void test_edge_antialiasing_blending(void)
12960 IDirectDrawSurface7 *offscreen;
12961 DDSURFACEDESC2 surface_desc;
12962 D3DDEVICEDESC7 device_desc;
12963 IDirect3DDevice7 *device;
12964 IDirectDraw7 *ddraw;
12965 IDirect3D7 *d3d;
12966 ULONG refcount;
12967 D3DCOLOR color;
12968 HWND window;
12969 HRESULT hr;
12971 static D3DMATRIX mat =
12973 1.0f, 0.0f, 0.0f, 0.0f,
12974 0.0f, 1.0f, 0.0f, 0.0f,
12975 0.0f, 0.0f, 1.0f, 0.0f,
12976 0.0f, 0.0f, 0.0f, 1.0f,
12978 static struct
12980 struct vec3 position;
12981 DWORD diffuse;
12983 green_quad[] =
12985 {{-1.0f, -1.0f, 0.1f}, 0x7f00ff00},
12986 {{-1.0f, 1.0f, 0.1f}, 0x7f00ff00},
12987 {{ 1.0f, -1.0f, 0.1f}, 0x7f00ff00},
12988 {{ 1.0f, 1.0f, 0.1f}, 0x7f00ff00},
12990 static struct
12992 struct vec3 position;
12993 DWORD diffuse;
12995 red_quad[] =
12997 {{-1.0f, -1.0f, 0.1f}, 0xccff0000},
12998 {{-1.0f, 1.0f, 0.1f}, 0xccff0000},
12999 {{ 1.0f, -1.0f, 0.1f}, 0xccff0000},
13000 {{ 1.0f, 1.0f, 0.1f}, 0xccff0000},
13003 window = create_window();
13004 if (!(device = create_device(window, DDSCL_NORMAL)))
13006 skip("Failed to create a 3D device.\n");
13007 DestroyWindow(window);
13008 return;
13011 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
13012 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
13013 trace("Line edge antialiasing support: %#x.\n",
13014 device_desc.dpcLineCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
13015 trace("Triangle edge antialiasing support: %#x.\n",
13016 device_desc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
13018 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
13019 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
13020 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
13021 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
13022 IDirect3D7_Release(d3d);
13024 memset(&surface_desc, 0, sizeof(surface_desc));
13025 surface_desc.dwSize = sizeof(surface_desc);
13026 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
13027 surface_desc.dwWidth = 640;
13028 surface_desc.dwHeight = 480;
13029 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
13030 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
13031 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
13032 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
13033 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
13034 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
13035 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
13036 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
13037 ok(hr == D3D_OK, "Creating the offscreen render target failed, hr %#x.\n", hr);
13039 hr = IDirect3DDevice7_SetRenderTarget(device, offscreen, 0);
13040 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
13042 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
13043 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
13044 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
13045 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
13046 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
13047 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
13048 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
13049 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
13050 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
13051 ok(SUCCEEDED(hr), "Failed to disable Z test, hr %#x.\n", hr);
13052 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
13053 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
13054 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
13055 ok(SUCCEEDED(hr), "Failed to disable stencil test, hr %#x.\n", hr);
13056 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
13057 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
13058 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
13059 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
13061 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
13062 ok(SUCCEEDED(hr), "Failed to enable blending, hr %#x.\n", hr);
13063 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
13064 ok(SUCCEEDED(hr), "Failed to set src blend, hr %#x.\n", hr);
13065 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_DESTALPHA);
13066 ok(SUCCEEDED(hr), "Failed to set dest blend, hr %#x.\n", hr);
13068 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
13069 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
13070 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
13071 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
13072 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
13073 ok(SUCCEEDED(hr), "Failed to set alpha op, hr %#x.\n", hr);
13074 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
13075 ok(SUCCEEDED(hr), "Failed to set alpha arg, hr %#x.\n", hr);
13077 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
13078 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13079 hr = IDirect3DDevice7_BeginScene(device);
13080 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
13081 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
13082 green_quad, 4, 0);
13083 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13084 hr = IDirect3DDevice7_EndScene(device);
13085 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
13086 color = get_surface_color(offscreen, 320, 240);
13087 ok(compare_color(color, 0x00cc7f00, 1), "Got unexpected color 0x%08x.\n", color);
13089 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
13090 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13091 hr = IDirect3DDevice7_BeginScene(device);
13092 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
13093 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
13094 red_quad, 4, 0);
13095 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13096 hr = IDirect3DDevice7_EndScene(device);
13097 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
13098 color = get_surface_color(offscreen, 320, 240);
13099 ok(compare_color(color, 0x00cc7f00, 1), "Got unexpected color 0x%08x.\n", color);
13101 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
13102 ok(SUCCEEDED(hr), "Failed to disable blending, hr %#x.\n", hr);
13104 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
13105 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13106 hr = IDirect3DDevice7_BeginScene(device);
13107 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
13108 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
13109 green_quad, 4, 0);
13110 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13111 hr = IDirect3DDevice7_EndScene(device);
13112 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
13113 color = get_surface_color(offscreen, 320, 240);
13114 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
13116 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
13117 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13118 hr = IDirect3DDevice7_BeginScene(device);
13119 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
13120 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
13121 red_quad, 4, 0);
13122 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13123 hr = IDirect3DDevice7_EndScene(device);
13124 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
13125 color = get_surface_color(offscreen, 320, 240);
13126 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
13128 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_EDGEANTIALIAS, TRUE);
13129 ok(SUCCEEDED(hr), "Failed to enable edge antialiasing, hr %#x.\n", hr);
13131 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
13132 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13133 hr = IDirect3DDevice7_BeginScene(device);
13134 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
13135 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
13136 green_quad, 4, 0);
13137 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13138 hr = IDirect3DDevice7_EndScene(device);
13139 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
13140 color = get_surface_color(offscreen, 320, 240);
13141 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
13143 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
13144 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13145 hr = IDirect3DDevice7_BeginScene(device);
13146 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
13147 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
13148 red_quad, 4, 0);
13149 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13150 hr = IDirect3DDevice7_EndScene(device);
13151 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
13152 color = get_surface_color(offscreen, 320, 240);
13153 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
13155 IDirectDrawSurface7_Release(offscreen);
13156 IDirectDraw7_Release(ddraw);
13157 refcount = IDirect3DDevice7_Release(device);
13158 ok(!refcount, "Device has %u references left.\n", refcount);
13159 DestroyWindow(window);
13162 static void test_display_mode_surface_pixel_format(void)
13164 unsigned int width, height, bpp;
13165 IDirectDrawSurface7 *surface;
13166 DDSURFACEDESC2 surface_desc;
13167 IDirectDraw7 *ddraw;
13168 ULONG refcount;
13169 HWND window;
13170 HRESULT hr;
13172 if (!(ddraw = create_ddraw()))
13174 skip("Failed to create ddraw.\n");
13175 return;
13178 surface_desc.dwSize = sizeof(surface_desc);
13179 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
13180 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr);
13181 width = surface_desc.dwWidth;
13182 height = surface_desc.dwHeight;
13184 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
13185 0, 0, width, height, NULL, NULL, NULL, NULL);
13186 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
13187 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13189 bpp = 0;
13190 if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 16, 0, 0)))
13191 bpp = 16;
13192 if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 24, 0, 0)))
13193 bpp = 24;
13194 if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
13195 bpp = 32;
13196 ok(bpp, "Set display mode failed.\n");
13198 surface_desc.dwSize = sizeof(surface_desc);
13199 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
13200 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr);
13201 ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width);
13202 ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height);
13203 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
13204 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
13206 memset(&surface_desc, 0, sizeof(surface_desc));
13207 surface_desc.dwSize = sizeof(surface_desc);
13208 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
13209 U5(surface_desc).dwBackBufferCount = 1;
13210 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE;
13211 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
13212 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
13213 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
13214 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
13215 ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width);
13216 ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height);
13217 ok(U4(surface_desc).ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n",
13218 U4(surface_desc).ddpfPixelFormat.dwFlags);
13219 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
13220 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
13221 IDirectDrawSurface7_Release(surface);
13223 memset(&surface_desc, 0, sizeof(surface_desc));
13224 surface_desc.dwSize = sizeof(surface_desc);
13225 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
13226 surface_desc.dwWidth = width;
13227 surface_desc.dwHeight = height;
13228 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13229 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
13230 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
13231 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
13232 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
13233 ok(U4(surface_desc).ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n",
13234 U4(surface_desc).ddpfPixelFormat.dwFlags);
13235 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
13236 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
13237 IDirectDrawSurface7_Release(surface);
13239 refcount = IDirectDraw7_Release(ddraw);
13240 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
13241 DestroyWindow(window);
13244 static void test_surface_desc_size(void)
13246 union
13248 DWORD dwSize;
13249 DDSURFACEDESC desc1;
13250 DDSURFACEDESC2 desc2;
13251 BYTE blob[1024];
13252 } desc;
13253 IDirectDrawSurface7 *surface7;
13254 IDirectDrawSurface3 *surface3;
13255 IDirectDrawSurface *surface;
13256 DDSURFACEDESC2 surface_desc;
13257 HRESULT expected_hr, hr;
13258 IDirectDraw7 *ddraw;
13259 unsigned int i, j;
13260 ULONG refcount;
13262 static const struct
13264 unsigned int caps;
13265 const char *name;
13267 surface_caps[] =
13269 {DDSCAPS_OFFSCREENPLAIN, "offscreenplain"},
13270 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, "systemmemory texture"},
13271 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, "videomemory texture"},
13273 static const unsigned int desc_sizes[] =
13275 sizeof(DDSURFACEDESC),
13276 sizeof(DDSURFACEDESC2),
13277 sizeof(DDSURFACEDESC) + 1,
13278 sizeof(DDSURFACEDESC2) + 1,
13279 2 * sizeof(DDSURFACEDESC),
13280 2 * sizeof(DDSURFACEDESC2),
13281 sizeof(DDSURFACEDESC) - 1,
13282 sizeof(DDSURFACEDESC2) - 1,
13283 sizeof(DDSURFACEDESC) / 2,
13284 sizeof(DDSURFACEDESC2) / 2,
13288 sizeof(desc) / 2,
13289 sizeof(desc) - 100,
13292 if (!(ddraw = create_ddraw()))
13294 skip("Failed to create ddraw.\n");
13295 return;
13297 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
13298 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13300 for (i = 0; i < ARRAY_SIZE(surface_caps); ++i)
13302 memset(&surface_desc, 0, sizeof(surface_desc));
13303 surface_desc.dwSize = sizeof(surface_desc);
13304 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
13305 surface_desc.ddsCaps.dwCaps = surface_caps[i].caps;
13306 surface_desc.dwHeight = 128;
13307 surface_desc.dwWidth = 128;
13308 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface7, NULL)))
13310 skip("Failed to create surface, type %s.\n", surface_caps[i].name);
13311 continue;
13313 hr = IDirectDrawSurface_QueryInterface(surface7, &IID_IDirectDrawSurface, (void **)&surface);
13314 ok(hr == DD_OK, "Failed to query IDirectDrawSurface, hr %#x, type %s.\n", hr, surface_caps[i].name);
13315 hr = IDirectDrawSurface_QueryInterface(surface7, &IID_IDirectDrawSurface3, (void **)&surface3);
13316 ok(hr == DD_OK, "Failed to query IDirectDrawSurface3, hr %#x, type %s.\n", hr, surface_caps[i].name);
13318 /* GetSurfaceDesc() */
13319 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
13321 memset(&desc, 0, sizeof(desc));
13322 desc.dwSize = desc_sizes[j];
13323 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC) ? DD_OK : DDERR_INVALIDPARAMS;
13324 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &desc.desc1);
13325 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13326 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13328 memset(&desc, 0, sizeof(desc));
13329 desc.dwSize = desc_sizes[j];
13330 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC) ? DD_OK : DDERR_INVALIDPARAMS;
13331 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &desc.desc1);
13332 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13333 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13335 memset(&desc, 0, sizeof(desc));
13336 desc.dwSize = desc_sizes[j];
13337 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC2) ? DD_OK : DDERR_INVALIDPARAMS;
13338 hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &desc.desc2);
13339 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13340 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13343 /* Lock() */
13344 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
13346 const BOOL ignore_size = surface_caps[i].caps & DDSCAPS_TEXTURE
13347 && !(surface_caps[i].caps & DDSCAPS_VIDEOMEMORY);
13348 const BOOL valid_size = desc_sizes[j] == sizeof(DDSURFACEDESC)
13349 || desc_sizes[j] == sizeof(DDSURFACEDESC2);
13350 DWORD expected_texture_stage;
13352 memset(&desc, 0, sizeof(desc));
13353 desc.dwSize = desc_sizes[j];
13354 desc.desc2.dwTextureStage = 0xdeadbeef;
13355 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
13356 hr = IDirectDrawSurface_Lock(surface, NULL, &desc.desc1, 0, 0);
13357 expected_hr = ignore_size || valid_size ? DD_OK : DDERR_INVALIDPARAMS;
13358 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13359 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13360 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
13361 desc_sizes[j], desc.dwSize, surface_caps[i].name);
13362 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
13363 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
13364 if (SUCCEEDED(hr))
13366 ok(desc.desc1.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
13367 desc.desc1.dwWidth, desc_sizes[j], surface_caps[i].name);
13368 ok(desc.desc1.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
13369 desc.desc1.dwHeight, desc_sizes[j], surface_caps[i].name);
13370 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
13371 todo_wine_if(!expected_texture_stage)
13372 ok(desc.desc2.dwTextureStage == expected_texture_stage,
13373 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
13374 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
13375 IDirectDrawSurface_Unlock(surface, NULL);
13378 memset(&desc, 0, sizeof(desc));
13379 desc.dwSize = desc_sizes[j];
13380 desc.desc2.dwTextureStage = 0xdeadbeef;
13381 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
13382 hr = IDirectDrawSurface3_Lock(surface3, NULL, &desc.desc1, 0, 0);
13383 expected_hr = ignore_size || valid_size ? DD_OK : DDERR_INVALIDPARAMS;
13384 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13385 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13386 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
13387 desc_sizes[j], desc.dwSize, surface_caps[i].name);
13388 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
13389 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
13390 if (SUCCEEDED(hr))
13392 ok(desc.desc1.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
13393 desc.desc1.dwWidth, desc_sizes[j], surface_caps[i].name);
13394 ok(desc.desc1.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
13395 desc.desc1.dwHeight, desc_sizes[j], surface_caps[i].name);
13396 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
13397 todo_wine_if(!expected_texture_stage)
13398 ok(desc.desc2.dwTextureStage == expected_texture_stage,
13399 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
13400 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
13401 IDirectDrawSurface3_Unlock(surface3, NULL);
13404 memset(&desc, 0, sizeof(desc));
13405 desc.dwSize = desc_sizes[j];
13406 desc.desc2.dwTextureStage = 0xdeadbeef;
13407 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
13408 hr = IDirectDrawSurface7_Lock(surface7, NULL, &desc.desc2, 0, 0);
13409 expected_hr = ignore_size || valid_size ? DD_OK : DDERR_INVALIDPARAMS;
13410 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13411 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13412 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
13413 desc_sizes[j], desc.dwSize, surface_caps[i].name);
13414 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
13415 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
13416 if (SUCCEEDED(hr))
13418 ok(desc.desc2.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
13419 desc.desc2.dwWidth, desc_sizes[j], surface_caps[i].name);
13420 ok(desc.desc2.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
13421 desc.desc2.dwHeight, desc_sizes[j], surface_caps[i].name);
13422 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
13423 ok(desc.desc2.dwTextureStage == expected_texture_stage,
13424 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
13425 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
13426 IDirectDrawSurface7_Unlock(surface7, NULL);
13430 IDirectDrawSurface7_Release(surface7);
13431 IDirectDrawSurface3_Release(surface3);
13432 IDirectDrawSurface_Release(surface);
13435 /* GetDisplayMode() */
13436 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
13438 memset(&desc, 0xcc, sizeof(desc));
13439 desc.dwSize = desc_sizes[j];
13440 expected_hr = (desc.dwSize == sizeof(DDSURFACEDESC) || desc.dwSize == sizeof(DDSURFACEDESC2))
13441 ? DD_OK : DDERR_INVALIDPARAMS;
13442 hr = IDirectDraw7_GetDisplayMode(ddraw, &desc.desc2);
13443 ok(hr == expected_hr, "Got hr %#x, expected %#x, size %u.\n", hr, expected_hr, desc_sizes[j]);
13444 if (SUCCEEDED(hr))
13446 ok(desc.dwSize == sizeof(DDSURFACEDESC2), "Wrong size %u for %u.\n", desc.dwSize, desc_sizes[j]);
13447 ok(desc.blob[desc_sizes[j]] == 0xcc, "Overflow for size %u.\n", desc_sizes[j]);
13448 ok(desc.blob[desc_sizes[j] - 1] != 0xcc, "Struct not cleared for size %u.\n", desc_sizes[j]);
13452 refcount = IDirectDraw7_Release(ddraw);
13453 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
13456 static void test_get_surface_from_dc(void)
13458 IDirectDrawSurface *surface1, *tmp1;
13459 IDirectDrawSurface7 *surface, *tmp;
13460 DDSURFACEDESC2 surface_desc;
13461 IDirectDraw7 *ddraw;
13462 HDC dc, device_dc;
13463 ULONG refcount;
13464 HWND window;
13465 HRESULT hr;
13466 DWORD ret;
13468 window = create_window();
13469 ddraw = create_ddraw();
13470 ok(!!ddraw, "Failed to create a ddraw object.\n");
13471 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
13472 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13474 memset(&surface_desc, 0, sizeof(surface_desc));
13475 surface_desc.dwSize = sizeof(surface_desc);
13476 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
13477 surface_desc.dwWidth = 64;
13478 surface_desc.dwHeight = 64;
13479 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13481 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
13482 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13483 hr = IDirectDrawSurface7_QueryInterface(surface, &IID_IDirectDrawSurface, (void **)&surface1);
13484 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
13486 refcount = get_refcount((IUnknown *)surface1);
13487 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
13488 refcount = get_refcount((IUnknown *)surface);
13489 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
13491 hr = IDirectDrawSurface7_GetDC(surface, &dc);
13492 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
13494 tmp1 = (void *)0xdeadbeef;
13495 device_dc = (void *)0xdeadbeef;
13496 hr = GetSurfaceFromDC(NULL, &tmp1, &device_dc);
13497 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
13498 ok(!tmp1, "Got unexpected surface %p.\n", tmp1);
13499 ok(!device_dc, "Got unexpected device_dc %p.\n", device_dc);
13501 device_dc = (void *)0xdeadbeef;
13502 hr = GetSurfaceFromDC(dc, NULL, &device_dc);
13503 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
13504 ok(device_dc == (void *)0xdeadbeef, "Got unexpected device_dc %p.\n", device_dc);
13506 tmp1 = (void *)0xdeadbeef;
13507 hr = GetSurfaceFromDC(dc, &tmp1, NULL);
13508 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
13509 ok(!tmp1, "Got unexpected surface %p.\n", tmp1);
13511 hr = GetSurfaceFromDC(dc, &tmp1, &device_dc);
13512 ok(SUCCEEDED(hr), "GetSurfaceFromDC failed, hr %#x.\n", hr);
13513 ok(tmp1 == surface1, "Got unexpected surface %p, expected %p.\n", tmp1, surface1);
13514 IDirectDrawSurface_Release(tmp1);
13516 ret = GetObjectType(device_dc);
13517 todo_wine ok(ret == OBJ_DC, "Got unexpected object type %#x.\n", ret);
13518 ret = GetDeviceCaps(device_dc, TECHNOLOGY);
13519 todo_wine ok(ret == DT_RASDISPLAY, "Got unexpected technology %#x.\n", ret);
13521 hr = IDirectDraw7_GetSurfaceFromDC(ddraw, dc, NULL);
13522 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
13524 hr = IDirectDraw7_GetSurfaceFromDC(ddraw, dc, &tmp);
13525 ok(SUCCEEDED(hr), "GetSurfaceFromDC failed, hr %#x.\n", hr);
13526 ok(tmp == surface, "Got unexpected surface %p, expected %p.\n", tmp, surface);
13528 refcount = get_refcount((IUnknown *)surface1);
13529 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
13530 refcount = get_refcount((IUnknown *)surface);
13531 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
13533 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
13534 ok(SUCCEEDED(hr), "ReleaseDC failed, hr %#x.\n", hr);
13536 IDirectDrawSurface_Release(tmp);
13538 dc = CreateCompatibleDC(NULL);
13539 ok(!!dc, "CreateCompatibleDC failed.\n");
13541 tmp1 = (void *)0xdeadbeef;
13542 device_dc = (void *)0xdeadbeef;
13543 hr = GetSurfaceFromDC(dc, &tmp1, &device_dc);
13544 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
13545 ok(!tmp1, "Got unexpected surface %p.\n", tmp1);
13546 ok(!device_dc, "Got unexpected device_dc %p.\n", device_dc);
13548 tmp = (void *)0xdeadbeef;
13549 hr = IDirectDraw7_GetSurfaceFromDC(ddraw, dc, &tmp);
13550 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
13551 ok(!tmp, "Got unexpected surface %p.\n", tmp);
13553 ok(DeleteDC(dc), "DeleteDC failed.\n");
13555 tmp = (void *)0xdeadbeef;
13556 hr = IDirectDraw7_GetSurfaceFromDC(ddraw, NULL, &tmp);
13557 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
13558 ok(!tmp, "Got unexpected surface %p.\n", tmp);
13560 IDirectDrawSurface7_Release(surface);
13561 IDirectDrawSurface_Release(surface1);
13562 IDirectDraw7_Release(ddraw);
13563 DestroyWindow(window);
13566 static void test_ck_operation(void)
13568 IDirectDrawSurface7 *src, *dst;
13569 IDirectDrawSurface *src1, *dst1;
13570 DDSURFACEDESC2 surface_desc;
13571 IDirectDraw7 *ddraw;
13572 ULONG refcount;
13573 HWND window;
13574 HRESULT hr;
13575 D3DCOLOR *color;
13576 unsigned int i;
13577 DDCOLORKEY ckey;
13578 DDBLTFX fx;
13580 window = create_window();
13581 ddraw = create_ddraw();
13582 ok(!!ddraw, "Failed to create a ddraw object.\n");
13583 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
13584 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13586 memset(&surface_desc, 0, sizeof(surface_desc));
13587 surface_desc.dwSize = sizeof(surface_desc);
13588 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
13589 surface_desc.dwWidth = 4;
13590 surface_desc.dwHeight = 1;
13591 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13592 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
13593 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
13594 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
13595 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
13596 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
13597 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
13598 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13600 surface_desc.dwFlags |= DDSD_CKSRCBLT;
13601 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff00ff;
13602 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff00ff;
13603 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
13604 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13606 hr = IDirectDrawSurface7_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13607 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13608 ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n");
13609 color = surface_desc.lpSurface;
13610 color[0] = 0x77010203;
13611 color[1] = 0x00010203;
13612 color[2] = 0x77ff00ff;
13613 color[3] = 0x00ff00ff;
13614 hr = IDirectDrawSurface7_Unlock(src, NULL);
13615 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13617 for (i = 0; i < 2; ++i)
13619 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13620 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13621 color = surface_desc.lpSurface;
13622 color[0] = 0xcccccccc;
13623 color[1] = 0xcccccccc;
13624 color[2] = 0xcccccccc;
13625 color[3] = 0xcccccccc;
13626 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13627 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13629 if (i)
13631 hr = IDirectDrawSurface7_BltFast(dst, 0, 0, src, NULL, DDBLTFAST_SRCCOLORKEY);
13632 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13634 else
13636 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, NULL);
13637 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13640 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT | DDLOCK_READONLY, NULL);
13641 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13642 ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n");
13643 color = surface_desc.lpSurface;
13644 /* Different behavior on some drivers / windows versions. Some versions ignore the X channel when
13645 * color keying, but copy it to the destination surface. Others (sysmem surfaces) apply it for
13646 * color keying, but do not copy it into the destination surface. Nvidia neither uses it for
13647 * color keying nor copies it. */
13648 ok((color[0] == 0x77010203 && color[1] == 0x00010203
13649 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* AMD, Wine */
13650 || broken(color[0] == 0x00010203 && color[1] == 0x00010203
13651 && color[2] == 0x00ff00ff && color[3] == 0xcccccccc) /* Sysmem surfaces? */
13652 || broken(color[0] == 0x00010203 && color[1] == 0x00010203
13653 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Nvidia */
13654 || broken(color[0] == 0xff010203 && color[1] == 0xff010203
13655 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Testbot */,
13656 "Destination data after blitting is %08x %08x %08x %08x, i=%u.\n",
13657 color[0], color[1], color[2], color[3], i);
13658 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13659 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13662 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13663 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
13664 ok(ckey.dwColorSpaceLowValue == 0x00ff00ff && ckey.dwColorSpaceHighValue == 0x00ff00ff,
13665 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13667 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
13668 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13669 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13671 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
13672 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13673 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
13674 ok(ckey.dwColorSpaceLowValue == 0x0000ff00 && ckey.dwColorSpaceHighValue == 0x0000ff00,
13675 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13677 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0;
13678 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0;
13679 hr = IDirectDrawSurface7_GetSurfaceDesc(src, &surface_desc);
13680 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
13681 ok(surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue == 0x0000ff00
13682 && surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue == 0x0000ff00,
13683 "Got unexpected color key low=%08x high=%08x.\n", surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue,
13684 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue);
13686 /* Test SetColorKey with dwColorSpaceHighValue < dwColorSpaceLowValue */
13687 ckey.dwColorSpaceLowValue = 0x000000ff;
13688 ckey.dwColorSpaceHighValue = 0x00000000;
13689 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13690 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13692 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
13693 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13694 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
13695 ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff,
13696 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13698 ckey.dwColorSpaceLowValue = 0x000000ff;
13699 ckey.dwColorSpaceHighValue = 0x00000001;
13700 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13701 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13703 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
13704 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13705 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
13706 ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff,
13707 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13709 ckey.dwColorSpaceLowValue = 0x000000fe;
13710 ckey.dwColorSpaceHighValue = 0x000000fd;
13711 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13712 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13714 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
13715 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13716 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
13717 ok(ckey.dwColorSpaceLowValue == 0x000000fe && ckey.dwColorSpaceHighValue == 0x000000fe,
13718 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13720 IDirectDrawSurface7_Release(src);
13721 IDirectDrawSurface7_Release(dst);
13723 /* Test source and destination keys and where they are read from. Use a surface with alpha
13724 * to avoid driver-dependent content in the X channel. */
13725 memset(&surface_desc, 0, sizeof(surface_desc));
13726 surface_desc.dwSize = sizeof(surface_desc);
13727 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
13728 surface_desc.dwWidth = 6;
13729 surface_desc.dwHeight = 1;
13730 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13731 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
13732 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
13733 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
13734 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
13735 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
13736 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
13737 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
13738 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13739 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
13740 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13742 ckey.dwColorSpaceLowValue = 0x0000ff00;
13743 ckey.dwColorSpaceHighValue = 0x0000ff00;
13744 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
13745 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13746 ckey.dwColorSpaceLowValue = 0x00ff0000;
13747 ckey.dwColorSpaceHighValue = 0x00ff0000;
13748 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_DESTBLT, &ckey);
13749 ok(SUCCEEDED(hr) || hr == DDERR_NOCOLORKEYHW, "Failed to set color key, hr %#x.\n", hr);
13750 if (FAILED(hr))
13752 /* Nvidia reject dest keys, AMD allows them. This applies to vidmem and sysmem surfaces. */
13753 skip("Failed to set destination color key, skipping related tests.\n");
13754 goto done;
13757 ckey.dwColorSpaceLowValue = 0x000000ff;
13758 ckey.dwColorSpaceHighValue = 0x000000ff;
13759 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13760 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13761 ckey.dwColorSpaceLowValue = 0x000000aa;
13762 ckey.dwColorSpaceHighValue = 0x000000aa;
13763 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_DESTBLT, &ckey);
13764 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13766 memset(&fx, 0, sizeof(fx));
13767 fx.dwSize = sizeof(fx);
13768 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x00110000;
13769 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x00110000;
13770 fx.ddckDestColorkey.dwColorSpaceHighValue = 0x00001100;
13771 fx.ddckDestColorkey.dwColorSpaceLowValue = 0x00001100;
13773 hr = IDirectDrawSurface7_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13774 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13775 color = surface_desc.lpSurface;
13776 color[0] = 0x000000ff; /* Applies to src blt key in src surface. */
13777 color[1] = 0x000000aa; /* Applies to dst blt key in src surface. */
13778 color[2] = 0x00ff0000; /* Dst color key in dst surface. */
13779 color[3] = 0x0000ff00; /* Src color key in dst surface. */
13780 color[4] = 0x00001100; /* Src color key in ddbltfx. */
13781 color[5] = 0x00110000; /* Dst color key in ddbltfx. */
13782 hr = IDirectDrawSurface7_Unlock(src, NULL);
13783 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13785 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13786 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13787 color = surface_desc.lpSurface;
13788 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
13789 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13790 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13792 /* Test a blit without keying. */
13793 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, 0, &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 /* Should have copied src data unmodified to dst. */
13800 ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
13801 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
13802 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13803 color[0], color[1], color[2], color[3], color[4], color[5]);
13805 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
13806 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13807 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13809 /* Src key. */
13810 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx);
13811 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13813 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13814 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13815 color = surface_desc.lpSurface;
13816 /* Src key applied to color[0]. It is unmodified, the others are copied. */
13817 ok(color[0] == 0x55555555 && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
13818 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
13819 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13820 color[0], color[1], color[2], color[3], color[4], color[5]);
13822 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
13823 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13824 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13826 /* Src override. */
13827 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, &fx);
13828 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13830 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13831 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13832 color = surface_desc.lpSurface;
13833 /* Override key applied to color[5]. It is unmodified, the others are copied. */
13834 ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
13835 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x55555555,
13836 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13837 color[0], color[1], color[2], color[3], color[4], color[5]);
13839 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
13840 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13841 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13843 /* Src override AND src key. That is not supposed to work. */
13844 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE, &fx);
13845 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13847 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13848 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13849 color = surface_desc.lpSurface;
13850 /* Ensure the destination was not changed. */
13851 ok(color[0] == 0x55555555 && color[1] == 0x55555555 && color[2] == 0x55555555 &&
13852 color[3] == 0x55555555 && color[4] == 0x55555555 && color[5] == 0x55555555,
13853 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13854 color[0], color[1], color[2], color[3], color[4], color[5]);
13856 /* Use different dst colors for the dst key test. */
13857 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13858 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13859 color[2] = 0x00001100; /* Dest key in override. */
13860 color[3] = 0x00001100; /* Dest key in override. */
13861 color[4] = 0x000000aa; /* Dest key in src surface. */
13862 color[5] = 0x000000aa; /* Dest key in src surface. */
13863 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13864 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13866 /* Dest key blit. The key is taken from the DESTINATION surface in v7! */
13867 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
13868 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13870 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13871 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13872 color = surface_desc.lpSurface;
13873 /* Dst key applied to color[0,1], they are the only changed pixels. */
13874 todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 &&
13875 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
13876 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13877 color[0], color[1], color[2], color[3], color[4], color[5]);
13879 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13880 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13881 color[2] = 0x00001100; /* Dest key in override. */
13882 color[3] = 0x00001100; /* Dest key in override. */
13883 color[4] = 0x000000aa; /* Dest key in src surface. */
13884 color[5] = 0x000000aa; /* Dest key in src surface. */
13885 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13886 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13888 /* What happens with a QI'd older version of the interface? It takes the key
13889 * from the source surface. */
13890 hr = IDirectDrawSurface7_QueryInterface(src, &IID_IDirectDrawSurface, (void **)&src1);
13891 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
13892 hr = IDirectDrawSurface7_QueryInterface(dst, &IID_IDirectDrawSurface, (void **)&dst1);
13893 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
13895 hr = IDirectDrawSurface_Blt(dst1, NULL, src1, NULL, DDBLT_KEYDEST, &fx);
13896 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13898 IDirectDrawSurface_Release(dst1);
13899 IDirectDrawSurface_Release(src1);
13901 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13902 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13903 color = surface_desc.lpSurface;
13904 /* Dst key applied to color[4,5], they are the only changed pixels. */
13905 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
13906 color[3] == 0x00001100 && color[4] == 0x00001100 && color[5] == 0x00110000,
13907 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13908 color[0], color[1], color[2], color[3], color[4], color[5]);
13910 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13911 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13912 color[2] = 0x00001100; /* Dest key in override. */
13913 color[3] = 0x00001100; /* Dest key in override. */
13914 color[4] = 0x000000aa; /* Dest key in src surface. */
13915 color[5] = 0x000000aa; /* Dest key in src surface. */
13916 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13917 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13919 /* Dest override key blit. */
13920 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, &fx);
13921 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13923 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13924 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13925 color = surface_desc.lpSurface;
13926 /* Dst key applied to color[2,3], they are the only changed pixels. */
13927 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00ff0000 &&
13928 color[3] == 0x0000ff00 && color[4] == 0x000000aa && color[5] == 0x000000aa,
13929 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13930 color[0], color[1], color[2], color[3], color[4], color[5]);
13932 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13933 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13934 color[2] = 0x00001100; /* Dest key in override. */
13935 color[3] = 0x00001100; /* Dest key in override. */
13936 color[4] = 0x000000aa; /* Dest key in src surface. */
13937 color[5] = 0x000000aa; /* Dest key in src surface. */
13938 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13939 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13941 /* Dest override together with surface key. Supposed to fail. */
13942 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYDESTOVERRIDE, &fx);
13943 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13945 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13946 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13947 color = surface_desc.lpSurface;
13948 /* Destination is unchanged. */
13949 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
13950 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
13951 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13952 color[0], color[1], color[2], color[3], color[4], color[5]);
13953 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13954 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13956 /* Source and destination key. This is driver dependent. New HW treats it like
13957 * DDBLT_KEYSRC. Older HW and some software renderers apply both keys. */
13958 if (0)
13960 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYSRC, &fx);
13961 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13963 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13964 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13965 color = surface_desc.lpSurface;
13966 /* Color[0] is filtered by the src key, 2-5 are filtered by the dst key, if
13967 * the driver applies it. */
13968 ok(color[0] == 0x00ff0000 && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
13969 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
13970 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13971 color[0], color[1], color[2], color[3], color[4], color[5]);
13973 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13974 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13975 color[2] = 0x00001100; /* Dest key in override. */
13976 color[3] = 0x00001100; /* Dest key in override. */
13977 color[4] = 0x000000aa; /* Dest key in src surface. */
13978 color[5] = 0x000000aa; /* Dest key in src surface. */
13979 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13980 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13983 /* Override keys without ddbltfx parameter fail */
13984 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, NULL);
13985 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13986 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, NULL);
13987 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13989 /* Try blitting without keys in the source surface. */
13990 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, NULL);
13991 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13992 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_DESTBLT, NULL);
13993 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13995 /* That fails now. Do not bother to check that the data is unmodified. */
13996 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx);
13997 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13999 /* Dest key blit still works, the destination surface key is used in v7. */
14000 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
14001 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14003 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14004 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14005 color = surface_desc.lpSurface;
14006 /* Dst key applied to color[0,1], they are the only changed pixels. */
14007 todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 &&
14008 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
14009 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14010 color[0], color[1], color[2], color[3], color[4], color[5]);
14011 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14012 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14014 /* Try blitting without keys in the destination surface. */
14015 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_SRCBLT, NULL);
14016 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14017 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_DESTBLT, NULL);
14018 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14020 /* This fails, as sanity would dictate. */
14021 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
14022 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14024 done:
14025 IDirectDrawSurface7_Release(src);
14026 IDirectDrawSurface7_Release(dst);
14027 refcount = IDirectDraw7_Release(ddraw);
14028 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
14029 DestroyWindow(window);
14032 static void test_vb_refcount(void)
14034 ULONG prev_d3d_refcount, prev_device_refcount;
14035 ULONG cur_d3d_refcount, cur_device_refcount;
14036 IDirect3DVertexBuffer7 *vb, *vb7;
14037 D3DVERTEXBUFFERDESC vb_desc;
14038 IDirect3DVertexBuffer *vb1;
14039 IDirect3DDevice7 *device;
14040 IDirect3D7 *d3d;
14041 ULONG refcount;
14042 IUnknown *unk;
14043 HWND window;
14044 HRESULT hr;
14046 window = create_window();
14047 if (!(device = create_device(window, DDSCL_NORMAL)))
14049 skip("Failed to create a 3D device, skipping test.\n");
14050 DestroyWindow(window);
14051 return;
14054 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
14055 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
14057 prev_d3d_refcount = get_refcount((IUnknown *)d3d);
14058 prev_device_refcount = get_refcount((IUnknown *)device);
14060 memset(&vb_desc, 0, sizeof(vb_desc));
14061 vb_desc.dwSize = sizeof(vb_desc);
14062 vb_desc.dwFVF = D3DFVF_XYZ;
14063 vb_desc.dwNumVertices = 4;
14064 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &vb, 0);
14065 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
14067 cur_d3d_refcount = get_refcount((IUnknown *)d3d);
14068 cur_device_refcount = get_refcount((IUnknown *)device);
14069 ok(cur_d3d_refcount > prev_d3d_refcount, "D3D object refcount didn't change from %u.\n", prev_d3d_refcount);
14070 ok(cur_device_refcount == prev_device_refcount, "Device refcount changed from %u to %u.\n",
14071 prev_device_refcount, cur_device_refcount);
14073 prev_d3d_refcount = cur_d3d_refcount;
14074 hr = IDirect3DVertexBuffer7_QueryInterface(vb, &IID_IDirect3DVertexBuffer7, (void **)&vb7);
14075 ok(hr == DD_OK, "Failed to query IDirect3DVertexBuffer7, hr %#x.\n", hr);
14076 cur_d3d_refcount = get_refcount((IUnknown *)d3d);
14077 ok(cur_d3d_refcount == prev_d3d_refcount, "D3D object refcount changed from %u to %u.\n",
14078 prev_d3d_refcount, cur_d3d_refcount);
14079 IDirect3DVertexBuffer7_Release(vb7);
14081 hr = IDirect3DVertexBuffer7_QueryInterface(vb, &IID_IDirect3DVertexBuffer, (void **)&vb1);
14082 ok(hr == E_NOINTERFACE, "Querying IDirect3DVertexBuffer returned unexpected hr %#x.\n", hr);
14084 hr = IDirect3DVertexBuffer_QueryInterface(vb, &IID_IUnknown, (void **)&unk);
14085 ok(hr == DD_OK, "Failed to query IUnknown, hr %#x.\n", hr);
14086 ok((IUnknown *)vb == unk,
14087 "IDirect3DVertexBuffer7 and IUnknown interface pointers don't match, %p != %p.\n", vb, unk);
14088 IUnknown_Release(unk);
14090 refcount = IDirect3DVertexBuffer7_Release(vb);
14091 ok(!refcount, "Vertex buffer has %u references left.\n", refcount);
14093 IDirect3D7_Release(d3d);
14094 refcount = IDirect3DDevice7_Release(device);
14095 ok(!refcount, "Device has %u references left.\n", refcount);
14096 DestroyWindow(window);
14099 static void test_compute_sphere_visibility(void)
14101 static D3DVALUE clip_plane[4] = {1.0f, 0.0f, 0.0f, 0.5f};
14102 static D3DMATRIX proj_1 =
14104 1.810660f, 0.000000f, 0.000000f, 0.000000f,
14105 0.000000f, 2.414213f, 0.000000f, 0.000000f,
14106 0.000000f, 0.000000f, 1.020408f, 1.000000f,
14107 0.000000f, 0.000000f, -0.102041f, 0.000000f,
14109 static D3DMATRIX proj_2 =
14111 10.0f, 0.0f, 0.0f, 0.0f,
14112 0.0f, 10.0f, 0.0f, 0.0f,
14113 0.0f, 0.0f, 10.0f, 0.0f,
14114 0.0f, 0.0f, 0.0f, 1.0f,
14116 static D3DMATRIX view_1 =
14118 1.000000f, 0.000000f, 0.000000f, 0.000000f,
14119 0.000000f, 0.768221f, -0.640185f, 0.000000f,
14120 -0.000000f, 0.640185f, 0.768221f, 0.000000f,
14121 -14.852037f, 9.857489f, 11.600972f, 1.000000f,
14123 static D3DMATRIX identity =
14125 1.0f, 0.0f, 0.0f, 0.0f,
14126 0.0f, 1.0f, 0.0f, 0.0f,
14127 0.0f, 0.0f, 1.0f, 0.0f,
14128 0.0f, 0.0f, 0.0f, 1.0f,
14130 static struct
14132 D3DMATRIX *view, *proj;
14133 unsigned int sphere_count;
14134 D3DVECTOR center[3];
14135 D3DVALUE radius[3];
14136 DWORD enable_planes;
14137 const DWORD expected[3];
14139 tests[] =
14141 {&view_1, &proj_1, 1, {{{11.461533f}, {-4.761727f}, {-1.171646f}}}, {38.252632f}, 0, {0x3f}},
14142 {&view_1, &proj_1, 3, {{{-3.515620f}, {-1.560661f}, {-12.464638f}},
14143 {{14.290396f}, {-2.981143f}, {-24.311312f}},
14144 {{1.461626f}, {-6.093709f}, {-13.901010f}}},
14145 {4.354097f, 12.500704f, 17.251318f}, 0, {0x103d, 0x3f, 0x3f}},
14146 {&identity, &proj_2, 1, {{{0.0f}, {0.0f}, {0.05f}}}, {0.04f}, 0, {0}},
14147 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.5f}}}, {0.5f}, 0, {0}},
14148 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.0f}}}, {0.0f}, 0, {0}},
14149 {&identity, &identity, 1, {{{-1.0f}, {-1.0f}, {0.5f}}}, {0.25f}, 0, {0x9}}, /* 5 */
14150 {&identity, &identity, 1, {{{-20.0f}, {0.0f}, {0.5f}}}, {3.0f}, 0, {0x103d}},
14151 {&identity, &identity, 1, {{{20.0f}, {0.0f}, {0.5f}}}, {3.0f}, 0, {0x203e}},
14152 {&identity, &identity, 1, {{{0.0f}, {-20.0f}, {0.5f}}}, {3.0f}, 0, {0x803b}},
14153 {&identity, &identity, 1, {{{0.0f}, {20.0f}, {0.5f}}}, {3.0f}, 0, {0x4037}},
14154 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {-20.0f}}}, {3.0f}, 0, {0x1001f}}, /* 10 */
14155 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {20.0f}}}, {3.0f}, 0, {0x2002f}},
14156 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.0f}}}, {5.0f}, 1, {0x7f}},
14157 {&identity, &identity, 1, {{{-0.5f}, {0.0f}, {0.0f}}}, {5.0f}, 1, {0x7f}},
14158 {&identity, &identity, 1, {{{-0.5f}, {0.0f}, {0.0f}}}, {1.0f}, 1, {0x51}},
14159 {&identity, &identity, 1, {{{-2.5f}, {0.0f}, {0.0f}}}, {1.0f}, 1, {0x41051}}, /* 15 */
14161 IDirect3DDevice7 *device;
14162 unsigned int i, j;
14163 DWORD result[3];
14164 ULONG refcount;
14165 HWND window;
14166 HRESULT hr;
14168 window = create_window();
14169 if (!(device = create_device(window, DDSCL_NORMAL)))
14171 skip("Failed to create a 3D device, skipping test.\n");
14172 DestroyWindow(window);
14173 return;
14176 hr = IDirect3DDevice7_SetClipPlane(device, 0, clip_plane);
14177 ok(SUCCEEDED(hr), "Failed to set user clip plane, hr %#x.\n", hr);
14179 IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &identity);
14181 for (i = 0; i < ARRAY_SIZE(tests); ++i)
14183 IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, tests[i].view);
14184 IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, tests[i].proj);
14186 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE,
14187 tests[i].enable_planes);
14188 ok(SUCCEEDED(hr), "Failed to enable / disable user clip planes, hr %#x.\n", hr);
14190 hr = IDirect3DDevice7_ComputeSphereVisibility(device, tests[i].center, tests[i].radius,
14191 tests[i].sphere_count, 0, result);
14192 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14194 for (j = 0; j < tests[i].sphere_count; ++j)
14195 ok(result[j] == tests[i].expected[j], "Test %u sphere %u: expected %#x, got %#x.\n",
14196 i, j, tests[i].expected[j], result[j]);
14199 refcount = IDirect3DDevice7_Release(device);
14200 ok(!refcount, "Device has %u references left.\n", refcount);
14201 DestroyWindow(window);
14204 static void test_clip_planes_limits(void)
14206 IDirect3DDevice7 *device;
14207 D3DDEVICEDESC7 caps;
14208 unsigned int i;
14209 ULONG refcount;
14210 float plane[4];
14211 HWND window;
14212 DWORD state;
14213 HRESULT hr;
14215 window = create_window();
14216 if (!(device = create_device(window, DDSCL_NORMAL)))
14218 skip("Failed to create 3D device.\n");
14219 DestroyWindow(window);
14220 return;
14223 memset(&caps, 0, sizeof(caps));
14224 hr = IDirect3DDevice7_GetCaps(device, &caps);
14225 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
14227 trace("Max user clip planes: %u.\n", caps.wMaxUserClipPlanes);
14229 for (i = 0; i < caps.wMaxUserClipPlanes; ++i)
14231 memset(plane, 0xff, sizeof(plane));
14232 hr = IDirect3DDevice7_GetClipPlane(device, i, plane);
14233 ok(hr == D3D_OK, "Failed to get clip plane %u, hr %#x.\n", i, hr);
14234 ok(!plane[0] && !plane[1] && !plane[2] && !plane[3],
14235 "Got unexpected plane %u: %.8e, %.8e, %.8e, %.8e.\n",
14236 i, plane[0], plane[1], plane[2], plane[3]);
14239 plane[0] = 2.0f;
14240 plane[1] = 8.0f;
14241 plane[2] = 5.0f;
14242 for (i = 0; i < caps.wMaxUserClipPlanes; ++i)
14244 plane[3] = i;
14245 hr = IDirect3DDevice7_SetClipPlane(device, i, plane);
14246 ok(hr == D3D_OK, "Failed to set clip plane %u, hr %#x.\n", i, hr);
14248 for (i = 0; i < caps.wMaxUserClipPlanes; ++i)
14250 memset(plane, 0xff, sizeof(plane));
14251 hr = IDirect3DDevice7_GetClipPlane(device, i, plane);
14252 ok(hr == D3D_OK, "Failed to get clip plane %u, hr %#x.\n", i, hr);
14253 ok(plane[0] == 2.0f && plane[1] == 8.0f && plane[2] == 5.0f && plane[3] == i,
14254 "Got unexpected plane %u: %.8e, %.8e, %.8e, %.8e.\n",
14255 i, plane[0], plane[1], plane[2], plane[3]);
14258 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE, 0xffffffff);
14259 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
14260 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE, &state);
14261 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
14262 ok(state == 0xffffffff, "Got unexpected state %#x.\n", state);
14263 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE, 0x80000000);
14264 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
14265 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE, &state);
14266 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
14267 ok(state == 0x80000000, "Got unexpected state %#x.\n", state);
14269 refcount = IDirect3DDevice7_Release(device);
14270 ok(!refcount, "Device has %u references left.\n", refcount);
14271 DestroyWindow(window);
14274 static void test_texture_stages_limits(void)
14276 IDirectDrawSurface7 *texture;
14277 DDSURFACEDESC2 surface_desc;
14278 IDirect3DDevice7 *device;
14279 IDirectDraw7 *ddraw;
14280 IDirect3D7 *d3d;
14281 unsigned int i;
14282 ULONG refcount;
14283 HWND window;
14284 HRESULT hr;
14286 window = create_window();
14287 if (!(device = create_device(window, DDSCL_NORMAL)))
14289 skip("Failed to create 3D device.\n");
14290 DestroyWindow(window);
14291 return;
14293 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
14294 ok(SUCCEEDED(hr), "Failed to get Direct3D interface, hr %#x.\n", hr);
14295 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
14296 ok(SUCCEEDED(hr), "Failed to get DirectDraw interface, hr %#x.\n", hr);
14297 IDirect3D7_Release(d3d);
14299 memset(&surface_desc, 0, sizeof(surface_desc));
14300 surface_desc.dwSize = sizeof(surface_desc);
14301 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
14302 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
14303 surface_desc.dwWidth = 16;
14304 surface_desc.dwHeight = 16;
14305 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
14306 ok(hr == DD_OK, "Failed to create surface, hr %#x.\n", hr);
14308 for (i = 0; i < 8; ++i)
14310 hr = IDirect3DDevice7_SetTexture(device, i, texture);
14311 ok(hr == D3D_OK, "Failed to set texture %u, hr %#x.\n", i, hr);
14312 hr = IDirect3DDevice7_SetTexture(device, i, NULL);
14313 ok(hr == D3D_OK, "Failed to set texture %u, hr %#x.\n", i, hr);
14314 hr = IDirect3DDevice7_SetTextureStageState(device, i, D3DTSS_COLOROP, D3DTOP_ADD);
14315 ok(hr == D3D_OK, "Failed to set texture stage state %u, hr %#x.\n", i, hr);
14318 IDirectDrawSurface7_Release(texture);
14319 IDirectDraw7_Release(ddraw);
14320 refcount = IDirect3DDevice7_Release(device);
14321 ok(!refcount, "Device has %u references left.\n", refcount);
14322 DestroyWindow(window);
14325 static void test_set_render_state(void)
14327 IDirect3DDevice7 *device;
14328 ULONG refcount;
14329 HWND window;
14330 DWORD state;
14331 HRESULT hr;
14333 window = create_window();
14334 if (!(device = create_device(window, DDSCL_NORMAL)))
14336 skip("Failed to create 3D device.\n");
14337 DestroyWindow(window);
14338 return;
14341 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZVISIBLE, TRUE);
14342 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14343 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZVISIBLE, FALSE);
14344 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14346 /* States deprecated in D3D7 */
14347 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
14348 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14349 state = 0xdeadbeef;
14350 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, &state);
14351 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14352 ok(state == 0xdeadbeef, "Got unexpected render state %#x.\n", state);
14353 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
14354 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14355 state = 0xdeadbeef;
14356 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, &state);
14357 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14358 ok(state == 0xdeadbeef, "Got unexpected render state %#x.\n", state);
14360 refcount = IDirect3DDevice7_Release(device);
14361 ok(!refcount, "Device has %u references left.\n", refcount);
14362 DestroyWindow(window);
14365 static void test_map_synchronisation(void)
14367 LARGE_INTEGER frequency, diff, ts[3];
14368 IDirect3DVertexBuffer7 *buffer;
14369 unsigned int i, j, tri_count;
14370 D3DVERTEXBUFFERDESC vb_desc;
14371 IDirect3DDevice7 *device;
14372 BOOL unsynchronised, ret;
14373 IDirectDrawSurface7 *rt;
14374 IDirectDraw7 *ddraw;
14375 IDirect3D7 *d3d;
14376 D3DCOLOR colour;
14377 ULONG refcount;
14378 HWND window;
14379 HRESULT hr;
14381 static const struct
14383 unsigned int flags;
14384 BOOL unsynchronised;
14386 tests[] =
14388 {0, FALSE},
14389 {DDLOCK_NOOVERWRITE, TRUE},
14390 {DDLOCK_DISCARDCONTENTS, FALSE},
14391 {DDLOCK_NOOVERWRITE | DDLOCK_DISCARDCONTENTS, TRUE},
14394 static const struct quad
14396 struct
14398 struct vec3 position;
14399 DWORD diffuse;
14400 } strip[4];
14402 quad1 =
14405 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
14406 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
14407 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
14408 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
14411 quad2 =
14414 {{-1.0f, -1.0f, 0.0f}, 0xffffff00},
14415 {{-1.0f, 1.0f, 0.0f}, 0xffffff00},
14416 {{ 1.0f, -1.0f, 0.0f}, 0xffffff00},
14417 {{ 1.0f, 1.0f, 0.0f}, 0xffffff00},
14420 struct quad *quads;
14422 window = create_window();
14423 ok(!!window, "Failed to create a window.\n");
14425 if (!(device = create_device(window, DDSCL_NORMAL)))
14427 skip("Failed to create a D3D device, skipping tests.\n");
14428 DestroyWindow(window);
14429 return;
14432 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
14433 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
14434 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
14435 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
14436 /* Maps are always synchronised on WARP. */
14437 if (ddraw_is_warp(ddraw))
14439 skip("Running on WARP, skipping test.\n");
14440 goto done;
14443 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
14444 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
14446 tri_count = 0x1000;
14448 ret = QueryPerformanceFrequency(&frequency);
14449 ok(ret, "Failed to get performance counter frequency.\n");
14451 vb_desc.dwSize = sizeof(vb_desc);
14452 vb_desc.dwCaps = D3DVBCAPS_WRITEONLY;
14453 vb_desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
14454 vb_desc.dwNumVertices = tri_count + 2;
14455 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &buffer, 0);
14456 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
14457 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&quads, NULL);
14458 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
14459 for (j = 0; j < vb_desc.dwNumVertices / 4; ++j)
14461 quads[j] = quad1;
14463 hr = IDirect3DVertexBuffer7_Unlock(buffer);
14464 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
14466 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
14467 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
14469 /* Initial draw to initialise states, compile shaders, etc. */
14470 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
14471 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14472 hr = IDirect3DDevice7_BeginScene(device);
14473 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14474 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, vb_desc.dwNumVertices, 0);
14475 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14476 hr = IDirect3DDevice7_EndScene(device);
14477 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14478 /* Read the result to ensure the GPU has finished drawing. */
14479 colour = get_surface_color(rt, 320, 240);
14481 /* Time drawing tri_count triangles. */
14482 ret = QueryPerformanceCounter(&ts[0]);
14483 ok(ret, "Failed to read performance counter.\n");
14484 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
14485 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14486 hr = IDirect3DDevice7_BeginScene(device);
14487 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14488 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, vb_desc.dwNumVertices, 0);
14489 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14490 hr = IDirect3DDevice7_EndScene(device);
14491 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14492 colour = get_surface_color(rt, 320, 240);
14493 /* Time drawing a single triangle. */
14494 ret = QueryPerformanceCounter(&ts[1]);
14495 ok(ret, "Failed to read performance counter.\n");
14496 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
14497 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14498 hr = IDirect3DDevice7_BeginScene(device);
14499 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14500 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 3, 0);
14501 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14502 hr = IDirect3DDevice7_EndScene(device);
14503 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14504 colour = get_surface_color(rt, 320, 240);
14505 ret = QueryPerformanceCounter(&ts[2]);
14506 ok(ret, "Failed to read performance counter.\n");
14508 IDirect3DVertexBuffer7_Release(buffer);
14510 /* Estimate the number of triangles we can draw in 100ms. */
14511 diff.QuadPart = ts[1].QuadPart - ts[0].QuadPart + ts[1].QuadPart - ts[2].QuadPart;
14512 tri_count = (tri_count * frequency.QuadPart) / (diff.QuadPart * 10);
14513 tri_count = ((tri_count + 2 + 3) & ~3) - 2;
14514 vb_desc.dwNumVertices = tri_count + 2;
14516 for (i = 0; i < ARRAY_SIZE(tests); ++i)
14518 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &buffer, 0);
14519 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
14520 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&quads, NULL);
14521 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
14522 for (j = 0; j < vb_desc.dwNumVertices / 4; ++j)
14524 quads[j] = quad1;
14526 hr = IDirect3DVertexBuffer7_Unlock(buffer);
14527 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
14529 /* Start a draw operation. */
14530 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
14531 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14532 hr = IDirect3DDevice7_BeginScene(device);
14533 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14534 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, vb_desc.dwNumVertices, 0);
14535 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14536 hr = IDirect3DDevice7_EndScene(device);
14537 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14539 /* Map the last quad while the draw is in progress. */
14540 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_WAIT | tests[i].flags, (void **)&quads, NULL);
14541 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
14542 quads[(vb_desc.dwNumVertices / 4) - 1] = quad2;
14543 hr = IDirect3DVertexBuffer7_Unlock(buffer);
14544 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
14546 colour = get_surface_color(rt, 320, 240);
14547 unsynchronised = compare_color(colour, 0x00ffff00, 1);
14548 ok(tests[i].unsynchronised == unsynchronised, "Expected %s map for flags %#x.\n",
14549 tests[i].unsynchronised ? "unsynchronised" : "synchronised", tests[i].flags);
14551 IDirect3DVertexBuffer7_Release(buffer);
14554 IDirectDrawSurface7_Release(rt);
14555 done:
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_depth_readback(void)
14565 DWORD depth, expected_depth, max_diff, raw_value, passed_fmts = 0;
14566 IDirectDrawSurface7 *rt, *ds;
14567 DDSURFACEDESC2 surface_desc;
14568 IDirect3DDevice7 *device;
14569 unsigned int i, x, y;
14570 IDirectDraw7 *ddraw;
14571 IDirect3D7 *d3d;
14572 ULONG refcount;
14573 HWND window;
14574 HRESULT hr;
14575 RECT r;
14576 BOOL all_zero, all_one, all_pass;
14578 static struct
14580 struct vec3 position;
14581 DWORD diffuse;
14583 quad[] =
14585 {{-1.0f, -1.0f, 0.1f}, 0xff00ff00},
14586 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
14587 {{ 1.0f, -1.0f, 1.0f}, 0xff00ff00},
14588 {{ 1.0f, 1.0f, 0.9f}, 0xff00ff00},
14591 static const struct
14593 unsigned int z_depth, s_depth, z_mask, s_mask;
14594 BOOL todo;
14596 tests[] =
14598 {16, 0, 0x0000ffff, 0x00000000},
14599 {24, 0, 0x00ffffff, 0x00000000},
14600 {32, 0, 0x00ffffff, 0x00000000},
14601 {32, 8, 0x00ffffff, 0xff000000, TRUE},
14602 {32, 0, 0xffffffff, 0x00000000},
14605 window = create_window();
14606 ok(!!window, "Failed to create a window.\n");
14608 if (!(device = create_device(window, DDSCL_NORMAL)))
14610 skip("Failed to create a D3D device, skipping tests.\n");
14611 DestroyWindow(window);
14612 return;
14615 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
14616 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
14617 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
14618 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
14620 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
14621 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
14623 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
14624 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
14626 ds = get_depth_stencil(device);
14627 hr = IDirectDrawSurface7_DeleteAttachedSurface(rt, 0, ds);
14628 ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
14629 IDirectDrawSurface7_Release(ds);
14631 for (i = 0; i < ARRAY_SIZE(tests); ++i)
14633 memset(&surface_desc, 0, sizeof(surface_desc));
14634 surface_desc.dwSize = sizeof(surface_desc);
14635 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
14636 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
14637 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
14638 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
14639 if (tests[i].s_depth)
14640 U4(surface_desc).ddpfPixelFormat.dwFlags |= DDPF_STENCILBUFFER;
14641 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = tests[i].z_depth;
14642 U2(U4(surface_desc).ddpfPixelFormat).dwStencilBitDepth = tests[i].s_depth;
14643 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = tests[i].z_mask;
14644 U4(U4(surface_desc).ddpfPixelFormat).dwStencilBitMask = tests[i].s_mask;
14645 surface_desc.dwWidth = 640;
14646 surface_desc.dwHeight = 480;
14647 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL);
14648 if (FAILED(hr))
14650 skip("Format %u not supported, skipping test.\n", i);
14651 continue;
14654 hr = IDirectDrawSurface_AddAttachedSurface(rt, ds);
14655 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
14656 hr = IDirect3DDevice7_SetRenderTarget(device, rt, 0);
14657 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
14659 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 1.0f, 0);
14660 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14661 hr = IDirect3DDevice7_BeginScene(device);
14662 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14663 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, 4, 0);
14664 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14665 hr = IDirect3DDevice7_EndScene(device);
14666 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14668 all_zero = all_one = all_pass = TRUE;
14669 for (y = 60; y < 480; y += 120)
14671 for (x = 80; x < 640; x += 160)
14673 SetRect(&r, x, y, x + 1, y + 1);
14674 memset(&surface_desc, 0, sizeof(surface_desc));
14675 surface_desc.dwSize = sizeof(surface_desc);
14676 hr = IDirectDrawSurface7_Lock(ds, &r, &surface_desc, DDLOCK_READONLY, NULL);
14677 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14679 raw_value = *((DWORD *)surface_desc.lpSurface);
14680 if (raw_value)
14681 all_zero = FALSE;
14682 if (raw_value != 0x00ffffff)
14683 all_one = FALSE;
14685 depth = raw_value & tests[i].z_mask;
14686 expected_depth = (x * (0.9 / 640.0) + y * (0.1 / 480.0)) * tests[i].z_mask;
14687 max_diff = ((0.5f * 0.9f) / 640.0f) * tests[i].z_mask;
14688 /* This test is very reliably on AMD, but fails in a number of interesting ways on Nvidia GPUs:
14690 * Geforce 7 GPUs work only with D16. D24 and D24S8 return 0, D24X8 broken data.
14692 * Geforce 9 GPUs return broken data for D16 that resembles the expected data in
14693 * the lower 8 bits and has 0xff in the upper 8 bits. D24X8 works, D24 and D24S8 return
14694 * 0x00ffffff.
14696 * Geforce GTX 650 has working D16 and D24, but D24S8 returns 0.
14698 * Arx Fatalis is broken on the Geforce 9 in the same way it was broken in Wine (bug 43654).
14699 * The !tests[i].s_depth is supposed to rule out D16 on GF9 and D24X8 on GF7. */
14700 todo_wine_if(tests[i].todo)
14701 ok(abs(expected_depth - depth) <= max_diff
14702 || (ddraw_is_nvidia(ddraw) && (all_zero || all_one || !tests[i].s_depth)),
14703 "Test %u: Got depth 0x%08x (diff %d), expected 0x%08x+/-%u, at %u, %u.\n",
14704 i, depth, expected_depth - depth, expected_depth, max_diff, x, y);
14705 if (abs(expected_depth - depth) > max_diff)
14706 all_pass = FALSE;
14708 hr = IDirectDrawSurface7_Unlock(ds, &r);
14709 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14712 if (all_pass)
14713 passed_fmts++;
14715 hr = IDirectDrawSurface7_DeleteAttachedSurface(rt, 0, ds);
14716 ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
14717 IDirectDrawSurface7_Release(ds);
14720 ok(passed_fmts, "Not a single format passed the tests, this is bad even by Nvidia's standards.\n");
14722 IDirectDrawSurface7_Release(rt);
14723 IDirectDraw7_Release(ddraw);
14724 IDirect3D7_Release(d3d);
14725 refcount = IDirect3DDevice7_Release(device);
14726 ok(!refcount, "Device has %u references left.\n", refcount);
14727 DestroyWindow(window);
14730 static void test_clear(void)
14732 IDirect3DDevice7 *device;
14733 IDirectDrawSurface7 *rt;
14734 D3DVIEWPORT7 vp, old_vp;
14735 IDirectDraw7 *ddraw;
14736 D3DRECT rect_negneg;
14737 IDirect3D7 *d3d;
14738 D3DRECT rect[2];
14739 D3DCOLOR color;
14740 ULONG refcount;
14741 HWND window;
14742 HRESULT hr;
14744 window = create_window();
14745 if (!(device = create_device(window, DDSCL_NORMAL)))
14747 skip("Failed to create 3D device.\n");
14748 DestroyWindow(window);
14749 return;
14752 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
14753 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
14754 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
14755 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
14757 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
14758 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
14760 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
14761 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14763 /* Positive x, negative y. */
14764 U1(rect[0]).x1 = 0;
14765 U2(rect[0]).y1 = 480;
14766 U3(rect[0]).x2 = 320;
14767 U4(rect[0]).y2 = 240;
14769 /* Positive x, positive y. */
14770 U1(rect[1]).x1 = 0;
14771 U2(rect[1]).y1 = 0;
14772 U3(rect[1]).x2 = 320;
14773 U4(rect[1]).y2 = 240;
14775 /* Clear 2 rectangles with one call. Unlike d3d8/9, the refrast does not
14776 * refuse negative rectangles, but it will not clear them either. */
14777 hr = IDirect3DDevice7_Clear(device, 2, rect, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
14778 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14780 color = get_surface_color(rt, 160, 360);
14781 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 3 (pos, neg) has color 0x%08x.\n", color);
14782 color = get_surface_color(rt, 160, 120);
14783 ok(compare_color(color, 0x00ff0000, 0), "Clear rectangle 1 (pos, pos) has color 0x%08x.\n", color);
14784 color = get_surface_color(rt, 480, 360);
14785 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 4 (NULL) has color 0x%08x.\n", color);
14786 color = get_surface_color(rt, 480, 120);
14787 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 4 (neg, neg) has color 0x%08x.\n", color);
14789 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
14790 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14791 /* negative x, negative y.
14792 * Also ignored, except on WARP, which clears the entire screen. */
14793 U1(rect_negneg).x1 = 640;
14794 U2(rect_negneg).y1 = 240;
14795 U3(rect_negneg).x2 = 320;
14796 U4(rect_negneg).y2 = 0;
14797 hr = IDirect3DDevice7_Clear(device, 1, &rect_negneg, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
14798 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14800 color = get_surface_color(rt, 160, 360);
14801 ok(compare_color(color, 0x00ffffff, 0)
14802 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
14803 "Got unexpected color 0x%08x.\n", color);
14804 color = get_surface_color(rt, 160, 120);
14805 ok(compare_color(color, 0x00ffffff, 0)
14806 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
14807 "Got unexpected color 0x%08x.\n", color);
14808 color = get_surface_color(rt, 480, 360);
14809 ok(compare_color(color, 0x00ffffff, 0)
14810 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
14811 "Got unexpected color 0x%08x.\n", color);
14812 color = get_surface_color(rt, 480, 120);
14813 ok(compare_color(color, 0x00ffffff, 0)
14814 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
14815 "Got unexpected color 0x%08x.\n", color);
14817 /* Test how the viewport affects clears. */
14818 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
14819 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14820 hr = IDirect3DDevice7_GetViewport(device, &old_vp);
14821 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
14823 vp.dwX = 160;
14824 vp.dwY = 120;
14825 vp.dwWidth = 160;
14826 vp.dwHeight = 120;
14827 vp.dvMinZ = 0.0f;
14828 vp.dvMaxZ = 1.0f;
14829 hr = IDirect3DDevice7_SetViewport(device, &vp);
14830 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
14831 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
14832 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14834 vp.dwX = 320;
14835 vp.dwY = 240;
14836 vp.dwWidth = 320;
14837 vp.dwHeight = 240;
14838 vp.dvMinZ = 0.0f;
14839 vp.dvMaxZ = 1.0f;
14840 hr = IDirect3DDevice7_SetViewport(device, &vp);
14841 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
14843 U1(rect[0]).x1 = 160;
14844 U2(rect[0]).y1 = 120;
14845 U3(rect[0]).x2 = 480;
14846 U4(rect[0]).y2 = 360;
14847 hr = IDirect3DDevice7_Clear(device, 1, &rect[0], D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
14848 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14850 hr = IDirect3DDevice7_SetViewport(device, &old_vp);
14851 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
14853 color = get_surface_color(rt, 158, 118);
14854 ok(compare_color(color, 0x00ffffff, 0), "(158, 118) has color 0x%08x.\n", color);
14855 color = get_surface_color(rt, 162, 118);
14856 ok(compare_color(color, 0x00ffffff, 0), "(162, 118) has color 0x%08x.\n", color);
14857 color = get_surface_color(rt, 158, 122);
14858 ok(compare_color(color, 0x00ffffff, 0), "(158, 122) has color 0x%08x.\n", color);
14859 color = get_surface_color(rt, 162, 122);
14860 ok(compare_color(color, 0x000000ff, 0), "(162, 122) has color 0x%08x.\n", color);
14862 color = get_surface_color(rt, 318, 238);
14863 ok(compare_color(color, 0x000000ff, 0), "(318, 238) has color 0x%08x.\n", color);
14864 color = get_surface_color(rt, 322, 238);
14865 ok(compare_color(color, 0x00ffffff, 0), "(322, 328) has color 0x%08x.\n", color);
14866 color = get_surface_color(rt, 318, 242);
14867 ok(compare_color(color, 0x00ffffff, 0), "(318, 242) has color 0x%08x.\n", color);
14868 color = get_surface_color(rt, 322, 242);
14869 ok(compare_color(color, 0x0000ff00, 0), "(322, 242) has color 0x%08x.\n", color);
14871 color = get_surface_color(rt, 478, 358);
14872 ok(compare_color(color, 0x0000ff00, 0), "(478, 358) has color 0x%08x.\n", color);
14873 color = get_surface_color(rt, 482, 358);
14874 ok(compare_color(color, 0x00ffffff, 0), "(482, 358) has color 0x%08x.\n", color);
14875 color = get_surface_color(rt, 478, 362);
14876 ok(compare_color(color, 0x00ffffff, 0), "(478, 362) has color 0x%08x.\n", color);
14877 color = get_surface_color(rt, 482, 362);
14878 ok(compare_color(color, 0x00ffffff, 0), "(482, 362) has color 0x%08x.\n", color);
14880 /* COLORWRITEENABLE, SRGBWRITEENABLE and scissor rectangles do not exist
14881 * in d3d7. */
14883 IDirectDrawSurface7_Release(rt);
14884 IDirectDraw7_Release(ddraw);
14885 IDirect3D7_Release(d3d);
14886 refcount = IDirect3DDevice7_Release(device);
14887 ok(!refcount, "Device has %u references left.\n", refcount);
14888 DestroyWindow(window);
14891 struct enum_surfaces_param
14893 IDirectDrawSurface7 *surfaces[8];
14894 unsigned int count;
14897 static HRESULT WINAPI enum_surfaces_cb(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
14899 struct enum_surfaces_param *param = context;
14900 BOOL found = FALSE;
14901 unsigned int i;
14903 for (i = 0; i < ARRAY_SIZE(param->surfaces); ++i)
14905 if (param->surfaces[i] == surface)
14907 found = TRUE;
14908 break;
14912 ok(found, "Unexpected surface %p enumerated.\n", surface);
14913 IDirectDrawSurface7_Release(surface);
14914 ++param->count;
14916 return DDENUMRET_OK;
14919 static void test_enum_surfaces(void)
14921 struct enum_surfaces_param param = {{0}};
14922 DDSURFACEDESC2 desc;
14923 IDirectDraw7 *ddraw;
14924 HRESULT hr;
14926 ddraw = create_ddraw();
14927 ok(!!ddraw, "Failed to create a ddraw object.\n");
14929 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
14930 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
14932 memset(&desc, 0, sizeof(desc));
14933 desc.dwSize = sizeof(desc);
14934 desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
14935 desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
14936 U2(desc).dwMipMapCount = 3;
14937 desc.dwWidth = 32;
14938 desc.dwHeight = 32;
14939 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &desc, &param.surfaces[0], NULL)))
14941 win_skip("Failed to create a texture, skipping tests.\n");
14942 IDirectDraw7_Release(ddraw);
14943 return;
14946 hr = IDirectDrawSurface7_GetAttachedSurface(param.surfaces[0], &desc.ddsCaps, &param.surfaces[1]);
14947 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
14948 hr = IDirectDrawSurface7_GetAttachedSurface(param.surfaces[1], &desc.ddsCaps, &param.surfaces[2]);
14949 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
14950 hr = IDirectDrawSurface7_GetAttachedSurface(param.surfaces[2], &desc.ddsCaps, &param.surfaces[3]);
14951 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
14952 ok(!param.surfaces[3], "Got unexpected pointer %p.\n", param.surfaces[3]);
14954 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
14955 &desc, &param, enum_surfaces_cb);
14956 ok(SUCCEEDED(hr), "Failed to enumerate surfaces, hr %#x.\n", hr);
14957 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
14959 param.count = 0;
14960 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
14961 NULL, &param, enum_surfaces_cb);
14962 ok(SUCCEEDED(hr), "Failed to enumerate surfaces, hr %#x.\n", hr);
14963 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
14965 IDirectDrawSurface7_Release(param.surfaces[2]);
14966 IDirectDrawSurface7_Release(param.surfaces[1]);
14967 IDirectDrawSurface7_Release(param.surfaces[0]);
14968 IDirectDraw7_Release(ddraw);
14971 static void test_viewport(void)
14973 static struct
14975 D3DVIEWPORT7 vp;
14976 float expected_z;
14977 RECT expected_rect;
14978 const char *message;
14980 tests[] =
14982 {{ 0, 0, 640, 480}, 0.001f, { 0, 120, 479, 359}, "Viewport (0, 0) - (640, 480)"},
14983 {{ 0, 0, 320, 240}, 0.001f, { 0, 60, 239, 179}, "Viewport (0, 0) - (320, 240)"},
14984 /* Don't run this right after the other 640x480 test, it breaks r500. */
14985 {{ 0, 0, 640, 480, 0.5f, 0.0f}, 0.501f,
14986 {0, 120, 479, 359}, "Viewport (0, 0, 0.5) - (640, 480, 0.0)"},
14987 {{ 0, 0, 1280, 960}, 0.001f, { 0, 240, 639, 479}, "Viewport (0, 0) - (1280, 960)"},
14988 {{ 0, 0, 2000, 1600}, 0.001f, {-10, -10, -10, -10}, "Viewport (0, 0) - (2000, 1600)"},
14989 {{100, 100, 640, 480}, 0.001f, {100, 220, 579, 459}, "Viewport (100, 100) - (640, 480)"},
14990 {{ 0, 0, 8192, 8192}, 0.001f, {-10, -10, -10, -10}, "Viewport (0, 0) - (8192, 8192)"},
14992 static struct vec3 quad[] =
14994 {-1.5f, -0.5f, 1.0f},
14995 {-1.5f, 0.5f, 1.0f},
14996 { 0.5f, -0.5f, 1.0f},
14997 { 0.5f, 0.5f, 1.0f},
14999 static const struct vec2 rt_sizes[] =
15001 {640, 480}, {1280, 960}, {320, 240}, {800, 600},
15003 IDirectDrawSurface7 *rt, *ds;
15004 DDSURFACEDESC2 surface_desc;
15005 const float z_eps = 0.0001;
15006 IDirect3DDevice7 *device;
15007 IDirectDraw7 *ddraw;
15008 DDPIXELFORMAT z_fmt;
15009 unsigned int i, j;
15010 IDirect3D7 *d3d;
15011 ULONG refcount;
15012 HWND window;
15013 HRESULT hr;
15015 window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
15016 0, 0, 640, 480, 0, 0, 0, 0);
15017 if (!(device = create_device(window, DDSCL_NORMAL)))
15019 skip("Failed to create a 3D device, skipping test.\n");
15020 DestroyWindow(window);
15021 return;
15024 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
15025 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15026 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
15027 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15028 IDirect3D7_Release(d3d);
15030 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
15031 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15033 /* Well, by default the vertices without color info should be white, and without any texture
15034 * ops this should just show up in the output, but the r200 driver begs to differ and draws a
15035 * random color. */
15036 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
15037 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15038 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
15039 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15040 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x00ffffff);
15041 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15043 hr = IDirect3DDevice7_SetViewport(device, NULL);
15044 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
15046 ds = get_depth_stencil(device);
15047 memset(&surface_desc, 0, sizeof(surface_desc));
15048 surface_desc.dwSize = sizeof(surface_desc);
15049 hr = IDirectDrawSurface7_GetSurfaceDesc(ds, &surface_desc);
15050 z_fmt = U4(surface_desc).ddpfPixelFormat;
15052 for (i = 0; i < ARRAY_SIZE(rt_sizes); ++i)
15054 if (i)
15056 memset(&surface_desc, 0, sizeof(surface_desc));
15057 surface_desc.dwSize = sizeof(surface_desc);
15058 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
15059 surface_desc.dwWidth = rt_sizes[i].x;
15060 surface_desc.dwHeight = rt_sizes[i].y;
15061 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
15062 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &rt, NULL);
15063 ok(hr == DD_OK, "Got unexpected hr %#x (i %u).\n", hr, i);
15065 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
15066 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
15067 U4(surface_desc).ddpfPixelFormat = z_fmt;
15068 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL);
15069 ok(hr == DD_OK, "Got unexpected hr %#x (i %u).\n", hr, i);
15070 hr = IDirectDrawSurface7_AddAttachedSurface(rt, ds);
15071 ok(hr == DD_OK, "Got unexpected hr %#x (i %u).\n", hr, i);
15073 hr = IDirect3DDevice7_SetRenderTarget(device, rt, 0);
15074 ok(hr == DD_OK, "Got unexpected hr %#x (i %u).\n", hr, i);
15076 else
15078 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
15079 ok(hr == DD_OK, "Got unexpected hr %#x (i %u).\n", hr, i);
15082 for (j = 0; j < ARRAY_SIZE(tests); ++j)
15084 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff000000,
15085 tests[j].expected_z - z_eps, 0);
15086 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
15087 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_GREATER);
15088 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
15090 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, !i);
15091 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
15093 hr = IDirect3DDevice7_SetViewport(device, &tests[j].vp);
15094 if (tests[j].vp.dwX + tests[j].vp.dwWidth > rt_sizes[i].x
15095 || tests[j].vp.dwY + tests[j].vp.dwHeight > rt_sizes[i].y)
15097 ok(hr == E_INVALIDARG, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
15098 continue;
15100 else
15102 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
15105 hr = IDirect3DDevice7_BeginScene(device);
15106 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
15107 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
15108 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
15109 hr = IDirect3DDevice7_EndScene(device);
15110 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
15112 check_rect(rt, tests[j].expected_rect, tests[j].message);
15114 if (!i)
15116 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff000000,
15117 tests[j].expected_z + z_eps, 0);
15118 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
15119 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESS);
15120 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
15122 hr = IDirect3DDevice7_BeginScene(device);
15123 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
15124 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
15125 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
15126 hr = IDirect3DDevice7_EndScene(device);
15127 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
15129 check_rect(rt, tests[j].expected_rect, tests[j].message);
15133 hr = IDirectDrawSurface7_DeleteAttachedSurface(rt, 0, ds);
15134 ok(hr == DD_OK, "Got unexpected hr %#x (i %u).\n", hr, i);
15135 IDirectDrawSurface7_Release(ds);
15136 IDirectDrawSurface7_Release(rt);
15139 refcount = IDirect3DDevice7_Release(device);
15140 ok(!refcount, "Device has %u references left.\n", refcount);
15141 IDirectDraw7_Release(ddraw);
15142 DestroyWindow(window);
15145 static unsigned int validate_loaded_surface(IDirectDrawSurface7 *surface, unsigned int face,
15146 unsigned int level, const RECT *src_rect, const POINT *dst_point)
15148 DDSURFACEDESC2 surface_desc;
15149 unsigned int diff, x, y;
15150 HRESULT hr;
15152 memset(&surface_desc, 0, sizeof(surface_desc));
15153 surface_desc.dwSize = sizeof(surface_desc);
15154 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
15155 ok(SUCCEEDED(hr), "Failed to map surface, hr %#x.\n", hr);
15157 for (y = 0, diff = 0; y < surface_desc.dwHeight; ++y)
15159 DWORD *texture_row = (DWORD *)((char *)surface_desc.lpSurface + y * U1(surface_desc).lPitch);
15161 for (x = 0; x < surface_desc.dwWidth; ++x)
15163 DWORD colour = texture_row[x];
15164 DWORD r = (colour & 0xff0000) >> 16;
15165 DWORD g = (colour & 0xff00) >> 8;
15166 DWORD b = (colour & 0xff);
15168 if (x < dst_point->x || x >= dst_point->x + src_rect->right - src_rect->left
15169 || y < dst_point->y || y >= dst_point->y + src_rect->bottom - src_rect->top)
15171 if (colour & 0xffffff)
15172 ++diff;
15174 else
15176 if (r != ((face << 4) | level)
15177 || g != x + src_rect->left - dst_point->x
15178 || b != y + src_rect->top - dst_point->y)
15179 ++diff;
15184 hr = IDirectDrawSurface7_Unlock(surface, NULL);
15185 ok(SUCCEEDED(hr), "Failed to unmap surface, hr %#x.\n", hr);
15187 return diff;
15190 static void test_device_load(void)
15192 IDirectDrawSurface7 *src_surface, *dst_surface, *surface, *tmp;
15193 DDSCAPS2 mip_caps = {0, DDSCAPS2_MIPMAPSUBLEVEL, 0, {0}};
15194 IDirectDrawPalette *src_palette, *dst_palette, *palette;
15195 unsigned int i, j, k, l, x, y;
15196 DDSURFACEDESC2 surface_desc;
15197 IDirect3DDevice7 *device;
15198 PALETTEENTRY table1[256];
15199 D3DDEVICEDESC7 d3d_caps;
15200 DDCOLORKEY colour_key;
15201 IDirectDraw7 *ddraw;
15202 BOOL cube_support;
15203 IDirect3D7 *d3d;
15204 ULONG refcount;
15205 HWND window;
15206 DDBLTFX fx;
15207 HRESULT hr;
15209 #define TEX_MIP 0x01
15210 #define TEX_CUBE 0x02
15211 #define NULL_COORDS 0x04
15213 /* Creating partial cube maps (e.g. created with just
15214 * DDSCAPS2_CUBEMAP_POSITIVEX) BSODs some Windows machines. (Radeon X1600,
15215 * Windows XP, Catalyst 10.2 driver, 6.14.10.6925)
15217 * Passing non-toplevel surfaces to IDirect3DDevice7_Load() crashes on
15218 * native. (Windows XP / NVIDIA, Windows 98 / RGB software rasteriser) */
15219 static const struct
15221 unsigned int src_w, src_h, src_mip_count;
15222 RECT src_rect;
15223 DWORD src_flags;
15224 unsigned int dst_w, dst_h, dst_mip_count;
15225 POINT dst_point;
15226 DWORD dst_flags;
15227 HRESULT hr;
15229 tests[] =
15231 {128, 128, 0, { 0, 0, 0, 0}, TEX_MIP, 128, 128, 0, { 0, 0}, TEX_MIP, DDERR_INVALIDPARAMS},
15232 {128, 128, 0, { 0, 0, 100, 100}, TEX_MIP, 128, 128, 0, {50, 50}, TEX_MIP, DDERR_INVALIDPARAMS},
15233 {128, 128, 0, {30, 20, 93, 52}, TEX_MIP, 128, 128, 0, {31, 31}, TEX_MIP, D3D_OK},
15234 {128, 128, 0, { 0, 0, 0, 0}, NULL_COORDS, 128, 128, 0, { 0, 0}, NULL_COORDS, D3D_OK},
15235 {128, 128, 0, { 0, 0, 0, 0}, NULL_COORDS, 256, 128, 0, { 0, 0}, NULL_COORDS, DDERR_INVALIDPARAMS},
15236 {256, 128, 0, { 0, 0, 0, 0}, NULL_COORDS, 128, 128, 0, { 0, 0}, NULL_COORDS, DDERR_INVALIDPARAMS},
15237 {128, 128, 0, {30, 20, 93, 52}, TEX_MIP | TEX_CUBE, 128, 128, 0, {10, 10}, TEX_MIP | TEX_CUBE, D3D_OK},
15238 {128, 128, 0, { 0, 0, 0, 0}, NULL_COORDS, 128, 128, 0, { 0, 0}, TEX_CUBE | NULL_COORDS, DDERR_INVALIDPARAMS},
15239 {128, 128, 0, {30, 20, 93, 52}, TEX_MIP, 128, 128, 4, {31, 31}, TEX_MIP, D3D_OK},
15240 {128, 128, 4, {30, 20, 93, 52}, TEX_MIP, 128, 128, 0, {31, 31}, TEX_MIP, DDERR_INVALIDPARAMS},
15241 {128, 128, 0, {32, 32, 96, 96}, TEX_MIP, 32, 32, 0, {32, 32}, 0, D3D_OK},
15242 {128, 128, 0, { 0, 0, 64, 64}, TEX_MIP, 32, 32, 4, { 0, 0}, TEX_MIP, D3D_OK},
15245 window = create_window();
15246 if (!(device = create_device(window, DDSCL_NORMAL)))
15248 skip("Failed to create a 3D device, skipping test.\n");
15249 DestroyWindow(window);
15250 return;
15253 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
15254 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
15255 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
15256 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
15257 IDirect3D7_Release(d3d);
15259 memset(&d3d_caps, 0, sizeof(d3d_caps));
15260 hr = IDirect3DDevice7_GetCaps(device, &d3d_caps);
15261 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
15262 cube_support = d3d_caps.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP;
15264 for (i = 0; i < ARRAY_SIZE(tests); ++i)
15266 unsigned int src_count, dst_count;
15267 POINT dst_point, dst_point_broken;
15268 RECT src_rect, src_rect_broken;
15270 if ((tests[i].src_flags | tests[i].dst_flags) & TEX_CUBE && !cube_support)
15272 skip("No cubemap support, skipping test %u.\n", i);
15273 continue;
15276 memset(&surface_desc, 0, sizeof(surface_desc));
15277 surface_desc.dwSize = sizeof(surface_desc);
15278 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
15279 if (tests[i].src_mip_count)
15280 surface_desc.dwFlags |= DDSD_MIPMAPCOUNT;
15281 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
15282 if (tests[i].src_flags & (TEX_MIP | TEX_CUBE))
15283 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
15284 if (tests[i].src_flags & TEX_MIP)
15285 surface_desc.ddsCaps.dwCaps |= DDSCAPS_MIPMAP;
15286 if (tests[i].src_flags & TEX_CUBE)
15287 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
15288 surface_desc.dwWidth = tests[i].src_w;
15289 surface_desc.dwHeight = tests[i].src_h;
15290 U2(surface_desc).dwMipMapCount = tests[i].src_mip_count;
15291 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
15292 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
15293 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
15294 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
15295 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
15296 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
15297 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
15298 ok(SUCCEEDED(hr), "Test %u: Failed to create source surface, hr %#x.\n", i, hr);
15300 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
15301 if (tests[i].dst_mip_count)
15302 surface_desc.dwFlags |= DDSD_MIPMAPCOUNT;
15303 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
15304 if (tests[i].dst_flags & (TEX_MIP | TEX_CUBE))
15305 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
15306 if (tests[i].dst_flags & TEX_MIP)
15307 surface_desc.ddsCaps.dwCaps |= DDSCAPS_MIPMAP;
15308 surface_desc.ddsCaps.dwCaps2 = 0;
15309 if (tests[i].dst_flags & TEX_CUBE)
15310 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
15311 surface_desc.dwWidth = tests[i].dst_w;
15312 surface_desc.dwHeight = tests[i].dst_h;
15313 U2(surface_desc).dwMipMapCount = tests[i].dst_mip_count;
15314 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
15315 ok(SUCCEEDED(hr), "Test %u: Failed to create destination surface, hr %#x.\n", i, hr);
15317 src_count = dst_count = 1;
15318 if (tests[i].src_flags & TEX_MIP)
15319 src_count = tests[i].src_mip_count ? tests[i].src_mip_count : 8;
15320 if (tests[i].dst_flags & TEX_MIP)
15321 dst_count = tests[i].dst_mip_count ? tests[i].dst_mip_count : 8;
15323 surface = src_surface;
15324 IDirectDrawSurface7_AddRef(surface);
15325 for (j = 0;;)
15327 DDSCAPS2 face_caps = {0, 0, 0, {0}};
15329 /* Check the number of created mipmaps. */
15330 if (tests[i].src_flags & TEX_MIP)
15332 memset(&surface_desc, 0, sizeof(surface_desc));
15333 surface_desc.dwSize = sizeof(surface_desc);
15334 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
15335 ok(SUCCEEDED(hr), "Test %u: Failed to get surface description, hr %#x.\n", i, hr);
15336 ok(U2(surface_desc).dwMipMapCount == src_count,
15337 "Test %u: Got unexpected mip count %u, expected %u.\n",
15338 i, U2(surface_desc).dwMipMapCount, src_count);
15341 for (k = 0; ; ++k)
15343 memset(&surface_desc, 0, sizeof(surface_desc));
15344 surface_desc.dwSize = sizeof(surface_desc);
15345 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
15346 ok(SUCCEEDED(hr), "Test %u: Failed to map surface, hr %#x.\n", i, hr);
15348 for (y = 0; y < surface_desc.dwHeight; ++y)
15350 DWORD *texture_row = (DWORD *)((BYTE *)surface_desc.lpSurface + y * U1(surface_desc).lPitch);
15352 for (x = 0; x < surface_desc.dwWidth; ++x)
15354 /* The face number is stored in the high 4 bits of the
15355 * red component, the mip-level in the low 4 bits. The
15356 * x-coordinate is stored in the green component, and
15357 * the y-coordinate in the blue component. */
15358 texture_row[x] = (j << 20) | (k << 16) | (x << 8) | y;
15362 hr = IDirectDrawSurface7_Unlock(surface, NULL);
15363 ok(SUCCEEDED(hr), "Test %u: Failed to unmap surface, hr %#x.\n", i, hr);
15365 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &mip_caps, &tmp);
15366 IDirectDrawSurface7_Release(surface);
15367 if (FAILED(hr))
15368 break;
15369 surface = tmp;
15372 if (!(tests[i].src_flags & TEX_CUBE) || ++j >= 6)
15373 break;
15375 face_caps.dwCaps2 = DDSCAPS2_CUBEMAP | (DDSCAPS2_CUBEMAP_POSITIVEX << j);
15376 hr = IDirectDrawSurface7_GetAttachedSurface(src_surface, &face_caps, &surface);
15377 ok(SUCCEEDED(hr), "Test %u: Failed to get face %u.\n", i, j);
15380 surface = dst_surface;
15381 IDirectDrawSurface7_AddRef(surface);
15382 for (j = 0;;)
15384 DDSCAPS2 face_caps = {0, 0, 0, {0}};
15386 /* Check the number of created mipmaps. */
15387 if (tests[i].dst_flags & TEX_MIP)
15389 memset(&surface_desc, 0, sizeof(surface_desc));
15390 surface_desc.dwSize = sizeof(surface_desc);
15391 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
15392 ok(SUCCEEDED(hr), "Test %u: Failed to get surface description, hr %#x.\n", i, hr);
15393 ok(U2(surface_desc).dwMipMapCount == dst_count,
15394 "Test %u: Got unexpected mip count %u, expected %u.\n",
15395 i, U2(surface_desc).dwMipMapCount, dst_count);
15398 for (;;)
15400 memset(&fx, 0, sizeof(fx));
15401 fx.dwSize = sizeof(fx);
15402 U5(fx).dwFillColor = 0x00000000;
15403 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
15404 ok(SUCCEEDED(hr), "Test %u: Failed to clear surface, hr %#x.\n", i, hr);
15406 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &mip_caps, &tmp);
15407 IDirectDrawSurface7_Release(surface);
15408 if (FAILED(hr))
15409 break;
15410 surface = tmp;
15413 if (!(tests[i].dst_flags & TEX_CUBE) || ++j >= 6)
15414 break;
15416 face_caps.dwCaps2 = DDSCAPS2_CUBEMAP | (DDSCAPS2_CUBEMAP_POSITIVEX << j);
15417 hr = IDirectDrawSurface7_GetAttachedSurface(dst_surface, &face_caps, &surface);
15418 ok(SUCCEEDED(hr), "Test %u: Failed to get face %u.\n", i, j);
15421 src_rect = tests[i].src_rect;
15422 dst_point = tests[i].dst_point;
15423 hr = IDirect3DDevice7_Load(device,
15424 dst_surface, tests[i].dst_flags & NULL_COORDS ? NULL : &dst_point,
15425 src_surface, tests[i].src_flags & NULL_COORDS ? NULL : &src_rect,
15426 tests[i].dst_flags & TEX_CUBE ? DDSCAPS2_CUBEMAP_ALLFACES : 0);
15427 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x.\n", i, hr);
15429 if (SUCCEEDED(hr))
15431 unsigned int level_offset, level_offset_broken;
15433 for (level_offset = 0, k = tests[i].src_w; k > tests[i].dst_w; ++level_offset, k /= 2);
15434 level_offset_broken = src_count - dst_count;
15436 surface = dst_surface;
15437 IDirectDrawSurface7_AddRef(surface);
15438 for (j = 0;;)
15440 DDSCAPS2 face_caps = {0, 0, 0, {0}};
15442 if (tests[i].src_flags & NULL_COORDS)
15443 SetRect(&src_rect, 0, 0, tests[i].src_w, tests[i].src_h);
15444 else
15445 src_rect = tests[i].src_rect;
15447 if (tests[i].dst_flags & NULL_COORDS)
15448 dst_point.x = dst_point.y = 0;
15449 else
15450 dst_point = tests[i].dst_point;
15452 for (k = 0; k < level_offset; ++k)
15454 dst_point.x /= 2;
15455 dst_point.y /= 2;
15456 src_rect.top /= 2;
15457 src_rect.left /= 2;
15458 src_rect.right = (src_rect.right + 1) / 2;
15459 src_rect.bottom = (src_rect.bottom + 1) / 2;
15462 for (k = 0; ; ++k)
15464 unsigned int diff, diff2, diff3;
15466 diff = validate_loaded_surface(surface, j, k + level_offset, &src_rect, &dst_point);
15468 /* On some newer (XP+) versions of Windows, it appears the
15469 * source/destination coordinates are divided too often.
15470 * This works correctly on Windows 98 with the RGB
15471 * software rasteriser. */
15472 src_rect_broken = src_rect;
15473 dst_point_broken = dst_point;
15474 for (l = 0; l < level_offset; ++l)
15476 dst_point_broken.x /= 2;
15477 dst_point_broken.y /= 2;
15478 src_rect_broken.top /= 2;
15479 src_rect_broken.left /= 2;
15480 src_rect_broken.right = (src_rect_broken.right + 1) / 2;
15481 src_rect_broken.bottom = (src_rect_broken.bottom + 1) / 2;
15483 diff2 = validate_loaded_surface(surface, j, k + level_offset,
15484 &src_rect_broken, &dst_point_broken);
15486 /* On Windows 8+ things are slightly worse still. Instead
15487 * of applying the correct level offset twice, like on
15488 * XP+, an incorrect offset is applied in addition to the
15489 * correct one. Additionally, on Windows 8+, this offset
15490 * also affects the selected source mip-level, as opposed
15491 * to Windows XP+ where it only affects the
15492 * source/destination coordinates. */
15493 src_rect_broken = src_rect;
15494 dst_point_broken = dst_point;
15495 for (l = 0; l < level_offset_broken; ++l)
15497 dst_point_broken.x /= 2;
15498 dst_point_broken.y /= 2;
15499 src_rect_broken.top /= 2;
15500 src_rect_broken.left /= 2;
15501 src_rect_broken.right = (src_rect_broken.right + 1) / 2;
15502 src_rect_broken.bottom = (src_rect_broken.bottom + 1) / 2;
15504 diff3 = validate_loaded_surface(surface, j, k + level_offset_broken,
15505 &src_rect_broken, &dst_point_broken);
15507 ok(!diff || broken(!diff2 || !diff3), "Test %u, face %u, level %u: "
15508 "Unexpected destination texture level pixels; %u/%u/%u differences.\n",
15509 i, j, k, diff, diff2, diff3);
15511 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &mip_caps, &tmp);
15512 IDirectDrawSurface7_Release(surface);
15513 if (FAILED(hr))
15514 break;
15515 surface = tmp;
15517 dst_point.x /= 2;
15518 dst_point.y /= 2;
15519 src_rect.top /= 2;
15520 src_rect.left /= 2;
15521 src_rect.right = (src_rect.right + 1) / 2;
15522 src_rect.bottom = (src_rect.bottom + 1) / 2;
15525 if (!(tests[i].dst_flags & TEX_CUBE) || ++j >= 6)
15526 break;
15528 face_caps.dwCaps2 = DDSCAPS2_CUBEMAP | (DDSCAPS2_CUBEMAP_POSITIVEX << j);
15529 hr = IDirectDrawSurface7_GetAttachedSurface(dst_surface, &face_caps, &surface);
15530 ok(SUCCEEDED(hr), "Test %u: Failed to get face %u.\n", i, j);
15534 IDirectDrawSurface7_Release(dst_surface);
15535 IDirectDrawSurface7_Release(src_surface);
15537 #undef TEX_MIP
15538 #undef TEX_CUBE
15539 #undef NULL_COORDS
15541 memset(&surface_desc, 0, sizeof(surface_desc));
15542 surface_desc.dwSize = sizeof(surface_desc);
15543 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
15544 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
15545 surface_desc.dwWidth = 128;
15546 surface_desc.dwHeight = 128;
15547 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
15548 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
15549 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
15550 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
15551 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
15552 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
15553 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
15554 hr = IDirectDrawSurface7_GetAttachedSurface(src_surface, &mip_caps, &surface);
15555 ok(SUCCEEDED(hr), "Failed to get surface, hr %#x.\n", hr);
15557 /* Test palette copying. */
15558 memset(table1, 0, sizeof(table1));
15559 table1[0].peBlue = 1;
15560 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &src_palette, NULL);
15561 ok(SUCCEEDED(hr), "Failed to create source palette, hr %#x.\n", hr);
15562 table1[0].peBlue = 3;
15563 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &dst_palette, NULL);
15564 ok(SUCCEEDED(hr), "Failed to create destination palette, hr %#x.\n", hr);
15566 hr = IDirectDrawSurface7_SetPalette(src_surface, src_palette);
15567 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
15569 hr = IDirect3DDevice7_Load(device, dst_surface, NULL, src_surface, NULL, 0);
15570 ok(SUCCEEDED(hr), "Failed to load texture, hr %#x.\n", hr);
15572 hr = IDirectDrawSurface7_GetPalette(surface, &palette);
15573 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
15574 hr = IDirectDrawSurface7_GetPalette(dst_surface, &palette);
15575 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
15577 hr = IDirectDrawSurface7_SetPalette(surface, src_palette);
15578 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x.\n", hr);
15579 hr = IDirectDrawSurface7_SetPalette(dst_surface, dst_palette);
15580 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
15582 hr = IDirect3DDevice7_Load(device, dst_surface, NULL, src_surface, NULL, 0);
15583 ok(SUCCEEDED(hr), "Failed to load texture, hr %#x.\n", hr);
15585 hr = IDirectDrawSurface7_GetPalette(dst_surface, &palette);
15586 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
15587 ok(palette == dst_palette, "Got unexpected palette %p, expected %p.\n", palette, dst_palette);
15588 memset(table1, 0, sizeof(table1));
15589 hr = IDirectDrawPalette_GetEntries(palette, 0, 0, 256, table1);
15590 ok(SUCCEEDED(hr), "Failed to retrieve palette entries, hr %#x.\n", hr);
15591 ok(table1[0].peBlue == 1, "Got unexpected palette colour %#x.\n", (unsigned int)table1[0].peBlue);
15592 IDirectDrawPalette_Release(palette);
15594 IDirectDrawPalette_Release(dst_palette);
15595 IDirectDrawPalette_Release(src_palette);
15597 /* Test colour-key copying. */
15598 colour_key.dwColorSpaceLowValue = 32;
15599 colour_key.dwColorSpaceHighValue = 64;
15600 hr = IDirectDrawSurface7_SetColorKey(src_surface, DDCKEY_SRCBLT, &colour_key);
15601 ok(SUCCEEDED(hr), "Failed to set colour-key, hr %#x.\n", hr);
15602 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &colour_key);
15603 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x.\n", hr);
15605 hr = IDirectDrawSurface7_GetColorKey(dst_surface, DDCKEY_SRCBLT, &colour_key);
15606 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
15608 hr = IDirect3DDevice7_Load(device, dst_surface, NULL, src_surface, NULL, 0);
15609 ok(SUCCEEDED(hr), "Failed to load texture, hr %#x.\n", hr);
15611 hr = IDirectDrawSurface7_GetColorKey(dst_surface, DDCKEY_SRCBLT, &colour_key);
15612 ok(SUCCEEDED(hr), "Failed to get colour-key, hr %#x.\n", hr);
15613 ok(colour_key.dwColorSpaceLowValue == 32, "Got unexpected value %u.\n", colour_key.dwColorSpaceLowValue);
15614 ok(colour_key.dwColorSpaceHighValue == 32, "Got unexpected value %u.\n", colour_key.dwColorSpaceHighValue);
15616 IDirectDrawSurface7_Release(surface);
15617 IDirectDrawSurface7_Release(dst_surface);
15618 IDirectDrawSurface7_Release(src_surface);
15620 IDirectDraw7_Release(ddraw);
15621 refcount = IDirect3DDevice7_Release(device);
15622 ok(!refcount, "Device has %u references left.\n", refcount);
15623 DestroyWindow(window);
15626 static void test_color_vertex(void)
15628 IDirect3DDevice7 *device;
15629 IDirectDrawSurface7 *rt;
15630 D3DMATERIAL7 material;
15631 D3DCOLOR colour;
15632 unsigned int i;
15633 ULONG refcount;
15634 HWND window;
15635 HRESULT hr;
15637 static struct
15639 struct vec3 position;
15640 DWORD diffuse;
15641 DWORD specular;
15643 quad_2c[] =
15645 {{-1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff00ff00},
15646 {{-1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff00ff00},
15647 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff00ff00},
15648 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff00ff00},
15650 static struct
15652 struct vec3 position;
15653 DWORD colour;
15655 quad_1c[] =
15657 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
15658 {{-1.0f, 1.0f, 0.0f}, 0xffff0000},
15659 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000},
15660 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000},
15662 static struct
15664 struct vec3 position;
15666 quad_0c[] =
15668 {{-1.0f, -1.0f, 0.0f}},
15669 {{-1.0f, 1.0f, 0.0f}},
15670 {{ 1.0f, -1.0f, 0.0f}},
15671 {{ 1.0f, 1.0f, 0.0f}},
15674 /* The idea here is to set up ambient light parameters in a way that the
15675 * ambient colour from the material is just passed through. The emissive
15676 * colour is just passed through anyway. The sum of ambient + emissive
15677 * should allow deduction of where the material colour came from. */
15678 static const struct
15680 DWORD fvf, color_vertex, ambient, emissive, result;
15681 void *vtx;
15683 tests[] =
15685 {D3DFVF_DIFFUSE | D3DFVF_SPECULAR, FALSE, D3DMCS_COLOR1, D3DMCS_COLOR2, 0x000000c0, quad_2c},
15687 {D3DFVF_DIFFUSE | D3DFVF_SPECULAR, TRUE, D3DMCS_COLOR1, D3DMCS_COLOR2, 0x00ffff00, quad_2c},
15688 {D3DFVF_DIFFUSE | D3DFVF_SPECULAR, TRUE, D3DMCS_MATERIAL, D3DMCS_COLOR2, 0x0000ff80, quad_2c},
15689 {D3DFVF_DIFFUSE | D3DFVF_SPECULAR, TRUE, D3DMCS_COLOR1, D3DMCS_MATERIAL, 0x00ff0040, quad_2c},
15690 {D3DFVF_DIFFUSE | D3DFVF_SPECULAR, TRUE, D3DMCS_COLOR1, D3DMCS_COLOR1, 0x00ff0000, quad_2c},
15691 {D3DFVF_DIFFUSE | D3DFVF_SPECULAR, TRUE, D3DMCS_COLOR2, D3DMCS_COLOR2, 0x0000ff00, quad_2c},
15693 {D3DFVF_SPECULAR, TRUE, D3DMCS_COLOR1, D3DMCS_COLOR2, 0x00ff0080, quad_1c},
15694 {D3DFVF_SPECULAR, TRUE, D3DMCS_COLOR1, D3DMCS_MATERIAL, 0x000000c0, quad_1c},
15695 {D3DFVF_SPECULAR, TRUE, D3DMCS_MATERIAL, D3DMCS_COLOR2, 0x00ff0080, quad_1c},
15696 {D3DFVF_DIFFUSE, TRUE, D3DMCS_COLOR1, D3DMCS_COLOR2, 0x00ff0040, quad_1c},
15697 {D3DFVF_DIFFUSE, TRUE, D3DMCS_COLOR1, D3DMCS_MATERIAL, 0x00ff0040, quad_1c},
15698 {D3DFVF_DIFFUSE, TRUE, D3DMCS_COLOR2, D3DMCS_MATERIAL, 0x000000c0, quad_1c},
15700 {0, TRUE, D3DMCS_COLOR1, D3DMCS_COLOR2, 0x000000c0, quad_0c},
15703 window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
15704 0, 0, 640, 480, 0, 0, 0, 0);
15705 if (!(device = create_device(window, DDSCL_NORMAL)))
15707 skip("Failed to create a 3D device, skipping test.\n");
15708 DestroyWindow(window);
15709 return;
15711 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
15712 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
15714 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
15715 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
15716 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_AMBIENT, 0xffffffff);
15717 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
15719 memset(&material, 0, sizeof(material));
15720 U3(U1(material).ambient).b = 0.5f;
15721 U3(U3(material).emissive).b = 0.25f;
15722 hr = IDirect3DDevice7_SetMaterial(device, &material);
15723 ok(SUCCEEDED(hr), "Failed to set material, hr %#x\n", hr);
15725 for (i = 0; i < ARRAY_SIZE(tests); ++i)
15727 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORVERTEX, tests[i].color_vertex);
15728 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
15729 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_AMBIENTMATERIALSOURCE, tests[i].ambient);
15730 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
15731 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_EMISSIVEMATERIALSOURCE, tests[i].emissive);
15732 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
15733 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
15734 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
15736 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x77777777, 0.0f, 0);
15737 ok(SUCCEEDED(hr), "Failed to clear depth/stencil, hr %#x.\n", hr);
15739 hr = IDirect3DDevice7_BeginScene(device);
15740 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
15741 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
15742 D3DFVF_XYZ | tests[i].fvf, tests[i].vtx, 4, 0);
15743 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
15744 hr = IDirect3DDevice7_EndScene(device);
15745 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
15747 colour = get_surface_color(rt, 320, 240);
15748 ok(compare_color(colour, tests[i].result, 1),
15749 "Expected colour 0x%08x for test %u, got 0x%08x.\n",
15750 tests[i].result, i, colour);
15753 IDirectDrawSurface7_Release(rt);
15754 refcount = IDirect3DDevice7_Release(device);
15755 ok(!refcount, "Device has %u references left.\n", refcount);
15756 DestroyWindow(window);
15759 static IDirectDraw7 *killfocus_ddraw;
15760 static IDirectDrawSurface7 *killfocus_surface;
15762 static LRESULT CALLBACK killfocus_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
15764 ULONG ref;
15766 if (message == WM_KILLFOCUS)
15768 ref = IDirectDrawSurface7_Release(killfocus_surface);
15769 ok(!ref, "Unexpected surface refcount %u.\n", ref);
15770 ref = IDirectDraw7_Release(killfocus_ddraw);
15771 ok(!ref, "Unexpected ddraw refcount %u.\n", ref);
15772 killfocus_ddraw = NULL;
15775 return DefWindowProcA(window, message, wparam, lparam);
15778 static void test_killfocus(void)
15780 DDSURFACEDESC2 surface_desc;
15781 HRESULT hr;
15782 HWND window;
15783 WNDCLASSA wc = {0};
15785 wc.lpfnWndProc = killfocus_proc;
15786 wc.lpszClassName = "ddraw_killfocus_wndproc_wc";
15787 ok(RegisterClassA(&wc), "Failed to register window class.\n");
15789 window = CreateWindowA("ddraw_killfocus_wndproc_wc", "d3d7_test", WS_OVERLAPPEDWINDOW,
15790 0, 0, 640, 480, 0, 0, 0, 0);
15792 killfocus_ddraw = create_ddraw();
15793 ok(!!killfocus_ddraw, "Failed to create a ddraw object.\n");
15795 hr = IDirectDraw7_SetCooperativeLevel(killfocus_ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
15796 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
15798 memset(&surface_desc, 0, sizeof(surface_desc));
15799 surface_desc.dwSize = sizeof(surface_desc);
15800 surface_desc.dwFlags = DDSD_CAPS;
15801 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
15802 hr = IDirectDraw7_CreateSurface(killfocus_ddraw, &surface_desc, &killfocus_surface, NULL);
15803 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
15805 SetForegroundWindow(GetDesktopWindow());
15806 ok(!killfocus_ddraw, "WM_KILLFOCUS was not received.\n");
15808 DestroyWindow(window);
15809 UnregisterClassA("ddraw_killfocus_wndproc_wc", GetModuleHandleA(NULL));
15812 static void test_sysmem_draw(void)
15814 IDirectDrawSurface7 *rt, *texture;
15815 DDSURFACEDESC2 surface_desc;
15816 D3DVERTEXBUFFERDESC vb_desc;
15817 IDirect3DVertexBuffer7 *vb;
15818 IDirect3DDevice7 *device;
15819 IDirectDraw7 *ddraw;
15820 IDirect3D7 *d3d;
15821 D3DCOLOR colour;
15822 ULONG refcount;
15823 HWND window;
15824 HRESULT hr;
15825 BYTE *data;
15827 static const struct
15829 struct vec3 position;
15830 DWORD diffuse;
15832 quad[] =
15834 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
15835 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
15836 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
15837 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
15839 static WORD indices[] = {0, 1, 2, 3};
15841 window = create_window();
15842 ok(!!window, "Failed to create a window.\n");
15844 if (!(device = create_device(window, DDSCL_NORMAL)))
15846 skip("Failed to create a 3D device, skipping test.\n");
15847 DestroyWindow(window);
15848 return;
15851 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
15852 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15853 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
15854 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15855 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
15856 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15858 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
15859 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15861 vb_desc.dwSize = sizeof(vb_desc);
15862 vb_desc.dwCaps = D3DVBCAPS_SYSTEMMEMORY;
15863 vb_desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
15864 vb_desc.dwNumVertices = 4;
15865 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &vb, 0);
15866 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15868 hr = IDirect3DVertexBuffer7_Lock(vb, 0, (void **)&data, NULL);
15869 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15870 memcpy(data, quad, sizeof(quad));
15871 hr = IDirect3DVertexBuffer7_Unlock(vb);
15872 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15874 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x77777777, 0.0f, 0);
15875 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15877 hr = IDirect3DDevice7_BeginScene(device);
15878 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15879 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, 0);
15880 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15881 hr = IDirect3DDevice7_EndScene(device);
15882 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15884 colour = get_surface_color(rt, 320, 240);
15885 ok(compare_color(colour, 0x00007f7f, 1), "Got unexpected colour 0x%08x.\n", colour);
15887 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x77777777, 0.0f, 0);
15888 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15890 hr = IDirect3DDevice7_BeginScene(device);
15891 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15892 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, indices, 4, 0);
15893 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15894 hr = IDirect3DDevice7_EndScene(device);
15895 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15897 colour = get_surface_color(rt, 320, 240);
15898 ok(compare_color(colour, 0x00007f7f, 1), "Got unexpected colour 0x%08x.\n", colour);
15900 memset(&surface_desc, 0, sizeof(surface_desc));
15901 surface_desc.dwSize = sizeof(surface_desc);
15902 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
15903 surface_desc.dwHeight = 2;
15904 surface_desc.dwWidth = 2;
15905 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
15906 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
15907 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
15908 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
15909 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
15910 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
15911 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
15912 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
15913 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
15914 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15915 hr = IDirect3DDevice7_SetTexture(device, 0, texture);
15916 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
15918 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x77777777, 0.0f, 0);
15919 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
15921 hr = IDirect3DDevice7_BeginScene(device);
15922 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
15923 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, 0);
15924 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
15925 hr = IDirect3DDevice7_EndScene(device);
15926 ok(hr == D3D_OK || hr == D3DERR_SCENE_END_FAILED, "Got unexpected hr %#x.\n", hr);
15928 IDirectDrawSurface7_Release(texture);
15929 IDirect3DVertexBuffer7_Release(vb);
15930 IDirectDrawSurface7_Release(rt);
15931 IDirectDraw7_Release(ddraw);
15932 IDirect3D7_Release(d3d);
15933 refcount = IDirect3DDevice7_Release(device);
15934 ok(!refcount, "Device has %u references left.\n", refcount);
15935 DestroyWindow(window);
15938 static void test_gdi_surface(void)
15940 IDirectDrawSurface7 *primary, *backbuffer, *gdi_surface;
15941 DDSCAPS2 caps = {DDSCAPS_BACKBUFFER, 0, 0, {0}};
15942 DDSURFACEDESC2 surface_desc;
15943 IDirectDraw7 *ddraw;
15944 ULONG refcount;
15945 HWND window;
15946 HRESULT hr;
15948 window = create_window();
15949 ddraw = create_ddraw();
15950 ok(!!ddraw, "Failed to create a ddraw object.\n");
15951 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
15952 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15954 /* Retrieving the GDI surface requires a primary surface to exist. */
15955 gdi_surface = (void *)0xc0dec0de;
15956 hr = IDirectDraw7_GetGDISurface(ddraw, &gdi_surface);
15957 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
15958 ok(!gdi_surface, "Got unexpected surface %p.\n", gdi_surface);
15960 hr = IDirectDraw7_FlipToGDISurface(ddraw);
15961 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
15963 memset(&surface_desc, 0, sizeof(surface_desc));
15964 surface_desc.dwSize = sizeof(surface_desc);
15965 surface_desc.dwFlags = DDSD_CAPS;
15966 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
15967 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
15968 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15970 hr = IDirectDraw7_GetGDISurface(ddraw, &gdi_surface);
15971 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15972 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
15973 IDirectDrawSurface7_Release(gdi_surface);
15975 /* Flipping to the GDI surface requires the primary surface to be
15976 * flippable. */
15977 hr = IDirectDraw7_FlipToGDISurface(ddraw);
15978 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
15980 IDirectDrawSurface7_Release(primary);
15982 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
15983 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15985 memset(&surface_desc, 0, sizeof(surface_desc));
15986 surface_desc.dwSize = sizeof(surface_desc);
15987 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
15988 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
15989 U5(surface_desc).dwBackBufferCount = 1;
15990 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
15991 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15992 hr = IDirectDrawSurface7_GetAttachedSurface(primary, &caps, &backbuffer);
15993 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15994 ok(backbuffer != primary, "Got unexpected backbuffer %p.\n", backbuffer);
15996 hr = IDirectDraw7_GetGDISurface(ddraw, &gdi_surface);
15997 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15998 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
15999 IDirectDrawSurface7_Release(gdi_surface);
16001 hr = IDirectDrawSurface7_Flip(primary, NULL, DDFLIP_WAIT);
16002 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16003 hr = IDirectDraw7_GetGDISurface(ddraw, &gdi_surface);
16004 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16005 ok(gdi_surface == backbuffer || broken(gdi_surface == primary),
16006 "Got unexpected surface %p, expected %p.\n", gdi_surface, backbuffer);
16007 IDirectDrawSurface7_Release(gdi_surface);
16009 hr = IDirectDraw7_FlipToGDISurface(ddraw);
16010 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16012 hr = IDirectDraw7_GetGDISurface(ddraw, &gdi_surface);
16013 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16014 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
16015 IDirectDrawSurface7_Release(gdi_surface);
16017 hr = IDirectDraw7_FlipToGDISurface(ddraw);
16018 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16020 IDirectDrawSurface7_Release(backbuffer);
16021 IDirectDrawSurface7_Release(primary);
16023 refcount = IDirectDraw7_Release(ddraw);
16024 ok(!refcount, "%u references left.\n", refcount);
16025 DestroyWindow(window);
16028 static void test_multiply_transform(void)
16030 IDirect3DDevice7 *device;
16031 D3DMATRIX ret_mat;
16032 DWORD stateblock;
16033 unsigned int i;
16034 ULONG refcount;
16035 HWND window;
16036 HRESULT hr;
16038 static const D3DTRANSFORMSTATETYPE tests[] =
16040 D3DTRANSFORMSTATE_WORLD,
16041 D3DTRANSFORMSTATE_VIEW,
16042 D3DTRANSFORMSTATE_PROJECTION,
16043 D3DTRANSFORMSTATE_WORLD1,
16044 D3DTRANSFORMSTATE_WORLD2,
16045 D3DTRANSFORMSTATE_WORLD3,
16046 D3DTRANSFORMSTATE_TEXTURE0,
16047 D3DTRANSFORMSTATE_TEXTURE1,
16048 D3DTRANSFORMSTATE_TEXTURE2,
16049 D3DTRANSFORMSTATE_TEXTURE3,
16050 D3DTRANSFORMSTATE_TEXTURE4,
16051 D3DTRANSFORMSTATE_TEXTURE5,
16052 D3DTRANSFORMSTATE_TEXTURE6,
16053 D3DTRANSFORMSTATE_TEXTURE7,
16056 D3DMATRIX mat1 =
16058 1.0f, 0.0f, 0.0f, 0.0f,
16059 0.0f, 1.0f, 0.0f, 0.0f,
16060 0.0f, 0.0f, 1.0f, 0.0f,
16061 0.0f, 0.0f, 0.0f, 1.0f,
16063 mat2 =
16065 2.0f, 0.0f, 0.0f, 0.0f,
16066 0.0f, 2.0f, 0.0f, 0.0f,
16067 0.0f, 0.0f, 2.0f, 0.0f,
16068 0.0f, 0.0f, 0.0f, 2.0f,
16071 window = create_window();
16072 if (!(device = create_device(window, DDSCL_NORMAL)))
16074 skip("Failed to create 3D device.\n");
16075 DestroyWindow(window);
16076 return;
16079 for (i = 0; i < ARRAY_SIZE(tests); ++i)
16081 hr = IDirect3DDevice7_GetTransform(device, tests[i], &ret_mat);
16082 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
16083 ok(!memcmp(&ret_mat, &mat1, sizeof(mat1)), "Test %u: Got unexpected transform matrix.\n", i);
16085 hr = IDirect3DDevice7_MultiplyTransform(device, tests[i], &mat2);
16086 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
16088 hr = IDirect3DDevice7_GetTransform(device, tests[i], &ret_mat);
16089 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
16090 ok(!memcmp(&ret_mat, &mat2, sizeof(mat2)), "Test %u: Got unexpected transform matrix.\n", i);
16092 /* MultiplyTransform() goes directly into the primary stateblock. */
16094 hr = IDirect3DDevice7_SetTransform(device, tests[i], &mat1);
16095 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
16097 hr = IDirect3DDevice7_BeginStateBlock(device);
16098 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
16100 hr = IDirect3DDevice7_MultiplyTransform(device, tests[i], &mat2);
16101 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
16103 hr = IDirect3DDevice7_EndStateBlock(device, &stateblock);
16104 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
16106 hr = IDirect3DDevice7_GetTransform(device, tests[i], &ret_mat);
16107 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
16108 ok(!memcmp(&ret_mat, &mat2, sizeof(mat2)), "Test %u: Got unexpected transform matrix.\n", i);
16110 hr = IDirect3DDevice7_CaptureStateBlock(device, stateblock);
16111 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
16113 hr = IDirect3DDevice7_SetTransform(device, tests[i], &mat1);
16114 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
16116 hr = IDirect3DDevice7_ApplyStateBlock(device, stateblock);
16117 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
16119 hr = IDirect3DDevice7_GetTransform(device, tests[i], &ret_mat);
16120 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
16121 ok(!memcmp(&ret_mat, &mat1, sizeof(mat1)), "Test %u: Got unexpected transform matrix.\n", i);
16123 IDirect3DDevice7_DeleteStateBlock(device, stateblock);
16126 refcount = IDirect3DDevice7_Release(device);
16127 ok(!refcount, "Device has %u references left.\n", refcount);
16128 DestroyWindow(window);
16131 static void test_alphatest(void)
16133 #define ALPHATEST_PASSED 0x0000ff00
16134 #define ALPHATEST_FAILED 0x00ff0000
16135 IDirect3DDevice7 *device;
16136 IDirectDrawSurface7 *rt;
16137 unsigned int i;
16138 D3DCOLOR color;
16139 ULONG refcount;
16140 HWND window;
16141 DWORD value;
16142 HRESULT hr;
16144 static const struct
16146 D3DCMPFUNC func;
16147 D3DCOLOR color_less;
16148 D3DCOLOR color_equal;
16149 D3DCOLOR color_greater;
16151 test_data[] =
16153 {D3DCMP_NEVER, ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_FAILED},
16154 {D3DCMP_LESS, ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_FAILED},
16155 {D3DCMP_EQUAL, ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_FAILED},
16156 {D3DCMP_LESSEQUAL, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_FAILED},
16157 {D3DCMP_GREATER, ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_PASSED},
16158 {D3DCMP_NOTEQUAL, ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_PASSED},
16159 {D3DCMP_GREATEREQUAL, ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_PASSED},
16160 {D3DCMP_ALWAYS, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_PASSED},
16162 static struct
16164 struct vec3 position;
16165 DWORD diffuse;
16167 quad[] =
16169 {{-1.0f, -1.0f, 0.1f}, ALPHATEST_PASSED | 0x80000000},
16170 {{-1.0f, 1.0f, 0.1f}, ALPHATEST_PASSED | 0x80000000},
16171 {{ 1.0f, -1.0f, 0.1f}, ALPHATEST_PASSED | 0x80000000},
16172 {{ 1.0f, 1.0f, 0.1f}, ALPHATEST_PASSED | 0x80000000},
16175 window = create_window();
16176 if (!(device = create_device(window, DDSCL_NORMAL)))
16178 skip("Failed to create a 3D device.\n");
16179 DestroyWindow(window);
16180 return;
16182 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
16183 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16185 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
16186 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16187 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
16188 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16189 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
16190 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16191 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHATESTENABLE, TRUE);
16192 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16194 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
16196 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHAFUNC, test_data[i].func);
16197 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16199 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, ALPHATEST_FAILED, 0.0f, 0);
16200 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16201 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHAREF, 0x70);
16202 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16203 hr = IDirect3DDevice7_BeginScene(device);
16204 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16205 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
16206 D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, ARRAY_SIZE(quad), 0);
16207 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16208 hr = IDirect3DDevice7_EndScene(device);
16209 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16210 color = get_surface_color(rt, 320, 240);
16211 ok(compare_color(color, test_data[i].color_greater, 0),
16212 "Alphatest failed, color 0x%08x, expected 0x%08x, alpha > ref, func %u.\n",
16213 color, test_data[i].color_greater, test_data[i].func);
16215 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, ALPHATEST_FAILED, 0.0f, 0);
16216 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16217 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHAREF, 0xff70);
16218 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16219 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ALPHAREF, &value);
16220 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16221 ok(value == 0xff70, "Got unexpected value %#x.\n", value);
16222 hr = IDirect3DDevice7_BeginScene(device);
16223 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16224 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
16225 D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, ARRAY_SIZE(quad), 0);
16226 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16227 hr = IDirect3DDevice7_EndScene(device);
16228 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16229 color = get_surface_color(rt, 320, 240);
16230 ok(compare_color(color, test_data[i].color_greater, 0),
16231 "Alphatest failed, color 0x%08x, expected 0x%08x, alpha > ref, func %u.\n",
16232 color, test_data[i].color_greater, test_data[i].func);
16235 IDirectDrawSurface7_Release(rt);
16236 refcount = IDirect3DDevice7_Release(device);
16237 ok(!refcount, "Device has %u references left.\n", refcount);
16238 DestroyWindow(window);
16241 static void test_clipper_refcount(void)
16243 IDirectDrawSurface7 *surface;
16244 IDirectDrawClipper *clipper, *clipper2;
16245 DDSURFACEDESC2 surface_desc;
16246 IDirectDraw7 *ddraw;
16247 IDirectDraw *ddraw1;
16248 ULONG refcount;
16249 HWND window;
16250 HRESULT hr;
16251 BOOL changed;
16252 const IDirectDrawClipperVtbl *orig_vtbl;
16254 window = create_window();
16255 ddraw = create_ddraw();
16256 ok(!!ddraw, "Failed to create a ddraw object.\n");
16257 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
16258 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16260 memset(&surface_desc, 0, sizeof(surface_desc));
16261 surface_desc.dwSize = sizeof(surface_desc);
16262 surface_desc.dwFlags = DDSD_CAPS;
16263 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
16264 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
16265 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16267 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
16268 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
16269 refcount = get_refcount((IUnknown *)clipper);
16270 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
16272 /* Show that clipper validation doesn't somehow happen through per-clipper vtable
16273 * pointers. */
16274 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper2, NULL);
16275 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
16276 ok(clipper->lpVtbl == clipper2->lpVtbl, "Got different clipper vtables %p and %p.\n",
16277 clipper->lpVtbl, clipper2->lpVtbl);
16278 orig_vtbl = clipper->lpVtbl;
16279 IDirectDrawClipper_Release(clipper2);
16281 /* Surfaces hold a reference to clippers. No surprises there. */
16282 hr = IDirectDrawSurface7_SetClipper(surface, clipper);
16283 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
16284 refcount = get_refcount((IUnknown *)clipper);
16285 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
16287 hr = IDirectDrawSurface7_GetClipper(surface, &clipper2);
16288 ok(SUCCEEDED(hr), "Failed to get clipper, hr %#x.\n", hr);
16289 ok(clipper == clipper2, "Got clipper %p, expected %p.\n", clipper2, clipper);
16290 refcount = IDirectDrawClipper_Release(clipper2);
16291 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
16293 hr = IDirectDrawSurface7_SetClipper(surface, NULL);
16294 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
16295 refcount = get_refcount((IUnknown *)clipper);
16296 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
16298 hr = IDirectDrawSurface7_SetClipper(surface, clipper);
16299 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
16300 refcount = get_refcount((IUnknown *)clipper);
16301 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
16303 refcount = IDirectDrawSurface7_Release(surface);
16304 ok(!refcount, "%u references left.\n", refcount);
16305 refcount = get_refcount((IUnknown *)clipper);
16306 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
16308 /* SetClipper with an invalid pointer crashes. */
16310 /* Clipper methods work with a broken vtable, with the exception of Release. */
16311 clipper->lpVtbl = (void *)0xdeadbeef;
16312 refcount = orig_vtbl->AddRef(clipper);
16313 todo_wine ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
16314 refcount = orig_vtbl->Release(clipper);
16315 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
16317 clipper->lpVtbl = orig_vtbl;
16318 refcount = orig_vtbl->Release(clipper);
16319 todo_wine ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
16321 /* Fix the refcount difference because Wine did not increase the ref in the
16322 * AddRef call above. */
16323 if (refcount)
16325 refcount = IDirectDrawClipper_Release(clipper);
16326 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
16329 /* Steal the reference and see what happens - releasing the surface works fine.
16330 * The clipper is destroyed and not kept alive by a hidden refcount - trying to
16331 * release it after the GetClipper call is likely to crash, and certain to crash
16332 * if we allocate and zero as much heap memory as we can get. */
16333 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
16334 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16335 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
16336 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
16337 hr = IDirectDrawSurface7_SetClipper(surface, clipper);
16338 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
16340 IDirectDrawClipper_Release(clipper);
16341 IDirectDrawClipper_Release(clipper);
16343 if (0)
16345 /* Disabled because it causes heap corruption (HeapValidate fails and random
16346 * hangs in a later HeapFree) on Windows on one of my Machines: MacbookPro 10,1
16347 * running Windows 10 18363.535 and Nvidia driver 425.31. Driver version 441.66
16348 * is affected too. Some testbot machines have crashes directly in GetClipper
16349 * or proceed with a corrupted heap too.
16351 * The same Windows and driver versions run the test without heap corruption on
16352 * a Geforce 1060 GTX card. I have not seen the problem on AMD GPUs either. */
16353 hr = IDirectDrawSurface7_GetClipper(surface, &clipper2);
16354 ok(SUCCEEDED(hr), "Failed to get clipper, hr %#x.\n", hr);
16355 ok(clipper == clipper2, "Got clipper %p, expected %p.\n", clipper2, clipper);
16358 /* Show that invoking the Release method does not crash, but don't get the
16359 * vtable through the clipper pointer because it is no longer pointing to
16360 * valid memory. */
16361 refcount = orig_vtbl->Release(clipper);
16362 ok(!refcount, "%u references left.\n", refcount);
16364 refcount = IDirectDrawSurface7_Release(surface);
16365 ok(!refcount, "%u references left.\n", refcount);
16367 /* It looks like the protection against invalid thispointers is part of
16368 * the IDirectDrawClipper method implementation, not IDirectDrawSurface. */
16369 clipper = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 0x1000);
16370 ok(!!clipper, "failed to allocate memory\n");
16372 /* Assigning the vtable to our fake clipper does NOT make a difference on
16373 * native - there is a different member of the clipper implementation struct
16374 * that is used to determine if a clipper is valid. */
16375 clipper->lpVtbl = orig_vtbl;
16377 refcount = orig_vtbl->AddRef(clipper);
16378 todo_wine ok(!refcount, "Got refcount %u.\n", refcount);
16379 refcount = orig_vtbl->AddRef((IDirectDrawClipper *)(ULONG_PTR)0xdeadbeef);
16380 ok(!refcount, "Got refcount %u.\n", refcount);
16382 changed = 0x1234;
16383 hr = orig_vtbl->IsClipListChanged(clipper, &changed);
16384 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
16385 todo_wine ok(changed == 0x1234, "'changed' changed: %x.\n", changed);
16387 changed = 0x1234;
16388 hr = orig_vtbl->IsClipListChanged((IDirectDrawClipper *)(ULONG_PTR)0xdeadbeef, &changed);
16389 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
16390 ok(changed == 0x1234, "'changed' changed: %x.\n", changed);
16392 /* Nope, we can't initialize our fake clipper. */
16393 hr = IDirectDraw7_QueryInterface(ddraw, &IID_IDirectDraw, (void **)&ddraw1);
16394 ok(SUCCEEDED(hr), "Failed to get ddraw1 interface, hr %#x.\n", hr);
16396 hr = orig_vtbl->Initialize(clipper, ddraw1, 0);
16397 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
16399 IDirectDraw_Release(ddraw1);
16401 HeapFree(GetProcessHeap(), 0, clipper);
16403 refcount = IDirectDraw7_Release(ddraw);
16404 ok(!refcount, "%u references left.\n", refcount);
16405 DestroyWindow(window);
16408 static void test_begin_end_state_block(void)
16410 DWORD stateblock, stateblock2;
16411 IDirect3DDevice7 *device;
16412 ULONG refcount;
16413 DWORD value;
16414 HWND window;
16415 HRESULT hr;
16417 window = create_window();
16418 if (!(device = create_device(window, DDSCL_NORMAL)))
16420 skip("Failed to create 3D device.\n");
16421 DestroyWindow(window);
16422 return;
16425 hr = IDirect3DDevice7_BeginStateBlock(device);
16426 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16428 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
16429 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16431 stateblock = 0xdeadbeef;
16432 hr = IDirect3DDevice7_EndStateBlock(device, &stateblock);
16433 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16434 ok(!!stateblock && stateblock != 0xdeadbeef, "Got unexpected stateblock %#x.\n", stateblock);
16436 stateblock2 = 0xdeadbeef;
16437 hr = IDirect3DDevice7_EndStateBlock(device, &stateblock2);
16438 ok(hr == D3DERR_NOTINBEGINSTATEBLOCK, "Got unexpected hr %#x.\n", hr);
16439 ok(stateblock2 == 0xdeadbeef, "Got unexpected stateblock %#x.\n", stateblock2);
16441 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &value);
16442 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16443 ok(value == TRUE, "Got unexpected value %#x.\n", value);
16445 hr = IDirect3DDevice7_BeginStateBlock(device);
16446 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16448 hr = IDirect3DDevice7_BeginStateBlock(device);
16449 ok(hr == D3DERR_INBEGINSTATEBLOCK, "Got unexpected hr %#x.\n", hr);
16451 hr = IDirect3DDevice7_ApplyStateBlock(device, stateblock);
16452 ok(hr == D3DERR_INBEGINSTATEBLOCK, "Got unexpected hr %#x.\n", hr);
16454 hr = IDirect3DDevice7_CaptureStateBlock(device, stateblock);
16455 ok(hr == D3DERR_INBEGINSTATEBLOCK, "Got unexpected hr %#x.\n", hr);
16457 hr = IDirect3DDevice7_CreateStateBlock(device, D3DSBT_ALL, &stateblock2);
16458 ok(hr == D3DERR_INBEGINSTATEBLOCK, "Got unexpected hr %#x.\n", hr);
16460 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &value);
16461 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16462 ok(value == TRUE, "Got unexpected value %#x.\n", value);
16464 hr = IDirect3DDevice7_EndStateBlock(device, &stateblock2);
16465 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16467 hr = IDirect3DDevice7_ApplyStateBlock(device, stateblock2);
16468 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16470 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &value);
16471 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16472 ok(value == TRUE, "Got unexpected value %#x.\n", value);
16474 refcount = IDirect3DDevice7_Release(device);
16475 ok(!refcount, "Device has %u references left.\n", refcount);
16476 DestroyWindow(window);
16479 static void test_caps(void)
16481 DWORD caps_never, caps_always, caps_hal;
16482 DDCAPS hal_caps, hel_caps;
16483 IDirectDraw7 *ddraw;
16484 HRESULT hr;
16485 BOOL no3d;
16487 caps_never = DDSCAPS_RESERVED1
16488 | DDSCAPS_ALPHA
16489 | DDSCAPS_PRIMARYSURFACELEFT
16490 | DDSCAPS_SYSTEMMEMORY
16491 | DDSCAPS_VISIBLE
16492 | DDSCAPS_WRITEONLY
16493 | DDSCAPS_LIVEVIDEO
16494 | DDSCAPS_HWCODEC
16495 | DDSCAPS_MODEX
16496 | DDSCAPS_RESERVED2
16497 | 0x01000000u
16498 | 0x02000000u
16499 | DDSCAPS_ALLOCONLOAD
16500 | DDSCAPS_VIDEOPORT
16501 | DDSCAPS_STANDARDVGAMODE
16502 | DDSCAPS_OPTIMIZED;
16504 caps_always = DDSCAPS_FLIP
16505 | DDSCAPS_OFFSCREENPLAIN
16506 | DDSCAPS_PRIMARYSURFACE
16507 | DDSCAPS_TEXTURE
16508 | DDSCAPS_ZBUFFER
16509 | DDSCAPS_MIPMAP;
16511 caps_hal = DDSCAPS_BACKBUFFER
16512 | DDSCAPS_COMPLEX
16513 | DDSCAPS_FRONTBUFFER
16514 | DDSCAPS_3DDEVICE
16515 | DDSCAPS_VIDEOMEMORY
16516 | DDSCAPS_LOCALVIDMEM
16517 | DDSCAPS_NONLOCALVIDMEM;
16519 ddraw = create_ddraw();
16520 ok(!!ddraw, "Failed to create a ddraw object.\n");
16522 memset(&hal_caps, 0, sizeof(hal_caps));
16523 memset(&hel_caps, 0, sizeof(hel_caps));
16524 hal_caps.dwSize = sizeof(hal_caps);
16525 hel_caps.dwSize = sizeof(hel_caps);
16526 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, &hel_caps);
16527 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16528 ok(hal_caps.ddsOldCaps.dwCaps == hal_caps.ddsCaps.dwCaps,
16529 "Got unexpected caps %#x, expected %#x.\n",
16530 hal_caps.ddsOldCaps.dwCaps, hal_caps.ddsCaps.dwCaps);
16531 ok(hel_caps.ddsOldCaps.dwCaps == hel_caps.ddsCaps.dwCaps,
16532 "Got unexpected caps %#x, expected %#x.\n",
16533 hel_caps.ddsOldCaps.dwCaps, hel_caps.ddsCaps.dwCaps);
16535 no3d = !(hal_caps.ddsCaps.dwCaps & DDSCAPS_3DDEVICE);
16536 if (hal_caps.ddsCaps.dwCaps)
16538 ok(!(hal_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
16539 ok(!(~hal_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
16540 todo_wine_if(no3d) ok(!(~hal_caps.ddsCaps.dwCaps & caps_hal),
16541 "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
16543 ok(!(hel_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
16544 ok(!(~hel_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
16545 todo_wine_if(!no3d) ok(!(hel_caps.ddsCaps.dwCaps & caps_hal),
16546 "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
16548 IDirectDraw7_Release(ddraw);
16550 if (hal_caps.ddsCaps.dwCaps)
16552 hr = pDirectDrawCreateEx((GUID *)DDCREATE_HARDWAREONLY, (void **)&ddraw, &IID_IDirectDraw7, NULL);
16553 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16555 memset(&hal_caps, 0, sizeof(hal_caps));
16556 memset(&hel_caps, 0, sizeof(hel_caps));
16557 hal_caps.dwSize = sizeof(hal_caps);
16558 hel_caps.dwSize = sizeof(hel_caps);
16559 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, &hel_caps);
16560 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16561 ok(hal_caps.ddsOldCaps.dwCaps == hal_caps.ddsCaps.dwCaps,
16562 "Got unexpected caps %#x, expected %#x.\n",
16563 hal_caps.ddsOldCaps.dwCaps, hal_caps.ddsCaps.dwCaps);
16564 ok(hel_caps.ddsOldCaps.dwCaps == hel_caps.ddsCaps.dwCaps,
16565 "Got unexpected caps %#x, expected %#x.\n",
16566 hel_caps.ddsOldCaps.dwCaps, hel_caps.ddsCaps.dwCaps);
16568 ok(!(hal_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
16569 ok(!(~hal_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
16570 todo_wine_if(no3d) ok(!(~hal_caps.ddsCaps.dwCaps & caps_hal),
16571 "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
16572 todo_wine ok(!hel_caps.ddsCaps.dwCaps, "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
16574 IDirectDraw7_Release(ddraw);
16577 hr = pDirectDrawCreateEx((GUID *)DDCREATE_EMULATIONONLY, (void **)&ddraw, &IID_IDirectDraw7, NULL);
16578 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16580 memset(&hal_caps, 0, sizeof(hal_caps));
16581 memset(&hel_caps, 0, sizeof(hel_caps));
16582 hal_caps.dwSize = sizeof(hal_caps);
16583 hel_caps.dwSize = sizeof(hel_caps);
16584 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, &hel_caps);
16585 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16586 ok(hal_caps.ddsOldCaps.dwCaps == hal_caps.ddsCaps.dwCaps,
16587 "Got unexpected caps %#x, expected %#x.\n",
16588 hal_caps.ddsOldCaps.dwCaps, hal_caps.ddsCaps.dwCaps);
16589 ok(hel_caps.ddsOldCaps.dwCaps == hel_caps.ddsCaps.dwCaps,
16590 "Got unexpected caps %#x, expected %#x.\n",
16591 hel_caps.ddsOldCaps.dwCaps, hel_caps.ddsCaps.dwCaps);
16593 todo_wine ok(!hal_caps.ddsCaps.dwCaps, "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
16594 ok(!(hel_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
16595 ok(!(~hel_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
16596 todo_wine_if(!no3d) ok(!(hel_caps.ddsCaps.dwCaps & caps_hal),
16597 "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
16599 IDirectDraw7_Release(ddraw);
16602 static void test_d32_support(void)
16604 IDirectDrawSurface7 *surface;
16605 DDSURFACEDESC2 surface_desc;
16606 IDirectDraw7 *ddraw;
16607 ULONG refcount;
16608 HWND window;
16609 HRESULT hr;
16611 window = create_window();
16612 ddraw = create_ddraw();
16613 ok(!!ddraw, "Failed to create a ddraw object.\n");
16614 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
16615 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16617 memset(&surface_desc, 0, sizeof(surface_desc));
16618 surface_desc.dwSize = sizeof(surface_desc);
16619 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
16620 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
16621 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
16622 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
16623 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = 32;
16624 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = 0xffffffff;
16625 surface_desc.dwWidth = 64;
16626 surface_desc.dwHeight = 64;
16627 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
16628 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16630 memset(&surface_desc, 0, sizeof(surface_desc));
16631 surface_desc.dwSize = sizeof(surface_desc);
16632 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
16633 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16634 ok((surface_desc.dwFlags & DDSD_PIXELFORMAT), "Got unexpected flags %#x.\n", surface_desc.dwFlags);
16635 ok(U4(surface_desc).ddpfPixelFormat.dwFlags & DDPF_ZBUFFER,
16636 "Got unexpected format flags %#x.\n", U4(surface_desc).ddpfPixelFormat.dwFlags);
16637 ok(U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth == 32,
16638 "Got unexpected dwZBufferBitDepth %u.\n", U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth);
16639 ok(U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask == 0xffffffff,
16640 "Got unexpected Z mask 0x%08x.\n", U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask);
16641 ok(!(surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY),
16642 "Got unexpected surface caps %#x.\n", surface_desc.ddsCaps.dwCaps);
16643 IDirectDrawSurface7_Release(surface);
16645 refcount = IDirectDraw7_Release(ddraw);
16646 ok(!refcount, "%u references left.\n", refcount);
16647 DestroyWindow(window);
16650 static void test_surface_format_conversion_alpha(void)
16652 static const unsigned int rgba_data[4 * 4] =
16654 0xff00ff00, 0xff0000ff, 0xff0000ff, 0xff0000ff,
16655 0xff0000ff, 0xff00ff00, 0xff0000ff, 0xff0000ff,
16656 0xff00ff00, 0xff0000ff, 0xff00ff00, 0xff0000ff,
16657 0xff00ff00, 0xff0000ff, 0xff0000ff, 0xff00ff00,
16659 static const unsigned int rgbx_data[4 * 4] =
16661 0x0000ff00, 0x000000ff, 0x000000ff, 0x000000ff,
16662 0x000000ff, 0x0000ff00, 0x000000ff, 0x000000ff,
16663 0x0000ff00, 0x000000ff, 0x0000ff00, 0x000000ff,
16664 0x0000ff00, 0x000000ff, 0x000000ff, 0x0000ff00,
16666 static const unsigned short int r5g6b5_data[4 * 4] =
16668 0x07e0, 0x001f, 0x001f, 0x001f,
16669 0x001f, 0x07e0, 0x001f, 0x001f,
16670 0x07e0, 0x001f, 0x07e0, 0x001f,
16671 0x07e0, 0x001f, 0x001f, 0x07e0,
16673 static const unsigned short int r5g5b5x1_data[4 * 4] =
16675 0x03e0, 0x001f, 0x001f, 0x001f,
16676 0x001f, 0x03e0, 0x001f, 0x001f,
16677 0x03e0, 0x001f, 0x03e0, 0x001f,
16678 0x03e0, 0x001f, 0x001f, 0x03e0,
16680 static const unsigned short int r5g5b5a1_data[4 * 4] =
16682 0x83e0, 0x801f, 0x801f, 0x801f,
16683 0x801f, 0x83e0, 0x801f, 0x801f,
16684 0x83e0, 0x801f, 0x83e0, 0x801f,
16685 0x83e0, 0x801f, 0x801f, 0x83e0,
16687 static const unsigned int dxt1_data[8] =
16689 0x001f07e0, 0x14445154,
16691 static const unsigned int dxt2_data[16] =
16693 0xffffffff, 0xffffffff, 0x001f07e0, 0x14445154,
16696 enum test_format_id
16698 FMT_RGBA,
16699 FMT_RGBX,
16700 FMT_R5G6B5,
16701 FMT_R5G5B5X1,
16702 FMT_R5G5B5A1,
16703 FMT_DXT1,
16704 FMT_DXT2,
16705 FMT_DXT3,
16708 static const struct test_format
16710 DDPIXELFORMAT fmt;
16711 const char *name;
16712 unsigned int block_size, x_blocks, y_blocks;
16713 DWORD support_flag;
16714 BOOL broken_software_blit, broken_hardware_blit;
16716 formats[] =
16720 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
16721 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
16723 "RGBA", 4, 4, 4,
16727 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
16728 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
16730 "RGBX", 4, 4, 4,
16734 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
16735 {16}, {0x0000f800}, {0x000007e0}, {0x0000001f}, {0x00000000}
16737 "R5G6B5", 2, 4, 4, 0, TRUE,
16738 /* Looks broken for sysmem texture conversions on Windows (at
16739 * least with hardware device), the result is either error from
16740 * _Blt() or a copy of the source data without any conversion. */
16744 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
16745 {16}, {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00000000}
16747 "R5G5B5X1", 2, 4, 4,
16751 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
16752 {16}, {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00008000}
16754 "R5G5B5A1", 2, 4, 4, 0, FALSE, TRUE,
16758 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
16759 {0}, {0}, {0}, {0}, {0}
16761 "DXT1", 8, 1, 1, SUPPORT_DXT1,
16765 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '2'),
16766 {0}, {0}, {0}, {0}, {0}
16768 "DXT2", 16, 1, 1, SUPPORT_DXT2,
16772 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '3'),
16773 {0}, {0}, {0}, {0}, {0}
16775 "DXT3", 16, 1, 1, SUPPORT_DXT3,
16779 static const struct
16781 DWORD src_caps, dst_caps;
16783 test_caps[] =
16785 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY},
16786 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY},
16787 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY},
16788 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY},
16791 static const struct
16793 enum test_format_id src_format;
16794 const void *src_data;
16795 enum test_format_id dst_format;
16796 const void *expected_data;
16797 BOOL todo;
16799 tests[] =
16801 #if 0
16802 /* The following 3 tests give different results on AMD and NVIDIA on Windows, disabling. */
16803 {FMT_RGBX, rgbx_data, FMT_RGBA, rgba_data},
16804 {FMT_RGBA, rgba_data, FMT_RGBX, rgbx_data},
16805 {FMT_R5G5B5X1, r5g5b5x1_data, FMT_RGBA, rgba_data},
16806 #endif
16807 {FMT_R5G6B5, r5g6b5_data, FMT_RGBA, rgba_data},
16808 {FMT_R5G6B5, r5g6b5_data, FMT_R5G5B5A1, r5g5b5a1_data},
16809 {FMT_R5G5B5X1, r5g5b5x1_data, FMT_R5G5B5A1, r5g5b5x1_data, TRUE},
16810 {FMT_R5G5B5A1, r5g5b5a1_data, FMT_R5G6B5, r5g6b5_data},
16811 {FMT_RGBA, rgba_data, FMT_DXT1, dxt1_data},
16812 {FMT_RGBX, rgbx_data, FMT_DXT1, dxt1_data},
16813 {FMT_RGBA, rgba_data, FMT_DXT2, dxt2_data},
16814 {FMT_RGBX, rgbx_data, FMT_DXT2, dxt2_data},
16815 {FMT_RGBA, rgba_data, FMT_DXT3, dxt2_data},
16816 {FMT_RGBX, rgbx_data, FMT_DXT3, dxt2_data},
16817 {FMT_DXT1, dxt1_data, FMT_DXT2, dxt2_data},
16818 {FMT_DXT1, dxt1_data, FMT_RGBA, rgba_data},
16819 {FMT_DXT1, dxt1_data, FMT_RGBX, rgba_data},
16820 {FMT_DXT3, dxt2_data, FMT_RGBA, rgba_data},
16821 {FMT_DXT3, dxt2_data, FMT_RGBX, rgba_data},
16824 const struct test_format *src_format, *dst_format;
16825 IDirectDrawSurface7 *src_surf, *dst_surf;
16826 DDSURFACEDESC2 surface_desc, lock;
16827 unsigned int i, j, x, y, pitch;
16828 IDirect3DDevice7 *device;
16829 DWORD supported_fmts;
16830 IDirectDraw7 *ddraw;
16831 ULONG refcount;
16832 BOOL is_wine;
16833 HWND window;
16834 BOOL passed;
16835 HRESULT hr;
16837 window = create_window();
16838 if (!(device = create_device(window, DDSCL_NORMAL)))
16840 skip("Failed to create a 3D device, skipping test.\n");
16841 DestroyWindow(window);
16842 return;
16845 ddraw = create_ddraw();
16846 ok(!!ddraw, "Failed to create a ddraw object.\n");
16847 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
16848 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16850 hr = IDirect3DDevice7_EnumTextureFormats(device, test_block_formats_creation_cb,
16851 &supported_fmts);
16852 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16854 is_wine = !strcmp(winetest_platform, "wine");
16856 memset(&surface_desc, 0, sizeof(surface_desc));
16857 surface_desc.dwSize = sizeof(surface_desc);
16858 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
16859 surface_desc.dwWidth = 4;
16860 surface_desc.dwHeight = 4;
16862 for (i = 0; i < ARRAY_SIZE(tests); ++i)
16864 src_format = &formats[tests[i].src_format];
16865 dst_format = &formats[tests[i].dst_format];
16867 if (~supported_fmts & dst_format->support_flag)
16869 skip("%s format is not supported, skipping test %u.\n", dst_format->name, i);
16870 continue;
16872 if (~supported_fmts & src_format->support_flag)
16874 skip("%s format is not supported, skipping test %u.\n", src_format->name, i);
16875 continue;
16878 for (j = 0; j < ARRAY_SIZE(test_caps); ++j)
16880 if (!is_wine && ((test_caps[j].src_caps | test_caps[j].dst_caps) & DDSCAPS_SYSTEMMEMORY)
16881 && (src_format->broken_software_blit || dst_format->broken_software_blit))
16882 continue;
16883 if (!is_wine && (test_caps[j].dst_caps & DDSCAPS_VIDEOMEMORY)
16884 && dst_format->broken_hardware_blit)
16885 continue;
16887 U4(surface_desc).ddpfPixelFormat = src_format->fmt;
16888 surface_desc.ddsCaps.dwCaps = test_caps[j].src_caps;
16889 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surf, NULL);
16890 ok(hr == DD_OK, "Test (%u, %u), got unexpected hr %#x.\n", j, i, hr);
16892 U4(surface_desc).ddpfPixelFormat = dst_format->fmt;
16893 surface_desc.ddsCaps.dwCaps = test_caps[j].dst_caps;
16894 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surf, NULL);
16895 ok(hr == DD_OK, "Test (%u, %u), got unexpected hr %#x.\n", j, i, hr);
16897 memset(&lock, 0, sizeof(lock));
16898 lock.dwSize = sizeof(lock);
16899 hr = IDirectDrawSurface7_Lock(src_surf, NULL, &lock, 0, NULL);
16900 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16901 pitch = U1(lock).lPitch;
16902 for (y = 0; y < src_format->y_blocks; ++y)
16904 memcpy((BYTE *)lock.lpSurface + y * pitch,
16905 (BYTE *)tests[i].src_data + y * src_format->x_blocks * src_format->block_size,
16906 src_format->block_size * src_format->x_blocks);
16908 hr = IDirectDrawSurface7_Unlock(src_surf, NULL);
16909 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16911 hr = IDirectDrawSurface7_Blt(dst_surf, NULL, src_surf, NULL, DDBLT_WAIT, NULL);
16912 if (!is_wine && FAILED(hr))
16914 /* Some software blits are rejected on Windows. */
16915 IDirectDrawSurface7_Release(dst_surf);
16916 IDirectDrawSurface7_Release(src_surf);
16917 skip("Skipping test (%u, %u), cannot blit %s -> %s, hr %#x.\n", j, i,
16918 src_format->name, dst_format->name, hr);
16919 continue;
16921 ok(hr == DD_OK, "Test (%u, %s -> %s), got unexpected hr %#x.\n", j,
16922 src_format->name, dst_format->name, hr);
16924 memset(&lock, 0, sizeof(lock));
16925 lock.dwSize = sizeof(lock);
16926 hr = IDirectDrawSurface7_Lock(dst_surf, NULL, &lock, 0, NULL);
16927 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16928 pitch = U1(lock).lPitch;
16930 for (y = 0; y < dst_format->y_blocks; ++y)
16932 const void *expected_data = tests[i].expected_data;
16934 passed = !memcmp((BYTE*)lock.lpSurface + y * pitch,
16935 (BYTE *)expected_data + y * dst_format->x_blocks * dst_format->block_size,
16936 dst_format->block_size * dst_format->x_blocks);
16937 todo_wine_if(tests[i].todo)
16938 ok(passed, "Test (%u, %s -> %s), row %u, unexpected surface data.\n", j,
16939 src_format->name, dst_format->name, y);
16941 if (!passed && !(is_wine && tests[i].todo))
16943 for (x = 0; x < dst_format->x_blocks * dst_format->block_size / 4; ++x)
16945 trace("Test (%u, %u), x %u, y %u, got 0x%08x, expected 0x%08x.\n", j, i, x, y,
16946 *(unsigned int *)((BYTE *)lock.lpSurface + y * pitch + x * 4),
16947 *(unsigned int *)((BYTE *)expected_data + y * dst_format->x_blocks
16948 * dst_format->block_size + x * 4));
16951 if (!passed)
16952 break;
16954 hr = IDirectDrawSurface7_Unlock(dst_surf, NULL);
16955 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16957 IDirectDrawSurface7_Release(dst_surf);
16958 IDirectDrawSurface7_Release(src_surf);
16962 IDirect3DDevice7_Release(device);
16963 refcount = IDirectDraw7_Release(ddraw);
16964 ok(!refcount, "%u references left.\n", refcount);
16965 DestroyWindow(window);
16968 static void test_compressed_surface_stretch(void)
16970 static const struct
16972 unsigned int src_width, src_height;
16973 unsigned int dst_width, dst_height;
16974 unsigned int src_x, src_y;
16975 unsigned int dst_x, dst_y;
16976 BOOL todo_src, todo_dst;
16978 test_sizes[] =
16980 {4, 4, 8, 8},
16981 {8, 8, 4, 4},
16982 {4, 4, 2, 2, 0, 0, 0, 0, FALSE, TRUE},
16983 {4, 4, 6, 6, 0, 0, 0, 0, FALSE, TRUE},
16984 {4, 4, 8, 8, 2, 2, 2, 2, TRUE, TRUE},
16987 static const struct
16989 DWORD src_caps, dst_caps;
16991 test_caps[] =
16993 #if 0
16994 /* Broken on Windows. */
16995 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY},
16996 #endif
16997 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY},
16998 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY},
16999 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY},
17002 static struct
17004 DDPIXELFORMAT fmt;
17005 const char *name;
17006 DWORD support_flag;
17008 test_formats[] =
17012 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
17013 {16}, {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00008000}
17015 "R5G5B5A1",
17019 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
17020 {0}, {0}, {0}, {0}, {0}
17022 "DXT1", SUPPORT_DXT1,
17026 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '3'),
17027 {0}, {0}, {0}, {0}, {0}
17029 "DXT3", SUPPORT_DXT3,
17033 unsigned int i, j, k, l, x, y, pitch;
17034 DDSURFACEDESC2 rb_surface_desc, src_surface_desc, dst_surface_desc, lock;
17035 IDirectDrawSurface7 *src_surf, *dst_surf, *rb_surf;
17036 IDirect3DDevice7 *device;
17037 RECT src_rect, dst_rect;
17038 DWORD supported_fmts;
17039 unsigned short *data;
17040 IDirectDraw7 *ddraw;
17041 ULONG refcount;
17042 HWND window;
17043 BOOL passed;
17044 DDBLTFX fx;
17045 HRESULT hr;
17047 window = create_window();
17048 if (!(device = create_device(window, DDSCL_NORMAL)))
17050 skip("Failed to create a 3D device, skipping test.\n");
17051 DestroyWindow(window);
17052 return;
17055 ddraw = create_ddraw();
17056 ok(!!ddraw, "Failed to create a ddraw object.\n");
17057 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
17058 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17060 hr = IDirect3DDevice7_EnumTextureFormats(device, test_block_formats_creation_cb,
17061 &supported_fmts);
17062 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17064 memset(&src_surface_desc, 0, sizeof(src_surface_desc));
17065 src_surface_desc.dwSize = sizeof(src_surface_desc);
17066 src_surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
17067 dst_surface_desc = src_surface_desc;
17069 memset(&rb_surface_desc, 0, sizeof(rb_surface_desc));
17070 rb_surface_desc.dwSize = sizeof(rb_surface_desc);
17071 rb_surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
17072 U4(rb_surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(rb_surface_desc).ddpfPixelFormat);
17073 U4(rb_surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
17074 U1(U4(rb_surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
17075 U2(U4(rb_surface_desc).ddpfPixelFormat).dwRBitMask = 0x00007c00;
17076 U3(U4(rb_surface_desc).ddpfPixelFormat).dwGBitMask = 0x000003e0;
17077 U4(U4(rb_surface_desc).ddpfPixelFormat).dwBBitMask = 0x0000001f;
17078 U5(U4(rb_surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0x00008000;
17079 rb_surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
17081 memset(&fx, 0, sizeof(fx));
17082 fx.dwSize = sizeof(fx);
17084 memset(&lock, 0, sizeof(lock));
17085 lock.dwSize = sizeof(lock);
17087 for (i = 0; i < ARRAY_SIZE(test_caps); ++i)
17089 src_surface_desc.ddsCaps.dwCaps = test_caps[i].src_caps;
17090 dst_surface_desc.ddsCaps.dwCaps = test_caps[i].dst_caps;
17092 for (j = 0; j < ARRAY_SIZE(test_sizes); ++j)
17094 SetRect(&src_rect, test_sizes[j].src_x, test_sizes[j].src_y,
17095 test_sizes[j].src_width, test_sizes[j].src_height);
17096 SetRect(&dst_rect, test_sizes[j].dst_x, test_sizes[j].dst_y,
17097 test_sizes[j].dst_width, test_sizes[j].dst_height);
17099 src_surface_desc.dwWidth = test_sizes[j].src_width;
17100 src_surface_desc.dwHeight = test_sizes[j].src_height;
17102 dst_surface_desc.dwWidth = (test_sizes[j].dst_width + 3) & ~3;
17103 dst_surface_desc.dwHeight = (test_sizes[j].dst_height + 3) & ~3;
17105 rb_surface_desc.dwWidth = max(src_surface_desc.dwWidth, dst_surface_desc.dwWidth);
17106 rb_surface_desc.dwHeight = max(src_surface_desc.dwHeight, dst_surface_desc.dwHeight);
17108 hr = IDirectDraw7_CreateSurface(ddraw, &rb_surface_desc, &rb_surf, NULL);
17109 ok(hr == DD_OK, "Test (%u, %u), got unexpected hr %#x.\n", i, j, hr);
17111 for (k = 0; k < ARRAY_SIZE(test_formats); ++k)
17113 U4(src_surface_desc).ddpfPixelFormat = test_formats[k].fmt;
17114 hr = IDirectDraw7_CreateSurface(ddraw, &src_surface_desc, &src_surf, NULL);
17115 ok(hr == DD_OK, "Test (%u, %u, %u, %u), got unexpected hr %#x.\n", i, j, k, l, hr);
17117 U5(fx).dwFillColor = 0x801f;
17118 hr = IDirectDrawSurface7_Blt(rb_surf, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
17119 ok(hr == DD_OK, "Test (%u, %u, %u, %u), got unexpected hr %#x.\n", i, j, k, l, hr);
17121 hr = IDirectDrawSurface7_Blt(src_surf, &src_rect, rb_surf, &src_rect, DDBLT_WAIT, NULL);
17123 todo_wine_if(test_formats[k].fmt.dwFlags == DDPF_FOURCC && test_sizes[j].todo_src)
17124 ok(hr == DD_OK, "Test (%u, %u, %u, %u), got unexpected hr %#x.\n", i, j, k, l, hr);
17125 if (FAILED(hr))
17127 IDirectDrawSurface7_Release(src_surf);
17128 continue;
17131 for (l = 0; l < ARRAY_SIZE(test_formats); ++l)
17133 if (~supported_fmts & test_formats[l].support_flag)
17135 skip("%s format is not supported, skipping test %u.\n", test_formats[l].name, i);
17136 continue;
17139 U4(dst_surface_desc).ddpfPixelFormat = test_formats[l].fmt;
17141 hr = IDirectDraw7_CreateSurface(ddraw, &dst_surface_desc, &dst_surf, NULL);
17142 ok(hr == DD_OK, "Test (%u, %u, %u, %u), got unexpected hr %#x.\n", i, j, k, l, hr);
17144 hr = IDirectDrawSurface7_Blt(dst_surf, &dst_rect, src_surf, &src_rect, DDBLT_WAIT, NULL);
17145 todo_wine_if(test_formats[l].fmt.dwFlags == DDPF_FOURCC && test_sizes[j].todo_dst)
17146 ok(hr == DD_OK, "Test (%u, %u, %u, %u), got unexpected hr %#x.\n", i, j, k, l, hr);
17147 if (FAILED(hr))
17149 IDirectDrawSurface7_Release(dst_surf);
17150 continue;
17153 U5(fx).dwFillColor = 0xffffffff;
17154 hr = IDirectDrawSurface7_Blt(rb_surf, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
17155 ok(hr == DD_OK, "Test (%u, %u, %u, %u), got unexpected hr %#x.\n", i, j, k, l, hr);
17157 hr = IDirectDrawSurface7_Blt(rb_surf, &dst_rect, dst_surf, &dst_rect, DDBLT_WAIT, NULL);
17158 ok(hr == DD_OK, "Test (%u, %u, %u, %u), got unexpected hr %#x.\n", i, j, k, l, hr);
17159 hr = IDirectDrawSurface7_Lock(rb_surf, NULL, &lock, 0, NULL);
17160 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17161 pitch = U1(lock).lPitch;
17163 passed = TRUE;
17164 for (y = dst_rect.top; y < dst_rect.bottom && passed; ++y)
17166 data = (unsigned short *)((BYTE *)lock.lpSurface + y * pitch);
17168 for (x = dst_rect.left; x < dst_rect.right && passed; ++x)
17170 passed = data[x] == 0x801f;
17171 ok(passed, "Test (%u, %u, %u, %u), x %u, y %u, "
17172 "got unexpected colour 0x%04x.\n", i, j, k, l, x, y, data[x]);
17175 hr = IDirectDrawSurface7_Unlock(rb_surf, NULL);
17176 IDirectDrawSurface7_Release(dst_surf);
17178 IDirectDrawSurface7_Release(src_surf);
17180 IDirectDrawSurface7_Release(rb_surf);
17184 IDirect3DDevice7_Release(device);
17185 refcount = IDirectDraw7_Release(ddraw);
17186 ok(!refcount, "%u references left.\n", refcount);
17187 DestroyWindow(window);
17190 START_TEST(ddraw7)
17192 DDDEVICEIDENTIFIER2 identifier;
17193 HMODULE module, dwmapi;
17194 DEVMODEW current_mode;
17195 IDirectDraw7 *ddraw;
17197 module = GetModuleHandleA("ddraw.dll");
17198 if (!(pDirectDrawCreateEx = (void *)GetProcAddress(module, "DirectDrawCreateEx")))
17200 win_skip("DirectDrawCreateEx not available, skipping tests.\n");
17201 return;
17204 if (!(ddraw = create_ddraw()))
17206 skip("Failed to create a ddraw object, skipping tests.\n");
17207 return;
17210 if (ddraw_get_identifier(ddraw, &identifier))
17212 trace("Driver string: \"%s\"\n", identifier.szDriver);
17213 trace("Description string: \"%s\"\n", identifier.szDescription);
17214 trace("Driver version %d.%d.%d.%d\n",
17215 HIWORD(U(identifier.liDriverVersion).HighPart), LOWORD(U(identifier.liDriverVersion).HighPart),
17216 HIWORD(U(identifier.liDriverVersion).LowPart), LOWORD(U(identifier.liDriverVersion).LowPart));
17218 IDirectDraw7_Release(ddraw);
17220 memset(&current_mode, 0, sizeof(current_mode));
17221 current_mode.dmSize = sizeof(current_mode);
17222 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
17223 registry_mode.dmSize = sizeof(registry_mode);
17224 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
17225 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
17226 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
17228 skip("Current mode does not match registry mode, skipping test.\n");
17229 return;
17232 if ((dwmapi = LoadLibraryA("dwmapi.dll")))
17233 pDwmIsCompositionEnabled = (void *)GetProcAddress(dwmapi, "DwmIsCompositionEnabled");
17235 test_process_vertices();
17236 test_coop_level_create_device_window();
17237 test_clipper_blt();
17238 test_coop_level_d3d_state();
17239 test_surface_interface_mismatch();
17240 test_coop_level_threaded();
17241 test_depth_blit();
17242 test_texture_load_ckey();
17243 test_zenable();
17244 test_ck_rgba();
17245 test_ck_default();
17246 test_ck_complex();
17247 test_surface_qi();
17248 test_device_qi();
17249 test_wndproc();
17250 test_window_style();
17251 test_redundant_mode_set();
17252 test_coop_level_mode_set();
17253 test_coop_level_mode_set_multi();
17254 test_initialize();
17255 test_coop_level_surf_create();
17256 test_vb_discard();
17257 test_coop_level_multi_window();
17258 test_draw_strided();
17259 test_lighting();
17260 test_specular_lighting();
17261 test_clear_rect_count();
17262 test_coop_level_versions();
17263 test_fog_special();
17264 test_lighting_interface_versions();
17265 test_coop_level_activateapp();
17266 test_texturemanage();
17267 test_block_formats_creation();
17268 test_unsupported_formats();
17269 test_rt_caps();
17270 test_primary_caps();
17271 test_surface_lock();
17272 test_surface_discard();
17273 test_flip();
17274 test_set_surface_desc();
17275 test_user_memory_getdc();
17276 test_sysmem_overlay();
17277 test_primary_palette();
17278 test_surface_attachment();
17279 test_private_data();
17280 test_pixel_format();
17281 test_create_surface_pitch();
17282 test_mipmap();
17283 test_palette_complex();
17284 test_p8_blit();
17285 test_material();
17286 test_palette_gdi();
17287 test_palette_alpha();
17288 test_vb_writeonly();
17289 test_lost_device();
17290 test_resource_priority();
17291 test_surface_desc_lock();
17292 test_fog_interpolation();
17293 test_fog_process_vertices();
17294 test_negative_fixedfunction_fog();
17295 test_table_fog_zw();
17296 test_signed_formats();
17297 test_color_fill();
17298 test_texcoordindex();
17299 test_colorkey_precision();
17300 test_range_colorkey();
17301 test_shademode();
17302 test_lockrect_invalid();
17303 test_yv12_overlay();
17304 test_offscreen_overlay();
17305 test_overlay_rect();
17306 test_blt();
17307 test_blt_z_alpha();
17308 test_cross_device_blt();
17309 test_color_clamping();
17310 test_getdc();
17311 test_draw_primitive();
17312 test_edge_antialiasing_blending();
17313 test_display_mode_surface_pixel_format();
17314 test_surface_desc_size();
17315 test_get_surface_from_dc();
17316 test_ck_operation();
17317 test_vb_refcount();
17318 test_compute_sphere_visibility();
17319 test_clip_planes_limits();
17320 test_texture_stages_limits();
17321 test_set_render_state();
17322 test_map_synchronisation();
17323 test_depth_readback();
17324 test_clear();
17325 test_enum_surfaces();
17326 test_viewport();
17327 test_device_load();
17328 test_color_vertex();
17329 test_killfocus();
17330 test_sysmem_draw();
17331 test_gdi_surface();
17332 test_multiply_transform();
17333 test_alphatest();
17334 test_clipper_refcount();
17335 test_begin_end_state_block();
17336 test_caps();
17337 test_d32_support();
17338 test_surface_format_conversion_alpha();
17339 test_compressed_surface_stretch();