ddraw/tests: Add more managed texture tests.
[wine.git] / dlls / ddraw / tests / ddraw7.c
blob34ac5935fb8b129fa4546619cd28aa010f68491e
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_uint(unsigned int x, unsigned int y, unsigned int max_diff)
92 unsigned int diff = x > y ? x - y : y - x;
94 return diff <= max_diff;
97 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
99 return compare_uint(c1 & 0xff, c2 & 0xff, max_diff)
100 && compare_uint((c1 >> 8) & 0xff, (c2 >> 8) & 0xff, max_diff)
101 && compare_uint((c1 >> 16) & 0xff, (c2 >> 16) & 0xff, max_diff)
102 && compare_uint((c1 >> 24) & 0xff, (c2 >> 24) & 0xff, max_diff);
105 static ULONG get_refcount(IUnknown *iface)
107 IUnknown_AddRef(iface);
108 return IUnknown_Release(iface);
111 static BOOL ddraw_get_identifier(IDirectDraw7 *ddraw, DDDEVICEIDENTIFIER2 *identifier)
113 HRESULT hr;
115 hr = IDirectDraw7_GetDeviceIdentifier(ddraw, identifier, 0);
116 ok(SUCCEEDED(hr), "Failed to get device identifier, hr %#x.\n", hr);
118 return SUCCEEDED(hr);
121 static BOOL ddraw_is_warp(IDirectDraw7 *ddraw)
123 DDDEVICEIDENTIFIER2 identifier;
125 return strcmp(winetest_platform, "wine")
126 && ddraw_get_identifier(ddraw, &identifier)
127 && strstr(identifier.szDriver, "warp");
130 static BOOL ddraw_is_vendor(IDirectDraw7 *ddraw, DWORD vendor)
132 DDDEVICEIDENTIFIER2 identifier;
134 return strcmp(winetest_platform, "wine")
135 && ddraw_get_identifier(ddraw, &identifier)
136 && identifier.dwVendorId == vendor;
139 static BOOL ddraw_is_intel(IDirectDraw7 *ddraw)
141 return ddraw_is_vendor(ddraw, 0x8086);
144 static BOOL ddraw_is_nvidia(IDirectDraw7 *ddraw)
146 return ddraw_is_vendor(ddraw, 0x10de);
149 static BOOL ddraw_is_vmware(IDirectDraw7 *ddraw)
151 return ddraw_is_vendor(ddraw, 0x15ad);
154 static BOOL ddraw_is_amd(IDirectDraw7 *ddraw)
156 return ddraw_is_vendor(ddraw, 0x1002);
159 static IDirectDrawSurface7 *create_overlay(IDirectDraw7 *ddraw,
160 unsigned int width, unsigned int height, DWORD format)
162 IDirectDrawSurface7 *surface;
163 DDSURFACEDESC2 desc;
165 memset(&desc, 0, sizeof(desc));
166 desc.dwSize = sizeof(desc);
167 desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
168 desc.dwWidth = width;
169 desc.dwHeight = height;
170 desc.ddsCaps.dwCaps = DDSCAPS_OVERLAY;
171 U4(desc).ddpfPixelFormat.dwSize = sizeof(U4(desc).ddpfPixelFormat);
172 U4(desc).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
173 U4(desc).ddpfPixelFormat.dwFourCC = format;
175 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &desc, &surface, NULL)))
176 return NULL;
177 return surface;
180 static HWND create_window(void)
182 RECT r = {0, 0, 640, 480};
184 AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
186 return CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
187 CW_USEDEFAULT, CW_USEDEFAULT, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL);
190 static DWORD WINAPI create_window_thread_proc(void *param)
192 struct create_window_thread_param *p = param;
193 DWORD res;
194 BOOL ret;
196 p->window = create_window();
197 ret = SetEvent(p->window_created);
198 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
200 for (;;)
202 MSG msg;
204 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
205 DispatchMessageA(&msg);
206 res = WaitForSingleObject(p->destroy_window, 100);
207 if (res == WAIT_OBJECT_0)
208 break;
209 if (res != WAIT_TIMEOUT)
211 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
212 break;
216 DestroyWindow(p->window);
218 return 0;
221 static void create_window_thread(struct create_window_thread_param *p)
223 DWORD res, tid;
225 p->window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
226 ok(!!p->window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
227 p->destroy_window = CreateEventA(NULL, FALSE, FALSE, NULL);
228 ok(!!p->destroy_window, "CreateEvent failed, last error %#x.\n", GetLastError());
229 p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
230 ok(!!p->thread, "Failed to create thread, last error %#x.\n", GetLastError());
231 res = WaitForSingleObject(p->window_created, INFINITE);
232 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
235 static void destroy_window_thread(struct create_window_thread_param *p)
237 SetEvent(p->destroy_window);
238 WaitForSingleObject(p->thread, INFINITE);
239 CloseHandle(p->destroy_window);
240 CloseHandle(p->window_created);
241 CloseHandle(p->thread);
244 static IDirectDrawSurface7 *get_depth_stencil(IDirect3DDevice7 *device)
246 IDirectDrawSurface7 *rt, *ret;
247 DDSCAPS2 caps = {DDSCAPS_ZBUFFER, 0, 0, {0}};
248 HRESULT hr;
250 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
251 ok(SUCCEEDED(hr), "Failed to get the render target, hr %#x.\n", hr);
252 hr = IDirectDrawSurface7_GetAttachedSurface(rt, &caps, &ret);
253 ok(SUCCEEDED(hr) || hr == DDERR_NOTFOUND, "Failed to get the z buffer, hr %#x.\n", hr);
254 IDirectDrawSurface7_Release(rt);
255 return ret;
258 static HRESULT set_display_mode(IDirectDraw7 *ddraw, DWORD width, DWORD height)
260 if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
261 return DD_OK;
262 return IDirectDraw7_SetDisplayMode(ddraw, width, height, 24, 0, 0);
265 static D3DCOLOR get_surface_color(IDirectDrawSurface7 *surface, UINT x, UINT y)
267 RECT rect = {x, y, x + 1, y + 1};
268 DDSURFACEDESC2 surface_desc;
269 D3DCOLOR color;
270 HRESULT hr;
272 memset(&surface_desc, 0, sizeof(surface_desc));
273 surface_desc.dwSize = sizeof(surface_desc);
275 hr = IDirectDrawSurface7_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY, NULL);
276 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
277 if (FAILED(hr))
278 return 0xdeadbeef;
280 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
282 hr = IDirectDrawSurface7_Unlock(surface, &rect);
283 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
285 return color;
288 #define check_rect(a, b, c) check_rect_(__LINE__, a, b, c)
289 static void check_rect_(unsigned int line, IDirectDrawSurface7 *surface, RECT r, const char *message)
291 LONG x_coords[2][2] =
293 {r.left - 1, r.left + 1},
294 {r.right + 1, r.right - 1},
296 LONG y_coords[2][2] =
298 {r.top - 1, r.top + 1},
299 {r.bottom + 1, r.bottom - 1}
301 unsigned int i, j, x_side, y_side;
302 DWORD color;
303 LONG x, y;
305 for (i = 0; i < 2; ++i)
307 for (j = 0; j < 2; ++j)
309 for (x_side = 0; x_side < 2; ++x_side)
311 for (y_side = 0; y_side < 2; ++y_side)
313 DWORD expected = (x_side == 1 && y_side == 1) ? 0x00ffffff : 0x00000000;
315 x = x_coords[i][x_side];
316 y = y_coords[j][y_side];
317 if (x < 0 || x >= 640 || y < 0 || y >= 480)
318 continue;
319 color = get_surface_color(surface, x, y);
320 ok_(__FILE__, line)(color == expected, "%s: Pixel (%d, %d) has color %08x, expected %08x.\n",
321 message, x, y, color, expected);
328 static HRESULT CALLBACK enum_z_fmt(DDPIXELFORMAT *format, void *ctx)
330 DDPIXELFORMAT *z_fmt = ctx;
332 if (U1(*format).dwZBufferBitDepth > U1(*z_fmt).dwZBufferBitDepth)
333 *z_fmt = *format;
335 return DDENUMRET_OK;
338 static IDirectDraw7 *create_ddraw(void)
340 IDirectDraw7 *ddraw;
342 if (FAILED(pDirectDrawCreateEx(NULL, (void **)&ddraw, &IID_IDirectDraw7, NULL)))
343 return NULL;
345 return ddraw;
348 static HRESULT WINAPI enum_devtype_cb(char *desc_str, char *name, D3DDEVICEDESC7 *desc, void *ctx)
350 BOOL *hal_ok = ctx;
351 if (IsEqualGUID(&desc->deviceGUID, &IID_IDirect3DTnLHalDevice))
353 *hal_ok = TRUE;
354 return DDENUMRET_CANCEL;
356 return DDENUMRET_OK;
359 static IDirect3DDevice7 *create_device(HWND window, DWORD coop_level)
361 IDirectDrawSurface7 *surface, *ds;
362 IDirect3DDevice7 *device = NULL;
363 DDSURFACEDESC2 surface_desc;
364 DDPIXELFORMAT z_fmt;
365 IDirectDraw7 *ddraw;
366 IDirect3D7 *d3d7;
367 HRESULT hr;
368 BOOL hal_ok = FALSE;
369 const GUID *devtype = &IID_IDirect3DHALDevice;
371 if (!(ddraw = create_ddraw()))
372 return NULL;
374 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, coop_level);
375 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
377 memset(&surface_desc, 0, sizeof(surface_desc));
378 surface_desc.dwSize = sizeof(surface_desc);
379 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
380 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
381 surface_desc.dwWidth = 640;
382 surface_desc.dwHeight = 480;
384 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
385 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
387 if (coop_level & DDSCL_NORMAL)
389 IDirectDrawClipper *clipper;
391 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
392 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
393 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
394 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
395 hr = IDirectDrawSurface7_SetClipper(surface, clipper);
396 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\n", hr);
397 IDirectDrawClipper_Release(clipper);
400 hr = IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d7);
401 IDirectDraw7_Release(ddraw);
402 if (FAILED(hr))
404 IDirectDrawSurface7_Release(surface);
405 return NULL;
408 hr = IDirect3D7_EnumDevices(d3d7, enum_devtype_cb, &hal_ok);
409 ok(SUCCEEDED(hr), "Failed to enumerate devices, hr %#x.\n", hr);
410 if (hal_ok) devtype = &IID_IDirect3DTnLHalDevice;
412 memset(&z_fmt, 0, sizeof(z_fmt));
413 hr = IDirect3D7_EnumZBufferFormats(d3d7, devtype, enum_z_fmt, &z_fmt);
414 if (FAILED(hr) || !z_fmt.dwSize)
416 IDirect3D7_Release(d3d7);
417 IDirectDrawSurface7_Release(surface);
418 return NULL;
421 memset(&surface_desc, 0, sizeof(surface_desc));
422 surface_desc.dwSize = sizeof(surface_desc);
423 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
424 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
425 U4(surface_desc).ddpfPixelFormat = z_fmt;
426 surface_desc.dwWidth = 640;
427 surface_desc.dwHeight = 480;
428 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL);
429 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
430 if (FAILED(hr))
432 IDirect3D7_Release(d3d7);
433 IDirectDrawSurface7_Release(surface);
434 return NULL;
437 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
438 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
439 IDirectDrawSurface7_Release(ds);
440 if (FAILED(hr))
442 IDirect3D7_Release(d3d7);
443 IDirectDrawSurface7_Release(surface);
444 return NULL;
447 hr = IDirect3D7_CreateDevice(d3d7, devtype, surface, &device);
448 IDirect3D7_Release(d3d7);
449 IDirectDrawSurface7_Release(surface);
450 if (FAILED(hr))
451 return NULL;
453 return device;
456 struct message
458 UINT message;
459 BOOL check_wparam;
460 WPARAM expect_wparam;
461 HRESULT ddraw_state;
464 static const struct message *expect_messages;
465 static IDirectDraw7 *focus_test_ddraw;
467 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
469 HRESULT hr;
471 if (expect_messages && message == expect_messages->message)
473 if (expect_messages->check_wparam)
474 ok (wparam == expect_messages->expect_wparam,
475 "Got unexpected wparam %lx for message %x, expected %lx.\n",
476 wparam, message, expect_messages->expect_wparam);
478 if (focus_test_ddraw)
480 hr = IDirectDraw7_TestCooperativeLevel(focus_test_ddraw);
481 ok(hr == expect_messages->ddraw_state, "Got ddraw state %#x on message %#x, expected %#x.\n",
482 hr, message, expect_messages->ddraw_state);
485 ++expect_messages;
488 return DefWindowProcA(hwnd, message, wparam, lparam);
491 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
492 * interface. This prevents subsequent SetCooperativeLevel() calls on a
493 * different window from failing with DDERR_HWNDALREADYSET. */
494 static void fix_wndproc(HWND window, LONG_PTR proc)
496 IDirectDraw7 *ddraw;
497 HRESULT hr;
499 if (!(ddraw = create_ddraw()))
500 return;
502 SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
503 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
504 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
505 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
506 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
508 IDirectDraw7_Release(ddraw);
511 static void test_process_vertices(void)
513 IDirect3DVertexBuffer7 *src_vb, *dst_vb1, *dst_vb2;
514 D3DVERTEXBUFFERDESC vb_desc;
515 IDirect3DDevice7 *device;
516 struct vec4 *dst_data;
517 struct vec3 *dst_data2;
518 struct vec3 *src_data;
519 IDirect3D7 *d3d7;
520 D3DVIEWPORT7 vp;
521 HWND window;
522 HRESULT hr;
524 static D3DMATRIX world =
526 0.0f, 1.0f, 0.0f, 0.0f,
527 1.0f, 0.0f, 0.0f, 0.0f,
528 0.0f, 0.0f, 0.0f, 1.0f,
529 0.0f, 1.0f, 1.0f, 1.0f,
531 static D3DMATRIX view =
533 2.0f, 0.0f, 0.0f, 0.0f,
534 0.0f, -1.0f, 0.0f, 0.0f,
535 0.0f, 0.0f, 1.0f, 0.0f,
536 0.0f, 0.0f, 0.0f, 3.0f,
538 static D3DMATRIX proj =
540 1.0f, 0.0f, 0.0f, 1.0f,
541 0.0f, 1.0f, 1.0f, 0.0f,
542 0.0f, 1.0f, 1.0f, 0.0f,
543 1.0f, 0.0f, 0.0f, 1.0f,
546 window = create_window();
547 if (!(device = create_device(window, DDSCL_NORMAL)))
549 skip("Failed to create a 3D device, skipping test.\n");
550 DestroyWindow(window);
551 return;
554 hr = IDirect3DDevice7_GetDirect3D(device, &d3d7);
555 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
557 memset(&vb_desc, 0, sizeof(vb_desc));
558 vb_desc.dwSize = sizeof(vb_desc);
559 vb_desc.dwFVF = D3DFVF_XYZ;
560 vb_desc.dwNumVertices = 4;
561 hr = IDirect3D7_CreateVertexBuffer(d3d7, &vb_desc, &src_vb, 0);
562 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
564 hr = IDirect3DVertexBuffer7_Lock(src_vb, 0, (void **)&src_data, NULL);
565 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
566 src_data[0].x = 0.0f;
567 src_data[0].y = 0.0f;
568 src_data[0].z = 0.0f;
569 src_data[1].x = 1.0f;
570 src_data[1].y = 1.0f;
571 src_data[1].z = 1.0f;
572 src_data[2].x = -1.0f;
573 src_data[2].y = -1.0f;
574 src_data[2].z = 0.5f;
575 src_data[3].x = 0.5f;
576 src_data[3].y = -0.5f;
577 src_data[3].z = 0.25f;
578 hr = IDirect3DVertexBuffer7_Unlock(src_vb);
579 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
581 memset(&vb_desc, 0, sizeof(vb_desc));
582 vb_desc.dwSize = sizeof(vb_desc);
583 vb_desc.dwFVF = D3DFVF_XYZRHW;
584 vb_desc.dwNumVertices = 4;
585 /* MSDN says that the last parameter must be 0 - check that. */
586 hr = IDirect3D7_CreateVertexBuffer(d3d7, &vb_desc, &dst_vb1, 4);
587 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
589 memset(&vb_desc, 0, sizeof(vb_desc));
590 vb_desc.dwSize = sizeof(vb_desc);
591 vb_desc.dwFVF = D3DFVF_XYZ;
592 vb_desc.dwNumVertices = 5;
593 /* MSDN says that the last parameter must be 0 - check that. */
594 hr = IDirect3D7_CreateVertexBuffer(d3d7, &vb_desc, &dst_vb2, 12345678);
595 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
597 memset(&vp, 0, sizeof(vp));
598 vp.dwX = 64;
599 vp.dwY = 64;
600 vp.dwWidth = 128;
601 vp.dwHeight = 128;
602 vp.dvMinZ = 0.0f;
603 vp.dvMaxZ = 1.0f;
604 hr = IDirect3DDevice7_SetViewport(device, &vp);
605 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
607 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
608 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
609 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb2, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
610 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
612 hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
613 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
614 ok(compare_vec4(&dst_data[0], +1.280e+2f, +1.280e+2f, +0.000e+0f, +1.000e+0f, 4096),
615 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
616 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
617 ok(compare_vec4(&dst_data[1], +1.920e+2f, +6.400e+1f, +1.000e+0f, +1.000e+0f, 4096),
618 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
619 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
620 ok(compare_vec4(&dst_data[2], +6.400e+1f, +1.920e+2f, +5.000e-1f, +1.000e+0f, 4096),
621 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
622 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
623 ok(compare_vec4(&dst_data[3], +1.600e+2f, +1.600e+2f, +2.500e-1f, +1.000e+0f, 4096),
624 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
625 dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
626 hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
627 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
629 hr = IDirect3DVertexBuffer7_Lock(dst_vb2, 0, (void **)&dst_data2, NULL);
630 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
631 /* Small thing without much practical meaning, but I stumbled upon it,
632 * so let's check for it: If the output vertex buffer has no RHW value,
633 * the RHW value of the last vertex is written into the next vertex. */
634 ok(compare_vec3(&dst_data2[4], +1.000e+0f, +0.000e+0f, +0.000e+0f, 4096),
635 "Got unexpected vertex 4 {%.8e, %.8e, %.8e}.\n",
636 dst_data2[4].x, dst_data2[4].y, dst_data2[4].z);
637 hr = IDirect3DVertexBuffer7_Unlock(dst_vb2);
638 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
640 /* Test degenerate viewport z ranges. */
641 vp.dvMinZ = 0.0f;
642 vp.dvMaxZ = 0.0f;
643 hr = IDirect3DDevice7_SetViewport(device, &vp);
644 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
646 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
647 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
648 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb2, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
649 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
651 hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
652 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
653 ok(compare_vec4(&dst_data[0], +1.280e+2f, +1.280e+2f, +0.000e+0f, +1.000e+0f, 4096),
654 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
655 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
656 ok(compare_vec4(&dst_data[1], +1.920e+2f, +6.400e+1f, +1.000e-3f, +1.000e+0f, 4096),
657 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
658 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
659 ok(compare_vec4(&dst_data[2], +6.400e+1f, +1.920e+2f, +5.000e-4f, +1.000e+0f, 4096),
660 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
661 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
662 ok(compare_vec4(&dst_data[3], +1.600e+2f, +1.600e+2f, +2.500e-4f, +1.000e+0f, 4096),
663 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
664 dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
665 hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
666 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
668 vp.dvMinZ = 1.0f;
669 vp.dvMaxZ = 0.0f;
670 hr = IDirect3DDevice7_SetViewport(device, &vp);
671 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
673 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
674 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
675 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb2, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
676 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
678 hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
679 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
680 ok(compare_vec4(&dst_data[0], +1.280e+2f, +1.280e+2f, +1.000e+0f, +1.000e+0f, 4096),
681 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
682 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
683 ok(compare_vec4(&dst_data[1], +1.920e+2f, +6.400e+1f, +1.001e+0f, +1.000e+0f, 4096),
684 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
685 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
686 ok(compare_vec4(&dst_data[2], +6.400e+1f, +1.920e+2f, +1.0005e+0f, +1.000e+0f, 4096),
687 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
688 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
689 ok(compare_vec4(&dst_data[3], +1.600e+2f, +1.600e+2f, +1.00025e+0f, +1.000e+0f, 4096),
690 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
691 dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
692 hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
693 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
695 /* Try a more complicated viewport, same vertices. */
696 memset(&vp, 0, sizeof(vp));
697 vp.dwX = 10;
698 vp.dwY = 5;
699 vp.dwWidth = 246;
700 vp.dwHeight = 130;
701 vp.dvMinZ = -2.0f;
702 vp.dvMaxZ = 4.0f;
703 hr = IDirect3DDevice7_SetViewport(device, &vp);
704 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
706 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
707 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
709 hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
710 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
711 ok(compare_vec4(&dst_data[0], +1.330e+2f, +7.000e+1f, -2.000e+0f, +1.000e+0f, 4096),
712 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
713 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
714 ok(compare_vec4(&dst_data[1], +2.560e+2f, +5.000e+0f, +4.000e+0f, +1.000e+0f, 4096),
715 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
716 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
717 ok(compare_vec4(&dst_data[2], +1.000e+1f, +1.350e+2f, +1.000e+0f, +1.000e+0f, 4096),
718 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
719 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
720 ok(compare_vec4(&dst_data[3], +1.945e+2f, +1.025e+2f, -5.000e-1f, +1.000e+0f, 4096),
721 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
722 dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
723 hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
724 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
726 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &world);
727 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
728 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &view);
729 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
730 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &proj);
731 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
733 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
734 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
736 hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
737 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
738 ok(compare_vec4(&dst_data[0], +2.560e+2f, +7.000e+1f, -2.000e+0f, +3.333e-1f, 4096),
739 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
740 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
741 ok(compare_vec4(&dst_data[1], +2.560e+2f, +7.813e+1f, -2.750e+0f, +1.250e-1f, 4096),
742 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
743 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
744 ok(compare_vec4(&dst_data[2], +2.560e+2f, +4.400e+1f, +4.000e-1f, +4.000e-1f, 4096),
745 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
746 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
747 ok(compare_vec4(&dst_data[3], +2.560e+2f, +8.182e+1f, -3.091e+0f, +3.636e-1f, 4096),
748 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
749 dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
750 hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
751 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
753 IDirect3DVertexBuffer7_Release(dst_vb2);
754 IDirect3DVertexBuffer7_Release(dst_vb1);
755 IDirect3DVertexBuffer7_Release(src_vb);
756 IDirect3D7_Release(d3d7);
757 IDirect3DDevice7_Release(device);
758 DestroyWindow(window);
761 static void test_coop_level_create_device_window(void)
763 HWND focus_window, device_window;
764 IDirectDraw7 *ddraw;
765 HRESULT hr;
767 focus_window = create_window();
768 ddraw = create_ddraw();
769 ok(!!ddraw, "Failed to create a ddraw object.\n");
771 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
772 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
773 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
774 ok(!device_window, "Unexpected device window found.\n");
775 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
776 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
777 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
778 ok(!device_window, "Unexpected device window found.\n");
779 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
780 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
781 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
782 ok(!device_window, "Unexpected device window found.\n");
783 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
784 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
785 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
786 ok(!device_window, "Unexpected device window found.\n");
787 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
788 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
789 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
790 ok(!device_window, "Unexpected device window found.\n");
792 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
793 if (broken(hr == DDERR_INVALIDPARAMS))
795 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
796 IDirectDraw7_Release(ddraw);
797 DestroyWindow(focus_window);
798 return;
801 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
802 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
803 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
804 ok(!device_window, "Unexpected device window found.\n");
805 hr = IDirectDraw7_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
806 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
807 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
808 ok(!device_window, "Unexpected device window found.\n");
810 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
811 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
812 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
813 ok(!device_window, "Unexpected device window found.\n");
814 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
815 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
816 ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
817 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
818 ok(!!device_window, "Device window not found.\n");
820 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
821 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
822 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
823 ok(!device_window, "Unexpected device window found.\n");
824 hr = IDirectDraw7_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
825 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
826 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
827 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
828 ok(!!device_window, "Device window not found.\n");
830 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
831 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
832 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
833 ok(!device_window, "Unexpected device window found.\n");
834 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
835 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
836 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
837 ok(!device_window, "Unexpected device window found.\n");
838 hr = IDirectDraw7_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
839 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
840 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
841 ok(!device_window, "Unexpected device window found.\n");
842 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
843 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
844 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
845 ok(!!device_window, "Device window not found.\n");
847 IDirectDraw7_Release(ddraw);
848 DestroyWindow(focus_window);
851 static void test_clipper_blt(void)
853 IDirectDrawSurface7 *src_surface, *dst_surface;
854 RECT client_rect, src_rect;
855 IDirectDrawClipper *clipper;
856 DDSURFACEDESC2 surface_desc;
857 unsigned int i, j, x, y;
858 IDirectDraw7 *ddraw;
859 RGNDATA *rgn_data;
860 D3DCOLOR color;
861 ULONG refcount;
862 HRGN r1, r2;
863 HWND window;
864 DDBLTFX fx;
865 HRESULT hr;
866 DWORD *ptr;
867 DWORD ret;
869 static const DWORD src_data[] =
871 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
872 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
873 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
875 static const D3DCOLOR expected1[] =
877 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
878 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
879 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
880 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
882 /* Nvidia on Windows seems to have an off-by-one error
883 * when processing source rectangles. Our left = 1 and
884 * right = 5 input reads from x = {1, 2, 3}. x = 4 is
885 * read as well, but only for the edge pixels on the
886 * output image. The bug happens on the y axis as well,
887 * but we only read one row there, and all source rows
888 * contain the same data. This bug is not dependent on
889 * the presence of a clipper. */
890 static const D3DCOLOR expected1_broken[] =
892 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
893 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
894 0x00000000, 0x00000000, 0x00ff0000, 0x00ff0000,
895 0x00000000, 0x00000000, 0x0000ff00, 0x00ff0000,
897 static const D3DCOLOR expected2[] =
899 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
900 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
901 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
902 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
905 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
906 10, 10, 640, 480, 0, 0, 0, 0);
907 ShowWindow(window, SW_SHOW);
908 ddraw = create_ddraw();
909 ok(!!ddraw, "Failed to create a ddraw object.\n");
911 ret = GetClientRect(window, &client_rect);
912 ok(ret, "Failed to get client rect.\n");
913 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
914 ok(ret, "Failed to map client rect.\n");
916 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
917 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
919 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
920 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
921 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
922 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
923 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
924 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
925 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
926 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
927 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
928 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
929 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
930 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
931 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
932 ok(rgn_data->rdh.nCount >= 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
933 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
934 "Got unexpected bounding rect %s, expected %s.\n",
935 wine_dbgstr_rect(&rgn_data->rdh.rcBound), wine_dbgstr_rect(&client_rect));
936 HeapFree(GetProcessHeap(), 0, rgn_data);
938 r1 = CreateRectRgn(0, 0, 320, 240);
939 ok(!!r1, "Failed to create region.\n");
940 r2 = CreateRectRgn(320, 240, 640, 480);
941 ok(!!r2, "Failed to create region.\n");
942 CombineRgn(r1, r1, r2, RGN_OR);
943 ret = GetRegionData(r1, 0, NULL);
944 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
945 ret = GetRegionData(r1, ret, rgn_data);
946 ok(!!ret, "Failed to get region data.\n");
948 DeleteObject(r2);
949 DeleteObject(r1);
951 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
952 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
953 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
954 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
955 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
956 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
958 HeapFree(GetProcessHeap(), 0, rgn_data);
960 memset(&surface_desc, 0, sizeof(surface_desc));
961 surface_desc.dwSize = sizeof(surface_desc);
962 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
963 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
964 surface_desc.dwWidth = 640;
965 surface_desc.dwHeight = 480;
966 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
967 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
968 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
969 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
970 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
971 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
973 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
974 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
975 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
976 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
978 memset(&fx, 0, sizeof(fx));
979 fx.dwSize = sizeof(fx);
980 hr = IDirectDrawSurface7_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
981 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
982 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
983 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
985 hr = IDirectDrawSurface7_Lock(src_surface, NULL, &surface_desc, 0, NULL);
986 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
987 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
988 ptr = surface_desc.lpSurface;
989 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
990 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
991 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
992 hr = IDirectDrawSurface7_Unlock(src_surface, NULL);
993 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
995 hr = IDirectDrawSurface7_SetClipper(dst_surface, clipper);
996 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
998 SetRect(&src_rect, 1, 1, 5, 2);
999 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
1000 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
1001 for (i = 0; i < 4; ++i)
1003 for (j = 0; j < 4; ++j)
1005 x = 80 * ((2 * j) + 1);
1006 y = 60 * ((2 * i) + 1);
1007 color = get_surface_color(dst_surface, x, y);
1008 ok(compare_color(color, expected1[i * 4 + j], 1)
1009 || broken(compare_color(color, expected1_broken[i * 4 + j], 1)),
1010 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
1014 U5(fx).dwFillColor = 0xff0000ff;
1015 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1016 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
1017 for (i = 0; i < 4; ++i)
1019 for (j = 0; j < 4; ++j)
1021 x = 80 * ((2 * j) + 1);
1022 y = 60 * ((2 * i) + 1);
1023 color = get_surface_color(dst_surface, x, y);
1024 ok(compare_color(color, expected2[i * 4 + j], 1),
1025 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
1029 hr = IDirectDrawSurface7_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
1030 ok(hr == DDERR_BLTFASTCANTCLIP, "Got unexpected hr %#x.\n", hr);
1032 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
1033 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
1034 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1035 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
1036 DestroyWindow(window);
1037 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1038 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
1039 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
1040 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
1041 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1042 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
1043 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
1044 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
1045 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1046 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
1047 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1048 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
1050 IDirectDrawSurface7_Release(dst_surface);
1051 IDirectDrawSurface7_Release(src_surface);
1052 refcount = IDirectDrawClipper_Release(clipper);
1053 ok(!refcount, "Clipper has %u references left.\n", refcount);
1054 IDirectDraw7_Release(ddraw);
1057 static void test_coop_level_d3d_state(void)
1059 IDirectDrawSurface7 *rt, *surface;
1060 IDirect3DDevice7 *device;
1061 IDirectDraw7 *ddraw;
1062 DDSURFACEDESC2 lock;
1063 IDirect3D7 *d3d;
1064 D3DCOLOR color;
1065 DDSCAPS2 caps;
1066 DWORD value;
1067 HWND window;
1068 HRESULT hr;
1070 static struct
1072 struct vec3 position;
1073 DWORD diffuse;
1075 quad[] =
1077 {{-1.0f, -1.0f, 0.1f}, 0x800000ff},
1078 {{-1.0f, 1.0f, 0.1f}, 0x800000ff},
1079 {{ 1.0f, -1.0f, 0.1f}, 0x800000ff},
1080 {{ 1.0f, 1.0f, 0.1f}, 0x800000ff},
1083 window = create_window();
1084 if (!(device = create_device(window, DDSCL_NORMAL)))
1086 skip("Failed to create a 3D device, skipping test.\n");
1087 DestroyWindow(window);
1088 return;
1091 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
1092 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1093 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1094 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1095 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_DESTALPHA);
1096 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1098 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1099 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1100 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
1101 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1102 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
1103 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
1104 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1105 ok(!value, "Got unexpected alpha blend enable state %#x.\n", value);
1106 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
1107 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1108 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
1109 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1110 color = get_surface_color(rt, 320, 240);
1111 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1113 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1114 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1115 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1116 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1117 IDirect3D7_Release(d3d);
1118 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1119 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1120 hr = IDirectDrawSurface7_IsLost(rt);
1121 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
1123 memset(&lock, 0, sizeof(lock));
1124 lock.dwSize = sizeof(lock);
1125 lock.lpSurface = (void *)0xdeadbeef;
1126 hr = IDirectDrawSurface7_Lock(rt, NULL, &lock, DDLOCK_READONLY, NULL);
1127 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
1128 ok(lock.lpSurface == (void *)0xdeadbeef, "Got unexpected lock.lpSurface %p.\n", lock.lpSurface);
1130 memset(&caps, 0, sizeof(caps));
1131 caps.dwCaps = DDSCAPS_ZBUFFER;
1132 hr = IDirectDrawSurface7_GetAttachedSurface(rt, &caps, &surface);
1133 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
1134 caps.dwCaps = DDSCAPS_FLIP;
1135 hr = IDirectDrawSurface7_GetAttachedSurface(rt, &caps, &surface);
1136 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
1138 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
1139 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1141 hr = IDirectDrawSurface7_Lock(rt, NULL, &lock, DDLOCK_READONLY, NULL);
1142 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1143 hr = IDirectDrawSurface7_Unlock(rt, NULL);
1144 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1146 caps.dwCaps = DDSCAPS_ZBUFFER;
1147 hr = IDirectDrawSurface7_GetAttachedSurface(rt, &caps, &surface);
1148 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1149 IDirectDrawSurface7_Release(surface);
1151 caps.dwCaps = DDSCAPS_FLIP;
1152 hr = IDirectDrawSurface7_GetAttachedSurface(rt, &caps, &surface);
1153 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
1155 IDirectDraw7_Release(ddraw);
1157 hr = IDirect3DDevice7_GetRenderTarget(device, &surface);
1158 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1159 ok(surface == rt, "Got unexpected surface %p.\n", surface);
1160 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
1161 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1162 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
1163 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
1164 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1165 ok(!!value, "Got unexpected alpha blend enable state %#x.\n", value);
1166 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff00ff00, 1.0f, 0);
1167 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1168 color = get_surface_color(rt, 320, 240);
1169 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1171 hr = IDirect3DDevice7_BeginScene(device);
1172 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1173 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
1174 D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, ARRAY_SIZE(quad), 0);
1175 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1176 hr = IDirect3DDevice7_EndScene(device);
1177 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1178 color = get_surface_color(rt, 320, 240);
1179 ok(compare_color(color, 0x0000ff80, 1), "Got unexpected color 0x%08x.\n", color);
1181 IDirectDrawSurface7_Release(surface);
1182 IDirectDrawSurface7_Release(rt);
1183 IDirect3DDevice7_Release(device);
1184 DestroyWindow(window);
1187 static void test_surface_interface_mismatch(void)
1189 IDirectDraw7 *ddraw = NULL;
1190 IDirect3D7 *d3d = NULL;
1191 IDirectDrawSurface7 *surface = NULL, *ds;
1192 IDirectDrawSurface3 *surface3 = NULL;
1193 IDirect3DDevice7 *device = NULL;
1194 DDSURFACEDESC2 surface_desc;
1195 DDPIXELFORMAT z_fmt;
1196 ULONG refcount;
1197 HRESULT hr;
1198 D3DCOLOR color;
1199 HWND window;
1201 window = create_window();
1202 ddraw = create_ddraw();
1203 ok(!!ddraw, "Failed to create a ddraw object.\n");
1204 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1205 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1207 memset(&surface_desc, 0, sizeof(surface_desc));
1208 surface_desc.dwSize = sizeof(surface_desc);
1209 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1210 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
1211 surface_desc.dwWidth = 640;
1212 surface_desc.dwHeight = 480;
1214 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1215 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1217 hr = IDirectDrawSurface7_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
1218 ok(SUCCEEDED(hr), "Failed to QI IDirectDrawSurface3, hr %#x.\n", hr);
1220 if (FAILED(IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d)))
1222 skip("D3D interface is not available, skipping test.\n");
1223 goto cleanup;
1226 memset(&z_fmt, 0, sizeof(z_fmt));
1227 hr = IDirect3D7_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
1228 if (FAILED(hr) || !z_fmt.dwSize)
1230 skip("No depth buffer formats available, skipping test.\n");
1231 goto cleanup;
1234 memset(&surface_desc, 0, sizeof(surface_desc));
1235 surface_desc.dwSize = sizeof(surface_desc);
1236 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
1237 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1238 U4(surface_desc).ddpfPixelFormat = z_fmt;
1239 surface_desc.dwWidth = 640;
1240 surface_desc.dwHeight = 480;
1241 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL);
1242 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
1243 if (FAILED(hr))
1244 goto cleanup;
1246 /* Using a different surface interface version still works */
1247 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
1248 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
1249 refcount = IDirectDrawSurface7_Release(ds);
1250 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
1251 if (FAILED(hr))
1252 goto cleanup;
1254 /* Here too */
1255 hr = IDirect3D7_CreateDevice(d3d, &IID_IDirect3DHALDevice, (IDirectDrawSurface7 *)surface3, &device);
1256 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
1257 if (FAILED(hr))
1258 goto cleanup;
1260 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
1261 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1262 color = get_surface_color(surface, 320, 240);
1263 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1265 cleanup:
1266 if (surface3) IDirectDrawSurface3_Release(surface3);
1267 if (surface) IDirectDrawSurface7_Release(surface);
1268 if (device) IDirect3DDevice7_Release(device);
1269 if (d3d) IDirect3D7_Release(d3d);
1270 if (ddraw) IDirectDraw7_Release(ddraw);
1271 DestroyWindow(window);
1274 static void test_coop_level_threaded(void)
1276 struct create_window_thread_param p;
1277 IDirectDraw7 *ddraw;
1278 HRESULT hr;
1280 ddraw = create_ddraw();
1281 ok(!!ddraw, "Failed to create a ddraw object.\n");
1282 create_window_thread(&p);
1284 hr = IDirectDraw7_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1285 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1287 destroy_window_thread(&p);
1288 IDirectDraw7_Release(ddraw);
1291 static void test_depth_blit(void)
1293 IDirect3DDevice7 *device;
1294 static struct
1296 float x, y, z;
1297 DWORD color;
1299 quad1[] =
1301 { -1.0, 1.0, 0.50f, 0xff00ff00},
1302 { 1.0, 1.0, 0.50f, 0xff00ff00},
1303 { -1.0, -1.0, 0.50f, 0xff00ff00},
1304 { 1.0, -1.0, 0.50f, 0xff00ff00},
1306 static const D3DCOLOR expected_colors[4][4] =
1308 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1309 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1310 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1311 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1313 DDSURFACEDESC2 ddsd_new, ddsd_existing;
1315 IDirectDrawSurface7 *ds1, *ds2, *ds3, *rt;
1316 RECT src_rect, dst_rect;
1317 unsigned int i, j;
1318 D3DCOLOR color;
1319 HRESULT hr;
1320 IDirect3D7 *d3d;
1321 IDirectDraw7 *ddraw;
1322 DDBLTFX fx;
1323 HWND window;
1325 window = create_window();
1326 if (!(device = create_device(window, DDSCL_NORMAL)))
1328 skip("Failed to create a 3D device, skipping test.\n");
1329 DestroyWindow(window);
1330 return;
1333 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1334 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
1335 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1336 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
1337 IDirect3D7_Release(d3d);
1339 ds1 = get_depth_stencil(device);
1341 memset(&ddsd_new, 0, sizeof(ddsd_new));
1342 ddsd_new.dwSize = sizeof(ddsd_new);
1343 memset(&ddsd_existing, 0, sizeof(ddsd_existing));
1344 ddsd_existing.dwSize = sizeof(ddsd_existing);
1345 hr = IDirectDrawSurface7_GetSurfaceDesc(ds1, &ddsd_existing);
1346 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
1347 ddsd_new.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1348 ddsd_new.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1349 ddsd_new.dwWidth = ddsd_existing.dwWidth;
1350 ddsd_new.dwHeight = ddsd_existing.dwHeight;
1351 U4(ddsd_new).ddpfPixelFormat = U4(ddsd_existing).ddpfPixelFormat;
1352 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd_new, &ds2, NULL);
1353 ok(SUCCEEDED(hr), "Failed to create a z buffer, hr %#x.\n", hr);
1354 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd_new, &ds3, NULL);
1355 ok(SUCCEEDED(hr), "Failed to create a z buffer, hr %#x.\n", hr);
1356 IDirectDraw7_Release(ddraw);
1358 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
1359 ok(SUCCEEDED(hr), "Failed to enable z testing, hr %#x.\n", hr);
1360 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
1361 ok(SUCCEEDED(hr), "Failed to set the z function, hr %#x.\n", hr);
1362 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
1363 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
1365 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
1366 ok(SUCCEEDED(hr), "Failed to clear the z buffer, hr %#x.\n", hr);
1368 /* Partial blit. */
1369 SetRect(&src_rect, 0, 0, 320, 240);
1370 SetRect(&dst_rect, 0, 0, 320, 240);
1371 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1372 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1373 /* Different locations. */
1374 SetRect(&src_rect, 0, 0, 320, 240);
1375 SetRect(&dst_rect, 320, 240, 640, 480);
1376 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1377 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1378 /* Stretched. */
1379 SetRect(&src_rect, 0, 0, 320, 240);
1380 SetRect(&dst_rect, 0, 0, 640, 480);
1381 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1382 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1383 /* Flipped. */
1384 SetRect(&src_rect, 0, 480, 640, 0);
1385 SetRect(&dst_rect, 0, 0, 640, 480);
1386 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1387 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1388 SetRect(&src_rect, 0, 0, 640, 480);
1389 SetRect(&dst_rect, 0, 480, 640, 0);
1390 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1391 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1392 /* Full, explicit. */
1393 SetRect(&src_rect, 0, 0, 640, 480);
1394 SetRect(&dst_rect, 0, 0, 640, 480);
1395 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1396 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1397 /* Depth -> color blit: Succeeds on Win7 + Radeon HD 5700, fails on WinXP + Radeon X1600 */
1399 /* Depth blit inside a BeginScene / EndScene pair */
1400 hr = IDirect3DDevice7_BeginScene(device);
1401 ok(SUCCEEDED(hr), "Failed to start scene, hr %#x.\n", hr);
1402 /* From the current depth stencil */
1403 hr = IDirectDrawSurface7_Blt(ds2, NULL, ds1, NULL, DDBLT_WAIT, NULL);
1404 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1405 /* To the current depth stencil */
1406 hr = IDirectDrawSurface7_Blt(ds1, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1407 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1408 /* Between unbound surfaces */
1409 hr = IDirectDrawSurface7_Blt(ds3, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1410 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1411 hr = IDirect3DDevice7_EndScene(device);
1412 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1414 /* Avoid changing the depth stencil, it doesn't work properly on Windows.
1415 * Instead use DDBLT_DEPTHFILL to clear the depth stencil. Unfortunately
1416 * drivers disagree on the meaning of dwFillDepth. Only 0 seems to produce
1417 * a reliable result(z = 0.0) */
1418 memset(&fx, 0, sizeof(fx));
1419 fx.dwSize = sizeof(fx);
1420 hr = IDirectDrawSurface7_Blt(ds2, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
1421 ok(SUCCEEDED(hr), "Failed to clear the source z buffer, hr %#x.\n", hr);
1423 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET, 0xffff0000, 1.0f, 0);
1424 ok(SUCCEEDED(hr), "Failed to clear the color and z buffers, hr %#x.\n", hr);
1425 SetRect(&dst_rect, 0, 0, 320, 240);
1426 hr = IDirectDrawSurface7_Blt(ds1, &dst_rect, ds2, NULL, DDBLT_WAIT, NULL);
1427 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1428 IDirectDrawSurface7_Release(ds3);
1429 IDirectDrawSurface7_Release(ds2);
1430 IDirectDrawSurface7_Release(ds1);
1432 hr = IDirect3DDevice7_BeginScene(device);
1433 ok(SUCCEEDED(hr), "Failed to start scene, hr %#x.\n", hr);
1434 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
1435 quad1, 4, 0);
1436 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1437 hr = IDirect3DDevice7_EndScene(device);
1438 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1440 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1441 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1442 for (i = 0; i < 4; ++i)
1444 for (j = 0; j < 4; ++j)
1446 unsigned int x = 80 * ((2 * j) + 1);
1447 unsigned int y = 60 * ((2 * i) + 1);
1448 color = get_surface_color(rt, x, y);
1449 ok(compare_color(color, expected_colors[i][j], 1),
1450 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
1454 IDirectDrawSurface7_Release(rt);
1455 IDirect3DDevice7_Release(device);
1456 DestroyWindow(window);
1459 static void test_texture_load_ckey(void)
1461 HWND window;
1462 IDirect3DDevice7 *device;
1463 IDirectDraw7 *ddraw;
1464 IDirectDrawSurface7 *src;
1465 IDirectDrawSurface7 *dst;
1466 DDSURFACEDESC2 ddsd;
1467 HRESULT hr;
1468 DDCOLORKEY ckey;
1469 IDirect3D7 *d3d;
1471 window = create_window();
1472 if (!(device = create_device(window, DDSCL_NORMAL)))
1474 skip("Failed to create a 3D device, skipping test.\n");
1475 DestroyWindow(window);
1476 return;
1479 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1480 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
1481 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1482 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
1483 IDirect3D7_Release(d3d);
1485 memset(&ddsd, 0, sizeof(ddsd));
1486 ddsd.dwSize = sizeof(ddsd);
1487 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
1488 ddsd.dwHeight = 128;
1489 ddsd.dwWidth = 128;
1490 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
1491 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &src, NULL);
1492 ok(SUCCEEDED(hr), "Failed to create source texture, hr %#x.\n", hr);
1493 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1494 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &dst, NULL);
1495 ok(SUCCEEDED(hr), "Failed to create destination texture, hr %#x.\n", hr);
1497 /* No surface has a color key */
1498 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1499 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1500 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0xdeadbeef;
1501 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1502 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1503 ok(ckey.dwColorSpaceLowValue == 0xdeadbeef, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1504 ok(ckey.dwColorSpaceHighValue == 0xdeadbeef, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1506 /* Source surface has a color key */
1507 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
1508 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
1509 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1510 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1511 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1512 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1513 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1514 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1515 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1517 /* Both surfaces have a color key: Dest ckey is overwritten */
1518 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x000000ff;
1519 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1520 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1521 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1522 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1523 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1524 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1525 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1526 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1528 /* Only the destination has a color key: It is deleted. This behavior differs from
1529 * IDirect3DTexture(2)::Load */
1530 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, NULL);
1531 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1532 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
1533 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1534 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1535 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1536 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1537 todo_wine ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1539 IDirectDrawSurface7_Release(dst);
1540 IDirectDrawSurface7_Release(src);
1541 IDirectDraw7_Release(ddraw);
1542 IDirect3DDevice7_Release(device);
1543 DestroyWindow(window);
1546 static void test_zenable(void)
1548 static struct
1550 struct vec4 position;
1551 D3DCOLOR diffuse;
1553 tquad[] =
1555 {{ 0.0f, 480.0f, -0.5f, 1.0f}, 0xff00ff00},
1556 {{ 0.0f, 0.0f, -0.5f, 1.0f}, 0xff00ff00},
1557 {{640.0f, 480.0f, 1.5f, 1.0f}, 0xff00ff00},
1558 {{640.0f, 0.0f, 1.5f, 1.0f}, 0xff00ff00},
1560 IDirect3DDevice7 *device;
1561 IDirectDrawSurface7 *rt;
1562 D3DCOLOR color;
1563 HWND window;
1564 HRESULT hr;
1565 UINT x, y;
1566 UINT i, j;
1568 window = create_window();
1569 if (!(device = create_device(window, DDSCL_NORMAL)))
1571 skip("Failed to create a 3D device, skipping test.\n");
1572 DestroyWindow(window);
1573 return;
1576 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1577 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
1579 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 0.0f, 0);
1580 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1581 hr = IDirect3DDevice7_BeginScene(device);
1582 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1583 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_DIFFUSE, tquad, 4, 0);
1584 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1585 hr = IDirect3DDevice7_EndScene(device);
1586 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1588 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1589 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1590 for (i = 0; i < 4; ++i)
1592 for (j = 0; j < 4; ++j)
1594 x = 80 * ((2 * j) + 1);
1595 y = 60 * ((2 * i) + 1);
1596 color = get_surface_color(rt, x, y);
1597 ok(compare_color(color, 0x0000ff00, 1),
1598 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1601 IDirectDrawSurface7_Release(rt);
1603 IDirect3DDevice7_Release(device);
1604 DestroyWindow(window);
1607 static void test_ck_rgba(void)
1609 static struct
1611 struct vec4 position;
1612 struct vec2 texcoord;
1614 tquad[] =
1616 {{ 0.0f, 480.0f, 0.25f, 1.0f}, {0.0f, 0.0f}},
1617 {{ 0.0f, 0.0f, 0.25f, 1.0f}, {0.0f, 1.0f}},
1618 {{640.0f, 480.0f, 0.25f, 1.0f}, {1.0f, 0.0f}},
1619 {{640.0f, 0.0f, 0.25f, 1.0f}, {1.0f, 1.0f}},
1620 {{ 0.0f, 480.0f, 0.75f, 1.0f}, {0.0f, 0.0f}},
1621 {{ 0.0f, 0.0f, 0.75f, 1.0f}, {0.0f, 1.0f}},
1622 {{640.0f, 480.0f, 0.75f, 1.0f}, {1.0f, 0.0f}},
1623 {{640.0f, 0.0f, 0.75f, 1.0f}, {1.0f, 1.0f}},
1625 static const struct
1627 D3DCOLOR fill_color;
1628 BOOL color_key;
1629 BOOL blend;
1630 D3DCOLOR result1, result1_broken;
1631 D3DCOLOR result2, result2_broken;
1633 tests[] =
1635 /* r200 on Windows doesn't check the alpha component when applying the color
1636 * key, so the key matches on every texel. */
1637 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1638 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1639 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1640 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1641 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00ff0000, 0x00807f00, 0x000000ff},
1642 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x00ff0000, 0x0000ff00, 0x000000ff},
1643 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00, 0x00807f00, 0x00807f00},
1644 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1647 IDirectDrawSurface7 *texture;
1648 DDSURFACEDESC2 surface_desc;
1649 IDirect3DDevice7 *device;
1650 IDirectDrawSurface7 *rt;
1651 IDirectDraw7 *ddraw;
1652 IDirect3D7 *d3d;
1653 D3DCOLOR color;
1654 HWND window;
1655 DDBLTFX fx;
1656 HRESULT hr;
1657 UINT i;
1659 window = create_window();
1660 if (!(device = create_device(window, DDSCL_NORMAL)))
1662 skip("Failed to create a 3D device, skipping test.\n");
1663 DestroyWindow(window);
1664 return;
1667 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1668 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1669 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1670 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1671 IDirect3D7_Release(d3d);
1673 memset(&surface_desc, 0, sizeof(surface_desc));
1674 surface_desc.dwSize = sizeof(surface_desc);
1675 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1676 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1677 surface_desc.dwWidth = 256;
1678 surface_desc.dwHeight = 256;
1679 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1680 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1681 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1682 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1683 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1684 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1685 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1686 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1687 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1688 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
1689 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1691 hr = IDirect3DDevice7_SetTexture(device, 0, texture);
1692 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1693 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1694 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1695 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1696 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1698 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1699 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1701 for (i = 0; i < ARRAY_SIZE(tests); ++i)
1703 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1704 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1705 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1706 ok(SUCCEEDED(hr), "Failed to enable alpha blending, hr %#x.\n", hr);
1708 memset(&fx, 0, sizeof(fx));
1709 fx.dwSize = sizeof(fx);
1710 U5(fx).dwFillColor = tests[i].fill_color;
1711 hr = IDirectDrawSurface7_Blt(texture, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1712 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1714 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 1.0f, 0);
1715 ok(SUCCEEDED(hr), "Failed to clear render target, 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[0], 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 color = get_surface_color(rt, 320, 240);
1724 ok(compare_color(color, tests[i].result1, 1) || compare_color(color, tests[i].result1_broken, 1),
1725 "Expected color 0x%08x for test %u, got 0x%08x.\n",
1726 tests[i].result1, i, color);
1728 U5(fx).dwFillColor = 0xff0000ff;
1729 hr = IDirectDrawSurface7_Blt(texture, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1730 ok(SUCCEEDED(hr), "Failed to fill texture, hr %#x.\n", hr);
1732 hr = IDirect3DDevice7_BeginScene(device);
1733 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1734 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[4], 4, 0);
1735 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1736 hr = IDirect3DDevice7_EndScene(device);
1737 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1739 /* This tests that fragments that are masked out by the color key are
1740 * discarded, instead of just fully transparent. */
1741 color = get_surface_color(rt, 320, 240);
1742 ok(compare_color(color, tests[i].result2, 1) || compare_color(color, tests[i].result2_broken, 1),
1743 "Expected color 0x%08x for test %u, got 0x%08x.\n",
1744 tests[i].result2, i, color);
1747 IDirectDrawSurface7_Release(rt);
1748 IDirectDrawSurface7_Release(texture);
1749 IDirectDraw7_Release(ddraw);
1750 IDirect3DDevice7_Release(device);
1751 DestroyWindow(window);
1754 static void test_ck_default(void)
1756 static struct
1758 struct vec4 position;
1759 struct vec2 texcoord;
1761 tquad[] =
1763 {{ 0.0f, 480.0f, 0.0f, 1.0f}, {0.0f, 0.0f}},
1764 {{ 0.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 1.0f}},
1765 {{640.0f, 480.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
1766 {{640.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
1768 IDirectDrawSurface7 *surface, *rt;
1769 DDSURFACEDESC2 surface_desc;
1770 IDirect3DDevice7 *device;
1771 IDirectDraw7 *ddraw;
1772 IDirect3D7 *d3d;
1773 D3DCOLOR color;
1774 DWORD value;
1775 HWND window;
1776 DDBLTFX fx;
1777 HRESULT hr;
1779 window = create_window();
1780 if (!(device = create_device(window, DDSCL_NORMAL)))
1782 skip("Failed to create a 3D device, skipping test.\n");
1783 DestroyWindow(window);
1784 return;
1787 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1788 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1789 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1790 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1791 IDirect3D7_Release(d3d);
1793 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1794 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1796 memset(&surface_desc, 0, sizeof(surface_desc));
1797 surface_desc.dwSize = sizeof(surface_desc);
1798 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1799 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1800 surface_desc.dwWidth = 256;
1801 surface_desc.dwHeight = 256;
1802 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1803 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
1804 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1805 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1806 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1807 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1808 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
1809 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
1810 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1811 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1812 hr = IDirect3DDevice7_SetTexture(device, 0, surface);
1813 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
1815 memset(&fx, 0, sizeof(fx));
1816 fx.dwSize = sizeof(fx);
1817 U5(fx).dwFillColor = 0x000000ff;
1818 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1819 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
1821 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
1822 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1823 hr = IDirect3DDevice7_BeginScene(device);
1824 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1825 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1826 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1827 ok(!value, "Got unexpected color keying state %#x.\n", value);
1828 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1829 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
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, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
1835 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
1836 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1837 hr = IDirect3DDevice7_BeginScene(device);
1838 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
1839 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
1840 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
1841 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1842 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
1843 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
1844 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1845 ok(!!value, "Got unexpected color keying state %#x.\n", value);
1846 hr = IDirect3DDevice7_EndScene(device);
1847 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1848 color = get_surface_color(rt, 320, 240);
1849 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1851 IDirectDrawSurface7_Release(surface);
1852 IDirectDrawSurface7_Release(rt);
1853 IDirect3DDevice7_Release(device);
1854 IDirectDraw7_Release(ddraw);
1855 DestroyWindow(window);
1858 static void test_ck_complex(void)
1860 IDirectDrawSurface7 *surface, *mipmap, *tmp;
1861 D3DDEVICEDESC7 device_desc;
1862 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
1863 DDSURFACEDESC2 surface_desc;
1864 IDirect3DDevice7 *device;
1865 DDCOLORKEY color_key;
1866 IDirectDraw7 *ddraw;
1867 IDirect3D7 *d3d;
1868 unsigned int i;
1869 ULONG refcount;
1870 HWND window;
1871 HRESULT hr;
1873 window = create_window();
1874 if (!(device = create_device(window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
1876 skip("Failed to create a 3D device, skipping test.\n");
1877 DestroyWindow(window);
1878 return;
1880 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
1881 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
1882 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1883 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1884 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1885 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1886 IDirect3D7_Release(d3d);
1888 memset(&surface_desc, 0, sizeof(surface_desc));
1889 surface_desc.dwSize = sizeof(surface_desc);
1890 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1891 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1892 surface_desc.dwWidth = 128;
1893 surface_desc.dwHeight = 128;
1894 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1895 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1897 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1898 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1899 color_key.dwColorSpaceLowValue = 0x0000ff00;
1900 color_key.dwColorSpaceHighValue = 0x0000ff00;
1901 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1902 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1903 memset(&color_key, 0, sizeof(color_key));
1904 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1905 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1906 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1907 color_key.dwColorSpaceLowValue);
1908 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1909 color_key.dwColorSpaceHighValue);
1911 mipmap = surface;
1912 IDirectDrawSurface_AddRef(mipmap);
1913 for (i = 0; i < 7; ++i)
1915 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
1916 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
1917 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1918 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1920 color_key.dwColorSpaceLowValue = 0x000000ff;
1921 color_key.dwColorSpaceHighValue = 0x000000ff;
1922 hr = IDirectDrawSurface7_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1923 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x, i %u.\n", hr, i);
1925 IDirectDrawSurface_Release(mipmap);
1926 mipmap = tmp;
1929 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
1930 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
1931 IDirectDrawSurface_Release(mipmap);
1932 refcount = IDirectDrawSurface7_Release(surface);
1933 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1935 memset(&surface_desc, 0, sizeof(surface_desc));
1936 surface_desc.dwSize = sizeof(surface_desc);
1937 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
1938 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
1939 U5(surface_desc).dwBackBufferCount = 1;
1940 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1941 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1943 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1944 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1945 color_key.dwColorSpaceLowValue = 0x0000ff00;
1946 color_key.dwColorSpaceHighValue = 0x0000ff00;
1947 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1948 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1949 memset(&color_key, 0, sizeof(color_key));
1950 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1951 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1952 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1953 color_key.dwColorSpaceLowValue);
1954 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1955 color_key.dwColorSpaceHighValue);
1957 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &tmp);
1958 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
1960 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1961 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
1962 color_key.dwColorSpaceLowValue = 0x0000ff00;
1963 color_key.dwColorSpaceHighValue = 0x0000ff00;
1964 hr = IDirectDrawSurface7_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1965 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1966 memset(&color_key, 0, sizeof(color_key));
1967 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
1968 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
1969 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1970 color_key.dwColorSpaceLowValue);
1971 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
1972 color_key.dwColorSpaceHighValue);
1974 IDirectDrawSurface_Release(tmp);
1976 refcount = IDirectDrawSurface7_Release(surface);
1977 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
1979 if (!(device_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP))
1981 skip("Device does not support cubemaps.\n");
1982 goto cleanup;
1984 memset(&surface_desc, 0, sizeof(surface_desc));
1985 surface_desc.dwSize = sizeof(surface_desc);
1986 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1987 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1988 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
1989 surface_desc.dwWidth = 128;
1990 surface_desc.dwHeight = 128;
1991 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1992 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1994 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1995 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1996 color_key.dwColorSpaceLowValue = 0x0000ff00;
1997 color_key.dwColorSpaceHighValue = 0x0000ff00;
1998 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
1999 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
2001 caps.dwCaps2 = DDSCAPS2_CUBEMAP_NEGATIVEZ;
2002 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
2003 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
2005 hr = IDirectDrawSurface7_GetColorKey(mipmap, DDCKEY_SRCBLT, &color_key);
2006 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
2007 color_key.dwColorSpaceLowValue = 0x000000ff;
2008 color_key.dwColorSpaceHighValue = 0x000000ff;
2009 hr = IDirectDrawSurface7_SetColorKey(mipmap, DDCKEY_SRCBLT, &color_key);
2010 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
2012 color_key.dwColorSpaceLowValue = 0;
2013 color_key.dwColorSpaceHighValue = 0;
2014 hr = IDirectDrawSurface7_GetColorKey(mipmap, DDCKEY_SRCBLT, &color_key);
2015 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
2016 ok(color_key.dwColorSpaceLowValue == 0x000000ff, "Got unexpected value 0x%08x.\n",
2017 color_key.dwColorSpaceLowValue);
2018 ok(color_key.dwColorSpaceHighValue == 0x000000ff, "Got unexpected value 0x%08x.\n",
2019 color_key.dwColorSpaceHighValue);
2021 IDirectDrawSurface_AddRef(mipmap);
2022 for (i = 0; i < 7; ++i)
2024 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
2025 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
2026 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2027 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
2029 color_key.dwColorSpaceLowValue = 0x000000ff;
2030 color_key.dwColorSpaceHighValue = 0x000000ff;
2031 hr = IDirectDrawSurface7_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2032 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x, i %u.\n", hr, i);
2034 IDirectDrawSurface_Release(mipmap);
2035 mipmap = tmp;
2038 IDirectDrawSurface7_Release(mipmap);
2040 refcount = IDirectDrawSurface7_Release(surface);
2041 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
2043 cleanup:
2044 IDirectDraw7_Release(ddraw);
2045 refcount = IDirect3DDevice7_Release(device);
2046 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
2047 DestroyWindow(window);
2050 struct qi_test
2052 REFIID iid;
2053 REFIID refcount_iid;
2054 HRESULT hr;
2057 static void test_qi(const char *test_name, IUnknown *base_iface,
2058 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
2060 ULONG refcount, expected_refcount;
2061 IUnknown *iface1, *iface2;
2062 HRESULT hr;
2063 UINT i, j;
2065 for (i = 0; i < entry_count; ++i)
2067 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
2068 ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
2069 if (SUCCEEDED(hr))
2071 for (j = 0; j < entry_count; ++j)
2073 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
2074 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
2075 if (SUCCEEDED(hr))
2077 expected_refcount = 0;
2078 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
2079 ++expected_refcount;
2080 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
2081 ++expected_refcount;
2082 refcount = IUnknown_Release(iface2);
2083 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
2084 refcount, test_name, i, j, expected_refcount);
2088 expected_refcount = 0;
2089 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
2090 ++expected_refcount;
2091 refcount = IUnknown_Release(iface1);
2092 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
2093 refcount, test_name, i, expected_refcount);
2098 static void test_surface_qi(void)
2100 static const struct qi_test tests[] =
2102 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
2103 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
2104 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
2105 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2106 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
2107 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
2108 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
2109 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
2110 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
2111 {&IID_IDirect3DDevice7, NULL, E_NOINTERFACE},
2112 {&IID_IDirect3DDevice3, NULL, E_NOINTERFACE},
2113 {&IID_IDirect3DDevice2, NULL, E_NOINTERFACE},
2114 {&IID_IDirect3DDevice, NULL, E_NOINTERFACE},
2115 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
2116 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
2117 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
2118 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
2119 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
2120 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
2121 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
2122 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
2123 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
2124 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
2125 {&IID_IDirect3D, NULL, E_NOINTERFACE},
2126 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
2127 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
2128 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
2129 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
2130 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
2131 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
2132 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
2133 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
2134 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
2135 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
2136 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
2137 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
2138 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
2139 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
2140 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
2141 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
2142 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
2143 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
2144 {NULL, NULL, E_INVALIDARG },
2147 IDirectDrawSurface7 *surface;
2148 DDSURFACEDESC2 surface_desc;
2149 IDirect3DDevice7 *device;
2150 IDirectDraw7 *ddraw;
2151 HWND window;
2152 HRESULT hr;
2154 window = create_window();
2155 /* Try to create a D3D device to see if the ddraw implementation supports
2156 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
2157 * doesn't support e.g. the IDirect3DTexture interfaces. */
2158 if (!(device = create_device(window, DDSCL_NORMAL)))
2160 skip("Failed to create a 3D device, skipping test.\n");
2161 DestroyWindow(window);
2162 return;
2164 IDirect3DDevice_Release(device);
2165 ddraw = create_ddraw();
2166 ok(!!ddraw, "Failed to create a ddraw object.\n");
2167 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2168 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2170 memset(&surface_desc, 0, sizeof(surface_desc));
2171 surface_desc.dwSize = sizeof(surface_desc);
2172 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2173 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2174 surface_desc.dwWidth = 512;
2175 surface_desc.dwHeight = 512;
2176 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, (IDirectDrawSurface7 **)0xdeadbeef, NULL);
2177 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
2178 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2179 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
2181 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface7, tests, ARRAY_SIZE(tests));
2183 IDirectDrawSurface7_Release(surface);
2184 IDirectDraw7_Release(ddraw);
2185 DestroyWindow(window);
2188 static void test_device_qi(void)
2190 static const struct qi_test tests[] =
2192 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
2193 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
2194 {&IID_IDirectDrawGammaControl, NULL, E_NOINTERFACE},
2195 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2196 {&IID_IDirectDrawSurface7, NULL, E_NOINTERFACE},
2197 {&IID_IDirectDrawSurface4, NULL, E_NOINTERFACE},
2198 {&IID_IDirectDrawSurface3, NULL, E_NOINTERFACE},
2199 {&IID_IDirectDrawSurface2, NULL, E_NOINTERFACE},
2200 {&IID_IDirectDrawSurface, NULL, E_NOINTERFACE},
2201 {&IID_IDirect3DDevice7, &IID_IDirect3DDevice7, S_OK },
2202 {&IID_IDirect3DDevice3, NULL, E_NOINTERFACE},
2203 {&IID_IDirect3DDevice2, NULL, E_NOINTERFACE},
2204 {&IID_IDirect3DDevice, NULL, E_NOINTERFACE},
2205 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
2206 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
2207 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
2208 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
2209 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
2210 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
2211 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
2212 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
2213 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
2214 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
2215 {&IID_IDirect3D, NULL, E_NOINTERFACE},
2216 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
2217 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
2218 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
2219 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
2220 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
2221 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
2222 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
2223 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
2224 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
2225 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
2226 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
2227 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
2228 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
2229 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
2230 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
2231 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
2232 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
2233 {&IID_IUnknown, &IID_IDirect3DDevice7, S_OK },
2236 IDirect3DDevice7 *device;
2237 HWND window;
2239 window = create_window();
2240 if (!(device = create_device(window, DDSCL_NORMAL)))
2242 skip("Failed to create a 3D device, skipping test.\n");
2243 DestroyWindow(window);
2244 return;
2247 test_qi("device_qi", (IUnknown *)device, &IID_IDirect3DDevice7, tests, ARRAY_SIZE(tests));
2249 IDirect3DDevice7_Release(device);
2250 DestroyWindow(window);
2253 static void test_wndproc(void)
2255 LONG_PTR proc, ddraw_proc;
2256 IDirectDraw7 *ddraw;
2257 WNDCLASSA wc = {0};
2258 HWND window;
2259 HRESULT hr;
2260 ULONG ref;
2262 static struct message messages[] =
2264 {WM_WINDOWPOSCHANGING, FALSE, 0},
2265 {WM_MOVE, FALSE, 0},
2266 {WM_SIZE, FALSE, 0},
2267 {WM_WINDOWPOSCHANGING, FALSE, 0},
2268 {WM_ACTIVATE, FALSE, 0},
2269 {WM_SETFOCUS, FALSE, 0},
2270 {0, FALSE, 0},
2273 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
2274 ddraw = create_ddraw();
2275 ok(!!ddraw, "Failed to create a ddraw object.\n");
2277 wc.lpfnWndProc = test_proc;
2278 wc.lpszClassName = "ddraw_test_wndproc_wc";
2279 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2281 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
2282 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
2284 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2285 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2286 (LONG_PTR)test_proc, proc);
2287 expect_messages = messages;
2288 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2289 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2290 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2291 expect_messages = NULL;
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 /* DDSCL_NORMAL doesn't. */
2302 ddraw = create_ddraw();
2303 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2304 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2305 (LONG_PTR)test_proc, proc);
2306 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2307 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2308 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2309 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2310 (LONG_PTR)test_proc, proc);
2311 ref = IDirectDraw7_Release(ddraw);
2312 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2313 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2314 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2315 (LONG_PTR)test_proc, proc);
2317 /* The original window proc is only restored by ddraw if the current
2318 * window proc matches the one ddraw set. This also affects switching
2319 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
2320 ddraw = create_ddraw();
2321 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
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_EXCLUSIVE | DDSCL_FULLSCREEN);
2325 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2326 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2327 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2328 (LONG_PTR)test_proc, proc);
2329 ddraw_proc = proc;
2330 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2331 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2332 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2333 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2334 (LONG_PTR)test_proc, proc);
2335 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2336 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2337 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2338 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2339 (LONG_PTR)test_proc, proc);
2340 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2341 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2342 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2343 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2344 (LONG_PTR)DefWindowProcA, proc);
2345 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2346 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2347 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, ddraw_proc);
2348 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2349 (LONG_PTR)DefWindowProcA, proc);
2350 ref = IDirectDraw7_Release(ddraw);
2351 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2352 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2353 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2354 (LONG_PTR)test_proc, proc);
2356 ddraw = create_ddraw();
2357 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2358 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2359 (LONG_PTR)test_proc, proc);
2360 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2361 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2362 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2363 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2364 (LONG_PTR)test_proc, proc);
2365 ref = IDirectDraw7_Release(ddraw);
2366 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2367 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2368 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2369 (LONG_PTR)DefWindowProcA, proc);
2371 fix_wndproc(window, (LONG_PTR)test_proc);
2372 expect_messages = NULL;
2373 DestroyWindow(window);
2374 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2377 static void test_window_style(void)
2379 LONG style, exstyle, tmp, expected_style;
2380 RECT fullscreen_rect, r;
2381 IDirectDraw7 *ddraw;
2382 HWND window;
2383 HRESULT hr;
2384 ULONG ref;
2385 BOOL ret;
2387 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2388 0, 0, 100, 100, 0, 0, 0, 0);
2389 ddraw = create_ddraw();
2390 ok(!!ddraw, "Failed to create a ddraw object.\n");
2392 style = GetWindowLongA(window, GWL_STYLE);
2393 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
2394 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2396 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2397 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2399 tmp = GetWindowLongA(window, GWL_STYLE);
2400 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2401 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2402 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2404 GetWindowRect(window, &r);
2405 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
2406 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
2407 GetClientRect(window, &r);
2408 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2410 ret = SetForegroundWindow(GetDesktopWindow());
2411 ok(ret, "Failed to set foreground window.\n");
2413 tmp = GetWindowLongA(window, GWL_STYLE);
2414 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2415 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2416 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2418 ret = SetForegroundWindow(window);
2419 ok(ret, "Failed to set foreground window.\n");
2420 /* Windows 7 (but not Vista and XP) shows the window when it receives focus. Hide it again,
2421 * the next tests expect this. */
2422 ShowWindow(window, SW_HIDE);
2424 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2425 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2427 tmp = GetWindowLongA(window, GWL_STYLE);
2428 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2429 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2430 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2432 ShowWindow(window, SW_SHOW);
2433 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2434 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2436 tmp = GetWindowLongA(window, GWL_STYLE);
2437 expected_style = style | WS_VISIBLE;
2438 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2439 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2440 expected_style = exstyle | WS_EX_TOPMOST;
2441 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2443 ret = SetForegroundWindow(GetDesktopWindow());
2444 ok(ret, "Failed to set foreground window.\n");
2445 tmp = GetWindowLongA(window, GWL_STYLE);
2446 expected_style = style | WS_VISIBLE | WS_MINIMIZE;
2447 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2448 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2449 expected_style = exstyle | WS_EX_TOPMOST;
2450 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2452 ref = IDirectDraw7_Release(ddraw);
2453 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2455 DestroyWindow(window);
2458 static void test_redundant_mode_set(void)
2460 DDSURFACEDESC2 surface_desc = {0};
2461 IDirectDraw7 *ddraw;
2462 RECT q, r, s;
2463 HWND window;
2464 HRESULT hr;
2465 ULONG ref;
2467 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2468 0, 0, 100, 100, 0, 0, 0, 0);
2469 ddraw = create_ddraw();
2470 ok(!!ddraw, "Failed to create a ddraw object.\n");
2471 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2472 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2474 surface_desc.dwSize = sizeof(surface_desc);
2475 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
2476 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
2478 hr = IDirectDraw7_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2479 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
2480 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2482 GetWindowRect(window, &q);
2483 r = q;
2484 r.right /= 2;
2485 r.bottom /= 2;
2486 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
2487 GetWindowRect(window, &s);
2488 ok(EqualRect(&r, &s), "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2490 hr = IDirectDraw7_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2491 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
2492 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2494 GetWindowRect(window, &s);
2495 ok(EqualRect(&r, &s) || broken(EqualRect(&q, &s) /* Windows 10 */),
2496 "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2498 ref = IDirectDraw7_Release(ddraw);
2499 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2501 DestroyWindow(window);
2504 static SIZE screen_size, screen_size2;
2506 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2508 if (message == WM_SIZE)
2510 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2511 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2514 return test_proc(hwnd, message, wparam, lparam);
2517 static LRESULT CALLBACK mode_set_proc2(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2519 if (message == WM_SIZE)
2521 screen_size2.cx = GetSystemMetrics(SM_CXSCREEN);
2522 screen_size2.cy = GetSystemMetrics(SM_CYSCREEN);
2525 return test_proc(hwnd, message, wparam, lparam);
2528 struct test_coop_level_mode_set_enum_param
2530 DWORD ddraw_width, ddraw_height, user32_width, user32_height;
2533 static HRESULT CALLBACK test_coop_level_mode_set_enum_cb(DDSURFACEDESC2 *surface_desc, void *context)
2535 struct test_coop_level_mode_set_enum_param *param = context;
2537 if (U1(U4(*surface_desc).ddpfPixelFormat).dwRGBBitCount != registry_mode.dmBitsPerPel)
2538 return DDENUMRET_OK;
2539 if (surface_desc->dwWidth == registry_mode.dmPelsWidth
2540 && surface_desc->dwHeight == registry_mode.dmPelsHeight)
2541 return DDENUMRET_OK;
2543 if (!param->ddraw_width)
2545 param->ddraw_width = surface_desc->dwWidth;
2546 param->ddraw_height = surface_desc->dwHeight;
2547 return DDENUMRET_OK;
2549 if (surface_desc->dwWidth == param->ddraw_width && surface_desc->dwHeight == param->ddraw_height)
2550 return DDENUMRET_OK;
2552 param->user32_width = surface_desc->dwWidth;
2553 param->user32_height = surface_desc->dwHeight;
2554 return DDENUMRET_CANCEL;
2557 static void test_coop_level_mode_set(void)
2559 IDirectDrawSurface7 *primary;
2560 RECT registry_rect, ddraw_rect, user32_rect, r;
2561 IDirectDraw7 *ddraw;
2562 DDSURFACEDESC2 ddsd;
2563 WNDCLASSA wc = {0};
2564 HWND window, window2;
2565 HRESULT hr;
2566 ULONG ref;
2567 MSG msg;
2568 struct test_coop_level_mode_set_enum_param param;
2569 DEVMODEW devmode;
2570 BOOL ret;
2571 LONG change_ret;
2573 static const struct message exclusive_messages[] =
2575 {WM_WINDOWPOSCHANGING, FALSE, 0},
2576 {WM_WINDOWPOSCHANGED, FALSE, 0},
2577 {WM_SIZE, FALSE, 0},
2578 {WM_DISPLAYCHANGE, FALSE, 0},
2579 {0, FALSE, 0},
2581 static const struct message exclusive_focus_loss_messages[] =
2583 {WM_ACTIVATE, TRUE, WA_INACTIVE, DD_OK},
2584 {WM_WINDOWPOSCHANGING, FALSE, 0, DD_OK}, /* Window resize due to mode change. */
2585 {WM_WINDOWPOSCHANGED, FALSE, 0, DD_OK},
2586 {WM_SIZE, TRUE, SIZE_RESTORED, DD_OK}, /* Generated by DefWindowProc. */
2587 {WM_DISPLAYCHANGE, FALSE, 0, DD_OK},
2588 {WM_KILLFOCUS, FALSE, 0, DDERR_NOEXCLUSIVEMODE},
2589 {WM_WINDOWPOSCHANGING, FALSE, 0, DDERR_NOEXCLUSIVEMODE}, /* Window minimized. */
2590 /* Like d3d8 and d3d9 ddraw seems to use SW_SHOWMINIMIZED instead of
2591 * SW_MINIMIZED, causing a recursive window activation that does not
2592 * produce the same result in Wine yet. Ignore the difference for now.
2593 * {WM_ACTIVATE, TRUE, 0x200000 | WA_ACTIVE}, */
2594 {WM_WINDOWPOSCHANGED, FALSE, 0, DDERR_NOEXCLUSIVEMODE},
2595 {WM_MOVE, FALSE, 0, DDERR_NOEXCLUSIVEMODE},
2596 {WM_SIZE, TRUE, SIZE_MINIMIZED, DDERR_NOEXCLUSIVEMODE},
2597 {WM_ACTIVATEAPP, TRUE, FALSE, DDERR_NOEXCLUSIVEMODE},
2598 {0, FALSE, 0, 0},
2600 static const struct message exclusive_focus_restore_messages[] =
2602 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* From the ShowWindow(SW_RESTORE). */
2603 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Generated by ddraw, matches d3d9 behavior. */
2604 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching previous message. */
2605 {WM_SIZE, FALSE, 0}, /* DefWindowProc. */
2606 {WM_DISPLAYCHANGE, FALSE, 0}, /* Ddraw restores mode. */
2607 /* Native redundantly sets the window size here. */
2608 {WM_ACTIVATEAPP, TRUE, TRUE}, /* End of ddraw's hooks. */
2609 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching the one from ShowWindow. */
2610 {WM_MOVE, FALSE, 0}, /* DefWindowProc. */
2611 {WM_SIZE, TRUE, SIZE_RESTORED}, /* DefWindowProc. */
2612 {0, FALSE, 0},
2614 static const struct message sc_restore_messages[] =
2616 {WM_SYSCOMMAND, TRUE, SC_RESTORE},
2617 {WM_WINDOWPOSCHANGING, FALSE, 0},
2618 {WM_WINDOWPOSCHANGED, FALSE, 0},
2619 {WM_SIZE, TRUE, SIZE_RESTORED},
2620 {0, FALSE, 0},
2622 static const struct message sc_minimize_messages[] =
2624 {WM_SYSCOMMAND, TRUE, SC_MINIMIZE},
2625 {WM_WINDOWPOSCHANGING, FALSE, 0},
2626 {WM_WINDOWPOSCHANGED, FALSE, 0},
2627 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2628 {0, FALSE, 0},
2630 static const struct message sc_maximize_messages[] =
2632 {WM_SYSCOMMAND, TRUE, SC_MAXIMIZE},
2633 {WM_WINDOWPOSCHANGING, FALSE, 0},
2634 {WM_WINDOWPOSCHANGED, FALSE, 0},
2635 {WM_SIZE, TRUE, SIZE_MAXIMIZED},
2636 {0, FALSE, 0},
2639 static const struct message normal_messages[] =
2641 {WM_DISPLAYCHANGE, FALSE, 0},
2642 {0, FALSE, 0},
2645 ddraw = create_ddraw();
2646 ok(!!ddraw, "Failed to create a ddraw object.\n");
2648 memset(&param, 0, sizeof(param));
2649 hr = IDirectDraw7_EnumDisplayModes(ddraw, 0, NULL, &param, test_coop_level_mode_set_enum_cb);
2650 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
2651 ref = IDirectDraw7_Release(ddraw);
2652 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2654 if (!param.user32_height)
2656 skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
2657 return;
2660 SetRect(&registry_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2661 SetRect(&ddraw_rect, 0, 0, param.ddraw_width, param.ddraw_height);
2662 SetRect(&user32_rect, 0, 0, param.user32_width, param.user32_height);
2664 memset(&devmode, 0, sizeof(devmode));
2665 devmode.dmSize = sizeof(devmode);
2666 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2667 devmode.dmPelsWidth = param.user32_width;
2668 devmode.dmPelsHeight = param.user32_height;
2669 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2670 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2672 ddraw = create_ddraw();
2673 ok(!!ddraw, "Failed to create a ddraw object.\n");
2675 wc.lpfnWndProc = mode_set_proc;
2676 wc.lpszClassName = "ddraw_test_wndproc_wc";
2677 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2678 wc.lpfnWndProc = mode_set_proc2;
2679 wc.lpszClassName = "ddraw_test_wndproc_wc2";
2680 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2682 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
2683 0, 0, 100, 100, 0, 0, 0, 0);
2684 window2 = CreateWindowA("ddraw_test_wndproc_wc2", "ddraw_test", WS_OVERLAPPEDWINDOW,
2685 0, 0, 100, 100, 0, 0, 0, 0);
2687 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2688 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2690 GetWindowRect(window, &r);
2691 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2692 wine_dbgstr_rect(&r));
2694 memset(&ddsd, 0, sizeof(ddsd));
2695 ddsd.dwSize = sizeof(ddsd);
2696 ddsd.dwFlags = DDSD_CAPS;
2697 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2699 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2700 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2701 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2702 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2703 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2704 param.user32_width, ddsd.dwWidth);
2705 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2706 param.user32_height, ddsd.dwHeight);
2708 GetWindowRect(window, &r);
2709 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2710 wine_dbgstr_rect(&r));
2712 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2713 expect_messages = exclusive_messages;
2714 screen_size.cx = 0;
2715 screen_size.cy = 0;
2717 hr = IDirectDrawSurface7_IsLost(primary);
2718 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2719 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2720 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2721 hr = IDirectDrawSurface7_IsLost(primary);
2722 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2724 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2725 expect_messages = NULL;
2726 ok(screen_size.cx == param.ddraw_width && screen_size.cy == param.ddraw_height,
2727 "Expected screen size %ux%u, got %ux%u.\n",
2728 param.ddraw_width, param.ddraw_height, screen_size.cx, screen_size.cy);
2730 GetWindowRect(window, &r);
2731 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2732 wine_dbgstr_rect(&r));
2734 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2735 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2736 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2737 param.user32_width, ddsd.dwWidth);
2738 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2739 param.user32_height, ddsd.dwHeight);
2740 IDirectDrawSurface7_Release(primary);
2742 memset(&ddsd, 0, sizeof(ddsd));
2743 ddsd.dwSize = sizeof(ddsd);
2744 ddsd.dwFlags = DDSD_CAPS;
2745 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2747 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2748 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2749 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2750 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2751 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2752 param.ddraw_width, ddsd.dwWidth);
2753 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2754 param.ddraw_height, ddsd.dwHeight);
2756 GetWindowRect(window, &r);
2757 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2758 wine_dbgstr_rect(&r));
2760 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2761 expect_messages = exclusive_messages;
2762 screen_size.cx = 0;
2763 screen_size.cy = 0;
2765 hr = IDirectDrawSurface7_IsLost(primary);
2766 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2767 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2768 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2769 hr = IDirectDrawSurface7_IsLost(primary);
2770 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2772 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2773 expect_messages = NULL;
2774 ok(screen_size.cx == param.user32_width && screen_size.cy == param.user32_height,
2775 "Expected screen size %ux%u, got %ux%u.\n",
2776 param.user32_width, param.user32_height, screen_size.cx, screen_size.cy);
2778 GetWindowRect(window, &r);
2779 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2780 wine_dbgstr_rect(&r));
2782 expect_messages = exclusive_focus_loss_messages;
2783 focus_test_ddraw = ddraw;
2784 ret = SetForegroundWindow(GetDesktopWindow());
2785 ok(ret, "Failed to set foreground window.\n");
2786 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2787 focus_test_ddraw = NULL;
2789 memset(&devmode, 0, sizeof(devmode));
2790 devmode.dmSize = sizeof(devmode);
2791 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2792 ok(ret, "Failed to get display mode.\n");
2793 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2794 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpected screen size %ux%u.\n",
2795 devmode.dmPelsWidth, devmode.dmPelsHeight);
2797 expect_messages = exclusive_focus_restore_messages;
2798 ShowWindow(window, SW_RESTORE);
2799 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2801 GetWindowRect(window, &r);
2802 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2803 wine_dbgstr_rect(&r));
2804 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2805 ok(ret, "Failed to get display mode.\n");
2806 ok(devmode.dmPelsWidth == param.ddraw_width
2807 && devmode.dmPelsHeight == param.ddraw_height, "Got unexpected screen size %ux%u.\n",
2808 devmode.dmPelsWidth, devmode.dmPelsHeight);
2810 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2811 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2812 /* Normally the primary should be restored here. Unfortunately this causes the
2813 * GetSurfaceDesc call after the next display mode change to crash on the Windows 8
2814 * testbot. Another Restore call would presumably avoid the crash, but it also moots
2815 * the point of the GetSurfaceDesc call. */
2817 expect_messages = sc_minimize_messages;
2818 SendMessageA(window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
2819 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2820 expect_messages = NULL;
2822 expect_messages = sc_restore_messages;
2823 SendMessageA(window, WM_SYSCOMMAND, SC_RESTORE, 0);
2824 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2825 expect_messages = NULL;
2827 expect_messages = sc_maximize_messages;
2828 SendMessageA(window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
2829 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2830 expect_messages = NULL;
2832 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2833 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2835 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2836 expect_messages = exclusive_messages;
2837 screen_size.cx = 0;
2838 screen_size.cy = 0;
2840 hr = IDirectDrawSurface7_IsLost(primary);
2841 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2842 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
2843 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
2844 hr = IDirectDrawSurface7_IsLost(primary);
2845 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2847 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2848 expect_messages = NULL;
2849 ok(screen_size.cx == registry_mode.dmPelsWidth
2850 && screen_size.cy == registry_mode.dmPelsHeight,
2851 "Expected screen size %ux%u, got %ux%u.\n",
2852 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size.cx, screen_size.cy);
2854 GetWindowRect(window, &r);
2855 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2856 wine_dbgstr_rect(&r));
2858 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2859 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2860 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2861 param.ddraw_width, ddsd.dwWidth);
2862 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2863 param.ddraw_height, ddsd.dwHeight);
2864 IDirectDrawSurface7_Release(primary);
2866 /* For Wine. */
2867 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
2868 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2870 memset(&ddsd, 0, sizeof(ddsd));
2871 ddsd.dwSize = sizeof(ddsd);
2872 ddsd.dwFlags = DDSD_CAPS;
2873 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2875 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2876 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2877 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2878 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2879 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2880 registry_mode.dmPelsWidth, ddsd.dwWidth);
2881 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2882 registry_mode.dmPelsHeight, ddsd.dwHeight);
2884 GetWindowRect(window, &r);
2885 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2886 wine_dbgstr_rect(&r));
2888 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2889 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2891 GetWindowRect(window, &r);
2892 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2893 wine_dbgstr_rect(&r));
2895 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2896 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2897 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2898 registry_mode.dmPelsWidth, ddsd.dwWidth);
2899 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2900 registry_mode.dmPelsHeight, ddsd.dwHeight);
2901 IDirectDrawSurface7_Release(primary);
2903 memset(&ddsd, 0, sizeof(ddsd));
2904 ddsd.dwSize = sizeof(ddsd);
2905 ddsd.dwFlags = DDSD_CAPS;
2906 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2908 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2909 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2910 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2911 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2912 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2913 registry_mode.dmPelsWidth, ddsd.dwWidth);
2914 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2915 registry_mode.dmPelsHeight, ddsd.dwHeight);
2917 GetWindowRect(window, &r);
2918 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2919 wine_dbgstr_rect(&r));
2921 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2922 expect_messages = normal_messages;
2923 screen_size.cx = 0;
2924 screen_size.cy = 0;
2926 hr = IDirectDrawSurface7_IsLost(primary);
2927 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2928 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2929 devmode.dmPelsWidth = param.user32_width;
2930 devmode.dmPelsHeight = param.user32_height;
2931 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2932 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2933 hr = IDirectDrawSurface7_IsLost(primary);
2934 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2936 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2937 expect_messages = NULL;
2938 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2940 GetWindowRect(window, &r);
2941 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2942 wine_dbgstr_rect(&r));
2944 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2945 expect_messages = normal_messages;
2946 screen_size.cx = 0;
2947 screen_size.cy = 0;
2949 hr = IDirectDrawSurface7_Restore(primary);
2950 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2951 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2952 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2953 hr = IDirectDrawSurface7_Restore(primary);
2954 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
2955 hr = IDirectDrawSurface7_IsLost(primary);
2956 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2958 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2959 expect_messages = NULL;
2960 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
2962 GetWindowRect(window, &r);
2963 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2964 wine_dbgstr_rect(&r));
2966 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2967 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2968 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
2969 registry_mode.dmPelsWidth, ddsd.dwWidth);
2970 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
2971 registry_mode.dmPelsHeight, ddsd.dwHeight);
2972 IDirectDrawSurface7_Release(primary);
2974 memset(&ddsd, 0, sizeof(ddsd));
2975 ddsd.dwSize = sizeof(ddsd);
2976 ddsd.dwFlags = DDSD_CAPS;
2977 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2979 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2980 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2981 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2982 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2983 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2984 param.ddraw_width, ddsd.dwWidth);
2985 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2986 param.ddraw_height, ddsd.dwHeight);
2988 GetWindowRect(window, &r);
2989 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
2990 wine_dbgstr_rect(&r));
2992 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2993 expect_messages = normal_messages;
2994 screen_size.cx = 0;
2995 screen_size.cy = 0;
2997 hr = IDirectDrawSurface7_IsLost(primary);
2998 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2999 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
3000 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3001 hr = IDirectDrawSurface7_IsLost(primary);
3002 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3004 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3005 expect_messages = NULL;
3006 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3008 GetWindowRect(window, &r);
3009 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3010 wine_dbgstr_rect(&r));
3012 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3013 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3014 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3015 param.ddraw_width, ddsd.dwWidth);
3016 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3017 param.ddraw_height, ddsd.dwHeight);
3018 IDirectDrawSurface7_Release(primary);
3020 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3021 ok(ret, "Failed to get display mode.\n");
3022 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3023 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3024 "Expected resolution %ux%u, got %ux%u.\n",
3025 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3026 devmode.dmPelsWidth, devmode.dmPelsHeight);
3027 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3028 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3030 memset(&ddsd, 0, sizeof(ddsd));
3031 ddsd.dwSize = sizeof(ddsd);
3032 ddsd.dwFlags = DDSD_CAPS;
3033 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3035 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3036 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3037 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3038 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3039 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3040 registry_mode.dmPelsWidth, ddsd.dwWidth);
3041 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3042 registry_mode.dmPelsHeight, ddsd.dwHeight);
3044 GetWindowRect(window, &r);
3045 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3046 wine_dbgstr_rect(&r));
3048 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
3049 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
3050 * not DDSCL_FULLSCREEN. */
3051 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3052 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3054 GetWindowRect(window, &r);
3055 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3056 wine_dbgstr_rect(&r));
3058 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3059 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3060 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3061 registry_mode.dmPelsWidth, ddsd.dwWidth);
3062 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3063 registry_mode.dmPelsHeight, ddsd.dwHeight);
3064 IDirectDrawSurface7_Release(primary);
3066 memset(&ddsd, 0, sizeof(ddsd));
3067 ddsd.dwSize = sizeof(ddsd);
3068 ddsd.dwFlags = DDSD_CAPS;
3069 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3071 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3072 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3073 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3074 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3075 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3076 registry_mode.dmPelsWidth, ddsd.dwWidth);
3077 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3078 registry_mode.dmPelsHeight, ddsd.dwHeight);
3080 GetWindowRect(window, &r);
3081 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3082 wine_dbgstr_rect(&r));
3084 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3085 expect_messages = normal_messages;
3086 screen_size.cx = 0;
3087 screen_size.cy = 0;
3089 hr = IDirectDrawSurface7_IsLost(primary);
3090 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3091 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3092 devmode.dmPelsWidth = param.user32_width;
3093 devmode.dmPelsHeight = param.user32_height;
3094 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3095 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3096 hr = IDirectDrawSurface7_IsLost(primary);
3097 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3099 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3100 expect_messages = NULL;
3101 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3103 GetWindowRect(window, &r);
3104 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3105 wine_dbgstr_rect(&r));
3107 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3108 expect_messages = normal_messages;
3109 screen_size.cx = 0;
3110 screen_size.cy = 0;
3112 hr = IDirectDrawSurface7_Restore(primary);
3113 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3114 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3115 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3116 hr = IDirectDrawSurface7_Restore(primary);
3117 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3118 hr = IDirectDrawSurface7_IsLost(primary);
3119 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3121 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3122 expect_messages = NULL;
3123 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3125 GetWindowRect(window, &r);
3126 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3127 wine_dbgstr_rect(&r));
3129 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3130 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3131 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3132 registry_mode.dmPelsWidth, ddsd.dwWidth);
3133 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3134 registry_mode.dmPelsHeight, ddsd.dwHeight);
3135 IDirectDrawSurface7_Release(primary);
3137 memset(&ddsd, 0, sizeof(ddsd));
3138 ddsd.dwSize = sizeof(ddsd);
3139 ddsd.dwFlags = DDSD_CAPS;
3140 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3142 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3143 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3144 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3145 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3146 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3147 param.ddraw_width, ddsd.dwWidth);
3148 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3149 param.ddraw_height, ddsd.dwHeight);
3151 GetWindowRect(window, &r);
3152 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3153 wine_dbgstr_rect(&r));
3155 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3156 expect_messages = normal_messages;
3157 screen_size.cx = 0;
3158 screen_size.cy = 0;
3160 hr = IDirectDrawSurface7_IsLost(primary);
3161 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3162 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
3163 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3164 hr = IDirectDrawSurface7_IsLost(primary);
3165 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3167 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3168 expect_messages = NULL;
3169 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3171 GetWindowRect(window, &r);
3172 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3173 wine_dbgstr_rect(&r));
3175 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3176 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3177 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3178 param.ddraw_width, ddsd.dwWidth);
3179 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3180 param.ddraw_height, ddsd.dwHeight);
3181 IDirectDrawSurface7_Release(primary);
3183 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3184 ok(ret, "Failed to get display mode.\n");
3185 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3186 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3187 "Expected resolution %ux%u, got %ux%u.\n",
3188 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3189 devmode.dmPelsWidth, devmode.dmPelsHeight);
3190 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3191 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3193 memset(&ddsd, 0, sizeof(ddsd));
3194 ddsd.dwSize = sizeof(ddsd);
3195 ddsd.dwFlags = DDSD_CAPS;
3196 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3198 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3199 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3200 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3201 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3202 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3203 registry_mode.dmPelsWidth, ddsd.dwWidth);
3204 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3205 registry_mode.dmPelsHeight, ddsd.dwHeight);
3206 IDirectDrawSurface7_Release(primary);
3208 GetWindowRect(window, &r);
3209 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3210 wine_dbgstr_rect(&r));
3212 /* Changing the coop level from EXCLUSIVE to NORMAL restores the screen resolution */
3213 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3214 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3215 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3216 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3218 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3219 expect_messages = exclusive_messages;
3220 screen_size.cx = 0;
3221 screen_size.cy = 0;
3223 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3224 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3226 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3227 expect_messages = NULL;
3228 ok(screen_size.cx == registry_mode.dmPelsWidth
3229 && screen_size.cy == registry_mode.dmPelsHeight,
3230 "Expected screen size %ux%u, got %ux%u.\n",
3231 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3232 screen_size.cx, screen_size.cy);
3234 GetWindowRect(window, &r);
3235 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3236 wine_dbgstr_rect(&r));
3238 memset(&ddsd, 0, sizeof(ddsd));
3239 ddsd.dwSize = sizeof(ddsd);
3240 ddsd.dwFlags = DDSD_CAPS;
3241 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3243 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3244 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3245 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3246 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3247 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3248 registry_mode.dmPelsWidth, ddsd.dwWidth);
3249 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3250 registry_mode.dmPelsHeight, ddsd.dwHeight);
3251 IDirectDrawSurface7_Release(primary);
3253 /* The screen restore is a property of DDSCL_EXCLUSIVE */
3254 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3255 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3256 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3257 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3259 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3260 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3262 memset(&ddsd, 0, sizeof(ddsd));
3263 ddsd.dwSize = sizeof(ddsd);
3264 ddsd.dwFlags = DDSD_CAPS;
3265 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3267 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3268 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3269 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3270 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3271 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3272 param.ddraw_width, ddsd.dwWidth);
3273 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3274 param.ddraw_height, ddsd.dwHeight);
3275 IDirectDrawSurface7_Release(primary);
3277 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
3278 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3280 /* If the window is changed at the same time, messages are sent to the new window. */
3281 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3282 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3283 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3284 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3286 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3287 expect_messages = exclusive_messages;
3288 screen_size.cx = 0;
3289 screen_size.cy = 0;
3290 screen_size2.cx = 0;
3291 screen_size2.cy = 0;
3293 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3294 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3296 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3297 expect_messages = NULL;
3298 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n",
3299 screen_size.cx, screen_size.cy);
3300 ok(screen_size2.cx == registry_mode.dmPelsWidth && screen_size2.cy == registry_mode.dmPelsHeight,
3301 "Expected screen size 2 %ux%u, got %ux%u.\n",
3302 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size2.cx, screen_size2.cy);
3304 GetWindowRect(window, &r);
3305 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3306 wine_dbgstr_rect(&r));
3307 GetWindowRect(window2, &r);
3308 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3309 wine_dbgstr_rect(&r));
3311 memset(&ddsd, 0, sizeof(ddsd));
3312 ddsd.dwSize = sizeof(ddsd);
3313 ddsd.dwFlags = DDSD_CAPS;
3314 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3316 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3317 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3318 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3319 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3320 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3321 registry_mode.dmPelsWidth, ddsd.dwWidth);
3322 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3323 registry_mode.dmPelsHeight, ddsd.dwHeight);
3324 IDirectDrawSurface7_Release(primary);
3326 ref = IDirectDraw7_Release(ddraw);
3327 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3329 GetWindowRect(window, &r);
3330 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3331 wine_dbgstr_rect(&r));
3333 expect_messages = NULL;
3334 DestroyWindow(window);
3335 DestroyWindow(window2);
3336 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
3337 UnregisterClassA("ddraw_test_wndproc_wc2", GetModuleHandleA(NULL));
3340 static void test_coop_level_mode_set_multi(void)
3342 IDirectDraw7 *ddraw1, *ddraw2;
3343 UINT w, h;
3344 HWND window;
3345 HRESULT hr;
3346 ULONG ref;
3348 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3349 0, 0, 100, 100, 0, 0, 0, 0);
3350 ddraw1 = create_ddraw();
3351 ok(!!ddraw1, "Failed to create a ddraw object.\n");
3353 /* With just a single ddraw object, the display mode is restored on
3354 * release. */
3355 hr = set_display_mode(ddraw1, 800, 600);
3356 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3357 w = GetSystemMetrics(SM_CXSCREEN);
3358 ok(w == 800, "Got unexpected screen width %u.\n", w);
3359 h = GetSystemMetrics(SM_CYSCREEN);
3360 ok(h == 600, "Got unexpected screen height %u.\n", h);
3362 ref = IDirectDraw7_Release(ddraw1);
3363 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3364 w = GetSystemMetrics(SM_CXSCREEN);
3365 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3366 h = GetSystemMetrics(SM_CYSCREEN);
3367 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3369 /* When there are multiple ddraw objects, the display mode is restored to
3370 * the initial mode, before the first SetDisplayMode() call. */
3371 ddraw1 = create_ddraw();
3372 hr = set_display_mode(ddraw1, 800, 600);
3373 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3374 w = GetSystemMetrics(SM_CXSCREEN);
3375 ok(w == 800, "Got unexpected screen width %u.\n", w);
3376 h = GetSystemMetrics(SM_CYSCREEN);
3377 ok(h == 600, "Got unexpected screen height %u.\n", h);
3379 ddraw2 = create_ddraw();
3380 hr = set_display_mode(ddraw2, 640, 480);
3381 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3382 w = GetSystemMetrics(SM_CXSCREEN);
3383 ok(w == 640, "Got unexpected screen width %u.\n", w);
3384 h = GetSystemMetrics(SM_CYSCREEN);
3385 ok(h == 480, "Got unexpected screen height %u.\n", h);
3387 ref = IDirectDraw7_Release(ddraw2);
3388 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3389 w = GetSystemMetrics(SM_CXSCREEN);
3390 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3391 h = GetSystemMetrics(SM_CYSCREEN);
3392 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3394 ref = IDirectDraw7_Release(ddraw1);
3395 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3396 w = GetSystemMetrics(SM_CXSCREEN);
3397 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3398 h = GetSystemMetrics(SM_CYSCREEN);
3399 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3401 /* Regardless of release ordering. */
3402 ddraw1 = create_ddraw();
3403 hr = set_display_mode(ddraw1, 800, 600);
3404 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3405 w = GetSystemMetrics(SM_CXSCREEN);
3406 ok(w == 800, "Got unexpected screen width %u.\n", w);
3407 h = GetSystemMetrics(SM_CYSCREEN);
3408 ok(h == 600, "Got unexpected screen height %u.\n", h);
3410 ddraw2 = create_ddraw();
3411 hr = set_display_mode(ddraw2, 640, 480);
3412 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3413 w = GetSystemMetrics(SM_CXSCREEN);
3414 ok(w == 640, "Got unexpected screen width %u.\n", w);
3415 h = GetSystemMetrics(SM_CYSCREEN);
3416 ok(h == 480, "Got unexpected screen height %u.\n", h);
3418 ref = IDirectDraw7_Release(ddraw1);
3419 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3420 w = GetSystemMetrics(SM_CXSCREEN);
3421 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3422 h = GetSystemMetrics(SM_CYSCREEN);
3423 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3425 ref = IDirectDraw7_Release(ddraw2);
3426 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3427 w = GetSystemMetrics(SM_CXSCREEN);
3428 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3429 h = GetSystemMetrics(SM_CYSCREEN);
3430 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3432 /* But only for ddraw objects that called SetDisplayMode(). */
3433 ddraw1 = create_ddraw();
3434 ddraw2 = create_ddraw();
3435 hr = set_display_mode(ddraw2, 640, 480);
3436 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3437 w = GetSystemMetrics(SM_CXSCREEN);
3438 ok(w == 640, "Got unexpected screen width %u.\n", w);
3439 h = GetSystemMetrics(SM_CYSCREEN);
3440 ok(h == 480, "Got unexpected screen height %u.\n", h);
3442 ref = IDirectDraw7_Release(ddraw1);
3443 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3444 w = GetSystemMetrics(SM_CXSCREEN);
3445 ok(w == 640, "Got unexpected screen width %u.\n", w);
3446 h = GetSystemMetrics(SM_CYSCREEN);
3447 ok(h == 480, "Got unexpected screen height %u.\n", h);
3449 ref = IDirectDraw7_Release(ddraw2);
3450 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3451 w = GetSystemMetrics(SM_CXSCREEN);
3452 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3453 h = GetSystemMetrics(SM_CYSCREEN);
3454 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3456 /* If there's a ddraw object that's currently in exclusive mode, it blocks
3457 * restoring the display mode. */
3458 ddraw1 = create_ddraw();
3459 hr = set_display_mode(ddraw1, 800, 600);
3460 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3461 w = GetSystemMetrics(SM_CXSCREEN);
3462 ok(w == 800, "Got unexpected screen width %u.\n", w);
3463 h = GetSystemMetrics(SM_CYSCREEN);
3464 ok(h == 600, "Got unexpected screen height %u.\n", h);
3466 ddraw2 = create_ddraw();
3467 hr = set_display_mode(ddraw2, 640, 480);
3468 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3469 w = GetSystemMetrics(SM_CXSCREEN);
3470 ok(w == 640, "Got unexpected screen width %u.\n", w);
3471 h = GetSystemMetrics(SM_CYSCREEN);
3472 ok(h == 480, "Got unexpected screen height %u.\n", h);
3474 hr = IDirectDraw7_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3475 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3477 ref = IDirectDraw7_Release(ddraw1);
3478 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3479 w = GetSystemMetrics(SM_CXSCREEN);
3480 ok(w == 640, "Got unexpected screen width %u.\n", w);
3481 h = GetSystemMetrics(SM_CYSCREEN);
3482 ok(h == 480, "Got unexpected screen height %u.\n", h);
3484 ref = IDirectDraw7_Release(ddraw2);
3485 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3486 w = GetSystemMetrics(SM_CXSCREEN);
3487 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3488 h = GetSystemMetrics(SM_CYSCREEN);
3489 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3491 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
3492 ddraw1 = create_ddraw();
3493 hr = set_display_mode(ddraw1, 800, 600);
3494 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3495 w = GetSystemMetrics(SM_CXSCREEN);
3496 ok(w == 800, "Got unexpected screen width %u.\n", w);
3497 h = GetSystemMetrics(SM_CYSCREEN);
3498 ok(h == 600, "Got unexpected screen height %u.\n", h);
3500 hr = IDirectDraw7_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3501 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3503 ddraw2 = create_ddraw();
3504 hr = set_display_mode(ddraw2, 640, 480);
3505 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
3507 ref = IDirectDraw7_Release(ddraw1);
3508 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3509 w = GetSystemMetrics(SM_CXSCREEN);
3510 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3511 h = GetSystemMetrics(SM_CYSCREEN);
3512 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3514 ref = IDirectDraw7_Release(ddraw2);
3515 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3516 w = GetSystemMetrics(SM_CXSCREEN);
3517 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3518 h = GetSystemMetrics(SM_CYSCREEN);
3519 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3521 DestroyWindow(window);
3524 static void test_initialize(void)
3526 IDirectDraw7 *ddraw;
3527 HRESULT hr;
3529 ddraw = create_ddraw();
3530 ok(!!ddraw, "Failed to create a ddraw object.\n");
3532 hr = IDirectDraw7_Initialize(ddraw, NULL);
3533 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
3534 IDirectDraw7_Release(ddraw);
3536 CoInitialize(NULL);
3537 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw7, (void **)&ddraw);
3538 ok(SUCCEEDED(hr), "Failed to create IDirectDraw7 instance, hr %#x.\n", hr);
3539 hr = IDirectDraw7_Initialize(ddraw, NULL);
3540 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
3541 hr = IDirectDraw7_Initialize(ddraw, NULL);
3542 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
3543 IDirectDraw7_Release(ddraw);
3544 CoUninitialize();
3547 static void test_coop_level_surf_create(void)
3549 IDirectDrawSurface7 *surface;
3550 IDirectDraw7 *ddraw;
3551 DDSURFACEDESC2 ddsd;
3552 HRESULT hr;
3554 ddraw = create_ddraw();
3555 ok(!!ddraw, "Failed to create a ddraw object.\n");
3557 memset(&ddsd, 0, sizeof(ddsd));
3558 ddsd.dwSize = sizeof(ddsd);
3559 ddsd.dwFlags = DDSD_CAPS;
3560 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3561 surface = (void *)0xdeadbeef;
3562 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
3563 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
3564 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
3566 surface = (void *)0xdeadbeef;
3567 hr = IDirectDraw7_CreateSurface(ddraw, NULL, &surface, NULL);
3568 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
3569 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
3571 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
3572 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3574 surface = (void *)0xdeadbeef;
3575 hr = IDirectDraw7_CreateSurface(ddraw, NULL, &surface, NULL);
3576 ok(hr == DDERR_INVALIDPARAMS, "Unexpected hr %#x.\n", hr);
3577 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
3579 IDirectDraw7_Release(ddraw);
3582 static void test_vb_discard(void)
3584 static const struct vec4 quad[] =
3586 { 0.0f, 480.0f, 0.0f, 1.0f},
3587 { 0.0f, 0.0f, 0.0f, 1.0f},
3588 {640.0f, 480.0f, 0.0f, 1.0f},
3589 {640.0f, 0.0f, 0.0f, 1.0f},
3592 IDirect3DDevice7 *device;
3593 IDirect3D7 *d3d;
3594 IDirect3DVertexBuffer7 *buffer;
3595 HWND window;
3596 HRESULT hr;
3597 D3DVERTEXBUFFERDESC desc;
3598 BYTE *data;
3599 static const unsigned int vbsize = 16;
3600 unsigned int i;
3602 window = create_window();
3603 if (!(device = create_device(window, DDSCL_NORMAL)))
3605 skip("Failed to create a 3D device, skipping test.\n");
3606 DestroyWindow(window);
3607 return;
3610 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
3611 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
3613 memset(&desc, 0, sizeof(desc));
3614 desc.dwSize = sizeof(desc);
3615 desc.dwCaps = D3DVBCAPS_WRITEONLY;
3616 desc.dwFVF = D3DFVF_XYZRHW;
3617 desc.dwNumVertices = vbsize;
3618 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &buffer, 0);
3619 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
3621 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3622 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3623 memcpy(data, quad, sizeof(quad));
3624 hr = IDirect3DVertexBuffer7_Unlock(buffer);
3625 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3627 hr = IDirect3DDevice7_BeginScene(device);
3628 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3629 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
3630 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3631 hr = IDirect3DDevice7_EndScene(device);
3632 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3634 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3635 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3636 memset(data, 0xaa, sizeof(struct vec4) * vbsize);
3637 hr = IDirect3DVertexBuffer7_Unlock(buffer);
3638 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3640 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
3641 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3642 for (i = 0; i < sizeof(struct vec4) * vbsize; i++)
3644 if (data[i] != 0xaa)
3646 ok(FALSE, "Vertex buffer data byte %u is 0x%02x, expected 0xaa\n", i, data[i]);
3647 break;
3650 hr = IDirect3DVertexBuffer7_Unlock(buffer);
3651 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3653 IDirect3DVertexBuffer7_Release(buffer);
3654 IDirect3D7_Release(d3d);
3655 IDirect3DDevice7_Release(device);
3656 DestroyWindow(window);
3659 static void test_coop_level_multi_window(void)
3661 HWND window1, window2;
3662 IDirectDraw7 *ddraw;
3663 HRESULT hr;
3665 window1 = create_window();
3666 window2 = create_window();
3667 ddraw = create_ddraw();
3668 ok(!!ddraw, "Failed to create a ddraw object.\n");
3670 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
3671 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3672 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3673 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
3674 ok(IsWindow(window1), "Window 1 was destroyed.\n");
3675 ok(IsWindow(window2), "Window 2 was destroyed.\n");
3677 IDirectDraw7_Release(ddraw);
3678 DestroyWindow(window2);
3679 DestroyWindow(window1);
3682 static void test_draw_strided(void)
3684 static struct vec3 position[] =
3686 {-1.0, -1.0, 0.0},
3687 {-1.0, 1.0, 0.0},
3688 { 1.0, 1.0, 0.0},
3689 { 1.0, -1.0, 0.0},
3691 static DWORD diffuse[] =
3693 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
3695 static WORD indices[] =
3697 0, 1, 2, 2, 3, 0
3700 IDirectDrawSurface7 *rt;
3701 IDirect3DDevice7 *device;
3702 D3DCOLOR color;
3703 HWND window;
3704 HRESULT hr;
3705 D3DDRAWPRIMITIVESTRIDEDDATA strided;
3707 window = create_window();
3708 if (!(device = create_device(window, DDSCL_NORMAL)))
3710 skip("Failed to create a 3D device, skipping test.\n");
3711 DestroyWindow(window);
3712 return;
3715 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
3716 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
3718 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
3719 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
3720 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 1.0f, 0);
3721 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
3722 hr = IDirect3DDevice7_BeginScene(device);
3723 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3725 memset(&strided, 0x55, sizeof(strided));
3726 strided.position.lpvData = position;
3727 strided.position.dwStride = sizeof(*position);
3728 strided.diffuse.lpvData = diffuse;
3729 strided.diffuse.dwStride = sizeof(*diffuse);
3730 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device, D3DPT_TRIANGLELIST, D3DFVF_XYZ | D3DFVF_DIFFUSE,
3731 &strided, 4, indices, 6, 0);
3732 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3734 hr = IDirect3DDevice7_EndScene(device);
3735 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3737 color = get_surface_color(rt, 320, 240);
3738 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
3740 IDirectDrawSurface7_Release(rt);
3741 IDirect3DDevice7_Release(device);
3742 DestroyWindow(window);
3745 static void test_lighting(void)
3747 static D3DMATRIX mat =
3749 1.0f, 0.0f, 0.0f, 0.0f,
3750 0.0f, 1.0f, 0.0f, 0.0f,
3751 0.0f, 0.0f, 1.0f, 0.0f,
3752 0.0f, 0.0f, 0.0f, 1.0f,
3754 mat_singular =
3756 1.0f, 0.0f, 1.0f, 0.0f,
3757 0.0f, 1.0f, 0.0f, 0.0f,
3758 1.0f, 0.0f, 1.0f, 0.0f,
3759 0.0f, 0.0f, 0.5f, 1.0f,
3761 mat_transf =
3763 0.0f, 0.0f, 1.0f, 0.0f,
3764 0.0f, 1.0f, 0.0f, 0.0f,
3765 -1.0f, 0.0f, 0.0f, 0.0f,
3766 10.f, 10.0f, 10.0f, 1.0f,
3768 mat_nonaffine =
3770 1.0f, 0.0f, 0.0f, 0.0f,
3771 0.0f, 1.0f, 0.0f, 0.0f,
3772 0.0f, 0.0f, 1.0f, -1.0f,
3773 10.f, 10.0f, 10.0f, 0.0f,
3775 static struct vertex
3777 struct vec3 position;
3778 DWORD diffuse;
3780 unlitquad[] =
3782 {{-1.0f, -1.0f, 0.1f}, 0xffff0000},
3783 {{-1.0f, 0.0f, 0.1f}, 0xffff0000},
3784 {{ 0.0f, 0.0f, 0.1f}, 0xffff0000},
3785 {{ 0.0f, -1.0f, 0.1f}, 0xffff0000},
3787 litquad[] =
3789 {{-1.0f, 0.0f, 0.1f}, 0xff00ff00},
3790 {{-1.0f, 1.0f, 0.1f}, 0xff00ff00},
3791 {{ 0.0f, 1.0f, 0.1f}, 0xff00ff00},
3792 {{ 0.0f, 0.0f, 0.1f}, 0xff00ff00},
3794 static struct vertex_normal
3796 struct vec3 position;
3797 struct vec3 normal;
3798 DWORD diffuse;
3800 unlitnquad[] =
3802 {{0.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3803 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3804 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3805 {{1.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
3807 litnquad[] =
3809 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3810 {{0.0f, 1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3811 {{1.0f, 1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3812 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
3814 nquad[] =
3816 {{-1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3817 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3818 {{ 1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3819 {{ 1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3821 rotatedquad[] =
3823 {{-10.0f, -11.0f, 11.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3824 {{-10.0f, -9.0f, 11.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3825 {{-10.0f, -9.0f, 9.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3826 {{-10.0f, -11.0f, 9.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
3828 translatedquad[] =
3830 {{-11.0f, -11.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3831 {{-11.0f, -9.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3832 {{ -9.0f, -9.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3833 {{ -9.0f, -11.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
3835 static WORD indices[] = {0, 1, 2, 2, 3, 0};
3836 static const struct
3838 D3DMATRIX *world_matrix;
3839 void *quad;
3840 DWORD expected, expected_process_vertices;
3841 const char *message;
3842 BOOL process_vertices_todo;
3844 tests[] =
3846 {&mat, nquad, 0x000000ff, 0xff0000ff, "Lit quad with light"},
3847 {&mat_singular, nquad, 0x000000ff, 0xff000000, "Lit quad with singular world matrix", TRUE},
3848 {&mat_transf, rotatedquad, 0x000000ff, 0xff0000ff, "Lit quad with transformation matrix"},
3849 {&mat_nonaffine, translatedquad, 0x00000000, 0xff000000, "Lit quad with non-affine matrix"},
3852 DWORD nfvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL;
3853 IDirect3DVertexBuffer7 *src_vb1, *src_vb2, *dst_vb;
3854 DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
3855 struct vertex_normal *src_data2;
3856 D3DVERTEXBUFFERDESC vb_desc;
3857 struct vertex *src_data1;
3858 IDirect3DDevice7 *device;
3859 IDirectDrawSurface7 *rt;
3860 IDirectDraw7 *ddraw;
3861 IDirect3D7 *d3d;
3862 D3DCOLOR color;
3863 ULONG refcount;
3864 unsigned int i;
3865 BOOL is_warp;
3866 HWND window;
3867 HRESULT hr;
3868 struct
3870 struct vec4 position;
3871 DWORD diffuse;
3872 DWORD specular;
3874 *dst_data;
3876 window = create_window();
3877 if (!(device = create_device(window, DDSCL_NORMAL)))
3879 skip("Failed to create a 3D device, skipping test.\n");
3880 DestroyWindow(window);
3881 return;
3883 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
3884 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3885 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
3886 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3888 is_warp = ddraw_is_warp(ddraw);
3890 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
3891 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3893 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
3894 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3896 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
3897 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3898 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
3899 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3900 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
3901 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3902 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
3903 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3904 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
3905 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3906 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
3907 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3908 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
3909 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3910 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
3911 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3913 hr = IDirect3DDevice7_BeginScene(device);
3914 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3916 memset(&vb_desc, 0, sizeof(vb_desc));
3917 vb_desc.dwSize = sizeof(vb_desc);
3918 vb_desc.dwFVF = fvf;
3919 vb_desc.dwNumVertices = 2;
3920 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &src_vb1, 0);
3921 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3922 vb_desc.dwSize = sizeof(vb_desc);
3923 vb_desc.dwFVF = nfvf;
3924 vb_desc.dwNumVertices = 2;
3925 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &src_vb2, 0);
3926 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3928 memset(&vb_desc, 0, sizeof(vb_desc));
3929 vb_desc.dwSize = sizeof(vb_desc);
3930 vb_desc.dwFVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR;
3931 vb_desc.dwNumVertices = 4;
3932 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &dst_vb, 0);
3933 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3935 hr = IDirect3DVertexBuffer7_Lock(src_vb1, 0, (void **)&src_data1, NULL);
3936 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3937 memcpy(src_data1, unlitquad, sizeof(*src_data1));
3938 memcpy(&src_data1[1], litquad, sizeof(*src_data1));
3939 hr = IDirect3DVertexBuffer7_Unlock(src_vb1);
3940 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3942 hr = IDirect3DVertexBuffer7_Lock(src_vb2, 0, (void **)&src_data2, NULL);
3943 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3944 memcpy(src_data2, unlitnquad, sizeof(*src_data2));
3945 memcpy(&src_data2[1], litnquad, sizeof(*src_data2));
3946 hr = IDirect3DVertexBuffer7_Unlock(src_vb2);
3947 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3949 /* No lights are defined... That means, lit vertices should be entirely black. */
3950 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
3951 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3952 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0,
3953 1, src_vb1, 0, device, 0);
3954 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3955 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, unlitquad, 4,
3956 indices, 6, 0);
3957 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3959 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
3960 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3961 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 1,
3962 1, src_vb1, 1, device, 0);
3963 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3964 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, litquad, 4,
3965 indices, 6, 0);
3966 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3968 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
3969 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3970 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 2,
3971 1, src_vb2, 0, device, 0);
3972 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3973 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, unlitnquad, 4,
3974 indices, 6, 0);
3975 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3977 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
3978 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3979 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 3,
3980 1, src_vb2, 1, device, 0);
3981 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3982 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, litnquad, 4,
3983 indices, 6, 0);
3984 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3986 hr = IDirect3DDevice7_EndScene(device);
3987 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3989 hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL);
3990 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3992 color = get_surface_color(rt, 160, 360);
3993 ok(color == 0x00ff0000, "Unlit quad without normals has color 0x%08x, expected 0x00ff0000.\n", color);
3994 ok(dst_data[0].diffuse == 0xffff0000,
3995 "Unlit quad without normals has color 0x%08x, expected 0xffff0000.\n", dst_data[0].diffuse);
3996 ok(!dst_data[0].specular,
3997 "Unexpected specular color 0x%08x.\n", dst_data[0].specular);
3998 color = get_surface_color(rt, 160, 120);
3999 /* Broken on some of WARP drivers. */
4000 ok(color == 0x00000000 || broken(is_warp && (color == 0x000000ff || color == 0x00ff00ff)),
4001 "Lit quad without normals has color 0x%08x, expected 0x00000000.\n", color);
4002 ok(dst_data[1].diffuse == 0xff000000,
4003 "Lit quad without normals has color 0x%08x, expected 0xff000000.\n", dst_data[1].diffuse);
4004 ok(!dst_data[1].specular,
4005 "Unexpected specular color 0x%08x.\n", dst_data[1].specular);
4006 color = get_surface_color(rt, 480, 360);
4007 ok(color == 0x000000ff, "Unlit quad with normals has color 0x%08x, expected 0x000000ff.\n", color);
4008 ok(dst_data[2].diffuse == 0xff0000ff,
4009 "Unlit quad with normals has color 0x%08x, expected 0xff0000ff.\n", dst_data[2].diffuse);
4010 ok(!dst_data[2].specular,
4011 "Unexpected specular color 0x%08x.\n", dst_data[2].specular);
4012 color = get_surface_color(rt, 480, 120);
4013 ok(color == 0x00000000 || broken(is_warp && (color == 0x000000ff || color == 0x00ff00ff)),
4014 "Lit quad with normals has color 0x%08x, expected 0x00000000.\n", color);
4015 ok(dst_data[3].diffuse == 0xff000000,
4016 "Lit quad with normals has color 0x%08x, expected 0xff000000.\n", dst_data[3].diffuse);
4017 ok(!dst_data[3].specular,
4018 "Unexpected specular color 0x%08x.\n", dst_data[3].specular);
4020 hr = IDirect3DVertexBuffer7_Unlock(dst_vb);
4021 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4023 hr = IDirect3DDevice7_LightEnable(device, 0, TRUE);
4024 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4026 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4028 hr = IDirect3DVertexBuffer7_Lock(src_vb2, 0, (void **)&src_data2, NULL);
4029 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4030 memcpy(src_data2, tests[i].quad, sizeof(*src_data2));
4031 hr = IDirect3DVertexBuffer7_Unlock(src_vb2);
4032 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4034 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, tests[i].world_matrix);
4035 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4037 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
4038 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4040 hr = IDirect3DDevice7_BeginScene(device);
4041 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4043 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 0,
4044 1, src_vb2, 0, device, 0);
4045 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4047 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, tests[i].quad,
4048 4, indices, 6, 0);
4049 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4051 hr = IDirect3DDevice7_EndScene(device);
4052 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4054 hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL);
4055 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4057 color = get_surface_color(rt, 320, 240);
4058 ok(color == tests[i].expected || broken(is_warp && (color == 0x000000ff || color == 0x00ff00ff)),
4059 "%s has color 0x%08x.\n", tests[i].message, color);
4060 todo_wine_if(tests[i].process_vertices_todo)
4061 ok(dst_data[0].diffuse == tests[i].expected_process_vertices,
4062 "%s has color 0x%08x.\n", tests[i].message, dst_data[0].diffuse);
4063 ok(!dst_data[0].specular,
4064 "%s has specular color 0x%08x.\n", tests[i].message, dst_data[0].specular);
4066 hr = IDirect3DVertexBuffer7_Unlock(dst_vb);
4067 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4070 IDirect3DVertexBuffer7_Release(src_vb1);
4071 IDirect3DVertexBuffer7_Release(src_vb2);
4072 IDirect3DVertexBuffer7_Release(dst_vb);
4074 IDirectDrawSurface7_Release(rt);
4076 IDirectDraw7_Release(ddraw);
4077 IDirect3D7_Release(d3d);
4078 refcount = IDirect3DDevice7_Release(device);
4079 ok(!refcount, "Device has %u references left.\n", refcount);
4080 DestroyWindow(window);
4083 static void test_specular_lighting(void)
4085 static const unsigned int vertices_side = 5;
4086 const unsigned int indices_count = (vertices_side - 1) * (vertices_side - 1) * 2 * 3;
4087 static const DWORD fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
4088 static D3DMATRIX mat =
4090 1.0f, 0.0f, 0.0f, 0.0f,
4091 0.0f, 1.0f, 0.0f, 0.0f,
4092 0.0f, 0.0f, 1.0f, 0.0f,
4093 0.0f, 0.0f, 0.0f, 1.0f,
4095 static const struct vertex
4097 struct vec3 position;
4098 struct vec3 normal;
4100 vertices[] =
4102 {{-0.5f, -0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4103 {{ 0.0f, -0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4104 {{ 0.5f, -0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4105 {{-0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4106 {{ 0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4107 {{ 0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4108 {{-0.5f, 0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4109 {{ 0.0f, 0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4110 {{ 0.5f, 0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4113 static D3DLIGHT7 directional =
4115 D3DLIGHT_DIRECTIONAL,
4116 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4117 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4118 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4119 {{0.0f}, {0.0f}, {0.0f}},
4120 {{0.0f}, {0.0f}, {1.0f}},
4122 point =
4124 D3DLIGHT_POINT,
4125 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4126 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4127 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4128 {{0.0f}, {0.0f}, {0.0f}},
4129 {{0.0f}, {0.0f}, {0.0f}},
4130 100.0f,
4131 0.0f,
4132 0.0f, 0.0f, 1.0f,
4134 spot =
4136 D3DLIGHT_SPOT,
4137 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4138 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4139 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4140 {{0.0f}, {0.0f}, {0.0f}},
4141 {{0.0f}, {0.0f}, {1.0f}},
4142 100.0f,
4143 1.0f,
4144 0.0f, 0.0f, 1.0f,
4145 M_PI / 12.0f, M_PI / 3.0f
4147 /* The chosen range value makes the test fail when using a manhattan
4148 * distance metric vs the correct euclidean distance. */
4149 point_range =
4151 D3DLIGHT_POINT,
4152 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4153 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4154 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4155 {{0.0f}, {0.0f}, {0.0f}},
4156 {{0.0f}, {0.0f}, {0.0f}},
4157 1.2f,
4158 0.0f,
4159 0.0f, 0.0f, 1.0f,
4161 point_side =
4163 D3DLIGHT_POINT,
4164 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4165 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4166 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4167 {{-1.1f}, {0.0f}, {1.1f}},
4168 {{0.0f}, {0.0f}, {0.0f}},
4169 100.0f,
4170 0.0f,
4171 1.0f, 0.0f, 0.0f,
4173 static const struct expected_color
4175 unsigned int x, y;
4176 D3DCOLOR color;
4178 expected_directional[] =
4180 {160, 120, 0x00ffffff},
4181 {320, 120, 0x00ffffff},
4182 {480, 120, 0x00ffffff},
4183 {160, 240, 0x00ffffff},
4184 {320, 240, 0x00ffffff},
4185 {480, 240, 0x00ffffff},
4186 {160, 360, 0x00ffffff},
4187 {320, 360, 0x00ffffff},
4188 {480, 360, 0x00ffffff},
4190 expected_directional_local[] =
4192 {160, 120, 0x003c3c3c},
4193 {320, 120, 0x00717171},
4194 {480, 120, 0x003c3c3c},
4195 {160, 240, 0x00717171},
4196 {320, 240, 0x00ffffff},
4197 {480, 240, 0x00717171},
4198 {160, 360, 0x003c3c3c},
4199 {320, 360, 0x00717171},
4200 {480, 360, 0x003c3c3c},
4202 expected_point[] =
4204 {160, 120, 0x00282828},
4205 {320, 120, 0x005a5a5a},
4206 {480, 120, 0x00282828},
4207 {160, 240, 0x005a5a5a},
4208 {320, 240, 0x00ffffff},
4209 {480, 240, 0x005a5a5a},
4210 {160, 360, 0x00282828},
4211 {320, 360, 0x005a5a5a},
4212 {480, 360, 0x00282828},
4214 expected_point_local[] =
4216 {160, 120, 0x00000000},
4217 {320, 120, 0x00070707},
4218 {480, 120, 0x00000000},
4219 {160, 240, 0x00070707},
4220 {320, 240, 0x00ffffff},
4221 {480, 240, 0x00070707},
4222 {160, 360, 0x00000000},
4223 {320, 360, 0x00070707},
4224 {480, 360, 0x00000000},
4226 expected_spot[] =
4228 {160, 120, 0x00000000},
4229 {320, 120, 0x00141414},
4230 {480, 120, 0x00000000},
4231 {160, 240, 0x00141414},
4232 {320, 240, 0x00ffffff},
4233 {480, 240, 0x00141414},
4234 {160, 360, 0x00000000},
4235 {320, 360, 0x00141414},
4236 {480, 360, 0x00000000},
4238 expected_spot_local[] =
4240 {160, 120, 0x00000000},
4241 {320, 120, 0x00020202},
4242 {480, 120, 0x00000000},
4243 {160, 240, 0x00020202},
4244 {320, 240, 0x00ffffff},
4245 {480, 240, 0x00020202},
4246 {160, 360, 0x00000000},
4247 {320, 360, 0x00020202},
4248 {480, 360, 0x00000000},
4250 expected_point_range[] =
4252 {160, 120, 0x00000000},
4253 {320, 120, 0x005a5a5a},
4254 {480, 120, 0x00000000},
4255 {160, 240, 0x005a5a5a},
4256 {320, 240, 0x00ffffff},
4257 {480, 240, 0x005a5a5a},
4258 {160, 360, 0x00000000},
4259 {320, 360, 0x005a5a5a},
4260 {480, 360, 0x00000000},
4262 expected_point_side[] =
4264 {160, 120, 0x00000000},
4265 {320, 120, 0x00000000},
4266 {480, 120, 0x00000000},
4267 {160, 240, 0x00000000},
4268 {320, 240, 0x00000000},
4269 {480, 240, 0x00000000},
4270 {160, 360, 0x00000000},
4271 {320, 360, 0x00000000},
4272 {480, 360, 0x00000000},
4274 expected_directional_local_0[] =
4276 {160, 120, 0x00ffffff},
4277 {320, 120, 0x00ffffff},
4278 {480, 120, 0x00ffffff},
4279 {160, 240, 0x00ffffff},
4280 {320, 240, 0x00ffffff},
4281 {480, 240, 0x00ffffff},
4282 {160, 360, 0x00ffffff},
4283 {320, 360, 0x00ffffff},
4284 {480, 360, 0x00ffffff},
4286 expected_point_0[] =
4288 {160, 120, 0x00aaaaaa},
4289 {320, 120, 0x00cccccc},
4290 {480, 120, 0x00aaaaaa},
4291 {160, 240, 0x00cccccc},
4292 {320, 240, 0x00ffffff},
4293 {480, 240, 0x00cccccc},
4294 {160, 360, 0x00aaaaaa},
4295 {320, 360, 0x00cccccc},
4296 {480, 360, 0x00aaaaaa},
4298 expected_spot_0[] =
4300 {160, 120, 0x00000000},
4301 {320, 120, 0x002e2e2e},
4302 {480, 120, 0x00000000},
4303 {160, 240, 0x002e2e2e},
4304 {320, 240, 0x00ffffff},
4305 {480, 240, 0x002e2e2e},
4306 {160, 360, 0x00000000},
4307 {320, 360, 0x002e2e2e},
4308 {480, 360, 0x00000000},
4310 expected_point_range_0[] =
4312 {160, 120, 0x00000000},
4313 {320, 120, 0x00cccccc},
4314 {480, 120, 0x00000000},
4315 {160, 240, 0x00cccccc},
4316 {320, 240, 0x00ffffff},
4317 {480, 240, 0x00cccccc},
4318 {160, 360, 0x00000000},
4319 {320, 360, 0x00cccccc},
4320 {480, 360, 0x00000000},
4322 static const struct
4324 D3DLIGHT7 *light;
4325 BOOL local_viewer;
4326 float specular_power;
4327 const struct expected_color *expected, *expected_process_vertices;
4328 unsigned int expected_count;
4329 BOOL todo_process_vertices;
4331 tests[] =
4333 {&directional, FALSE, 30.0f, expected_directional, expected_directional,
4334 ARRAY_SIZE(expected_directional)},
4335 {&directional, TRUE, 30.0f, expected_directional_local, expected_directional_local,
4336 ARRAY_SIZE(expected_directional_local)},
4337 {&point, FALSE, 30.0f, expected_point, expected_point, ARRAY_SIZE(expected_point)},
4338 {&point, TRUE, 30.0f, expected_point_local, expected_point_local, ARRAY_SIZE(expected_point_local)},
4339 {&spot, FALSE, 30.0f, expected_spot, expected_spot, ARRAY_SIZE(expected_spot)},
4340 {&spot, TRUE, 30.0f, expected_spot_local, expected_spot_local, ARRAY_SIZE(expected_spot_local)},
4341 {&point_range, FALSE, 30.0f, expected_point_range, expected_point_range,
4342 ARRAY_SIZE(expected_point_range)},
4344 /* For zero material shininess _ProcessVertices() seem to keep non-zero material shininess set previously. */
4345 {&point_side, TRUE, 0.0f, expected_point_side, expected_point_side, ARRAY_SIZE(expected_point_side), TRUE},
4346 {&directional, FALSE, 0.0f, expected_directional, expected_directional,
4347 ARRAY_SIZE(expected_directional), TRUE},
4348 {&directional, TRUE, 0.0f, expected_directional_local_0, expected_directional_local,
4349 ARRAY_SIZE(expected_directional_local_0), TRUE},
4350 {&point, FALSE, 0.0f, expected_point_0, expected_point, ARRAY_SIZE(expected_point_0), TRUE},
4351 {&point, TRUE, 0.0f, expected_point_0, expected_point_local, ARRAY_SIZE(expected_point_0), TRUE},
4352 {&spot, FALSE, 0.0f, expected_spot_0, expected_spot, ARRAY_SIZE(expected_spot_0), TRUE},
4353 {&spot, TRUE, 0.0f, expected_spot_0, expected_spot_local, ARRAY_SIZE(expected_spot_0), TRUE},
4354 {&point_range, FALSE, 0.0f, expected_point_range_0, expected_point_range, ARRAY_SIZE(expected_point_range_0), TRUE},
4357 IDirect3DVertexBuffer7 *src_vb, *dst_vb;
4358 D3DCOLOR color, expected_color;
4359 D3DVERTEXBUFFERDESC vb_desc;
4360 IDirect3DDevice7 *device;
4361 unsigned int i, j, x, y;
4362 IDirectDrawSurface7 *rt;
4363 D3DMATERIAL7 material;
4364 struct vec3 *src_data;
4365 struct vertex *quad;
4366 IDirect3D7 *d3d;
4367 ULONG refcount;
4368 WORD *indices;
4369 HWND window;
4370 HRESULT hr;
4371 struct
4373 struct vec4 position;
4374 DWORD diffuse;
4375 DWORD specular;
4376 } *dst_data;
4378 window = create_window();
4379 if (!(device = create_device(window, DDSCL_NORMAL)))
4381 skip("Failed to create a 3D device, skipping test.\n");
4382 DestroyWindow(window);
4383 return;
4385 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
4386 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4388 quad = heap_alloc(vertices_side * vertices_side * sizeof(*quad));
4389 indices = heap_alloc(indices_count * sizeof(*indices));
4390 for (i = 0, y = 0; y < vertices_side; ++y)
4392 for (x = 0; x < vertices_side; ++x)
4394 quad[i].position.x = x * 2.0f / (vertices_side - 1) - 1.0f;
4395 quad[i].position.y = y * 2.0f / (vertices_side - 1) - 1.0f;
4396 quad[i].position.z = 1.0f;
4397 quad[i].normal.x = 0.0f;
4398 quad[i].normal.y = 0.0f;
4399 quad[i++].normal.z = -1.0f;
4402 for (i = 0, y = 0; y < (vertices_side - 1); ++y)
4404 for (x = 0; x < (vertices_side - 1); ++x)
4406 indices[i++] = y * vertices_side + x + 1;
4407 indices[i++] = y * vertices_side + x;
4408 indices[i++] = (y + 1) * vertices_side + x;
4409 indices[i++] = y * vertices_side + x + 1;
4410 indices[i++] = (y + 1) * vertices_side + x;
4411 indices[i++] = (y + 1) * vertices_side + x + 1;
4415 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
4416 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4418 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
4419 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4420 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
4421 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4422 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
4423 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4424 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
4425 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4426 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
4427 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4428 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
4429 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4431 hr = IDirect3DDevice7_LightEnable(device, 0, TRUE);
4432 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4433 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, TRUE);
4434 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4436 memset(&vb_desc, 0, sizeof(vb_desc));
4437 vb_desc.dwSize = sizeof(vb_desc);
4438 vb_desc.dwFVF = fvf;
4439 vb_desc.dwNumVertices = ARRAY_SIZE(vertices);
4440 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &src_vb, 0);
4441 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4442 hr = IDirect3DVertexBuffer7_Lock(src_vb, 0, (void **)&src_data, NULL);
4443 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4444 memcpy(src_data, vertices, sizeof(vertices));
4445 hr = IDirect3DVertexBuffer7_Unlock(src_vb);
4446 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4448 memset(&vb_desc, 0, sizeof(vb_desc));
4449 vb_desc.dwSize = sizeof(vb_desc);
4450 vb_desc.dwFVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR;
4451 vb_desc.dwNumVertices = ARRAY_SIZE(vertices);
4452 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &dst_vb, 0);
4453 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4455 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4457 hr = IDirect3DDevice7_SetLight(device, 0, tests[i].light);
4458 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4460 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LOCALVIEWER, tests[i].local_viewer);
4461 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4463 memset(&material, 0, sizeof(material));
4464 U1(U2(material).specular).r = 1.0f;
4465 U2(U2(material).specular).g = 1.0f;
4466 U3(U2(material).specular).b = 1.0f;
4467 U4(U2(material).specular).a = 0.5f;
4468 U4(material).power = tests[i].specular_power;
4469 hr = IDirect3DDevice7_SetMaterial(device, &material);
4470 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4472 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
4473 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4475 hr = IDirect3DDevice7_BeginScene(device);
4476 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4478 hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL);
4479 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4480 memset(dst_data, 0, sizeof(*dst_data) * ARRAY_SIZE(vertices));
4481 hr = IDirect3DVertexBuffer7_Unlock(dst_vb);
4482 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4484 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 0,
4485 ARRAY_SIZE(vertices), src_vb, 0, device, 0);
4486 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4488 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, quad,
4489 vertices_side * vertices_side, indices, indices_count, 0);
4490 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4492 hr = IDirect3DDevice7_EndScene(device);
4493 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4495 hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL);
4496 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4498 ok(tests[i].expected_count == ARRAY_SIZE(vertices), "Array size mismatch.\n");
4499 for (j = 0; j < tests[i].expected_count; ++j)
4501 color = get_surface_color(rt, tests[i].expected[j].x, tests[i].expected[j].y);
4502 ok(compare_color(color, tests[i].expected[j].color, 1),
4503 "Expected color 0x%08x at location (%u, %u), got 0x%08x, case %u.\n",
4504 tests[i].expected[j].color, tests[i].expected[j].x,
4505 tests[i].expected[j].y, color, i);
4506 ok(!dst_data[j].diffuse, "Expected color 0x00000000 for vertex %u, got 0x%08x, case %u.\n",
4507 j, dst_data[j].diffuse, i);
4508 expected_color = tests[i].expected_process_vertices[j].color | 0x80000000;
4509 todo_wine_if(tests[i].todo_process_vertices && dst_data[j].specular != expected_color)
4510 ok(compare_color(dst_data[j].specular, expected_color, 1),
4511 "Expected color 0x%08x for vertex %u, got 0x%08x, case %u.\n",
4512 expected_color, j, dst_data[j].specular, i);
4514 hr = IDirect3DVertexBuffer7_Unlock(dst_vb);
4515 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4518 IDirect3DVertexBuffer7_Release(dst_vb);
4519 IDirect3DVertexBuffer7_Release(src_vb);
4520 IDirectDrawSurface7_Release(rt);
4522 IDirect3D7_Release(d3d);
4523 refcount = IDirect3DDevice7_Release(device);
4524 ok(!refcount, "Device has %u references left.\n", refcount);
4525 DestroyWindow(window);
4526 heap_free(indices);
4527 heap_free(quad);
4530 static void test_clear_rect_count(void)
4532 IDirectDrawSurface7 *rt;
4533 IDirect3DDevice7 *device;
4534 D3DCOLOR color;
4535 HWND window;
4536 HRESULT hr;
4537 D3DRECT rect = {{0}, {0}, {640}, {480}};
4539 window = create_window();
4540 if (!(device = create_device(window, DDSCL_NORMAL)))
4542 skip("Failed to create a 3D device, skipping test.\n");
4543 DestroyWindow(window);
4544 return;
4547 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
4548 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4550 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ffffff, 1.0f, 0);
4551 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4552 hr = IDirect3DDevice7_Clear(device, 0, &rect, D3DCLEAR_TARGET, 0x00ff0000, 1.0f, 0);
4553 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4555 color = get_surface_color(rt, 320, 240);
4556 ok(compare_color(color, 0x00ffffff, 1) || broken(compare_color(color, 0x00ff0000, 1)),
4557 "Clear with count = 0, rect != NULL has color %#08x.\n", color);
4559 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ffffff, 1.0f, 0);
4560 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4561 hr = IDirect3DDevice7_Clear(device, 1, NULL, D3DCLEAR_TARGET, 0x0000ff00, 1.0f, 0);
4562 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4564 color = get_surface_color(rt, 320, 240);
4565 ok(compare_color(color, 0x0000ff00, 1),
4566 "Clear with count = 1, rect = NULL has color %#08x.\n", color);
4568 IDirectDrawSurface7_Release(rt);
4569 IDirect3DDevice7_Release(device);
4570 DestroyWindow(window);
4573 static BOOL test_mode_restored(IDirectDraw7 *ddraw, HWND window)
4575 DDSURFACEDESC2 ddsd1, ddsd2;
4576 HRESULT hr;
4578 memset(&ddsd1, 0, sizeof(ddsd1));
4579 ddsd1.dwSize = sizeof(ddsd1);
4580 hr = IDirectDraw7_GetDisplayMode(ddraw, &ddsd1);
4581 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
4583 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
4584 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4585 hr = set_display_mode(ddraw, 640, 480);
4586 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
4587 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
4588 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4590 memset(&ddsd2, 0, sizeof(ddsd2));
4591 ddsd2.dwSize = sizeof(ddsd2);
4592 hr = IDirectDraw7_GetDisplayMode(ddraw, &ddsd2);
4593 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
4594 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
4595 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
4597 return ddsd1.dwWidth == ddsd2.dwWidth && ddsd1.dwHeight == ddsd2.dwHeight;
4600 static void test_coop_level_versions(void)
4602 HWND window;
4603 IDirectDraw *ddraw;
4604 HRESULT hr;
4605 BOOL restored;
4606 IDirectDrawSurface *surface;
4607 IDirectDraw7 *ddraw7;
4608 DDSURFACEDESC ddsd;
4610 window = create_window();
4611 ddraw7 = create_ddraw();
4612 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4613 /* Newly created ddraw objects restore the mode on ddraw2+::SetCooperativeLevel(NORMAL) */
4614 restored = test_mode_restored(ddraw7, window);
4615 ok(restored, "Display mode not restored in new ddraw object\n");
4617 /* A failing ddraw1::SetCooperativeLevel call does not have an effect */
4618 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4619 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4621 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4622 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
4623 restored = test_mode_restored(ddraw7, window);
4624 ok(restored, "Display mode not restored after bad ddraw1::SetCooperativeLevel call\n");
4626 /* A successful one does */
4627 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4628 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4629 restored = test_mode_restored(ddraw7, window);
4630 ok(!restored, "Display mode restored after good ddraw1::SetCooperativeLevel call\n");
4632 IDirectDraw_Release(ddraw);
4633 IDirectDraw7_Release(ddraw7);
4635 ddraw7 = create_ddraw();
4636 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4637 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4638 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4640 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_SETFOCUSWINDOW);
4641 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4642 restored = test_mode_restored(ddraw7, window);
4643 ok(!restored, "Display mode restored after ddraw1::SetCooperativeLevel(SETFOCUSWINDOW) call\n");
4645 IDirectDraw_Release(ddraw);
4646 IDirectDraw7_Release(ddraw7);
4648 /* A failing call does not restore the ddraw2+ behavior */
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 = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4657 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
4658 restored = test_mode_restored(ddraw7, window);
4659 ok(!restored, "Display mode restored after good-bad ddraw1::SetCooperativeLevel() call sequence\n");
4661 IDirectDraw_Release(ddraw);
4662 IDirectDraw7_Release(ddraw7);
4664 /* Neither does a sequence of successful calls with the new interface */
4665 ddraw7 = create_ddraw();
4666 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4667 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4668 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4670 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4671 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4672 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
4673 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4674 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
4675 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4677 restored = test_mode_restored(ddraw7, window);
4678 ok(!restored, "Display mode restored after ddraw1-ddraw7 SetCooperativeLevel() call sequence\n");
4679 IDirectDraw_Release(ddraw);
4680 IDirectDraw7_Release(ddraw7);
4682 /* ddraw1::CreateSurface does not triger the ddraw1 behavior */
4683 ddraw7 = create_ddraw();
4684 ok(!!ddraw7, "Failed to create a ddraw object.\n");
4685 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
4686 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4688 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
4689 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
4691 memset(&ddsd, 0, sizeof(ddsd));
4692 ddsd.dwSize = sizeof(ddsd);
4693 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
4694 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4695 ddsd.dwWidth = ddsd.dwHeight = 8;
4696 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
4697 ok(SUCCEEDED(hr), "CreateSurface failed, hr %#x.\n", hr);
4698 IDirectDrawSurface_Release(surface);
4699 restored = test_mode_restored(ddraw7, window);
4700 ok(restored, "Display mode not restored after ddraw1::CreateSurface() call\n");
4702 IDirectDraw_Release(ddraw);
4703 IDirectDraw7_Release(ddraw7);
4704 DestroyWindow(window);
4707 static void test_fog_special(void)
4709 static struct
4711 struct vec3 position;
4712 D3DCOLOR diffuse;
4714 quad[] =
4716 {{ -1.0f, 1.0f, 0.0f}, 0xff00ff00},
4717 {{ 1.0f, 1.0f, 1.0f}, 0xff00ff00},
4718 {{ -1.0f, -1.0f, 0.0f}, 0xff00ff00},
4719 {{ 1.0f, -1.0f, 1.0f}, 0xff00ff00},
4721 static const struct
4723 DWORD vertexmode, tablemode;
4724 D3DCOLOR color_left, color_right;
4726 tests[] =
4728 {D3DFOG_LINEAR, D3DFOG_NONE, 0x00ff0000, 0x00ff0000},
4729 {D3DFOG_NONE, D3DFOG_LINEAR, 0x0000ff00, 0x00ff0000},
4731 union
4733 float f;
4734 DWORD d;
4735 } conv;
4736 D3DCOLOR color;
4737 HRESULT hr;
4738 unsigned int i;
4739 HWND window;
4740 IDirect3DDevice7 *device;
4741 IDirectDrawSurface7 *rt;
4743 window = create_window();
4744 if (!(device = create_device(window, DDSCL_NORMAL)))
4746 skip("Failed to create a 3D device, skipping test.\n");
4747 DestroyWindow(window);
4748 return;
4751 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
4752 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4754 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
4755 ok(SUCCEEDED(hr), "Failed to enable fog, hr %#x.\n", hr);
4756 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0xffff0000);
4757 ok(SUCCEEDED(hr), "Failed to set fog color, hr %#x.\n", hr);
4758 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
4759 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
4760 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
4761 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
4763 conv.f = 0.5f;
4764 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGSTART, conv.d);
4765 ok(SUCCEEDED(hr), "Failed to set fog start, hr %#x.\n", hr);
4766 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGEND, conv.d);
4767 ok(SUCCEEDED(hr), "Failed to set fog end, hr %#x.\n", hr);
4769 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4771 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x000000ff, 1.0f, 0);
4772 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4774 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, tests[i].vertexmode);
4775 ok(SUCCEEDED(hr), "Failed to set fogvertexmode, hr %#x.\n", hr);
4776 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, tests[i].tablemode);
4777 ok(SUCCEEDED(hr), "Failed to set fogtablemode, hr %#x.\n", hr);
4779 hr = IDirect3DDevice7_BeginScene(device);
4780 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4781 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, 4, 0);
4782 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4783 hr = IDirect3DDevice7_EndScene(device);
4784 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4786 color = get_surface_color(rt, 310, 240);
4787 ok(compare_color(color, tests[i].color_left, 1),
4788 "Expected left color 0x%08x, got 0x%08x, case %u.\n", tests[i].color_left, color, i);
4789 color = get_surface_color(rt, 330, 240);
4790 ok(compare_color(color, tests[i].color_right, 1),
4791 "Expected right color 0x%08x, got 0x%08x, case %u.\n", tests[i].color_right, color, i);
4794 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
4795 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
4797 IDirectDrawSurface7_Release(rt);
4798 IDirect3DDevice7_Release(device);
4799 DestroyWindow(window);
4802 static void test_lighting_interface_versions(void)
4804 IDirect3DDevice7 *device;
4805 IDirectDrawSurface7 *rt;
4806 D3DCOLOR color;
4807 HWND window;
4808 HRESULT hr;
4809 DWORD rs;
4810 unsigned int i;
4811 ULONG ref;
4812 D3DMATERIAL7 material;
4813 static D3DVERTEX quad[] =
4815 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4816 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4817 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4818 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
4821 #define FVF_COLORVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_SPECULAR)
4822 static struct
4824 struct vec3 position;
4825 struct vec3 normal;
4826 DWORD diffuse, specular;
4828 quad2[] =
4830 {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4831 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4832 {{-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4833 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
4836 static D3DLVERTEX lquad[] =
4838 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4839 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4840 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4841 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
4844 #define FVF_LVERTEX2 (D3DFVF_LVERTEX & ~D3DFVF_RESERVED1)
4845 static struct
4847 struct vec3 position;
4848 DWORD diffuse, specular;
4849 struct vec2 texcoord;
4851 lquad2[] =
4853 {{-1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
4854 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
4855 {{-1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
4856 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
4859 static D3DTLVERTEX tlquad[] =
4861 {{ 0.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4862 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4863 {{ 640.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4864 {{ 640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
4867 static const struct
4869 DWORD vertextype;
4870 void *data;
4871 DWORD d3drs_lighting, d3drs_specular;
4872 DWORD draw_flags;
4873 D3DCOLOR color;
4875 tests[] =
4877 /* Lighting is enabled when D3DFVF_XYZ is used and D3DRENDERSTATE_LIGHTING is
4878 * enabled. D3DDP_DONOTLIGHT is ignored. Lighting is also enabled when normals
4879 * are not available
4881 * Note that the specular result is 0x00000000 when lighting is on even if the
4882 * input vertex has specular color because D3DRENDERSTATE_COLORVERTEX is not
4883 * enabled */
4885 /* 0 */
4886 { D3DFVF_VERTEX, quad, FALSE, FALSE, 0, 0x00ffffff},
4887 { D3DFVF_VERTEX, quad, TRUE, FALSE, 0, 0x0000ff00},
4888 { D3DFVF_VERTEX, quad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
4889 { D3DFVF_VERTEX, quad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
4890 { D3DFVF_VERTEX, quad, FALSE, TRUE, 0, 0x00ffffff},
4891 { D3DFVF_VERTEX, quad, TRUE, TRUE, 0, 0x0000ff00},
4892 { D3DFVF_VERTEX, quad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
4893 { D3DFVF_VERTEX, quad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
4895 /* 8 */
4896 { FVF_COLORVERTEX, quad2, FALSE, FALSE, 0, 0x00ff0000},
4897 { FVF_COLORVERTEX, quad2, TRUE, FALSE, 0, 0x0000ff00},
4898 { FVF_COLORVERTEX, quad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4899 { FVF_COLORVERTEX, quad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
4900 { FVF_COLORVERTEX, quad2, FALSE, TRUE, 0, 0x00ff8080},
4901 { FVF_COLORVERTEX, quad2, TRUE, TRUE, 0, 0x0000ff00},
4902 { FVF_COLORVERTEX, quad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4903 { FVF_COLORVERTEX, quad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
4905 /* 16 */
4906 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, 0, 0x00ff0000},
4907 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, 0, 0x0000ff00},
4908 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4909 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
4910 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, 0, 0x00ff8080},
4911 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, 0, 0x0000ff00},
4912 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4913 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
4915 /* 24 */
4916 { FVF_LVERTEX2, lquad2, FALSE, FALSE, 0, 0x00ff0000},
4917 { FVF_LVERTEX2, lquad2, TRUE, FALSE, 0, 0x0000ff00},
4918 { FVF_LVERTEX2, lquad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
4919 { FVF_LVERTEX2, lquad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
4920 { FVF_LVERTEX2, lquad2, FALSE, TRUE, 0, 0x00ff8080},
4921 { FVF_LVERTEX2, lquad2, TRUE, TRUE, 0, 0x0000ff00},
4922 { FVF_LVERTEX2, lquad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
4923 { FVF_LVERTEX2, lquad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
4925 /* 32 */
4926 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, 0, 0x000000ff},
4927 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, 0, 0x000000ff},
4928 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
4929 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
4930 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, 0, 0x008080ff},
4931 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, 0, 0x008080ff},
4932 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
4933 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
4936 window = create_window();
4937 if (!(device = create_device(window, DDSCL_NORMAL)))
4939 skip("Failed to create a 3D device, skipping test.\n");
4940 DestroyWindow(window);
4941 return;
4944 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
4945 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4947 memset(&material, 0, sizeof(material));
4948 U2(U3(material).emissive).g = 1.0f;
4949 hr = IDirect3DDevice7_SetMaterial(device, &material);
4950 ok(SUCCEEDED(hr), "Failed set material, hr %#x.\n", hr);
4951 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
4952 ok(SUCCEEDED(hr), "Failed to disable z test, hr %#x.\n", hr);
4954 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &rs);
4955 ok(SUCCEEDED(hr), "Failed to get lighting render state, hr %#x.\n", hr);
4956 ok(rs == TRUE, "Initial D3DRENDERSTATE_LIGHTING is %#x, expected TRUE.\n", rs);
4957 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, &rs);
4958 ok(SUCCEEDED(hr), "Failed to get specularenable render state, hr %#x.\n", hr);
4959 ok(rs == FALSE, "Initial D3DRENDERSTATE_SPECULARENABLE is %#x, expected FALSE.\n", rs);
4961 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4963 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff202020, 0.0f, 0);
4964 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
4966 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, tests[i].d3drs_lighting);
4967 ok(SUCCEEDED(hr), "Failed to set lighting render state, hr %#x.\n", hr);
4968 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE,
4969 tests[i].d3drs_specular);
4970 ok(SUCCEEDED(hr), "Failed to set specularenable render state, hr %#x.\n", hr);
4972 hr = IDirect3DDevice7_BeginScene(device);
4973 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4974 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
4975 tests[i].vertextype, tests[i].data, 4, tests[i].draw_flags | D3DDP_WAIT);
4976 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4977 hr = IDirect3DDevice7_EndScene(device);
4978 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4980 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &rs);
4981 ok(SUCCEEDED(hr), "Failed to get lighting render state, hr %#x.\n", hr);
4982 ok(rs == tests[i].d3drs_lighting, "D3DRENDERSTATE_LIGHTING is %#x, expected %#x.\n",
4983 rs, tests[i].d3drs_lighting);
4985 color = get_surface_color(rt, 320, 240);
4986 ok(compare_color(color, tests[i].color, 1),
4987 "Got unexpected color 0x%08x, expected 0x%08x, test %u.\n",
4988 color, tests[i].color, i);
4991 IDirectDrawSurface7_Release(rt);
4992 ref = IDirect3DDevice7_Release(device);
4993 ok(ref == 0, "Device not properly released, refcount %u.\n", ref);
4994 DestroyWindow(window);
4997 static struct
4999 BOOL received;
5000 IDirectDraw7 *ddraw;
5001 HWND window;
5002 DWORD coop_level;
5003 } activateapp_testdata;
5005 static LRESULT CALLBACK activateapp_test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
5007 if (message == WM_ACTIVATEAPP)
5009 if (activateapp_testdata.ddraw)
5011 HRESULT hr;
5012 activateapp_testdata.received = FALSE;
5013 hr = IDirectDraw7_SetCooperativeLevel(activateapp_testdata.ddraw,
5014 activateapp_testdata.window, activateapp_testdata.coop_level);
5015 ok(SUCCEEDED(hr), "Recursive SetCooperativeLevel call failed, hr %#x.\n", hr);
5016 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP during recursive SetCooperativeLevel call.\n");
5018 activateapp_testdata.received = TRUE;
5021 return DefWindowProcA(hwnd, message, wparam, lparam);
5024 static void test_coop_level_activateapp(void)
5026 IDirectDraw7 *ddraw;
5027 HRESULT hr;
5028 HWND window;
5029 WNDCLASSA wc = {0};
5030 DDSURFACEDESC2 ddsd;
5031 IDirectDrawSurface7 *surface;
5033 ddraw = create_ddraw();
5034 ok(!!ddraw, "Failed to create a ddraw object.\n");
5036 wc.lpfnWndProc = activateapp_test_proc;
5037 wc.lpszClassName = "ddraw_test_wndproc_wc";
5038 ok(RegisterClassA(&wc), "Failed to register window class.\n");
5040 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
5041 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
5043 /* Exclusive with window already active. */
5044 SetForegroundWindow(window);
5045 activateapp_testdata.received = FALSE;
5046 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5047 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5048 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP although window was already active.\n");
5049 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5050 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5052 /* Exclusive with window not active. */
5053 SetForegroundWindow(GetDesktopWindow());
5054 activateapp_testdata.received = FALSE;
5055 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5056 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5057 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
5058 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5059 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5061 /* Normal with window not active, then exclusive with the same window. */
5062 SetForegroundWindow(GetDesktopWindow());
5063 activateapp_testdata.received = FALSE;
5064 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5065 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5066 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP when setting DDSCL_NORMAL.\n");
5067 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5068 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5069 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
5070 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5071 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5073 /* Recursive set of DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. */
5074 SetForegroundWindow(GetDesktopWindow());
5075 activateapp_testdata.received = FALSE;
5076 activateapp_testdata.ddraw = ddraw;
5077 activateapp_testdata.window = window;
5078 activateapp_testdata.coop_level = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
5079 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5080 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5081 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
5082 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5083 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5085 /* The recursive call seems to have some bad effect on native ddraw, despite (apparently)
5086 * succeeding. Another switch to exclusive and back to normal is needed to release the
5087 * window properly. Without doing this, SetCooperativeLevel(EXCLUSIVE) will not send
5088 * WM_ACTIVATEAPP messages. */
5089 activateapp_testdata.ddraw = NULL;
5090 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5091 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5092 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5093 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5095 /* Setting DDSCL_NORMAL with recursive invocation. */
5096 SetForegroundWindow(GetDesktopWindow());
5097 activateapp_testdata.received = FALSE;
5098 activateapp_testdata.ddraw = ddraw;
5099 activateapp_testdata.window = window;
5100 activateapp_testdata.coop_level = DDSCL_NORMAL;
5101 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5102 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5103 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
5105 /* DDraw is in exclusive mode now. */
5106 memset(&ddsd, 0, sizeof(ddsd));
5107 ddsd.dwSize = sizeof(ddsd);
5108 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
5109 U5(ddsd).dwBackBufferCount = 1;
5110 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
5111 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5112 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5113 IDirectDrawSurface7_Release(surface);
5115 /* Recover again, just to be sure. */
5116 activateapp_testdata.ddraw = NULL;
5117 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5118 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5119 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5120 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5122 DestroyWindow(window);
5123 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
5124 IDirectDraw7_Release(ddraw);
5127 static void test_texturemanage(void)
5129 IDirectDraw7 *ddraw;
5130 HRESULT hr;
5131 DDSURFACEDESC2 ddsd;
5132 IDirectDrawSurface7 *surface;
5133 unsigned int i;
5134 DDCAPS hal_caps, hel_caps;
5135 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
5136 static const struct
5138 DWORD caps_in, caps2_in;
5139 HRESULT hr;
5140 DWORD caps_out, caps2_out;
5142 tests[] =
5144 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
5145 ~0U, ~0U},
5146 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
5147 ~0U, ~0U},
5148 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
5149 ~0U, ~0U},
5150 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
5151 ~0U, ~0U},
5152 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DD_OK,
5153 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE},
5154 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DD_OK,
5155 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE},
5156 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
5157 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_LOCALVIDMEM, 0},
5158 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
5159 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0},
5161 {0, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
5162 ~0U, ~0U},
5163 {0, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
5164 ~0U, ~0U},
5165 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
5166 ~0U, ~0U},
5167 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
5168 ~0U, ~0U},
5169 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
5170 ~0U, ~0U},
5171 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
5172 ~0U, ~0U},
5173 {DDSCAPS_VIDEOMEMORY, 0, DD_OK,
5174 DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY, 0},
5175 {DDSCAPS_SYSTEMMEMORY, 0, DD_OK,
5176 DDSCAPS_SYSTEMMEMORY, 0},
5179 ddraw = create_ddraw();
5180 ok(!!ddraw, "Failed to create a ddraw object.\n");
5181 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5182 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5184 memset(&hal_caps, 0, sizeof(hal_caps));
5185 hal_caps.dwSize = sizeof(hal_caps);
5186 memset(&hel_caps, 0, sizeof(hel_caps));
5187 hel_caps.dwSize = sizeof(hel_caps);
5188 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, &hel_caps);
5189 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
5190 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps)
5192 skip("Managed textures not supported, skipping managed texture test.\n");
5193 IDirectDraw7_Release(ddraw);
5194 return;
5197 for (i = 0; i < ARRAY_SIZE(tests); ++i)
5199 memset(&ddsd, 0, sizeof(ddsd));
5200 ddsd.dwSize = sizeof(ddsd);
5201 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
5202 ddsd.ddsCaps.dwCaps = tests[i].caps_in;
5203 ddsd.ddsCaps.dwCaps2 = tests[i].caps2_in;
5204 ddsd.dwWidth = 4;
5205 ddsd.dwHeight = 4;
5207 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5208 if (tests[i].hr == DD_OK && is_ddraw64 && (tests[i].caps_in & DDSCAPS_TEXTURE))
5209 todo_wine ok(hr == E_NOINTERFACE, "Test %u: Got unexpected hr %#x.\n", i, hr);
5210 else
5211 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, tests[i].hr);
5212 if (FAILED(hr))
5213 continue;
5215 memset(&ddsd, 0, sizeof(ddsd));
5216 ddsd.dwSize = sizeof(ddsd);
5217 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
5218 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5220 ok(ddsd.ddsCaps.dwCaps == tests[i].caps_out,
5221 "Input caps %#x, %#x, expected output caps %#x, got %#x, case %u.\n",
5222 tests[i].caps_in, tests[i].caps2_in, tests[i].caps_out, ddsd.ddsCaps.dwCaps, i);
5223 ok(ddsd.ddsCaps.dwCaps2 == tests[i].caps2_out,
5224 "Input caps %#x, %#x, expected output caps %#x, got %#x, case %u.\n",
5225 tests[i].caps_in, tests[i].caps2_in, tests[i].caps2_out, ddsd.ddsCaps.dwCaps2, i);
5227 IDirectDrawSurface7_Release(surface);
5230 IDirectDraw7_Release(ddraw);
5233 #define SUPPORT_DXT1 0x01
5234 #define SUPPORT_DXT2 0x02
5235 #define SUPPORT_DXT3 0x04
5236 #define SUPPORT_DXT4 0x08
5237 #define SUPPORT_DXT5 0x10
5238 #define SUPPORT_YUY2 0x20
5239 #define SUPPORT_UYVY 0x40
5241 static HRESULT WINAPI test_block_formats_creation_cb(DDPIXELFORMAT *fmt, void *ctx)
5243 DWORD *supported_fmts = ctx;
5245 if (!(fmt->dwFlags & DDPF_FOURCC))
5246 return DDENUMRET_OK;
5248 switch (fmt->dwFourCC)
5250 case MAKEFOURCC('D','X','T','1'):
5251 *supported_fmts |= SUPPORT_DXT1;
5252 break;
5253 case MAKEFOURCC('D','X','T','2'):
5254 *supported_fmts |= SUPPORT_DXT2;
5255 break;
5256 case MAKEFOURCC('D','X','T','3'):
5257 *supported_fmts |= SUPPORT_DXT3;
5258 break;
5259 case MAKEFOURCC('D','X','T','4'):
5260 *supported_fmts |= SUPPORT_DXT4;
5261 break;
5262 case MAKEFOURCC('D','X','T','5'):
5263 *supported_fmts |= SUPPORT_DXT5;
5264 break;
5265 case MAKEFOURCC('Y','U','Y','2'):
5266 *supported_fmts |= SUPPORT_YUY2;
5267 break;
5268 case MAKEFOURCC('U','Y','V','Y'):
5269 *supported_fmts |= SUPPORT_UYVY;
5270 break;
5271 default:
5272 break;
5275 return DDENUMRET_OK;
5278 static void test_block_formats_creation(void)
5280 HRESULT hr, expect_hr;
5281 unsigned int i, j, w, h;
5282 HWND window;
5283 IDirectDraw7 *ddraw;
5284 IDirect3D7 *d3d;
5285 IDirect3DDevice7 *device;
5286 IDirectDrawSurface7 *surface;
5287 DWORD supported_fmts = 0, supported_overlay_fmts = 0;
5288 DWORD num_fourcc_codes = 0, *fourcc_codes;
5289 DDSURFACEDESC2 ddsd;
5290 DDCAPS hal_caps;
5291 void *mem;
5293 static const struct
5295 DWORD fourcc;
5296 const char *name;
5297 DWORD support_flag;
5298 unsigned int block_width;
5299 unsigned int block_height;
5300 unsigned int block_size;
5301 BOOL create_size_checked, overlay;
5303 formats[] =
5305 {MAKEFOURCC('D','X','T','1'), "D3DFMT_DXT1", SUPPORT_DXT1, 4, 4, 8, TRUE, FALSE},
5306 {MAKEFOURCC('D','X','T','2'), "D3DFMT_DXT2", SUPPORT_DXT2, 4, 4, 16, TRUE, FALSE},
5307 {MAKEFOURCC('D','X','T','3'), "D3DFMT_DXT3", SUPPORT_DXT3, 4, 4, 16, TRUE, FALSE},
5308 {MAKEFOURCC('D','X','T','4'), "D3DFMT_DXT4", SUPPORT_DXT4, 4, 4, 16, TRUE, FALSE},
5309 {MAKEFOURCC('D','X','T','5'), "D3DFMT_DXT5", SUPPORT_DXT5, 4, 4, 16, TRUE, FALSE},
5310 {MAKEFOURCC('Y','U','Y','2'), "D3DFMT_YUY2", SUPPORT_YUY2, 2, 1, 4, FALSE, TRUE },
5311 {MAKEFOURCC('U','Y','V','Y'), "D3DFMT_UYVY", SUPPORT_UYVY, 2, 1, 4, FALSE, TRUE },
5313 static const struct
5315 DWORD caps, caps2;
5316 const char *name;
5317 BOOL overlay;
5319 types[] =
5321 /* DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY fails to create any fourcc
5322 * surface with DDERR_INVALIDPIXELFORMAT. Don't care about it for now.
5324 * Nvidia returns E_FAIL on DXTN DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY.
5325 * Other hw / drivers successfully create those surfaces. Ignore them, this
5326 * suggests that no game uses this, otherwise Nvidia would support it. */
5328 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0,
5329 "videomemory texture", FALSE
5332 DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY, 0,
5333 "videomemory overlay", TRUE
5336 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0,
5337 "systemmemory texture", FALSE
5340 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
5341 "managed texture", FALSE
5344 enum size_type
5346 SIZE_TYPE_ZERO,
5347 SIZE_TYPE_PITCH,
5348 SIZE_TYPE_SIZE,
5350 static const struct
5352 DWORD flags;
5353 enum size_type size_type;
5354 int rel_size;
5355 HRESULT hr;
5357 user_mem_tests[] =
5359 {DDSD_LINEARSIZE, SIZE_TYPE_ZERO, 0, DD_OK},
5360 {DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
5361 {DDSD_PITCH, SIZE_TYPE_ZERO, 0, DD_OK},
5362 {DDSD_PITCH, SIZE_TYPE_PITCH, 0, DD_OK},
5363 {DDSD_LPSURFACE, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
5364 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
5365 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_PITCH, 0, DDERR_INVALIDPARAMS},
5366 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
5367 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 1, DD_OK},
5368 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, -1, DDERR_INVALIDPARAMS},
5369 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
5370 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_PITCH, 0, DDERR_INVALIDPARAMS},
5371 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_SIZE, 0, DDERR_INVALIDPARAMS},
5372 {DDSD_LPSURFACE | DDSD_PITCH | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DDERR_INVALIDPARAMS},
5375 window = create_window();
5376 if (!(device = create_device(window, DDSCL_NORMAL)))
5378 skip("Failed to create a 3D device, skipping test.\n");
5379 DestroyWindow(window);
5380 return;
5383 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
5384 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
5385 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **) &ddraw);
5386 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
5387 IDirect3D7_Release(d3d);
5389 hr = IDirect3DDevice7_EnumTextureFormats(device, test_block_formats_creation_cb,
5390 &supported_fmts);
5391 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
5393 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
5394 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
5395 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5396 num_fourcc_codes * sizeof(*fourcc_codes));
5397 if (!fourcc_codes)
5398 goto cleanup;
5399 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
5400 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
5401 for (i = 0; i < num_fourcc_codes; i++)
5403 for (j = 0; j < ARRAY_SIZE(formats); ++j)
5405 if (fourcc_codes[i] == formats[j].fourcc)
5406 supported_overlay_fmts |= formats[j].support_flag;
5409 HeapFree(GetProcessHeap(), 0, fourcc_codes);
5411 memset(&hal_caps, 0, sizeof(hal_caps));
5412 hal_caps.dwSize = sizeof(hal_caps);
5413 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
5414 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
5416 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 2 * 2 * 16 + 1);
5418 for (i = 0; i < ARRAY_SIZE(formats); ++i)
5420 for (j = 0; j < ARRAY_SIZE(types); ++j)
5422 BOOL support;
5424 if (formats[i].overlay != types[j].overlay
5425 || (types[j].overlay && !(hal_caps.dwCaps & DDCAPS_OVERLAY)))
5426 continue;
5428 if (formats[i].overlay)
5429 support = supported_overlay_fmts & formats[i].support_flag;
5430 else
5431 support = supported_fmts & formats[i].support_flag;
5433 for (w = 1; w <= 8; w++)
5435 for (h = 1; h <= 8; h++)
5437 BOOL block_aligned = TRUE;
5438 BOOL todo = FALSE;
5440 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
5441 block_aligned = FALSE;
5443 memset(&ddsd, 0, sizeof(ddsd));
5444 ddsd.dwSize = sizeof(ddsd);
5445 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
5446 ddsd.ddsCaps.dwCaps = types[j].caps;
5447 ddsd.ddsCaps.dwCaps2 = types[j].caps2;
5448 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
5449 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
5450 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
5451 ddsd.dwWidth = w;
5452 ddsd.dwHeight = h;
5454 /* TODO: Handle power of two limitations. I cannot test the pow2
5455 * behavior on windows because I have no hardware that doesn't at
5456 * least support np2_conditional. There's probably no HW that
5457 * supports DXTN textures but no conditional np2 textures. */
5458 if (!support && !(types[j].caps & DDSCAPS_SYSTEMMEMORY))
5459 expect_hr = DDERR_INVALIDPARAMS;
5460 else if (formats[i].create_size_checked && !block_aligned)
5462 expect_hr = DDERR_INVALIDPARAMS;
5463 if (!(types[j].caps & DDSCAPS_TEXTURE))
5464 todo = TRUE;
5466 else
5467 expect_hr = D3D_OK;
5469 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5470 todo_wine_if (todo)
5471 ok(hr == expect_hr,
5472 "Got unexpected hr %#x for format %s, resource type %s, size %ux%u, expected %#x.\n",
5473 hr, formats[i].name, types[j].name, w, h, expect_hr);
5475 if (SUCCEEDED(hr))
5476 IDirectDrawSurface7_Release(surface);
5481 if (formats[i].overlay)
5482 continue;
5484 for (j = 0; j < ARRAY_SIZE(user_mem_tests); ++j)
5486 memset(&ddsd, 0, sizeof(ddsd));
5487 ddsd.dwSize = sizeof(ddsd);
5488 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | user_mem_tests[j].flags;
5489 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE;
5491 switch (user_mem_tests[j].size_type)
5493 case SIZE_TYPE_ZERO:
5494 U1(ddsd).dwLinearSize = 0;
5495 break;
5497 case SIZE_TYPE_PITCH:
5498 U1(ddsd).dwLinearSize = 2 * formats[i].block_size;
5499 break;
5501 case SIZE_TYPE_SIZE:
5502 U1(ddsd).dwLinearSize = 2 * 2 * formats[i].block_size;
5503 break;
5505 U1(ddsd).dwLinearSize += user_mem_tests[j].rel_size;
5507 ddsd.lpSurface = mem;
5508 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
5509 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
5510 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
5511 ddsd.dwWidth = 8;
5512 ddsd.dwHeight = 8;
5514 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5515 ok(hr == user_mem_tests[j].hr, "Test %u: Got unexpected hr %#x, format %s.\n", j, hr, formats[i].name);
5517 if (FAILED(hr))
5518 continue;
5520 memset(&ddsd, 0, sizeof(ddsd));
5521 ddsd.dwSize = sizeof(ddsd);
5522 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
5523 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", j, hr);
5524 ok(ddsd.dwFlags == (DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_LINEARSIZE),
5525 "Test %u: Got unexpected flags %#x.\n", j, ddsd.dwFlags);
5526 if (user_mem_tests[j].flags & DDSD_LPSURFACE)
5527 ok(U1(ddsd).dwLinearSize == ~0u, "Test %u: Got unexpected linear size %#x.\n",
5528 j, U1(ddsd).dwLinearSize);
5529 else
5530 ok(U1(ddsd).dwLinearSize == 2 * 2 * formats[i].block_size,
5531 "Test %u: Got unexpected linear size %#x, expected %#x.\n",
5532 j, U1(ddsd).dwLinearSize, 2 * 2 * formats[i].block_size);
5533 IDirectDrawSurface7_Release(surface);
5537 HeapFree(GetProcessHeap(), 0, mem);
5538 cleanup:
5539 IDirectDraw7_Release(ddraw);
5540 IDirect3DDevice7_Release(device);
5541 DestroyWindow(window);
5544 struct format_support_check
5546 const DDPIXELFORMAT *format;
5547 BOOL supported;
5550 static HRESULT WINAPI test_unsupported_formats_cb(DDPIXELFORMAT *fmt, void *ctx)
5552 struct format_support_check *format = ctx;
5554 if (!memcmp(format->format, fmt, sizeof(*fmt)))
5556 format->supported = TRUE;
5557 return DDENUMRET_CANCEL;
5560 return DDENUMRET_OK;
5563 static void test_unsupported_formats(void)
5565 HRESULT hr;
5566 BOOL expect_success;
5567 HWND window;
5568 IDirectDraw7 *ddraw;
5569 IDirect3D7 *d3d;
5570 IDirect3DDevice7 *device;
5571 IDirectDrawSurface7 *surface;
5572 DDSURFACEDESC2 ddsd;
5573 unsigned int i, j;
5574 DWORD expected_caps;
5575 static const struct
5577 const char *name;
5578 DDPIXELFORMAT fmt;
5580 formats[] =
5583 "D3DFMT_A8R8G8B8",
5585 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
5586 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
5590 "D3DFMT_P8",
5592 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
5593 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
5597 static const DWORD caps[] = {0, DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY};
5599 window = create_window();
5600 if (!(device = create_device(window, DDSCL_NORMAL)))
5602 skip("Failed to create a 3D device, skipping test.\n");
5603 DestroyWindow(window);
5604 return;
5607 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
5608 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
5609 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **) &ddraw);
5610 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
5611 IDirect3D7_Release(d3d);
5613 for (i = 0; i < ARRAY_SIZE(formats); ++i)
5615 struct format_support_check check = {&formats[i].fmt, FALSE};
5616 hr = IDirect3DDevice7_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
5617 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
5619 for (j = 0; j < ARRAY_SIZE(caps); ++j)
5621 memset(&ddsd, 0, sizeof(ddsd));
5622 ddsd.dwSize = sizeof(ddsd);
5623 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
5624 U4(ddsd).ddpfPixelFormat = formats[i].fmt;
5625 ddsd.dwWidth = 4;
5626 ddsd.dwHeight = 4;
5627 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | caps[j];
5629 if (caps[j] & DDSCAPS_VIDEOMEMORY && !check.supported)
5630 expect_success = FALSE;
5631 else
5632 expect_success = TRUE;
5634 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5635 ok(SUCCEEDED(hr) == expect_success,
5636 "Got unexpected hr %#x for format %s, caps %#x, expected %s.\n",
5637 hr, formats[i].name, caps[j], expect_success ? "success" : "failure");
5638 if (FAILED(hr))
5639 continue;
5641 memset(&ddsd, 0, sizeof(ddsd));
5642 ddsd.dwSize = sizeof(ddsd);
5643 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
5644 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5646 if (caps[j] & DDSCAPS_VIDEOMEMORY)
5647 expected_caps = DDSCAPS_VIDEOMEMORY;
5648 else if (caps[j] & DDSCAPS_SYSTEMMEMORY)
5649 expected_caps = DDSCAPS_SYSTEMMEMORY;
5650 else if (check.supported)
5651 expected_caps = DDSCAPS_VIDEOMEMORY;
5652 else
5653 expected_caps = DDSCAPS_SYSTEMMEMORY;
5655 ok(ddsd.ddsCaps.dwCaps & expected_caps,
5656 "Expected capability %#x, format %s, input cap %#x.\n",
5657 expected_caps, formats[i].name, caps[j]);
5659 IDirectDrawSurface7_Release(surface);
5663 IDirectDraw7_Release(ddraw);
5664 IDirect3DDevice7_Release(device);
5665 DestroyWindow(window);
5668 static void test_rt_caps(void)
5670 const GUID *devtype = &IID_IDirect3DHALDevice;
5671 PALETTEENTRY palette_entries[256];
5672 IDirectDrawPalette *palette;
5673 IDirectDraw7 *ddraw;
5674 BOOL hal_ok = FALSE;
5675 DDPIXELFORMAT z_fmt;
5676 IDirect3D7 *d3d;
5677 unsigned int i;
5678 ULONG refcount;
5679 HWND window;
5680 HRESULT hr;
5682 static const DDPIXELFORMAT p8_fmt =
5684 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
5685 {8}, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000},
5688 const struct
5690 const DDPIXELFORMAT *pf;
5691 DWORD caps_in;
5692 DWORD caps_out;
5693 DWORD caps2_in;
5694 DWORD caps2_out;
5695 HRESULT create_device_hr;
5696 HRESULT set_rt_hr, alternative_set_rt_hr;
5698 test_data[] =
5701 NULL,
5702 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
5703 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5706 D3D_OK,
5707 D3D_OK,
5708 D3D_OK,
5711 NULL,
5712 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5713 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5716 D3D_OK,
5717 D3D_OK,
5718 D3D_OK,
5721 NULL,
5722 DDSCAPS_OFFSCREENPLAIN,
5723 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5726 DDERR_INVALIDCAPS,
5727 DDERR_INVALIDCAPS,
5728 DDERR_INVALIDCAPS,
5731 NULL,
5732 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5733 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5736 D3DERR_SURFACENOTINVIDMEM,
5737 DDERR_INVALIDPARAMS,
5738 D3D_OK,
5741 NULL,
5742 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5743 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5746 DDERR_INVALIDCAPS,
5747 DDERR_INVALIDCAPS,
5748 DDERR_INVALIDCAPS,
5751 NULL,
5752 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
5753 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5756 D3D_OK,
5757 D3D_OK,
5758 D3D_OK,
5761 NULL,
5762 DDSCAPS_3DDEVICE,
5763 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5766 D3D_OK,
5767 D3D_OK,
5768 D3D_OK,
5771 NULL,
5773 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5776 DDERR_INVALIDCAPS,
5777 DDERR_INVALIDCAPS,
5778 DDERR_INVALIDCAPS,
5781 NULL,
5782 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5783 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5786 D3DERR_SURFACENOTINVIDMEM,
5787 DDERR_INVALIDPARAMS,
5788 D3D_OK,
5791 NULL,
5792 DDSCAPS_SYSTEMMEMORY,
5793 DDSCAPS_SYSTEMMEMORY,
5796 DDERR_INVALIDCAPS,
5797 DDERR_INVALIDCAPS,
5798 DDERR_INVALIDCAPS,
5801 NULL,
5802 DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE,
5803 DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE | DDSCAPS_SYSTEMMEMORY,
5804 DDSCAPS2_TEXTUREMANAGE,
5805 DDSCAPS2_TEXTUREMANAGE,
5806 D3DERR_SURFACENOTINVIDMEM,
5807 DDERR_INVALIDPARAMS,
5808 D3D_OK,
5811 NULL,
5812 DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE,
5813 DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE | DDSCAPS_SYSTEMMEMORY,
5814 DDSCAPS2_D3DTEXTUREMANAGE,
5815 DDSCAPS2_D3DTEXTUREMANAGE,
5816 D3DERR_SURFACENOTINVIDMEM,
5817 DDERR_INVALIDPARAMS,
5818 D3D_OK,
5821 &p8_fmt,
5823 DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5826 DDERR_INVALIDCAPS,
5827 DDERR_INVALIDCAPS,
5828 DDERR_INVALIDCAPS,
5831 &p8_fmt,
5832 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
5833 ~0U /* AMD r200 */,
5836 DDERR_NOPALETTEATTACHED,
5837 DDERR_INVALIDCAPS,
5838 DDERR_INVALIDCAPS,
5841 &p8_fmt,
5842 DDSCAPS_OFFSCREENPLAIN,
5843 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
5846 DDERR_INVALIDCAPS,
5847 DDERR_INVALIDCAPS,
5848 DDERR_INVALIDCAPS,
5851 &p8_fmt,
5852 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5853 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
5856 DDERR_NOPALETTEATTACHED,
5857 DDERR_INVALIDCAPS,
5858 DDERR_INVALIDCAPS,
5861 &p8_fmt,
5862 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5863 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
5866 DDERR_INVALIDCAPS,
5867 DDERR_INVALIDCAPS,
5868 DDERR_INVALIDCAPS,
5871 &z_fmt,
5872 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
5873 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5876 DDERR_INVALIDCAPS,
5877 DDERR_INVALIDPIXELFORMAT,
5878 DDERR_INVALIDPIXELFORMAT,
5881 &z_fmt,
5882 DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5883 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5886 DDERR_INVALIDCAPS,
5887 DDERR_INVALIDPIXELFORMAT,
5888 DDERR_INVALIDPIXELFORMAT,
5891 &z_fmt,
5892 DDSCAPS_ZBUFFER,
5893 DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM,
5896 DDERR_INVALIDCAPS,
5897 DDERR_INVALIDCAPS,
5898 DDERR_INVALIDCAPS,
5901 &z_fmt,
5902 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5903 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
5906 DDERR_INVALIDCAPS,
5907 DDERR_INVALIDPARAMS,
5908 DDERR_INVALIDPIXELFORMAT,
5911 &z_fmt,
5912 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
5913 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
5916 DDERR_INVALIDCAPS,
5917 DDERR_INVALIDCAPS,
5918 DDERR_INVALIDCAPS,
5922 window = create_window();
5923 ddraw = create_ddraw();
5924 ok(!!ddraw, "Failed to create a ddraw object.\n");
5925 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5926 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5928 if (FAILED(IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d)))
5930 skip("D3D interface is not available, skipping test.\n");
5931 goto done;
5934 hr = IDirect3D7_EnumDevices(d3d, enum_devtype_cb, &hal_ok);
5935 ok(SUCCEEDED(hr), "Failed to enumerate devices, hr %#x.\n", hr);
5936 if (hal_ok)
5937 devtype = &IID_IDirect3DTnLHalDevice;
5939 memset(&z_fmt, 0, sizeof(z_fmt));
5940 hr = IDirect3D7_EnumZBufferFormats(d3d, devtype, enum_z_fmt, &z_fmt);
5941 if (FAILED(hr) || !z_fmt.dwSize)
5943 skip("No depth buffer formats available, skipping test.\n");
5944 IDirect3D7_Release(d3d);
5945 goto done;
5948 memset(palette_entries, 0, sizeof(palette_entries));
5949 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
5950 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
5952 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
5954 IDirectDrawSurface7 *surface, *rt, *expected_rt, *tmp;
5955 DDSURFACEDESC2 surface_desc;
5956 IDirect3DDevice7 *device;
5958 memset(&surface_desc, 0, sizeof(surface_desc));
5959 surface_desc.dwSize = sizeof(surface_desc);
5960 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
5961 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
5962 surface_desc.ddsCaps.dwCaps2 = test_data[i].caps2_in;
5963 if (test_data[i].pf)
5965 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
5966 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
5968 surface_desc.dwWidth = 640;
5969 surface_desc.dwHeight = 480;
5970 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
5971 todo_wine_if(i == 10 || i == 11)
5972 ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x and caps2 %#x, hr %#x.\n",
5973 i, test_data[i].caps_in, test_data[i].caps2_in, hr);
5974 if (FAILED(hr)) continue;
5976 memset(&surface_desc, 0, sizeof(surface_desc));
5977 surface_desc.dwSize = sizeof(surface_desc);
5978 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
5979 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
5980 ok(test_data[i].caps_out == ~0U || surface_desc.ddsCaps.dwCaps == test_data[i].caps_out,
5981 "Test %u: Got unexpected caps %#x, expected %#x.\n",
5982 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
5983 ok(surface_desc.ddsCaps.dwCaps2 == test_data[i].caps2_out,
5984 "Test %u: Got unexpected caps2 %#x, expected %#x.\n",
5985 i, surface_desc.ddsCaps.dwCaps2, test_data[i].caps2_out);
5987 hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
5988 ok(hr == test_data[i].create_device_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n",
5989 i, hr, test_data[i].create_device_hr);
5990 if (FAILED(hr))
5992 if (hr == DDERR_NOPALETTEATTACHED)
5994 hr = IDirectDrawSurface7_SetPalette(surface, palette);
5995 ok(SUCCEEDED(hr), "Test %u: Failed to set palette, hr %#x.\n", i, hr);
5996 hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
5997 if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
5998 ok(hr == DDERR_INVALIDPIXELFORMAT, "Test %u: Got unexpected hr %#x.\n", i, hr);
5999 else
6000 ok(hr == D3DERR_SURFACENOTINVIDMEM, "Test %u: Got unexpected hr %#x.\n", i, hr);
6002 IDirectDrawSurface7_Release(surface);
6004 memset(&surface_desc, 0, sizeof(surface_desc));
6005 surface_desc.dwSize = sizeof(surface_desc);
6006 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6007 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
6008 surface_desc.dwWidth = 640;
6009 surface_desc.dwHeight = 480;
6010 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6011 ok(SUCCEEDED(hr), "Test %u: Failed to create surface, hr %#x.\n", i, hr);
6013 hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
6014 ok(SUCCEEDED(hr), "Test %u: Failed to create device, hr %#x.\n", i, hr);
6017 memset(&surface_desc, 0, sizeof(surface_desc));
6018 surface_desc.dwSize = sizeof(surface_desc);
6019 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6020 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
6021 surface_desc.ddsCaps.dwCaps2 = test_data[i].caps2_in;
6022 if (test_data[i].pf)
6024 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
6025 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
6027 surface_desc.dwWidth = 640;
6028 surface_desc.dwHeight = 480;
6029 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &rt, NULL);
6030 ok(SUCCEEDED(hr), "Test %u: Failed to create surface with caps %#x, hr %#x.\n",
6031 i, test_data[i].caps_in, hr);
6033 hr = IDirect3DDevice7_SetRenderTarget(device, rt, 0);
6034 ok(hr == test_data[i].set_rt_hr || broken(hr == test_data[i].alternative_set_rt_hr),
6035 "Test %u: Got unexpected hr %#x, expected %#x.\n",
6036 i, hr, test_data[i].set_rt_hr);
6037 if (SUCCEEDED(hr) || hr == DDERR_INVALIDPIXELFORMAT)
6038 expected_rt = rt;
6039 else
6040 expected_rt = surface;
6042 hr = IDirect3DDevice7_GetRenderTarget(device, &tmp);
6043 ok(SUCCEEDED(hr), "Test %u: Failed to get render target, hr %#x.\n", i, hr);
6044 ok(tmp == expected_rt, "Test %u: Got unexpected rt %p.\n", i, tmp);
6046 IDirectDrawSurface7_Release(tmp);
6047 IDirectDrawSurface7_Release(rt);
6048 refcount = IDirect3DDevice7_Release(device);
6049 ok(refcount == 0, "Test %u: The device was not properly freed, refcount %u.\n", i, refcount);
6050 refcount = IDirectDrawSurface7_Release(surface);
6051 ok(refcount == 0, "Test %u: The surface was not properly freed, refcount %u.\n", i, refcount);
6054 IDirectDrawPalette_Release(palette);
6055 IDirect3D7_Release(d3d);
6057 done:
6058 refcount = IDirectDraw7_Release(ddraw);
6059 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
6060 DestroyWindow(window);
6063 static void test_primary_caps(void)
6065 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
6066 IDirectDrawSurface7 *surface;
6067 DDSURFACEDESC2 surface_desc;
6068 IDirectDraw7 *ddraw;
6069 unsigned int i;
6070 ULONG refcount;
6071 HWND window;
6072 HRESULT hr;
6074 static const struct
6076 DWORD coop_level;
6077 DWORD caps_in;
6078 DWORD back_buffer_count;
6079 HRESULT hr;
6080 DWORD caps_out;
6082 test_data[] =
6085 DDSCL_NORMAL,
6086 DDSCAPS_PRIMARYSURFACE,
6087 ~0u,
6088 DD_OK,
6089 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE,
6092 DDSCL_NORMAL,
6093 DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE,
6094 ~0u,
6095 DDERR_INVALIDCAPS,
6096 ~0u,
6099 DDSCL_NORMAL,
6100 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
6101 ~0u,
6102 DDERR_INVALIDCAPS,
6103 ~0u,
6106 DDSCL_NORMAL,
6107 DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER,
6108 ~0u,
6109 DDERR_INVALIDCAPS,
6110 ~0u,
6113 DDSCL_NORMAL,
6114 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP,
6115 ~0u,
6116 DDERR_INVALIDCAPS,
6117 ~0u,
6120 DDSCL_NORMAL,
6121 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX,
6122 ~0u,
6123 DDERR_INVALIDCAPS,
6124 ~0u,
6127 DDSCL_NORMAL,
6128 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
6129 ~0u,
6130 DDERR_INVALIDCAPS,
6131 ~0u,
6134 DDSCL_NORMAL,
6135 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
6137 DDERR_INVALIDCAPS,
6138 ~0u,
6141 DDSCL_NORMAL,
6142 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
6144 DDERR_NOEXCLUSIVEMODE,
6145 ~0u,
6148 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
6149 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
6151 DDERR_INVALIDCAPS,
6152 ~0u,
6155 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
6156 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
6158 DD_OK,
6159 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX,
6162 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
6163 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER,
6165 DDERR_INVALIDCAPS,
6166 ~0u,
6169 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
6170 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_BACKBUFFER,
6172 DDERR_INVALIDCAPS,
6173 ~0u,
6177 window = create_window();
6178 ddraw = create_ddraw();
6179 ok(!!ddraw, "Failed to create a ddraw object.\n");
6181 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
6183 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, test_data[i].coop_level);
6184 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6186 memset(&surface_desc, 0, sizeof(surface_desc));
6187 surface_desc.dwSize = sizeof(surface_desc);
6188 surface_desc.dwFlags = DDSD_CAPS;
6189 if (test_data[i].back_buffer_count != ~0u)
6190 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
6191 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
6192 U5(surface_desc).dwBackBufferCount = test_data[i].back_buffer_count;
6193 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6194 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
6195 if (FAILED(hr))
6196 continue;
6198 memset(&surface_desc, 0, sizeof(surface_desc));
6199 surface_desc.dwSize = sizeof(surface_desc);
6200 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
6201 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
6202 ok((surface_desc.ddsCaps.dwCaps & ~placement) == test_data[i].caps_out,
6203 "Test %u: Got unexpected caps %#x, expected %#x.\n",
6204 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
6206 IDirectDrawSurface7_Release(surface);
6209 refcount = IDirectDraw7_Release(ddraw);
6210 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
6211 DestroyWindow(window);
6214 static void test_surface_lock(void)
6216 IDirectDraw7 *ddraw;
6217 IDirect3D7 *d3d = NULL;
6218 IDirectDrawSurface7 *surface;
6219 IDirect3DDevice7 *device;
6220 HRESULT hr, expected_hr;
6221 HWND window;
6222 unsigned int i;
6223 DDSURFACEDESC2 ddsd;
6224 ULONG refcount;
6225 DDPIXELFORMAT z_fmt;
6226 BOOL hal_ok = FALSE;
6227 const GUID *devtype = &IID_IDirect3DHALDevice;
6228 D3DDEVICEDESC7 device_desc;
6229 BOOL cubemap_supported;
6230 static const struct
6232 DWORD caps;
6233 DWORD caps2;
6234 const char *name;
6236 tests[] =
6239 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
6241 "videomemory offscreenplain"
6244 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
6246 "systemmemory offscreenplain"
6249 DDSCAPS_PRIMARYSURFACE,
6251 "primary"
6254 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
6256 "videomemory texture"
6259 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
6260 DDSCAPS2_OPAQUE,
6261 "opaque videomemory texture"
6264 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
6266 "systemmemory texture"
6269 DDSCAPS_TEXTURE,
6270 DDSCAPS2_TEXTUREMANAGE,
6271 "managed texture"
6274 DDSCAPS_TEXTURE,
6275 DDSCAPS2_D3DTEXTUREMANAGE,
6276 "managed texture"
6279 DDSCAPS_TEXTURE,
6280 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_OPAQUE,
6281 "opaque managed texture"
6284 DDSCAPS_TEXTURE,
6285 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_OPAQUE,
6286 "opaque managed texture"
6289 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
6291 "render target"
6294 DDSCAPS_ZBUFFER,
6296 "Z buffer"
6299 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY,
6300 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
6301 "videomemory cube"
6304 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY,
6305 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_OPAQUE,
6306 "opaque videomemory cube"
6309 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_SYSTEMMEMORY,
6310 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
6311 "systemmemory cube"
6314 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
6315 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
6316 "managed cube"
6319 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
6320 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
6321 "managed cube"
6324 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
6325 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_OPAQUE,
6326 "opaque managed cube"
6329 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
6330 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_OPAQUE,
6331 "opaque managed cube"
6335 window = create_window();
6336 ddraw = create_ddraw();
6337 ok(!!ddraw, "Failed to create a ddraw object.\n");
6338 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6339 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6341 if (FAILED(IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d)))
6343 skip("D3D interface is not available, skipping test.\n");
6344 goto done;
6347 hr = IDirect3D7_EnumDevices(d3d, enum_devtype_cb, &hal_ok);
6348 ok(SUCCEEDED(hr), "Failed to enumerate devices, hr %#x.\n", hr);
6349 if (hal_ok)
6350 devtype = &IID_IDirect3DTnLHalDevice;
6352 memset(&z_fmt, 0, sizeof(z_fmt));
6353 hr = IDirect3D7_EnumZBufferFormats(d3d, devtype, enum_z_fmt, &z_fmt);
6354 if (FAILED(hr) || !z_fmt.dwSize)
6356 skip("No depth buffer formats available, skipping test.\n");
6357 goto done;
6360 memset(&ddsd, 0, sizeof(ddsd));
6361 ddsd.dwSize = sizeof(ddsd);
6362 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6363 ddsd.dwWidth = 64;
6364 ddsd.dwHeight = 64;
6365 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
6366 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6367 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6369 hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
6370 ok(SUCCEEDED(hr), "Failed to create device, hr %#x.\n", hr);
6371 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
6372 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6373 cubemap_supported = !!(device_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP);
6374 IDirect3DDevice7_Release(device);
6376 IDirectDrawSurface7_Release(surface);
6378 for (i = 0; i < ARRAY_SIZE(tests); ++i)
6380 if (!cubemap_supported && tests[i].caps2 & DDSCAPS2_CUBEMAP)
6381 continue;
6383 memset(&ddsd, 0, sizeof(ddsd));
6384 ddsd.dwSize = sizeof(ddsd);
6385 ddsd.dwFlags = DDSD_CAPS;
6386 if (!(tests[i].caps & DDSCAPS_PRIMARYSURFACE))
6388 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
6389 ddsd.dwWidth = 64;
6390 ddsd.dwHeight = 64;
6392 if (tests[i].caps & DDSCAPS_ZBUFFER)
6394 ddsd.dwFlags |= DDSD_PIXELFORMAT;
6395 U4(ddsd).ddpfPixelFormat = z_fmt;
6397 ddsd.ddsCaps.dwCaps = tests[i].caps;
6398 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
6400 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6401 ok(SUCCEEDED(hr), "Failed to create surface, type %s, hr %#x.\n", tests[i].name, hr);
6403 memset(&ddsd, 0, sizeof(ddsd));
6404 ddsd.dwSize = sizeof(ddsd);
6405 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
6406 ok(SUCCEEDED(hr), "Failed to lock surface, type %s, hr %#x.\n", tests[i].name, hr);
6407 if (SUCCEEDED(hr))
6409 ok(ddsd.dwSize == sizeof(ddsd), "Got unexpected dwSize %u, type %s.\n", ddsd.dwSize, tests[i].name);
6410 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6411 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
6414 memset(&ddsd, 0, sizeof(ddsd));
6415 expected_hr = tests[i].caps & DDSCAPS_TEXTURE && !(tests[i].caps & DDSCAPS_VIDEOMEMORY)
6416 ? DD_OK : DDERR_INVALIDPARAMS;
6417 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
6418 ok(hr == expected_hr, "Got hr %#x, expected %#x, type %s.\n", hr, expected_hr, tests[i].name);
6419 if (SUCCEEDED(hr))
6421 ok(!ddsd.dwSize, "Got unexpected dwSize %u, type %s.\n", ddsd.dwSize, tests[i].name);
6422 ok(!!ddsd.lpSurface, "Got NULL lpSurface, type %s.\n", tests[i].name);
6423 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6424 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
6427 IDirectDrawSurface7_Release(surface);
6430 done:
6431 if (d3d)
6432 IDirect3D7_Release(d3d);
6433 refcount = IDirectDraw7_Release(ddraw);
6434 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
6435 DestroyWindow(window);
6438 static void test_surface_discard(void)
6440 IDirect3DDevice7 *device;
6441 IDirect3D7 *d3d;
6442 IDirectDraw7 *ddraw;
6443 HRESULT hr;
6444 HWND window;
6445 DDSURFACEDESC2 ddsd;
6446 IDirectDrawSurface7 *surface, *target;
6447 void *addr;
6448 static const struct
6450 DWORD caps, caps2;
6451 BOOL discard;
6453 tests[] =
6455 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, TRUE},
6456 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
6457 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, TRUE},
6458 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
6459 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE},
6460 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
6461 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE},
6462 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
6464 unsigned int i;
6466 window = create_window();
6468 for (i = 0; i < ARRAY_SIZE(tests); ++i)
6470 BOOL discarded;
6472 /* Sigh. Anything other than the first run of the loop randomly fails with
6473 * DDERR_SURFACELOST on my Radeon Pro 560 on Win10 19.09. Most of the time
6474 * the blit fails, but with sleeps added between surface creation and lock
6475 * the lock can fail too. Interestingly ddraw claims the render target has
6476 * been lost, not the test surface.
6478 * Recreating ddraw every iteration seems to fix this. */
6479 if (!(device = create_device(window, DDSCL_NORMAL)))
6481 skip("Failed to create a 3D device, skipping test.\n");
6482 DestroyWindow(window);
6483 return;
6485 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
6486 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
6487 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
6488 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
6489 hr = IDirect3DDevice7_GetRenderTarget(device, &target);
6490 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
6492 memset(&ddsd, 0, sizeof(ddsd));
6493 ddsd.dwSize = sizeof(ddsd);
6494 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6495 ddsd.ddsCaps.dwCaps = tests[i].caps;
6496 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
6497 ddsd.dwWidth = 64;
6498 ddsd.dwHeight = 64;
6499 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6500 ok(SUCCEEDED(hr), "Failed to create offscreen surface, hr %#x, case %u.\n", hr, i);
6502 memset(&ddsd, 0, sizeof(ddsd));
6503 ddsd.dwSize = sizeof(ddsd);
6504 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, 0, NULL);
6505 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6506 addr = ddsd.lpSurface;
6507 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6508 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6510 memset(&ddsd, 0, sizeof(ddsd));
6511 ddsd.dwSize = sizeof(ddsd);
6512 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
6513 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6514 discarded = ddsd.lpSurface != addr;
6515 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6516 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6518 hr = IDirectDrawSurface7_Blt(target, NULL, surface, NULL, DDBLT_WAIT, NULL);
6519 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
6521 memset(&ddsd, 0, sizeof(ddsd));
6522 ddsd.dwSize = sizeof(ddsd);
6523 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
6524 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6525 discarded |= ddsd.lpSurface != addr;
6526 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6527 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6529 IDirectDrawSurface7_Release(surface);
6531 /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler,
6532 * AMD r500, evergreen). Windows XP, at least on AMD r200, does not. */
6533 ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i);
6535 IDirectDrawSurface7_Release(target);
6536 IDirectDraw7_Release(ddraw);
6537 IDirect3D7_Release(d3d);
6538 IDirect3DDevice7_Release(device);
6541 DestroyWindow(window);
6544 static void fill_surface(IDirectDrawSurface7 *surface, D3DCOLOR color)
6546 DDSURFACEDESC2 surface_desc = {sizeof(surface_desc)};
6547 HRESULT hr;
6548 unsigned int x, y;
6549 DWORD *ptr;
6551 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
6552 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6554 for (y = 0; y < surface_desc.dwHeight; ++y)
6556 ptr = (DWORD *)((BYTE *)surface_desc.lpSurface + y * U1(surface_desc).lPitch);
6557 for (x = 0; x < surface_desc.dwWidth; ++x)
6559 ptr[x] = color;
6563 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6564 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6567 static void test_flip(void)
6569 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
6570 IDirectDrawSurface7 *frontbuffer, *backbuffer1, *backbuffer2, *backbuffer3, *surface;
6571 DDSCAPS2 caps = {DDSCAPS_FLIP, 0, 0, {0}};
6572 DDSURFACEDESC2 surface_desc;
6573 D3DDEVICEDESC7 device_desc;
6574 IDirect3DDevice7 *device;
6575 BOOL sysmem_primary;
6576 IDirectDraw7 *ddraw;
6577 DWORD expected_caps;
6578 unsigned int i;
6579 D3DCOLOR color;
6580 ULONG refcount;
6581 HWND window;
6582 HRESULT hr;
6584 static const struct
6586 const char *name;
6587 DWORD caps;
6589 test_data[] =
6591 {"PRIMARYSURFACE", DDSCAPS_PRIMARYSURFACE},
6592 {"OFFSCREENPLAIN", DDSCAPS_OFFSCREENPLAIN},
6593 {"TEXTURE", DDSCAPS_TEXTURE},
6596 window = create_window();
6597 ddraw = create_ddraw();
6598 ok(!!ddraw, "Failed to create a ddraw object.\n");
6600 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6601 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6603 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
6605 /* Creating a flippable texture induces a BSoD on some versions of the
6606 * Intel graphics driver. At least Intel GMA 950 with driver version
6607 * 6.14.10.4926 on Windows XP SP3 is affected. */
6608 if ((test_data[i].caps & DDSCAPS_TEXTURE) && ddraw_is_intel(ddraw))
6610 win_skip("Skipping flippable texture test.\n");
6611 continue;
6614 memset(&surface_desc, 0, sizeof(surface_desc));
6615 surface_desc.dwSize = sizeof(surface_desc);
6616 surface_desc.dwFlags = DDSD_CAPS;
6617 if (!(test_data[i].caps & DDSCAPS_PRIMARYSURFACE))
6618 surface_desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
6619 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
6620 surface_desc.dwWidth = 512;
6621 surface_desc.dwHeight = 512;
6622 U5(surface_desc).dwBackBufferCount = 3;
6623 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6624 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6626 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_FLIP;
6627 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
6628 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6629 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6631 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_COMPLEX;
6632 surface_desc.ddsCaps.dwCaps |= DDSCAPS_FLIP;
6633 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6634 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6636 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
6637 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6638 if (is_ddraw64 && test_data[i].caps & DDSCAPS_TEXTURE)
6639 todo_wine ok(hr == E_NOINTERFACE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6640 else todo_wine_if(test_data[i].caps & DDSCAPS_TEXTURE)
6641 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
6642 if (FAILED(hr))
6643 continue;
6645 memset(&surface_desc, 0, sizeof(surface_desc));
6646 surface_desc.dwSize = sizeof(surface_desc);
6647 hr = IDirectDrawSurface7_GetSurfaceDesc(frontbuffer, &surface_desc);
6648 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6649 expected_caps = DDSCAPS_FRONTBUFFER | DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
6650 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
6651 expected_caps |= DDSCAPS_VISIBLE;
6652 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6653 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6654 sysmem_primary = surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
6656 hr = IDirectDrawSurface7_GetAttachedSurface(frontbuffer, &caps, &backbuffer1);
6657 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6658 memset(&surface_desc, 0, sizeof(surface_desc));
6659 surface_desc.dwSize = sizeof(surface_desc);
6660 hr = IDirectDrawSurface7_GetSurfaceDesc(backbuffer1, &surface_desc);
6661 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6662 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
6663 test_data[i].name, U5(surface_desc).dwBackBufferCount);
6664 expected_caps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER);
6665 expected_caps |= DDSCAPS_BACKBUFFER;
6666 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6667 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6669 hr = IDirectDrawSurface7_GetAttachedSurface(backbuffer1, &caps, &backbuffer2);
6670 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6671 memset(&surface_desc, 0, sizeof(surface_desc));
6672 surface_desc.dwSize = sizeof(surface_desc);
6673 hr = IDirectDrawSurface7_GetSurfaceDesc(backbuffer2, &surface_desc);
6674 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6675 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
6676 test_data[i].name, U5(surface_desc).dwBackBufferCount);
6677 expected_caps &= ~DDSCAPS_BACKBUFFER;
6678 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6679 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6681 hr = IDirectDrawSurface7_GetAttachedSurface(backbuffer2, &caps, &backbuffer3);
6682 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6683 memset(&surface_desc, 0, sizeof(surface_desc));
6684 surface_desc.dwSize = sizeof(surface_desc);
6685 hr = IDirectDrawSurface7_GetSurfaceDesc(backbuffer3, &surface_desc);
6686 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
6687 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
6688 test_data[i].name, U5(surface_desc).dwBackBufferCount);
6689 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
6690 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
6692 hr = IDirectDrawSurface7_GetAttachedSurface(backbuffer3, &caps, &surface);
6693 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
6694 ok(surface == frontbuffer, "%s: Got unexpected surface %p, expected %p.\n",
6695 test_data[i].name, surface, frontbuffer);
6696 IDirectDrawSurface7_Release(surface);
6698 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
6699 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
6700 hr = IDirectDrawSurface7_IsLost(frontbuffer);
6701 ok(hr == DD_OK, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6702 hr = IDirectDrawSurface7_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6703 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
6704 ok(hr == DDERR_NOEXCLUSIVEMODE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6705 else
6706 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6707 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
6708 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
6709 hr = IDirectDrawSurface7_IsLost(frontbuffer);
6710 todo_wine ok(hr == DDERR_SURFACELOST, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6711 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
6712 ok(SUCCEEDED(hr), "%s: Failed to restore surfaces, hr %#x.\n", test_data[i].name, hr);
6714 memset(&surface_desc, 0, sizeof(surface_desc));
6715 surface_desc.dwSize = sizeof(surface_desc);
6716 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6717 surface_desc.ddsCaps.dwCaps = 0;
6718 surface_desc.dwWidth = 640;
6719 surface_desc.dwHeight = 480;
6720 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6721 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
6722 hr = IDirectDrawSurface7_Flip(frontbuffer, surface, DDFLIP_WAIT);
6723 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6724 IDirectDrawSurface7_Release(surface);
6726 hr = IDirectDrawSurface7_Flip(frontbuffer, frontbuffer, DDFLIP_WAIT);
6727 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6728 hr = IDirectDrawSurface7_Flip(backbuffer1, NULL, DDFLIP_WAIT);
6729 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6730 hr = IDirectDrawSurface7_Flip(backbuffer2, NULL, DDFLIP_WAIT);
6731 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6732 hr = IDirectDrawSurface7_Flip(backbuffer3, NULL, DDFLIP_WAIT);
6733 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
6735 /* The Nvidia Geforce 7 driver cannot do a color fill on a texture backbuffer after
6736 * the backbuffer has been locked. Do it ourselves as a workaround. Unlike ddraw1
6737 * and 2 GetSurfaceDesc does not cause issues in ddraw4 and ddraw7. */
6738 fill_surface(backbuffer1, 0xffff0000);
6739 fill_surface(backbuffer2, 0xff00ff00);
6740 fill_surface(backbuffer3, 0xff0000ff);
6742 hr = IDirectDrawSurface7_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6743 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6744 color = get_surface_color(backbuffer1, 320, 240);
6745 /* The testbot seems to just copy the contents of one surface to all the
6746 * others, instead of properly flipping. */
6747 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
6748 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6749 color = get_surface_color(backbuffer2, 320, 240);
6750 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6751 fill_surface(backbuffer3, 0xffff0000);
6753 hr = IDirectDrawSurface7_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6754 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6755 color = get_surface_color(backbuffer1, 320, 240);
6756 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
6757 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6758 color = get_surface_color(backbuffer2, 320, 240);
6759 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6760 fill_surface(backbuffer3, 0xff00ff00);
6762 hr = IDirectDrawSurface7_Flip(frontbuffer, NULL, DDFLIP_WAIT);
6763 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6764 color = get_surface_color(backbuffer1, 320, 240);
6765 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
6766 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6767 color = get_surface_color(backbuffer2, 320, 240);
6768 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6769 fill_surface(backbuffer3, 0xff0000ff);
6771 hr = IDirectDrawSurface7_Flip(frontbuffer, backbuffer1, DDFLIP_WAIT);
6772 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6773 color = get_surface_color(backbuffer2, 320, 240);
6774 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
6775 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6776 color = get_surface_color(backbuffer3, 320, 240);
6777 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6778 fill_surface(backbuffer1, 0xffff0000);
6780 hr = IDirectDrawSurface7_Flip(frontbuffer, backbuffer2, DDFLIP_WAIT);
6781 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6782 color = get_surface_color(backbuffer1, 320, 240);
6783 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6784 color = get_surface_color(backbuffer3, 320, 240);
6785 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
6786 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6787 fill_surface(backbuffer2, 0xff00ff00);
6789 hr = IDirectDrawSurface7_Flip(frontbuffer, backbuffer3, DDFLIP_WAIT);
6790 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
6791 color = get_surface_color(backbuffer1, 320, 240);
6792 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
6793 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6794 color = get_surface_color(backbuffer2, 320, 240);
6795 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
6797 IDirectDrawSurface7_Release(backbuffer3);
6798 IDirectDrawSurface7_Release(backbuffer2);
6799 IDirectDrawSurface7_Release(backbuffer1);
6800 IDirectDrawSurface7_Release(frontbuffer);
6803 if (!(device = create_device(window, DDSCL_NORMAL)))
6805 skip("Failed to create 3D device.\n");
6806 goto done;
6808 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
6809 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6810 IDirect3DDevice7_Release(device);
6811 if (!(device_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP))
6813 skip("Cubemaps are not supported.\n");
6814 goto done;
6817 memset(&surface_desc, 0, sizeof(surface_desc));
6818 surface_desc.dwSize = sizeof(surface_desc);
6819 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6820 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_TEXTURE;
6821 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
6822 surface_desc.dwWidth = 128;
6823 surface_desc.dwHeight = 128;
6824 U5(surface_desc).dwBackBufferCount = 3;
6825 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6826 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x.\n", hr);
6828 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_FLIP;
6829 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
6830 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6831 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6833 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_COMPLEX;
6834 surface_desc.ddsCaps.dwCaps |= DDSCAPS_FLIP;
6835 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6836 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x.\n", hr);
6838 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
6839 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6840 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6842 U5(surface_desc).dwBackBufferCount = 1;
6843 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6844 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
6846 U5(surface_desc).dwBackBufferCount = 0;
6847 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
6848 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x.\n", hr);
6850 done:
6851 refcount = IDirectDraw7_Release(ddraw);
6852 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
6853 DestroyWindow(window);
6856 static void reset_ddsd(DDSURFACEDESC2 *ddsd)
6858 memset(ddsd, 0, sizeof(*ddsd));
6859 ddsd->dwSize = sizeof(*ddsd);
6862 static void test_set_surface_desc(void)
6864 IDirectDraw7 *ddraw;
6865 HWND window;
6866 HRESULT hr;
6867 DDSURFACEDESC2 ddsd;
6868 IDirectDrawSurface7 *surface;
6869 BYTE data[16*16*4];
6870 ULONG ref;
6871 unsigned int i;
6872 static const struct
6874 DWORD caps, caps2;
6875 BOOL supported;
6876 const char *name;
6878 invalid_caps_tests[] =
6880 {DDSCAPS_VIDEOMEMORY, 0, FALSE, "videomemory plain"},
6881 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, TRUE, "systemmemory texture"},
6882 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE, "managed texture"},
6883 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE, "managed texture"},
6884 {DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY, 0, FALSE, "systemmemory primary"},
6887 window = create_window();
6888 ddraw = create_ddraw();
6889 ok(!!ddraw, "Failed to create a ddraw object.\n");
6890 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6891 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6893 reset_ddsd(&ddsd);
6894 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
6895 ddsd.dwWidth = 8;
6896 ddsd.dwHeight = 8;
6897 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6898 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
6899 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
6900 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
6901 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
6902 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
6903 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6905 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6906 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6908 reset_ddsd(&ddsd);
6909 ddsd.dwFlags = DDSD_LPSURFACE;
6910 ddsd.lpSurface = data;
6911 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6912 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6914 /* Redundantly setting the same lpSurface is not an error. */
6915 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6916 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6918 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6919 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6920 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
6921 ok(ddsd.lpSurface == NULL, "lpSurface is %p, expected NULL.\n", ddsd.lpSurface);
6923 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, 0, NULL);
6924 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6925 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
6926 ok(ddsd.lpSurface == data, "lpSurface is %p, expected %p.\n", data, data);
6927 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6928 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6930 reset_ddsd(&ddsd);
6931 ddsd.dwFlags = DDSD_LPSURFACE;
6932 ddsd.lpSurface = data;
6933 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 1);
6934 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with flags=1 returned %#x.\n", hr);
6936 ddsd.lpSurface = NULL;
6937 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6938 ok(hr == DDERR_INVALIDPARAMS, "Setting lpSurface=NULL returned %#x.\n", hr);
6940 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, NULL, 0);
6941 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with NULL desc returned %#x.\n", hr);
6943 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6944 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6945 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
6946 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
6947 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#x.\n", 0);
6949 /* Setting the caps is an error. This also means the original description cannot be reapplied. */
6950 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6951 ok(hr == DDERR_INVALIDPARAMS, "Setting the original desc returned %#x.\n", hr);
6953 ddsd.dwFlags = DDSD_CAPS;
6954 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6955 ok(hr == DDERR_INVALIDPARAMS, "Setting DDSD_CAPS returned %#x.\n", hr);
6957 /* dwCaps = 0 is allowed, but ignored. Caps2 can be anything and is ignored too. */
6958 ddsd.dwFlags = DDSD_CAPS | DDSD_LPSURFACE;
6959 ddsd.lpSurface = data;
6960 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6961 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
6962 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
6963 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6964 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
6965 ddsd.ddsCaps.dwCaps = 0;
6966 ddsd.ddsCaps.dwCaps2 = 0xdeadbeef;
6967 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6968 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6970 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6971 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6972 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
6973 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
6974 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#x.\n", 0);
6976 /* Setting the height is allowed, but it cannot be set to 0, and only if LPSURFACE is set too. */
6977 reset_ddsd(&ddsd);
6978 ddsd.dwFlags = DDSD_HEIGHT;
6979 ddsd.dwHeight = 16;
6980 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6981 ok(hr == DDERR_INVALIDPARAMS, "Setting height without lpSurface returned %#x.\n", hr);
6983 ddsd.lpSurface = data;
6984 ddsd.dwFlags = DDSD_HEIGHT | DDSD_LPSURFACE;
6985 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6986 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
6988 ddsd.dwHeight = 0;
6989 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
6990 ok(hr == DDERR_INVALIDPARAMS, "Setting height=0 returned %#x.\n", hr);
6992 reset_ddsd(&ddsd);
6993 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6994 ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr);
6995 ok(ddsd.dwWidth == 8, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
6996 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
6998 /* Pitch and width can be set, but only together, and only with LPSURFACE. They must not be 0. */
6999 reset_ddsd(&ddsd);
7000 ddsd.dwFlags = DDSD_PITCH;
7001 U1(ddsd).lPitch = 8 * 4;
7002 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7003 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch without lpSurface or width returned %#x.\n", hr);
7005 ddsd.dwFlags = DDSD_WIDTH;
7006 ddsd.dwWidth = 16;
7007 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7008 ok(hr == DDERR_INVALIDPARAMS, "Setting width without lpSurface or pitch returned %#x.\n", hr);
7010 ddsd.dwFlags = DDSD_PITCH | DDSD_LPSURFACE;
7011 ddsd.lpSurface = data;
7012 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7013 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch and lpSurface without width returned %#x.\n", hr);
7015 ddsd.dwFlags = DDSD_WIDTH | DDSD_LPSURFACE;
7016 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7017 ok(hr == DDERR_INVALIDPARAMS, "Setting width and lpSurface without pitch returned %#x.\n", hr);
7019 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
7020 U1(ddsd).lPitch = 16 * 4;
7021 ddsd.dwWidth = 16;
7022 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7023 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7025 reset_ddsd(&ddsd);
7026 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
7027 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7028 ok(ddsd.dwWidth == 16, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
7029 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
7030 ok(U1(ddsd).lPitch == 16 * 4, "SetSurfaceDesc: Expected pitch 64, got %u.\n", U1(ddsd).lPitch);
7032 /* The pitch must be 32 bit aligned and > 0, but is not verified for sanity otherwise.
7034 * VMware rejects those calls, but all real drivers accept it. Mark the VMware behavior broken. */
7035 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
7036 U1(ddsd).lPitch = 4 * 4;
7037 ddsd.lpSurface = data;
7038 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7039 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
7041 U1(ddsd).lPitch = 4;
7042 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7043 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
7045 U1(ddsd).lPitch = 16 * 4 + 1;
7046 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7047 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
7049 U1(ddsd).lPitch = 16 * 4 + 3;
7050 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7051 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
7053 U1(ddsd).lPitch = -4;
7054 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7055 ok(hr == DDERR_INVALIDPARAMS, "Setting negative pitch returned %#x.\n", hr);
7057 U1(ddsd).lPitch = 16 * 4;
7058 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7059 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7061 reset_ddsd(&ddsd);
7062 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
7063 U1(ddsd).lPitch = 0;
7064 ddsd.dwWidth = 16;
7065 ddsd.lpSurface = data;
7066 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7067 ok(hr == DDERR_INVALIDPARAMS, "Setting zero pitch returned %#x.\n", hr);
7069 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
7070 U1(ddsd).lPitch = 16 * 4;
7071 ddsd.dwWidth = 0;
7072 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7073 ok(hr == DDERR_INVALIDPARAMS, "Setting zero width returned %#x.\n", hr);
7075 /* Setting the pixelformat without LPSURFACE is an error, but with LPSURFACE it works. */
7076 ddsd.dwFlags = DDSD_PIXELFORMAT;
7077 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
7078 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
7079 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
7080 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7081 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7082 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7083 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7084 ok(hr == DDERR_INVALIDPARAMS, "Setting the pixel format returned %#x.\n", hr);
7086 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_LPSURFACE;
7087 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7088 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7090 /* Can't set color keys. */
7091 reset_ddsd(&ddsd);
7092 ddsd.dwFlags = DDSD_CKSRCBLT;
7093 ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff0000;
7094 ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff0000;
7095 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7096 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
7098 ddsd.dwFlags = DDSD_CKSRCBLT | DDSD_LPSURFACE;
7099 ddsd.lpSurface = data;
7100 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7101 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
7103 IDirectDrawSurface7_Release(surface);
7105 /* SetSurfaceDesc needs systemmemory surfaces.
7107 * As a sidenote, fourcc surfaces aren't allowed in sysmem, thus testing
7108 * DDSD_LINEARSIZE is moot. */
7109 for (i = 0; i < ARRAY_SIZE(invalid_caps_tests); ++i)
7111 reset_ddsd(&ddsd);
7112 ddsd.dwFlags = DDSD_CAPS;
7113 ddsd.ddsCaps.dwCaps = invalid_caps_tests[i].caps;
7114 ddsd.ddsCaps.dwCaps2 = invalid_caps_tests[i].caps2;
7115 if (!(invalid_caps_tests[i].caps & DDSCAPS_PRIMARYSURFACE))
7117 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7118 ddsd.dwWidth = 8;
7119 ddsd.dwHeight = 8;
7120 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
7121 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
7122 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
7123 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7124 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7125 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7128 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
7129 if (is_ddraw64 && (invalid_caps_tests[i].caps & DDSCAPS_TEXTURE))
7130 todo_wine ok(hr == E_NOINTERFACE, "Test %u: Got unexpected hr %#x.\n", i, hr);
7131 else
7132 ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWHW, "Test %u: Got unexpected hr %#x.\n", i, hr);
7133 if (FAILED(hr))
7134 continue;
7136 reset_ddsd(&ddsd);
7137 ddsd.dwFlags = DDSD_LPSURFACE;
7138 ddsd.lpSurface = data;
7139 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7140 if (invalid_caps_tests[i].supported)
7142 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7144 else
7146 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
7147 invalid_caps_tests[i].name, hr);
7149 /* Check priority of error conditions. */
7150 ddsd.dwFlags = DDSD_WIDTH;
7151 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7152 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
7153 invalid_caps_tests[i].name, hr);
7156 IDirectDrawSurface7_Release(surface);
7159 ref = IDirectDraw7_Release(ddraw);
7160 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
7161 DestroyWindow(window);
7164 static void test_user_memory_getdc(void)
7166 IDirectDraw7 *ddraw;
7167 HWND window;
7168 HRESULT hr;
7169 DDSURFACEDESC2 ddsd;
7170 IDirectDrawSurface7 *surface;
7171 DWORD data[16][16];
7172 HGDIOBJ *bitmap;
7173 DIBSECTION dib;
7174 ULONG ref;
7175 int size;
7176 HDC dc;
7177 unsigned int x, y;
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_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
7187 ddsd.dwWidth = 16;
7188 ddsd.dwHeight = 16;
7189 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
7190 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
7191 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
7192 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7193 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7194 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7195 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
7196 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
7197 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7199 memset(data, 0xaa, sizeof(data));
7200 reset_ddsd(&ddsd);
7201 ddsd.dwFlags = DDSD_LPSURFACE;
7202 ddsd.lpSurface = data;
7203 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7204 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7206 hr = IDirectDrawSurface7_GetDC(surface, &dc);
7207 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7208 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
7209 ok(!!bitmap, "Failed to get bitmap.\n");
7210 size = GetObjectA(bitmap, sizeof(dib), &dib);
7211 ok(size == sizeof(dib), "Got unexpected size %d.\n", size);
7212 ok(dib.dsBm.bmBits == data, "Got unexpected bits %p, expected %p.\n", dib.dsBm.bmBits, data);
7213 BitBlt(dc, 0, 0, 16, 8, NULL, 0, 0, WHITENESS);
7214 BitBlt(dc, 0, 8, 16, 8, NULL, 0, 0, BLACKNESS);
7215 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
7216 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7218 ok(data[0][0] == 0xffffffff, "Expected color 0xffffffff, got %#x.\n", data[0][0]);
7219 ok(data[15][15] == 0x00000000, "Expected color 0x00000000, got %#x.\n", data[15][15]);
7221 ddsd.dwFlags = DDSD_LPSURFACE | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH;
7222 ddsd.lpSurface = data;
7223 ddsd.dwWidth = 4;
7224 ddsd.dwHeight = 8;
7225 U1(ddsd).lPitch = sizeof(*data);
7226 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7227 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7229 memset(data, 0xaa, sizeof(data));
7230 hr = IDirectDrawSurface7_GetDC(surface, &dc);
7231 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7232 BitBlt(dc, 0, 0, 4, 8, NULL, 0, 0, BLACKNESS);
7233 BitBlt(dc, 1, 1, 2, 2, NULL, 0, 0, WHITENESS);
7234 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
7235 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7237 for (y = 0; y < 4; y++)
7239 for (x = 0; x < 4; x++)
7241 if ((x == 1 || x == 2) && (y == 1 || y == 2))
7242 ok(data[y][x] == 0xffffffff, "Expected color 0xffffffff on position %ux%u, got %#x.\n",
7243 x, y, data[y][x]);
7244 else
7245 ok(data[y][x] == 0x00000000, "Expected color 0x00000000 on position %ux%u, got %#x.\n",
7246 x, y, data[y][x]);
7249 ok(data[0][5] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 5x0, got %#x.\n",
7250 data[0][5]);
7251 ok(data[7][3] == 0x00000000, "Expected color 0x00000000 on position 3x7, got %#x.\n",
7252 data[7][3]);
7253 ok(data[7][4] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 4x7, got %#x.\n",
7254 data[7][4]);
7255 ok(data[8][0] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 0x8, got %#x.\n",
7256 data[8][0]);
7258 IDirectDrawSurface7_Release(surface);
7259 ref = IDirectDraw7_Release(ddraw);
7260 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
7261 DestroyWindow(window);
7264 static void test_sysmem_overlay(void)
7266 IDirectDraw7 *ddraw;
7267 HWND window;
7268 HRESULT hr;
7269 DDSURFACEDESC2 ddsd;
7270 IDirectDrawSurface7 *surface;
7271 ULONG ref;
7273 window = create_window();
7274 ddraw = create_ddraw();
7275 ok(!!ddraw, "Failed to create a ddraw object.\n");
7276 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7277 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7279 reset_ddsd(&ddsd);
7280 ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
7281 ddsd.dwWidth = 16;
7282 ddsd.dwHeight = 16;
7283 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OVERLAY;
7284 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
7285 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
7286 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
7287 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7288 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7289 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7290 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
7291 ok(hr == DDERR_NOOVERLAYHW, "Got unexpected hr %#x.\n", hr);
7293 ref = IDirectDraw7_Release(ddraw);
7294 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
7295 DestroyWindow(window);
7298 static void test_primary_palette(void)
7300 DDSCAPS2 surface_caps = {DDSCAPS_FLIP, 0, 0, {0}};
7301 IDirectDrawSurface7 *primary, *backbuffer;
7302 PALETTEENTRY palette_entries[256];
7303 IDirectDrawPalette *palette, *tmp;
7304 DDSURFACEDESC2 surface_desc;
7305 IDirectDraw7 *ddraw;
7306 DWORD palette_caps;
7307 ULONG refcount;
7308 HWND window;
7309 HRESULT hr;
7311 window = create_window();
7312 ddraw = create_ddraw();
7313 ok(!!ddraw, "Failed to create a ddraw object.\n");
7314 if (FAILED(IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
7316 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
7317 IDirectDraw7_Release(ddraw);
7318 DestroyWindow(window);
7319 return;
7321 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7322 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7324 memset(&surface_desc, 0, sizeof(surface_desc));
7325 surface_desc.dwSize = sizeof(surface_desc);
7326 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
7327 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
7328 U5(surface_desc).dwBackBufferCount = 1;
7329 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
7330 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7331 hr = IDirectDrawSurface7_GetAttachedSurface(primary, &surface_caps, &backbuffer);
7332 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
7334 memset(palette_entries, 0, sizeof(palette_entries));
7335 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_entries, &palette, NULL);
7336 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7337 refcount = get_refcount((IUnknown *)palette);
7338 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7340 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
7341 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
7342 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
7344 hr = IDirectDrawSurface7_SetPalette(primary, palette);
7345 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7347 /* The Windows 8 testbot attaches the palette to the backbuffer as well,
7348 * and is generally somewhat broken with respect to 8 bpp / palette
7349 * handling. */
7350 if (SUCCEEDED(IDirectDrawSurface7_GetPalette(backbuffer, &tmp)))
7352 win_skip("Broken palette handling detected, skipping tests.\n");
7353 IDirectDrawPalette_Release(tmp);
7354 IDirectDrawPalette_Release(palette);
7355 /* The Windows 8 testbot keeps extra references to the primary and
7356 * backbuffer while in 8 bpp mode. */
7357 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
7358 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
7359 goto done;
7362 refcount = get_refcount((IUnknown *)palette);
7363 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
7365 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
7366 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
7367 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE | DDPCAPS_ALLOW256),
7368 "Got unexpected palette caps %#x.\n", palette_caps);
7370 hr = IDirectDrawSurface7_SetPalette(primary, NULL);
7371 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7372 refcount = get_refcount((IUnknown *)palette);
7373 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7375 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
7376 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
7377 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
7379 hr = IDirectDrawSurface7_SetPalette(primary, palette);
7380 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7381 refcount = get_refcount((IUnknown *)palette);
7382 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
7384 hr = IDirectDrawSurface7_GetPalette(primary, &tmp);
7385 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
7386 ok(tmp == palette, "Got unexpected palette %p, expected %p.\n", tmp, palette);
7387 IDirectDrawPalette_Release(tmp);
7388 hr = IDirectDrawSurface7_GetPalette(backbuffer, &tmp);
7389 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
7391 refcount = IDirectDrawPalette_Release(palette);
7392 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7393 refcount = IDirectDrawPalette_Release(palette);
7394 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7396 /* Note that this only seems to work when the palette is attached to the
7397 * primary surface. When attached to a regular surface, attempting to get
7398 * the palette here will cause an access violation. */
7399 hr = IDirectDrawSurface7_GetPalette(primary, &tmp);
7400 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
7402 hr = IDirectDrawSurface7_IsLost(primary);
7403 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7405 memset(&surface_desc, 0, sizeof(surface_desc));
7406 surface_desc.dwSize = sizeof(surface_desc);
7407 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &surface_desc);
7408 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7409 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
7410 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
7411 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 8, "Got unexpected bit count %u.\n",
7412 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
7414 hr = set_display_mode(ddraw, 640, 480);
7415 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
7417 memset(&surface_desc, 0, sizeof(surface_desc));
7418 surface_desc.dwSize = sizeof(surface_desc);
7419 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &surface_desc);
7420 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7421 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
7422 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
7423 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 32
7424 || U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 24,
7425 "Got unexpected bit count %u.\n", U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
7427 hr = IDirectDrawSurface7_IsLost(primary);
7428 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7429 hr = IDirectDrawSurface7_Restore(primary);
7430 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
7431 hr = IDirectDrawSurface7_IsLost(primary);
7432 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
7434 memset(&surface_desc, 0, sizeof(surface_desc));
7435 surface_desc.dwSize = sizeof(surface_desc);
7436 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &surface_desc);
7437 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7438 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
7439 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
7440 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 32
7441 || U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 24,
7442 "Got unexpected bit count %u.\n", U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
7444 done:
7445 refcount = IDirectDrawSurface7_Release(backbuffer);
7446 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7447 refcount = IDirectDrawSurface7_Release(primary);
7448 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7449 refcount = IDirectDraw7_Release(ddraw);
7450 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7451 DestroyWindow(window);
7454 static HRESULT WINAPI surface_counter(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
7456 UINT *surface_count = context;
7458 ++(*surface_count);
7459 IDirectDrawSurface_Release(surface);
7461 return DDENUMRET_OK;
7464 static void test_surface_attachment(void)
7466 IDirectDrawSurface7 *surface1, *surface2, *surface3, *surface4;
7467 IDirectDrawSurface *surface1v1, *surface2v1;
7468 DDSCAPS2 caps = {DDSCAPS_TEXTURE, 0, 0, {0}};
7469 DDSURFACEDESC2 surface_desc;
7470 IDirectDraw7 *ddraw;
7471 UINT surface_count;
7472 ULONG refcount;
7473 HWND window;
7474 HRESULT hr;
7476 window = create_window();
7477 ddraw = create_ddraw();
7478 ok(!!ddraw, "Failed to create a ddraw object.\n");
7479 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7480 ok(SUCCEEDED(hr), "Failed to set cooperative level, 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 | DDSD_MIPMAPCOUNT;
7485 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7486 U2(surface_desc).dwMipMapCount = 3;
7487 surface_desc.dwWidth = 128;
7488 surface_desc.dwHeight = 128;
7489 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL)))
7491 skip("Failed to create a texture, skipping tests.\n");
7492 IDirectDraw7_Release(ddraw);
7493 DestroyWindow(window);
7494 return;
7497 hr = IDirectDrawSurface7_GetAttachedSurface(surface1, &caps, &surface2);
7498 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
7499 hr = IDirectDrawSurface7_GetAttachedSurface(surface2, &caps, &surface3);
7500 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
7501 hr = IDirectDrawSurface7_GetAttachedSurface(surface3, &caps, &surface4);
7502 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7504 surface_count = 0;
7505 IDirectDrawSurface7_EnumAttachedSurfaces(surface1, &surface_count, surface_counter);
7506 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
7507 surface_count = 0;
7508 IDirectDrawSurface7_EnumAttachedSurfaces(surface2, &surface_count, surface_counter);
7509 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
7510 surface_count = 0;
7511 IDirectDrawSurface7_EnumAttachedSurfaces(surface3, &surface_count, surface_counter);
7512 ok(!surface_count, "Got unexpected surface_count %u.\n", surface_count);
7514 memset(&surface_desc, 0, sizeof(surface_desc));
7515 surface_desc.dwSize = sizeof(surface_desc);
7516 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7517 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
7518 surface_desc.dwWidth = 16;
7519 surface_desc.dwHeight = 16;
7520 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
7521 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7523 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
7524 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7525 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
7526 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7527 hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface4);
7528 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7529 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface3);
7530 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7531 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface4);
7532 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7533 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface2);
7534 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7536 IDirectDrawSurface7_Release(surface4);
7538 memset(&surface_desc, 0, sizeof(surface_desc));
7539 surface_desc.dwSize = sizeof(surface_desc);
7540 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7541 surface_desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
7542 surface_desc.dwWidth = 16;
7543 surface_desc.dwHeight = 16;
7544 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
7545 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7547 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
7548 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7549 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
7550 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7551 hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface4);
7552 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7553 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface3);
7554 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7555 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface4);
7556 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7557 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface2);
7558 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7560 IDirectDrawSurface7_Release(surface4);
7561 IDirectDrawSurface7_Release(surface3);
7562 IDirectDrawSurface7_Release(surface2);
7563 IDirectDrawSurface7_Release(surface1);
7565 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7566 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7568 /* Try a single primary and two offscreen plain surfaces. */
7569 memset(&surface_desc, 0, sizeof(surface_desc));
7570 surface_desc.dwSize = sizeof(surface_desc);
7571 surface_desc.dwFlags = DDSD_CAPS;
7572 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7573 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7574 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7576 memset(&surface_desc, 0, sizeof(surface_desc));
7577 surface_desc.dwSize = sizeof(surface_desc);
7578 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7579 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7580 surface_desc.dwWidth = registry_mode.dmPelsWidth;
7581 surface_desc.dwHeight = registry_mode.dmPelsHeight;
7582 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
7583 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7585 memset(&surface_desc, 0, sizeof(surface_desc));
7586 surface_desc.dwSize = sizeof(surface_desc);
7587 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7588 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7589 surface_desc.dwWidth = registry_mode.dmPelsWidth;
7590 surface_desc.dwHeight = registry_mode.dmPelsHeight;
7591 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
7592 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7594 /* This one has a different size. */
7595 memset(&surface_desc, 0, sizeof(surface_desc));
7596 surface_desc.dwSize = sizeof(surface_desc);
7597 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7598 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
7599 surface_desc.dwWidth = 128;
7600 surface_desc.dwHeight = 128;
7601 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
7602 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7604 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
7605 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7606 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface1);
7607 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7608 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface3);
7609 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7610 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
7611 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7612 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
7613 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7615 IDirectDrawSurface7_Release(surface4);
7616 IDirectDrawSurface7_Release(surface3);
7617 IDirectDrawSurface7_Release(surface2);
7618 IDirectDrawSurface7_Release(surface1);
7620 /* Test depth surfaces of different sizes. */
7621 memset(&surface_desc, 0, sizeof(surface_desc));
7622 surface_desc.dwSize = sizeof(surface_desc);
7623 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7624 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
7625 surface_desc.dwWidth = 64;
7626 surface_desc.dwHeight = 64;
7627 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7628 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
7630 memset(&surface_desc, 0, sizeof(surface_desc));
7631 surface_desc.dwSize = sizeof(surface_desc);
7632 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
7633 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
7634 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7635 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
7636 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = 16;
7637 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = 0x0000ffff;
7638 surface_desc.dwWidth = 32;
7639 surface_desc.dwHeight = 32;
7640 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
7641 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
7642 surface_desc.dwWidth = 64;
7643 surface_desc.dwHeight = 64;
7644 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
7645 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
7646 surface_desc.dwWidth = 128;
7647 surface_desc.dwHeight = 128;
7648 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
7649 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
7651 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
7652 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7653 if (SUCCEEDED(hr))
7654 IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface2);
7655 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface3);
7656 ok(hr == D3D_OK, "Failed to attach depth buffer, hr %#x.\n", hr);
7657 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface3);
7658 ok(hr == D3D_OK, "Failed to detach depth buffer, hr %#x.\n", hr);
7659 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
7660 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7662 IDirectDrawSurface7_Release(surface4);
7663 IDirectDrawSurface7_Release(surface3);
7664 IDirectDrawSurface7_Release(surface2);
7665 IDirectDrawSurface7_Release(surface1);
7667 /* Test DeleteAttachedSurface() and automatic detachment of attached surfaces on release. */
7668 memset(&surface_desc, 0, sizeof(surface_desc));
7669 surface_desc.dwSize = sizeof(surface_desc);
7670 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7671 surface_desc.dwWidth = 64;
7672 surface_desc.dwHeight = 64;
7673 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
7674 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
7675 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
7676 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
7677 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
7678 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
7679 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
7680 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
7681 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7682 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
7683 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7685 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
7686 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
7687 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = 16;
7688 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = 0x0000ffff;
7689 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
7690 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7692 hr = IDirectDrawSurface7_QueryInterface(surface1, &IID_IDirectDrawSurface, (void **)&surface1v1);
7693 ok(SUCCEEDED(hr), "Failed to get interface, hr %#x.\n", hr);
7694 hr = IDirectDrawSurface7_QueryInterface(surface2, &IID_IDirectDrawSurface, (void **)&surface2v1);
7695 ok(SUCCEEDED(hr), "Failed to get interface, hr %#x.\n", hr);
7697 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
7698 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7699 refcount = get_refcount((IUnknown *)surface2);
7700 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
7701 refcount = get_refcount((IUnknown *)surface2v1);
7702 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7703 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
7704 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
7705 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
7706 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
7707 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
7708 ok(hr == DDERR_SURFACENOTATTACHED, "Got unexpected hr %#x.\n", hr);
7710 /* Attaching while already attached to other surface. */
7711 hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface2);
7712 todo_wine ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7713 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface3, 0, surface2);
7714 todo_wine ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7715 IDirectDrawSurface7_Release(surface3);
7717 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface2);
7718 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7719 refcount = get_refcount((IUnknown *)surface2);
7720 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7721 refcount = get_refcount((IUnknown *)surface2v1);
7722 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7724 /* DeleteAttachedSurface() when attaching via IDirectDrawSurface. */
7725 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
7726 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7727 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface2);
7728 ok(hr == DDERR_SURFACENOTATTACHED, "Got unexpected hr %#x.\n", hr);
7729 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
7730 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
7731 refcount = IDirectDrawSurface7_Release(surface2);
7732 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7733 refcount = IDirectDrawSurface7_Release(surface1);
7734 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7736 /* Automatic detachment on release. */
7737 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
7738 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
7739 refcount = get_refcount((IUnknown *)surface2v1);
7740 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
7741 refcount = IDirectDrawSurface_Release(surface1v1);
7742 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7743 refcount = IDirectDrawSurface_Release(surface2v1);
7744 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7745 refcount = IDirectDraw7_Release(ddraw);
7746 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7747 DestroyWindow(window);
7750 static void test_private_data(void)
7752 IDirectDraw7 *ddraw;
7753 IDirectDrawSurface7 *surface, *surface2;
7754 DDSURFACEDESC2 surface_desc;
7755 ULONG refcount, refcount2, refcount3;
7756 IUnknown *ptr;
7757 DWORD size = sizeof(ptr);
7758 HRESULT hr;
7759 HWND window;
7760 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
7761 DWORD data[] = {1, 2, 3, 4};
7762 DDCAPS hal_caps;
7763 static const GUID ddraw_private_data_test_guid =
7765 0xfdb37466,
7766 0x428f,
7767 0x4edf,
7768 {0xa3,0x7f,0x9b,0x1d,0xf4,0x88,0xc5,0xfc}
7770 static const GUID ddraw_private_data_test_guid2 =
7772 0x2e5afac2,
7773 0x87b5,
7774 0x4c10,
7775 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
7778 window = create_window();
7779 ddraw = create_ddraw();
7780 ok(!!ddraw, "Failed to create a ddraw object.\n");
7781 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7782 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7784 reset_ddsd(&surface_desc);
7785 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
7786 surface_desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
7787 surface_desc.dwHeight = 4;
7788 surface_desc.dwWidth = 4;
7789 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7790 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7792 /* NULL pointers are not valid, but don't cause a crash. */
7793 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL,
7794 sizeof(IUnknown *), DDSPD_IUNKNOWNPOINTER);
7795 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7796 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL, 0, 0);
7797 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7798 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL, 1, 0);
7799 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7801 /* DDSPD_IUNKNOWNPOINTER needs sizeof(IUnknown *) bytes of data. */
7802 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7803 0, DDSPD_IUNKNOWNPOINTER);
7804 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7805 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7806 5, DDSPD_IUNKNOWNPOINTER);
7807 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7808 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7809 sizeof(ddraw) * 2, DDSPD_IUNKNOWNPOINTER);
7810 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7812 /* Note that with a size != 0 and size != sizeof(IUnknown *) and
7813 * DDSPD_IUNKNOWNPOINTER set SetPrivateData in ddraw4 and ddraw7
7814 * erases the old content and returns an error. This behavior has
7815 * been fixed in d3d8 and d3d9. Unless an application is found
7816 * that depends on this we don't care about this behavior. */
7817 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7818 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7819 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7820 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7821 0, DDSPD_IUNKNOWNPOINTER);
7822 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7823 size = sizeof(ptr);
7824 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
7825 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7826 hr = IDirectDrawSurface7_FreePrivateData(surface, &ddraw_private_data_test_guid);
7827 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7829 refcount = get_refcount((IUnknown *)ddraw);
7830 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7831 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7832 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7833 refcount2 = get_refcount((IUnknown *)ddraw);
7834 ok(refcount2 == refcount + 1, "Got unexpected refcount %u.\n", refcount2);
7836 hr = IDirectDrawSurface7_FreePrivateData(surface, &ddraw_private_data_test_guid);
7837 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7838 refcount2 = get_refcount((IUnknown *)ddraw);
7839 ok(refcount2 == refcount, "Got unexpected refcount %u.\n", refcount2);
7841 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7842 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7843 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7844 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, surface,
7845 sizeof(surface), DDSPD_IUNKNOWNPOINTER);
7846 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7847 refcount2 = get_refcount((IUnknown *)ddraw);
7848 ok(refcount2 == refcount, "Got unexpected refcount %u.\n", refcount2);
7850 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
7851 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
7852 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7853 size = 2 * sizeof(ptr);
7854 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
7855 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7856 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
7857 refcount2 = get_refcount(ptr);
7858 /* Object is NOT addref'ed by the getter. */
7859 ok(ptr == (IUnknown *)ddraw, "Returned interface pointer is %p, expected %p.\n", ptr, ddraw);
7860 ok(refcount2 == refcount + 1, "Got unexpected refcount %u.\n", refcount2);
7862 ptr = (IUnknown *)0xdeadbeef;
7863 size = 1;
7864 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, &size);
7865 ok(hr == DDERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
7866 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
7867 size = 2 * sizeof(ptr);
7868 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, &size);
7869 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7870 ok(size == 2 * sizeof(ptr), "Got unexpected size %u.\n", size);
7871 size = 1;
7872 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
7873 ok(hr == DDERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
7874 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
7875 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7876 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid2, NULL, NULL);
7877 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7878 size = 0xdeadbabe;
7879 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid2, &ptr, &size);
7880 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7881 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7882 ok(size == 0xdeadbabe, "Got unexpected size %u.\n", size);
7883 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, NULL);
7884 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7886 refcount3 = IDirectDrawSurface7_Release(surface);
7887 ok(!refcount3, "Got unexpected refcount %u.\n", refcount3);
7889 /* Destroying the surface frees the reference held on the private data. It also frees
7890 * the reference the surface is holding on its creating object. */
7891 refcount2 = get_refcount((IUnknown *)ddraw);
7892 ok(refcount2 == refcount - 1, "Got unexpected refcount %u.\n", refcount2);
7894 memset(&hal_caps, 0, sizeof(hal_caps));
7895 hal_caps.dwSize = sizeof(hal_caps);
7896 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
7897 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7898 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) == (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)
7899 && !is_ddraw64)
7901 reset_ddsd(&surface_desc);
7902 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_MIPMAPCOUNT;
7903 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7904 surface_desc.dwHeight = 4;
7905 surface_desc.dwWidth = 4;
7906 U2(surface_desc).dwMipMapCount = 2;
7907 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7908 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7909 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &surface2);
7910 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
7912 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, data, sizeof(data), 0);
7913 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7914 hr = IDirectDrawSurface7_GetPrivateData(surface2, &ddraw_private_data_test_guid, NULL, NULL);
7915 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7917 IDirectDrawSurface7_Release(surface2);
7918 IDirectDrawSurface7_Release(surface);
7920 else
7921 skip("Mipmapped textures not supported, skipping mipmap private data test.\n");
7923 refcount = IDirectDraw7_Release(ddraw);
7924 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
7925 DestroyWindow(window);
7928 static void test_pixel_format(void)
7930 HWND window, window2 = NULL;
7931 HDC hdc, hdc2 = NULL;
7932 HMODULE gl = NULL;
7933 int format, test_format;
7934 PIXELFORMATDESCRIPTOR pfd;
7935 IDirectDraw7 *ddraw = NULL;
7936 IDirectDrawClipper *clipper = NULL;
7937 DDSURFACEDESC2 ddsd;
7938 IDirectDrawSurface7 *primary = NULL, *offscreen;
7939 DDBLTFX fx;
7940 HRESULT hr;
7942 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
7943 100, 100, 160, 160, NULL, NULL, NULL, NULL);
7944 if (!window)
7946 skip("Failed to create window\n");
7947 return;
7950 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
7951 100, 100, 160, 160, NULL, NULL, NULL, NULL);
7953 hdc = GetDC(window);
7954 if (!hdc)
7956 skip("Failed to get DC\n");
7957 goto cleanup;
7960 if (window2)
7961 hdc2 = GetDC(window2);
7963 gl = LoadLibraryA("opengl32.dll");
7964 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
7966 format = GetPixelFormat(hdc);
7967 ok(format == 0, "new window has pixel format %d\n", format);
7969 ZeroMemory(&pfd, sizeof(pfd));
7970 pfd.nSize = sizeof(pfd);
7971 pfd.nVersion = 1;
7972 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
7973 pfd.iPixelType = PFD_TYPE_RGBA;
7974 pfd.iLayerType = PFD_MAIN_PLANE;
7975 format = ChoosePixelFormat(hdc, &pfd);
7976 if (format <= 0)
7978 skip("no pixel format available\n");
7979 goto cleanup;
7982 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
7984 skip("failed to set pixel format\n");
7985 goto cleanup;
7988 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
7990 skip("failed to set pixel format on second window\n");
7991 if (hdc2)
7993 ReleaseDC(window2, hdc2);
7994 hdc2 = NULL;
7998 ddraw = create_ddraw();
7999 ok(!!ddraw, "Failed to create a ddraw object.\n");
8001 test_format = GetPixelFormat(hdc);
8002 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8004 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8005 if (FAILED(hr))
8007 skip("Failed to set cooperative level, hr %#x.\n", hr);
8008 goto cleanup;
8011 test_format = GetPixelFormat(hdc);
8012 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8014 if (hdc2)
8016 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
8017 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
8018 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window2);
8019 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
8021 test_format = GetPixelFormat(hdc);
8022 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8024 test_format = GetPixelFormat(hdc2);
8025 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
8028 memset(&ddsd, 0, sizeof(ddsd));
8029 ddsd.dwSize = sizeof(ddsd);
8030 ddsd.dwFlags = DDSD_CAPS;
8031 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8033 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
8034 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
8036 test_format = GetPixelFormat(hdc);
8037 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8039 if (hdc2)
8041 test_format = GetPixelFormat(hdc2);
8042 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
8045 if (clipper)
8047 hr = IDirectDrawSurface7_SetClipper(primary, clipper);
8048 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
8050 test_format = GetPixelFormat(hdc);
8051 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8053 test_format = GetPixelFormat(hdc2);
8054 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
8057 memset(&ddsd, 0, sizeof(ddsd));
8058 ddsd.dwSize = sizeof(ddsd);
8059 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8060 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8061 ddsd.dwWidth = ddsd.dwHeight = 64;
8062 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &offscreen, NULL);
8063 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
8065 memset(&fx, 0, sizeof(fx));
8066 fx.dwSize = sizeof(fx);
8067 hr = IDirectDrawSurface7_Blt(offscreen, NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &fx);
8068 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
8070 test_format = GetPixelFormat(hdc);
8071 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8073 hr = IDirectDrawSurface7_Blt(primary, NULL, offscreen, NULL, DDBLT_WAIT, NULL);
8074 ok(SUCCEEDED(hr), "Failed to blit to primary surface, hr %#x.\n", hr);
8076 test_format = GetPixelFormat(hdc);
8077 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8079 if (hdc2)
8081 test_format = GetPixelFormat(hdc2);
8082 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
8085 IDirectDrawSurface7_Release(offscreen);
8087 cleanup:
8088 if (primary) IDirectDrawSurface7_Release(primary);
8089 if (clipper) IDirectDrawClipper_Release(clipper);
8090 if (ddraw) IDirectDraw7_Release(ddraw);
8091 if (gl) FreeLibrary(gl);
8092 if (hdc) ReleaseDC(window, hdc);
8093 if (hdc2) ReleaseDC(window2, hdc2);
8094 DestroyWindow(window);
8095 if (window2) DestroyWindow(window2);
8098 static void test_create_surface_pitch(void)
8100 IDirectDrawSurface7 *surface;
8101 DDSURFACEDESC2 surface_desc;
8102 IDirectDraw7 *ddraw;
8103 unsigned int i;
8104 ULONG refcount;
8105 HWND window;
8106 HRESULT hr;
8107 void *mem;
8109 static const struct
8111 DWORD caps;
8112 DWORD flags_in;
8113 DWORD pitch_in;
8114 HRESULT hr;
8115 DWORD flags_out;
8116 DWORD pitch_out32;
8117 DWORD pitch_out64;
8119 test_data[] =
8121 /* 0 */
8122 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
8123 0, 0, DD_OK,
8124 DDSD_PITCH, 0x100, 0x100},
8125 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
8126 DDSD_PITCH, 0x104, DD_OK,
8127 DDSD_PITCH, 0x100, 0x100},
8128 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
8129 DDSD_PITCH, 0x0f8, DD_OK,
8130 DDSD_PITCH, 0x100, 0x100},
8131 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
8132 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
8133 0, 0, 0 },
8134 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8135 0, 0, DD_OK,
8136 DDSD_PITCH, 0x100, 0x0fc},
8137 /* 5 */
8138 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8139 DDSD_PITCH, 0x104, DD_OK,
8140 DDSD_PITCH, 0x100, 0x0fc},
8141 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8142 DDSD_PITCH, 0x0f8, DD_OK,
8143 DDSD_PITCH, 0x100, 0x0fc},
8144 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8145 DDSD_PITCH | DDSD_LINEARSIZE, 0, DD_OK,
8146 DDSD_PITCH, 0x100, 0x0fc},
8147 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8148 DDSD_LPSURFACE, 0, DDERR_INVALIDPARAMS,
8149 0, 0, 0 },
8150 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8151 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DD_OK,
8152 DDSD_PITCH, 0x100, 0x100},
8153 /* 10 */
8154 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8155 DDSD_LPSURFACE | DDSD_PITCH, 0x0fe, DDERR_INVALIDPARAMS,
8156 0, 0, 0 },
8157 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8158 DDSD_LPSURFACE | DDSD_PITCH, 0x0fc, DD_OK,
8159 DDSD_PITCH, 0x0fc, 0x0fc},
8160 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8161 DDSD_LPSURFACE | DDSD_PITCH, 0x0f8, DDERR_INVALIDPARAMS,
8162 0, 0, 0 },
8163 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8164 DDSD_LPSURFACE | DDSD_LINEARSIZE, 0x100, DDERR_INVALIDPARAMS,
8165 0, 0, 0 },
8166 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8167 DDSD_LPSURFACE | DDSD_LINEARSIZE, 0x3f00, DDERR_INVALIDPARAMS,
8168 0, 0, 0 },
8169 /* 15 */
8170 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8171 DDSD_LPSURFACE | DDSD_PITCH | DDSD_LINEARSIZE, 0x100, DD_OK,
8172 DDSD_PITCH, 0x100, 0x100},
8173 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
8174 0, 0, DDERR_INVALIDCAPS,
8175 0, 0, 0 },
8176 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
8177 0, 0, DD_OK,
8178 DDSD_PITCH, 0x100, 0 },
8179 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
8180 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
8181 0, 0, 0 },
8182 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
8183 0, 0, DDERR_INVALIDCAPS,
8184 0, 0, 0 },
8185 /* 20 */
8186 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
8187 0, 0, DD_OK,
8188 DDSD_PITCH, 0x100, 0 },
8189 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
8190 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DD_OK,
8191 DDSD_PITCH, 0x100, 0 },
8193 DWORD flags_mask = DDSD_PITCH | DDSD_LPSURFACE | DDSD_LINEARSIZE;
8195 window = create_window();
8196 ddraw = create_ddraw();
8197 ok(!!ddraw, "Failed to create a ddraw object.\n");
8198 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8199 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8201 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((63 * 4) + 8) * 63);
8203 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
8205 memset(&surface_desc, 0, sizeof(surface_desc));
8206 surface_desc.dwSize = sizeof(surface_desc);
8207 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | test_data[i].flags_in;
8208 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
8209 surface_desc.dwWidth = 63;
8210 surface_desc.dwHeight = 63;
8211 U1(surface_desc).lPitch = test_data[i].pitch_in;
8212 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8213 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
8214 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
8215 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8216 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8217 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
8218 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8219 if (test_data[i].flags_in & DDSD_LPSURFACE)
8221 HRESULT expected_hr = SUCCEEDED(test_data[i].hr) ? DDERR_INVALIDPARAMS : test_data[i].hr;
8222 ok(hr == expected_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, expected_hr);
8223 surface_desc.lpSurface = mem;
8224 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8226 if ((test_data[i].caps & DDSCAPS_VIDEOMEMORY) && hr == DDERR_NODIRECTDRAWHW)
8227 continue;
8228 if (is_ddraw64 && (test_data[i].caps & DDSCAPS_TEXTURE) && SUCCEEDED(test_data[i].hr))
8229 todo_wine ok(hr == E_NOINTERFACE, "Test %u: Got unexpected hr %#x.\n", i, hr);
8230 else
8231 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
8232 if (FAILED(hr))
8233 continue;
8235 memset(&surface_desc, 0, sizeof(surface_desc));
8236 surface_desc.dwSize = sizeof(surface_desc);
8237 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
8238 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
8239 ok((surface_desc.dwFlags & flags_mask) == test_data[i].flags_out,
8240 "Test %u: Got unexpected flags %#x, expected %#x.\n",
8241 i, surface_desc.dwFlags & flags_mask, test_data[i].flags_out);
8242 /* The pitch for textures seems to be implementation specific. */
8243 if (!(test_data[i].caps & DDSCAPS_TEXTURE))
8245 if (is_ddraw64 && test_data[i].pitch_out32 != test_data[i].pitch_out64)
8246 todo_wine ok(U1(surface_desc).lPitch == test_data[i].pitch_out64,
8247 "Test %u: Got unexpected pitch %u, expected %u.\n",
8248 i, U1(surface_desc).lPitch, test_data[i].pitch_out64);
8249 else
8250 ok(U1(surface_desc).lPitch == test_data[i].pitch_out32,
8251 "Test %u: Got unexpected pitch %u, expected %u.\n",
8252 i, U1(surface_desc).lPitch, test_data[i].pitch_out32);
8254 ok(!surface_desc.lpSurface, "Test %u: Got unexpected lpSurface %p.\n", i, surface_desc.lpSurface);
8256 IDirectDrawSurface7_Release(surface);
8259 HeapFree(GetProcessHeap(), 0, mem);
8260 refcount = IDirectDraw7_Release(ddraw);
8261 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8262 DestroyWindow(window);
8265 static void test_mipmap(void)
8267 IDirectDrawSurface7 *surface, *surface_base, *surface_mip;
8268 unsigned int i, mipmap_count;
8269 DDSURFACEDESC2 surface_desc;
8270 IDirectDraw7 *ddraw;
8271 ULONG refcount;
8272 HWND window;
8273 HRESULT hr;
8274 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
8275 DDCAPS hal_caps;
8277 static const struct
8279 DWORD flags;
8280 DWORD caps;
8281 DWORD width;
8282 DWORD height;
8283 DWORD mipmap_count_in;
8284 HRESULT hr;
8285 DWORD mipmap_count_out;
8287 tests[] =
8289 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 3, DD_OK, 3},
8290 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDPARAMS, 0},
8291 {0, DDSCAPS_TEXTURE | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 1},
8292 {0, DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDCAPS, 0},
8293 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 8},
8294 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 32, 64, 0, DD_OK, 7},
8297 window = create_window();
8298 ddraw = create_ddraw();
8299 ok(!!ddraw, "Failed to create a ddraw object.\n");
8300 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8301 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8303 memset(&hal_caps, 0, sizeof(hal_caps));
8304 hal_caps.dwSize = sizeof(hal_caps);
8305 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
8306 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8307 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)
8308 || is_ddraw64)
8310 skip("Mipmapped textures not supported, skipping tests.\n");
8311 IDirectDraw7_Release(ddraw);
8312 DestroyWindow(window);
8313 return;
8316 for (i = 0; i < ARRAY_SIZE(tests); ++i)
8318 memset(&surface_desc, 0, sizeof(surface_desc));
8319 surface_desc.dwSize = sizeof(surface_desc);
8320 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | tests[i].flags;
8321 surface_desc.ddsCaps.dwCaps = tests[i].caps;
8322 surface_desc.dwWidth = tests[i].width;
8323 surface_desc.dwHeight = tests[i].height;
8324 if (tests[i].flags & DDSD_MIPMAPCOUNT)
8325 U2(surface_desc).dwMipMapCount = tests[i].mipmap_count_in;
8326 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8327 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x.\n", i, hr);
8328 if (FAILED(hr))
8329 continue;
8331 memset(&surface_desc, 0, sizeof(surface_desc));
8332 surface_desc.dwSize = sizeof(surface_desc);
8333 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
8334 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
8335 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
8336 "Test %u: Got unexpected flags %#x.\n", i, surface_desc.dwFlags);
8337 ok(U2(surface_desc).dwMipMapCount == tests[i].mipmap_count_out,
8338 "Test %u: Got unexpected mipmap count %u.\n", i, U2(surface_desc).dwMipMapCount);
8340 surface_base = surface;
8341 IDirectDrawSurface7_AddRef(surface_base);
8342 mipmap_count = U2(surface_desc).dwMipMapCount;
8343 while (mipmap_count > 1)
8345 hr = IDirectDrawSurface7_GetAttachedSurface(surface_base, &caps, &surface_mip);
8346 ok(SUCCEEDED(hr), "Test %u, %u: Failed to get attached surface, hr %#x.\n", i, mipmap_count, hr);
8348 memset(&surface_desc, 0, sizeof(surface_desc));
8349 surface_desc.dwSize = sizeof(surface_desc);
8350 hr = IDirectDrawSurface7_GetSurfaceDesc(surface_base, &surface_desc);
8351 ok(SUCCEEDED(hr), "Test %u, %u: Failed to get surface desc, hr %#x.\n", i, mipmap_count, hr);
8352 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
8353 "Test %u, %u: Got unexpected flags %#x.\n", i, mipmap_count, surface_desc.dwFlags);
8354 ok(U2(surface_desc).dwMipMapCount == mipmap_count,
8355 "Test %u, %u: Got unexpected mipmap count %u.\n",
8356 i, mipmap_count, U2(surface_desc).dwMipMapCount);
8358 memset(&surface_desc, 0, sizeof(surface_desc));
8359 surface_desc.dwSize = sizeof(surface_desc);
8360 hr = IDirectDrawSurface7_Lock(surface_base, NULL, &surface_desc, 0, NULL);
8361 ok(SUCCEEDED(hr), "Test %u, %u: Failed to lock surface, hr %#x.\n", i, mipmap_count, hr);
8362 ok(surface_desc.dwMipMapCount == mipmap_count,
8363 "Test %u, %u: unexpected change of mipmap count %u.\n",
8364 i, mipmap_count, surface_desc.dwMipMapCount);
8365 memset(&surface_desc, 0, sizeof(surface_desc));
8366 surface_desc.dwSize = sizeof(surface_desc);
8367 hr = IDirectDrawSurface7_Lock(surface_mip, NULL, &surface_desc, 0, NULL);
8368 ok(SUCCEEDED(hr), "Test %u, %u: Failed to lock surface, hr %#x.\n", i, mipmap_count, hr);
8369 ok(surface_desc.dwMipMapCount == mipmap_count - 1,
8370 "Test %u, %u: Child mipmap count unexpected %u\n", i, mipmap_count, surface_desc.dwMipMapCount);
8371 IDirectDrawSurface7_Unlock(surface_mip, NULL);
8372 IDirectDrawSurface7_Unlock(surface_base, NULL);
8374 IDirectDrawSurface7_Release(surface_base);
8375 surface_base = surface_mip;
8376 --mipmap_count;
8378 IDirectDrawSurface7_Release(surface_base);
8380 IDirectDrawSurface7_Release(surface);
8383 refcount = IDirectDraw7_Release(ddraw);
8384 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8385 DestroyWindow(window);
8388 static void test_palette_complex(void)
8390 IDirectDrawSurface7 *surface, *mipmap, *tmp;
8391 DDSURFACEDESC2 surface_desc;
8392 IDirectDraw7 *ddraw;
8393 IDirectDrawPalette *palette, *palette2;
8394 ULONG refcount;
8395 HWND window;
8396 HRESULT hr;
8397 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
8398 DDCAPS hal_caps;
8399 PALETTEENTRY palette_entries[256];
8400 unsigned int i;
8402 window = create_window();
8403 ddraw = create_ddraw();
8404 ok(!!ddraw, "Failed to create a ddraw object.\n");
8405 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8406 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8408 memset(&hal_caps, 0, sizeof(hal_caps));
8409 hal_caps.dwSize = sizeof(hal_caps);
8410 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
8411 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8412 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)
8413 || is_ddraw64)
8415 skip("Mipmapped textures not supported, skipping mipmap palette test.\n");
8416 IDirectDraw7_Release(ddraw);
8417 DestroyWindow(window);
8418 return;
8421 memset(&surface_desc, 0, sizeof(surface_desc));
8422 surface_desc.dwSize = sizeof(surface_desc);
8423 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8424 surface_desc.dwWidth = 128;
8425 surface_desc.dwHeight = 128;
8426 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
8427 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8428 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
8429 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
8430 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8431 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8433 memset(palette_entries, 0, sizeof(palette_entries));
8434 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8435 palette_entries, &palette, NULL);
8436 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8438 palette2 = (void *)0xdeadbeef;
8439 hr = IDirectDrawSurface7_GetPalette(surface, &palette2);
8440 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
8441 ok(!palette2, "Got unexpected palette %p.\n", palette2);
8442 hr = IDirectDrawSurface7_SetPalette(surface, palette);
8443 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8444 hr = IDirectDrawSurface7_GetPalette(surface, &palette2);
8445 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
8446 ok(palette == palette2, "Got unexpected palette %p.\n", palette2);
8447 IDirectDrawPalette_Release(palette2);
8449 mipmap = surface;
8450 IDirectDrawSurface7_AddRef(mipmap);
8451 for (i = 0; i < 7; ++i)
8453 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
8454 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
8455 palette2 = (void *)0xdeadbeef;
8456 hr = IDirectDrawSurface7_GetPalette(tmp, &palette2);
8457 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x, i %u.\n", hr, i);
8458 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
8460 hr = IDirectDrawSurface7_SetPalette(tmp, palette);
8461 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x, i %u.\n", hr, i);
8463 hr = IDirectDrawSurface7_GetPalette(tmp, &palette2);
8464 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x, i %u.\n", hr, i);
8465 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
8467 /* Ddraw7 uses the palette of the mipmap for GetDC, just like previous
8468 * ddraw versions. Combined with the test results above this means no
8469 * palette is available. So depending on the driver either GetDC fails
8470 * or the DIB color table contains random data. */
8472 IDirectDrawSurface7_Release(mipmap);
8473 mipmap = tmp;
8476 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
8477 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
8478 IDirectDrawSurface7_Release(mipmap);
8479 refcount = IDirectDrawSurface7_Release(surface);
8480 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8482 /* Test DDERR_INVALIDPIXELFORMAT vs DDERR_NOTONMIPMAPSUBLEVEL. */
8483 memset(&surface_desc, 0, sizeof(surface_desc));
8484 surface_desc.dwSize = sizeof(surface_desc);
8485 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8486 surface_desc.dwWidth = 128;
8487 surface_desc.dwHeight = 128;
8488 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
8489 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8490 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
8491 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
8492 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8493 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8494 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
8495 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8496 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8498 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
8499 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
8500 hr = IDirectDrawSurface7_SetPalette(mipmap, palette);
8501 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x.\n", hr);
8503 IDirectDrawSurface7_Release(mipmap);
8504 refcount = IDirectDrawSurface7_Release(surface);
8505 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8506 refcount = IDirectDrawPalette_Release(palette);
8507 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8509 refcount = IDirectDraw7_Release(ddraw);
8510 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8511 DestroyWindow(window);
8514 static void test_p8_blit(void)
8516 IDirectDrawSurface7 *src, *dst, *dst_p8;
8517 DDSURFACEDESC2 surface_desc;
8518 IDirectDraw7 *ddraw;
8519 IDirectDrawPalette *palette, *palette2;
8520 ULONG refcount;
8521 HWND window;
8522 HRESULT hr;
8523 PALETTEENTRY palette_entries[256];
8524 unsigned int x;
8525 DDBLTFX fx;
8526 BOOL is_warp;
8527 static const BYTE src_data[] = {0x10, 0x1, 0x2, 0x3, 0x4, 0x5, 0xff, 0x80};
8528 static const BYTE src_data2[] = {0x10, 0x5, 0x4, 0x3, 0x2, 0x1, 0xff, 0x80};
8529 static const BYTE expected_p8[] = {0x10, 0x1, 0x4, 0x3, 0x4, 0x5, 0xff, 0x80};
8530 static const D3DCOLOR expected[] =
8532 0x00101010, 0x00010101, 0x00020202, 0x00030303,
8533 0x00040404, 0x00050505, 0x00ffffff, 0x00808080,
8535 D3DCOLOR color;
8537 window = create_window();
8538 ddraw = create_ddraw();
8539 ok(!!ddraw, "Failed to create a ddraw object.\n");
8540 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8541 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8542 is_warp = ddraw_is_warp(ddraw);
8544 memset(palette_entries, 0, sizeof(palette_entries));
8545 palette_entries[1].peGreen = 0xff;
8546 palette_entries[2].peBlue = 0xff;
8547 palette_entries[3].peFlags = 0xff;
8548 palette_entries[4].peRed = 0xff;
8549 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8550 palette_entries, &palette, NULL);
8551 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8552 palette_entries[1].peBlue = 0xff;
8553 palette_entries[2].peGreen = 0xff;
8554 palette_entries[3].peRed = 0xff;
8555 palette_entries[4].peFlags = 0x0;
8556 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8557 palette_entries, &palette2, NULL);
8558 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8560 memset(&surface_desc, 0, sizeof(surface_desc));
8561 surface_desc.dwSize = sizeof(surface_desc);
8562 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8563 surface_desc.dwWidth = 8;
8564 surface_desc.dwHeight = 1;
8565 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8566 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8567 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
8568 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
8569 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
8570 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8571 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_p8, NULL);
8572 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8573 hr = IDirectDrawSurface7_SetPalette(dst_p8, palette2);
8574 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8576 memset(&surface_desc, 0, sizeof(surface_desc));
8577 surface_desc.dwSize = sizeof(surface_desc);
8578 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8579 surface_desc.dwWidth = 8;
8580 surface_desc.dwHeight = 1;
8581 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8582 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8583 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
8584 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
8585 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8586 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8587 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
8588 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
8589 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
8590 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8592 memset(&surface_desc, 0, sizeof(surface_desc));
8593 surface_desc.dwSize = sizeof(surface_desc);
8594 hr = IDirectDrawSurface7_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
8595 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
8596 memcpy(surface_desc.lpSurface, src_data, sizeof(src_data));
8597 hr = IDirectDrawSurface7_Unlock(src, NULL);
8598 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
8600 hr = IDirectDrawSurface7_Lock(dst_p8, NULL, &surface_desc, DDLOCK_WAIT, NULL);
8601 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#x.\n", hr);
8602 memcpy(surface_desc.lpSurface, src_data2, sizeof(src_data2));
8603 hr = IDirectDrawSurface7_Unlock(dst_p8, NULL);
8604 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#x.\n", hr);
8606 fx.dwSize = sizeof(fx);
8607 fx.dwFillColor = 0xdeadbeef;
8608 hr = IDirectDrawSurface7_Blt(dst, NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &fx);
8609 ok(SUCCEEDED(hr), "Failed to color fill %#x.\n", hr);
8611 hr = IDirectDrawSurface7_SetPalette(src, palette);
8612 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8613 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_WAIT, NULL);
8614 /* The r500 Windows 7 driver returns E_NOTIMPL. r200 on Windows XP works.
8615 * The Geforce 7 driver on Windows Vista returns E_FAIL. Newer Nvidia GPUs work. */
8616 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL) || broken(hr == E_FAIL),
8617 "Failed to blit, hr %#x.\n", hr);
8619 if (SUCCEEDED(hr))
8621 for (x = 0; x < ARRAY_SIZE(expected); ++x)
8623 color = get_surface_color(dst, x, 0);
8624 /* WARP on 1709 and newer write zeroes on non-colorkeyed P8 -> RGB blits. For ckey
8625 * blits see below. */
8626 todo_wine ok(compare_color(color, expected[x], 0)
8627 || broken(is_warp && compare_color(color, 0x00000000, 0)),
8628 "Pixel %u: Got color %#x, expected %#x.\n",
8629 x, color, expected[x]);
8633 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x2;
8634 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x2;
8635 hr = IDirectDrawSurface7_Blt(dst_p8, NULL, src, NULL, DDBLT_WAIT | DDBLT_KEYSRCOVERRIDE, &fx);
8636 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
8638 hr = IDirectDrawSurface7_Lock(dst_p8, NULL, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
8639 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#x.\n", hr);
8640 /* A color keyed P8 blit doesn't do anything on WARP - it just leaves the data in the destination
8641 * surface untouched. Error checking (DDBLT_KEYSRC without a key
8642 * for example) also works as expected.
8644 * Using DDBLT_KEYSRC instead of DDBLT_KEYSRCOVERRIDE doesn't change this. Doing this blit with
8645 * the display mode set to P8 doesn't help either. */
8646 ok(!memcmp(surface_desc.lpSurface, expected_p8, sizeof(expected_p8))
8647 || broken(is_warp && !memcmp(surface_desc.lpSurface, src_data2, sizeof(src_data2))),
8648 "Got unexpected P8 color key blit result.\n");
8649 hr = IDirectDrawSurface7_Unlock(dst_p8, NULL);
8650 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#x.\n", hr);
8652 IDirectDrawSurface7_Release(src);
8653 IDirectDrawSurface7_Release(dst);
8654 IDirectDrawSurface7_Release(dst_p8);
8655 IDirectDrawPalette_Release(palette);
8656 IDirectDrawPalette_Release(palette2);
8658 refcount = IDirectDraw7_Release(ddraw);
8659 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8660 DestroyWindow(window);
8663 static void test_material(void)
8665 static const D3DCOLORVALUE null_color;
8666 IDirect3DDevice7 *device;
8667 D3DMATERIAL7 material;
8668 ULONG refcount;
8669 HWND window;
8670 HRESULT hr;
8672 window = create_window();
8673 if (!(device = create_device(window, DDSCL_NORMAL)))
8675 skip("Failed to create a 3D device, skipping test.\n");
8676 DestroyWindow(window);
8677 return;
8680 hr = IDirect3DDevice7_GetMaterial(device, &material);
8681 ok(SUCCEEDED(hr), "Failed to get material, hr %#x.\n", hr);
8682 ok(!memcmp(&U(material).diffuse, &null_color, sizeof(null_color)),
8683 "Got unexpected diffuse color {%.8e, %.8e, %.8e, %.8e}.\n",
8684 U1(U(material).diffuse).r, U2(U(material).diffuse).g,
8685 U3(U(material).diffuse).b, U4(U(material).diffuse).a);
8686 ok(!memcmp(&U1(material).ambient, &null_color, sizeof(null_color)),
8687 "Got unexpected ambient color {%.8e, %.8e, %.8e, %.8e}.\n",
8688 U1(U1(material).ambient).r, U2(U1(material).ambient).g,
8689 U3(U1(material).ambient).b, U4(U1(material).ambient).a);
8690 ok(!memcmp(&U2(material).specular, &null_color, sizeof(null_color)),
8691 "Got unexpected specular color {%.8e, %.8e, %.8e, %.8e}.\n",
8692 U1(U2(material).specular).r, U2(U2(material).specular).g,
8693 U3(U2(material).specular).b, U4(U2(material).specular).a);
8694 ok(!memcmp(&U3(material).emissive, &null_color, sizeof(null_color)),
8695 "Got unexpected emissive color {%.8e, %.8e, %.8e, %.8e}.\n",
8696 U1(U3(material).emissive).r, U2(U3(material).emissive).g,
8697 U3(U3(material).emissive).b, U4(U3(material).emissive).a);
8698 ok(U4(material).power == 0.0f, "Got unexpected power %.8e.\n", U4(material).power);
8700 refcount = IDirect3DDevice7_Release(device);
8701 ok(!refcount, "Device has %u references left.\n", refcount);
8702 DestroyWindow(window);
8705 static void test_palette_gdi(void)
8707 IDirectDrawSurface7 *surface, *primary;
8708 DDSURFACEDESC2 surface_desc;
8709 IDirectDraw7 *ddraw;
8710 IDirectDrawPalette *palette, *palette2;
8711 ULONG refcount;
8712 HWND window;
8713 HRESULT hr;
8714 PALETTEENTRY palette_entries[256];
8715 UINT i;
8716 HDC dc;
8717 DDBLTFX fx;
8718 RECT r;
8719 COLORREF color;
8720 /* On the Windows 8 testbot palette index 0 of the onscreen palette is forced to
8721 * r = 0, g = 0, b = 0. Do not attempt to set it to something else as this is
8722 * not the point of this test. */
8723 static const RGBQUAD expected1[] =
8725 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
8726 {0x03, 0x00, 0x00, 0x00}, {0x15, 0x14, 0x13, 0x00},
8728 static const RGBQUAD expected2[] =
8730 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
8731 {0x03, 0x00, 0x00, 0x00}, {0x25, 0x24, 0x23, 0x00},
8733 static const RGBQUAD expected3[] =
8735 {0x00, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x40, 0x00},
8736 {0x00, 0x40, 0x00, 0x00}, {0x56, 0x34, 0x12, 0x00},
8738 HPALETTE ddraw_palette_handle;
8739 /* Similar to index 0, index 255 is r = 0xff, g = 0xff, b = 0xff on the Win8 VMs. */
8740 RGBQUAD rgbquad[255];
8741 static const RGBQUAD rgb_zero = {0, 0, 0, 0};
8743 window = create_window();
8744 ddraw = create_ddraw();
8745 ok(!!ddraw, "Failed to create a ddraw object.\n");
8746 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8747 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8749 memset(&surface_desc, 0, sizeof(surface_desc));
8750 surface_desc.dwSize = sizeof(surface_desc);
8751 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8752 surface_desc.dwWidth = 16;
8753 surface_desc.dwHeight = 16;
8754 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8755 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8756 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
8757 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
8758 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8759 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8761 /* Avoid colors from the Windows default palette. */
8762 memset(palette_entries, 0, sizeof(palette_entries));
8763 palette_entries[1].peRed = 0x01;
8764 palette_entries[2].peGreen = 0x02;
8765 palette_entries[3].peBlue = 0x03;
8766 palette_entries[4].peRed = 0x13;
8767 palette_entries[4].peGreen = 0x14;
8768 palette_entries[4].peBlue = 0x15;
8769 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8770 palette_entries, &palette, NULL);
8771 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8773 /* If there is no palette assigned and the display mode is not 8 bpp, some
8774 * drivers refuse to create a DC while others allow it. If a DC is created,
8775 * the DIB color table is uninitialized and contains random colors. No error
8776 * is generated when trying to read pixels and random garbage is returned.
8778 * The most likely explanation is that if the driver creates a DC, it (or
8779 * the higher-level runtime) uses GetSystemPaletteEntries to find the
8780 * palette, but GetSystemPaletteEntries fails when bpp > 8 and the palette
8781 * contains uninitialized garbage. See comments below for the P8 case. */
8783 hr = IDirectDrawSurface7_SetPalette(surface, palette);
8784 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8785 hr = IDirectDrawSurface7_GetDC(surface, &dc);
8786 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8787 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
8788 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
8789 "Got unexpected palette %p, expected %p.\n",
8790 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
8792 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8793 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8794 for (i = 0; i < ARRAY_SIZE(expected1); ++i)
8796 ok(!memcmp(&rgbquad[i], &expected1[i], sizeof(rgbquad[i])),
8797 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8798 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8799 expected1[i].rgbRed, expected1[i].rgbGreen, expected1[i].rgbBlue);
8801 for (; i < ARRAY_SIZE(rgbquad); ++i)
8803 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8804 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8805 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8808 /* Update the palette while the DC is in use. This does not modify the DC. */
8809 palette_entries[4].peRed = 0x23;
8810 palette_entries[4].peGreen = 0x24;
8811 palette_entries[4].peBlue = 0x25;
8812 hr = IDirectDrawPalette_SetEntries(palette, 0, 4, 1, &palette_entries[4]);
8813 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
8815 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
8816 ok(i == 1, "Expected count 1, got %u.\n", i);
8817 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
8818 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8819 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
8820 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
8822 /* Neither does re-setting the palette. */
8823 hr = IDirectDrawSurface7_SetPalette(surface, NULL);
8824 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8825 hr = IDirectDrawSurface7_SetPalette(surface, palette);
8826 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8828 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
8829 ok(i == 1, "Expected count 1, got %u.\n", i);
8830 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
8831 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8832 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
8833 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
8835 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
8836 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8838 /* Refresh the DC. This updates the palette. */
8839 hr = IDirectDrawSurface7_GetDC(surface, &dc);
8840 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8841 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8842 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8843 for (i = 0; i < ARRAY_SIZE(expected2); ++i)
8845 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8846 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8847 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8848 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8850 for (; i < ARRAY_SIZE(rgbquad); ++i)
8852 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8853 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8854 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8856 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
8857 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8859 refcount = IDirectDrawSurface7_Release(surface);
8860 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8862 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
8863 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8864 if (FAILED(IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
8866 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
8867 IDirectDrawPalette_Release(palette);
8868 IDirectDraw7_Release(ddraw);
8869 DestroyWindow(window);
8870 return;
8872 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
8874 memset(&surface_desc, 0, sizeof(surface_desc));
8875 surface_desc.dwSize = sizeof(surface_desc);
8876 surface_desc.dwFlags = DDSD_CAPS;
8877 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8878 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
8879 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8881 memset(&fx, 0, sizeof(fx));
8882 fx.dwSize = sizeof(fx);
8883 U5(fx).dwFillColor = 3;
8884 SetRect(&r, 0, 0, 319, 479);
8885 hr = IDirectDrawSurface7_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8886 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#x.\n", hr);
8887 SetRect(&r, 320, 0, 639, 479);
8888 U5(fx).dwFillColor = 4;
8889 hr = IDirectDrawSurface7_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
8890 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#x.\n", hr);
8892 hr = IDirectDrawSurface7_SetPalette(primary, palette);
8893 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8894 hr = IDirectDrawSurface7_GetDC(primary, &dc);
8895 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8897 color = GetPixel(dc, 160, 240);
8898 ok(color == 0x00030000, "Clear index 3: Got unexpected color 0x%08x.\n", color);
8899 color = GetPixel(dc, 480, 240);
8900 ok(color == 0x00252423, "Clear index 4: Got unexpected color 0x%08x.\n", color);
8902 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
8903 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
8904 "Got unexpected palette %p, expected %p.\n",
8905 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
8906 SelectPalette(dc, ddraw_palette_handle, FALSE);
8908 /* The primary uses the system palette. In exclusive mode, the system palette matches
8909 * the ddraw palette attached to the primary, so the result is what you would expect
8910 * from a regular surface. Tests for the interaction between the ddraw palette and
8911 * the system palette are not included pending an application that depends on this.
8912 * The relation between those causes problems on Windows Vista and newer for games
8913 * like Age of Empires or StarcCaft. Don't emulate it without a real need. */
8914 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8915 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8916 for (i = 0; i < ARRAY_SIZE(expected2); ++i)
8918 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8919 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8920 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8921 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8923 for (; i < ARRAY_SIZE(rgbquad); ++i)
8925 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8926 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8927 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8929 hr = IDirectDrawSurface7_ReleaseDC(primary, dc);
8930 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8932 memset(&surface_desc, 0, sizeof(surface_desc));
8933 surface_desc.dwSize = sizeof(surface_desc);
8934 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8935 surface_desc.dwWidth = 16;
8936 surface_desc.dwHeight = 16;
8937 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8938 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8939 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8941 /* Here the offscreen surface appears to use the primary's palette,
8942 * but in all likelihood it is actually the system palette. */
8943 hr = IDirectDrawSurface7_GetDC(surface, &dc);
8944 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8945 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8946 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8947 for (i = 0; i < ARRAY_SIZE(expected2); ++i)
8949 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
8950 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8951 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8952 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
8954 for (; i < ARRAY_SIZE(rgbquad); ++i)
8956 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8957 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8958 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
8960 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
8961 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
8963 /* On real hardware a change to the primary surface's palette applies immediately,
8964 * even on device contexts from offscreen surfaces that do not have their own
8965 * palette. On the testbot VMs this is not the case. Don't test this until we
8966 * know of an application that depends on this. */
8968 memset(palette_entries, 0, sizeof(palette_entries));
8969 palette_entries[1].peBlue = 0x40;
8970 palette_entries[2].peRed = 0x40;
8971 palette_entries[3].peGreen = 0x40;
8972 palette_entries[4].peRed = 0x12;
8973 palette_entries[4].peGreen = 0x34;
8974 palette_entries[4].peBlue = 0x56;
8975 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
8976 palette_entries, &palette2, NULL);
8977 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8978 hr = IDirectDrawSurface7_SetPalette(surface, palette2);
8979 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8981 /* A palette assigned to the offscreen surface overrides the primary / system
8982 * palette. */
8983 hr = IDirectDrawSurface7_GetDC(surface, &dc);
8984 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
8985 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
8986 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
8987 for (i = 0; i < ARRAY_SIZE(expected3); ++i)
8989 ok(!memcmp(&rgbquad[i], &expected3[i], sizeof(rgbquad[i])),
8990 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
8991 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
8992 expected3[i].rgbRed, expected3[i].rgbGreen, expected3[i].rgbBlue);
8994 for (; i < ARRAY_SIZE(rgbquad); ++i)
8996 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
8997 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
8998 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
9000 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
9001 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
9003 refcount = IDirectDrawSurface7_Release(surface);
9004 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9006 /* The Windows 8 testbot keeps extra references to the primary and
9007 * backbuffer while in 8 bpp mode. */
9008 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
9009 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
9011 refcount = IDirectDrawSurface7_Release(primary);
9012 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9013 refcount = IDirectDrawPalette_Release(palette2);
9014 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9015 refcount = IDirectDrawPalette_Release(palette);
9016 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9017 refcount = IDirectDraw7_Release(ddraw);
9018 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9019 DestroyWindow(window);
9022 static void test_palette_alpha(void)
9024 IDirectDrawSurface7 *surface;
9025 DDSURFACEDESC2 surface_desc;
9026 IDirectDraw7 *ddraw;
9027 IDirectDrawPalette *palette;
9028 ULONG refcount;
9029 HWND window;
9030 HRESULT hr;
9031 PALETTEENTRY palette_entries[256];
9032 unsigned int i;
9033 static const struct
9035 DWORD caps, flags;
9036 BOOL attach_allowed;
9037 const char *name;
9039 test_data[] =
9041 {DDSCAPS_OFFSCREENPLAIN, DDSD_WIDTH | DDSD_HEIGHT, FALSE, "offscreenplain"},
9042 {DDSCAPS_TEXTURE, DDSD_WIDTH | DDSD_HEIGHT, TRUE, "texture"},
9043 {DDSCAPS_PRIMARYSURFACE, 0, FALSE, "primary"}
9046 window = create_window();
9047 ddraw = create_ddraw();
9048 ok(!!ddraw, "Failed to create a ddraw object.\n");
9049 if (FAILED(IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
9051 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
9052 IDirectDraw7_Release(ddraw);
9053 DestroyWindow(window);
9054 return;
9056 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
9057 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9059 memset(palette_entries, 0, sizeof(palette_entries));
9060 palette_entries[1].peFlags = 0x42;
9061 palette_entries[2].peFlags = 0xff;
9062 palette_entries[3].peFlags = 0x80;
9063 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
9064 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
9066 memset(palette_entries, 0x66, sizeof(palette_entries));
9067 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
9068 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
9069 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
9070 palette_entries[0].peFlags);
9071 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
9072 palette_entries[1].peFlags);
9073 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
9074 palette_entries[2].peFlags);
9075 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
9076 palette_entries[3].peFlags);
9078 IDirectDrawPalette_Release(palette);
9080 memset(palette_entries, 0, sizeof(palette_entries));
9081 palette_entries[1].peFlags = 0x42;
9082 palette_entries[1].peRed = 0xff;
9083 palette_entries[2].peFlags = 0xff;
9084 palette_entries[3].peFlags = 0x80;
9085 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT | DDPCAPS_ALPHA,
9086 palette_entries, &palette, NULL);
9087 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
9089 memset(palette_entries, 0x66, sizeof(palette_entries));
9090 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
9091 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
9092 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
9093 palette_entries[0].peFlags);
9094 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
9095 palette_entries[1].peFlags);
9096 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
9097 palette_entries[2].peFlags);
9098 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
9099 palette_entries[3].peFlags);
9101 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
9103 memset(&surface_desc, 0, sizeof(surface_desc));
9104 surface_desc.dwSize = sizeof(surface_desc);
9105 surface_desc.dwFlags = DDSD_CAPS | test_data[i].flags;
9106 surface_desc.dwWidth = 128;
9107 surface_desc.dwHeight = 128;
9108 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
9109 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9110 if (is_ddraw64 && test_data[i].caps & DDSCAPS_TEXTURE)
9111 todo_wine ok(hr == E_NOINTERFACE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
9112 else
9113 ok(hr == DD_OK, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
9114 if (FAILED(hr))
9115 continue;
9117 hr = IDirectDrawSurface7_SetPalette(surface, palette);
9118 if (test_data[i].attach_allowed)
9119 ok(SUCCEEDED(hr), "Failed to attach palette to %s surface, hr %#x.\n", test_data[i].name, hr);
9120 else
9121 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x, %s surface.\n", hr, test_data[i].name);
9123 if (SUCCEEDED(hr))
9125 HDC dc;
9126 RGBQUAD rgbquad;
9127 UINT retval;
9129 hr = IDirectDrawSurface7_GetDC(surface, &dc);
9130 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x, %s surface.\n", hr, test_data[i].name);
9131 retval = GetDIBColorTable(dc, 1, 1, &rgbquad);
9132 ok(retval == 1, "GetDIBColorTable returned unexpected result %u.\n", retval);
9133 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x, %s surface.\n",
9134 rgbquad.rgbRed, test_data[i].name);
9135 ok(rgbquad.rgbGreen == 0, "Expected rgbGreen = 0, got %#x, %s surface.\n",
9136 rgbquad.rgbGreen, test_data[i].name);
9137 ok(rgbquad.rgbBlue == 0, "Expected rgbBlue = 0, got %#x, %s surface.\n",
9138 rgbquad.rgbBlue, test_data[i].name);
9139 ok(rgbquad.rgbReserved == 0, "Expected rgbReserved = 0, got %u, %s surface.\n",
9140 rgbquad.rgbReserved, test_data[i].name);
9141 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
9142 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
9144 IDirectDrawSurface7_Release(surface);
9147 /* Test INVALIDSURFACETYPE vs INVALIDPIXELFORMAT. */
9148 memset(&surface_desc, 0, sizeof(surface_desc));
9149 surface_desc.dwSize = sizeof(surface_desc);
9150 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9151 surface_desc.dwWidth = 128;
9152 surface_desc.dwHeight = 128;
9153 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9154 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9155 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
9156 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
9157 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9158 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9159 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
9160 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9161 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9162 hr = IDirectDrawSurface7_SetPalette(surface, palette);
9163 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x.\n", hr);
9164 IDirectDrawSurface7_Release(surface);
9166 /* The Windows 8 testbot keeps extra references to the primary
9167 * while in 8 bpp mode. */
9168 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
9169 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
9171 refcount = IDirectDrawPalette_Release(palette);
9172 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9173 refcount = IDirectDraw7_Release(ddraw);
9174 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9175 DestroyWindow(window);
9178 static void test_vb_writeonly(void)
9180 IDirect3DDevice7 *device;
9181 IDirect3D7 *d3d;
9182 IDirect3DVertexBuffer7 *buffer;
9183 HWND window;
9184 HRESULT hr;
9185 D3DVERTEXBUFFERDESC desc;
9186 void *ptr;
9187 static const struct vec4 quad[] =
9189 { 0.0f, 480.0f, 0.0f, 1.0f},
9190 { 0.0f, 0.0f, 0.0f, 1.0f},
9191 {640.0f, 480.0f, 0.0f, 1.0f},
9192 {640.0f, 0.0f, 0.0f, 1.0f},
9195 window = create_window();
9196 if (!(device = create_device(window, DDSCL_NORMAL)))
9198 skip("Failed to create a 3D device, skipping test.\n");
9199 DestroyWindow(window);
9200 return;
9203 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
9204 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
9206 memset(&desc, 0, sizeof(desc));
9207 desc.dwSize = sizeof(desc);
9208 desc.dwCaps = D3DVBCAPS_WRITEONLY;
9209 desc.dwFVF = D3DFVF_XYZRHW;
9210 desc.dwNumVertices = ARRAY_SIZE(quad);
9211 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &buffer, 0);
9212 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
9214 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, &ptr, NULL);
9215 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
9216 memcpy(ptr, quad, sizeof(quad));
9217 hr = IDirect3DVertexBuffer7_Unlock(buffer);
9218 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
9220 hr = IDirect3DDevice7_BeginScene(device);
9221 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9222 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
9223 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9224 hr = IDirect3DDevice7_EndScene(device);
9225 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9227 hr = IDirect3DVertexBuffer7_Lock(buffer, 0, &ptr, NULL);
9228 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
9229 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
9230 hr = IDirect3DVertexBuffer7_Unlock(buffer);
9231 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
9233 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_READONLY, &ptr, NULL);
9234 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
9235 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
9236 hr = IDirect3DVertexBuffer7_Unlock(buffer);
9237 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
9239 IDirect3DVertexBuffer7_Release(buffer);
9240 IDirect3D7_Release(d3d);
9241 IDirect3DDevice7_Release(device);
9242 DestroyWindow(window);
9245 static void test_lost_device(void)
9247 IDirectDrawSurface7 *surface, *back_buffer;
9248 DDSURFACEDESC2 surface_desc;
9249 HWND window1, window2;
9250 IDirectDraw7 *ddraw;
9251 ULONG refcount;
9252 DDSCAPS2 caps;
9253 HRESULT hr;
9254 BOOL ret;
9256 window1 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9257 0, 0, 640, 480, 0, 0, 0, 0);
9258 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9259 0, 0, 640, 480, 0, 0, 0, 0);
9260 ddraw = create_ddraw();
9261 ok(!!ddraw, "Failed to create a ddraw object.\n");
9262 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
9263 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9265 memset(&surface_desc, 0, sizeof(surface_desc));
9266 surface_desc.dwSize = sizeof(surface_desc);
9267 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
9268 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
9269 U5(surface_desc).dwBackBufferCount = 1;
9270 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9271 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9273 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9274 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9275 hr = IDirectDrawSurface7_IsLost(surface);
9276 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9277 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9278 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9280 ret = SetForegroundWindow(GetDesktopWindow());
9281 ok(ret, "Failed to set foreground window.\n");
9282 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9283 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
9284 hr = IDirectDrawSurface7_IsLost(surface);
9285 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9286 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9287 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9289 ret = SetForegroundWindow(window1);
9290 ok(ret, "Failed to set foreground window.\n");
9291 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9292 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9293 hr = IDirectDrawSurface7_IsLost(surface);
9294 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9295 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9296 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9298 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
9299 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9300 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9301 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9302 hr = IDirectDrawSurface7_IsLost(surface);
9303 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9304 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9305 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9307 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
9308 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9309 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9310 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9311 hr = IDirectDrawSurface7_IsLost(surface);
9312 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9313 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9314 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9316 /* Trying to restore the primary will crash, probably because flippable
9317 * surfaces can't exist in DDSCL_NORMAL. */
9318 IDirectDrawSurface7_Release(surface);
9319 memset(&surface_desc, 0, sizeof(surface_desc));
9320 surface_desc.dwSize = sizeof(surface_desc);
9321 surface_desc.dwFlags = DDSD_CAPS;
9322 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
9323 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9324 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9326 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9327 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9328 hr = IDirectDrawSurface7_IsLost(surface);
9329 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9331 ret = SetForegroundWindow(GetDesktopWindow());
9332 ok(ret, "Failed to set foreground window.\n");
9333 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9334 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9335 hr = IDirectDrawSurface7_IsLost(surface);
9336 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9338 ret = SetForegroundWindow(window1);
9339 ok(ret, "Failed to set foreground window.\n");
9340 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9341 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9342 hr = IDirectDrawSurface7_IsLost(surface);
9343 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9345 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
9346 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9347 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9348 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9349 hr = IDirectDrawSurface7_IsLost(surface);
9350 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9352 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
9353 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9354 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9355 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9356 hr = IDirectDrawSurface7_IsLost(surface);
9357 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9359 IDirectDrawSurface7_Release(surface);
9360 memset(&surface_desc, 0, sizeof(surface_desc));
9361 surface_desc.dwSize = sizeof(surface_desc);
9362 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
9363 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
9364 U5(surface_desc).dwBackBufferCount = 1;
9365 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9366 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9368 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
9369 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9370 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9371 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9372 hr = IDirectDrawSurface7_IsLost(surface);
9373 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9374 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9375 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9377 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL | DDSCL_FULLSCREEN);
9378 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9379 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9380 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9381 hr = IDirectDrawSurface7_IsLost(surface);
9382 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9383 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9384 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
9386 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
9387 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9388 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9389 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9390 hr = IDirectDrawSurface7_IsLost(surface);
9391 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9392 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9393 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
9395 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
9396 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9397 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9398 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9399 hr = IDirectDrawSurface7_IsLost(surface);
9400 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9401 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9402 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
9404 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL | DDSCL_FULLSCREEN);
9405 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9406 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9407 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9408 hr = IDirectDrawSurface7_IsLost(surface);
9409 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9410 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9411 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
9413 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
9414 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9415 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9416 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9417 hr = IDirectDrawSurface7_IsLost(surface);
9418 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9419 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9420 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9422 memset(&caps, 0, sizeof(caps));
9423 caps.dwCaps = DDSCAPS_FLIP;
9425 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &back_buffer);
9426 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9427 hr = IDirectDrawSurface7_Restore(surface);
9428 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9429 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &back_buffer);
9430 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9431 hr = IDirectDrawSurface7_IsLost(back_buffer);
9432 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9433 IDirectDrawSurface7_Release(back_buffer);
9435 IDirectDrawSurface7_Release(surface);
9436 refcount = IDirectDraw7_Release(ddraw);
9437 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9438 DestroyWindow(window2);
9439 DestroyWindow(window1);
9442 static void test_resource_priority(void)
9444 IDirectDrawSurface7 *surface, *mipmap;
9445 DDSURFACEDESC2 surface_desc;
9446 IDirectDraw7 *ddraw;
9447 ULONG refcount;
9448 HWND window;
9449 HRESULT hr;
9450 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
9451 DDCAPS hal_caps;
9452 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_MIPMAP;
9453 unsigned int i;
9454 DWORD priority;
9455 static const struct
9457 DWORD caps, caps2;
9458 const char *name;
9459 HRESULT hr;
9460 /* SetPriority on offscreenplain surfaces crashes on AMD GPUs on Win7. */
9461 BOOL crash;
9463 test_data[] =
9465 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, "vidmem texture", DDERR_INVALIDPARAMS, FALSE},
9466 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, "sysmem texture", DDERR_INVALIDPARAMS, FALSE},
9467 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, "managed texture", DD_OK, FALSE},
9468 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, "managed texture", DD_OK, FALSE},
9469 {DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP,
9470 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_TEXTUREMANAGE,
9471 "cubemap", DD_OK, FALSE},
9472 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, "vidmem offscreenplain", DDERR_INVALIDOBJECT, TRUE},
9473 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, "sysmem offscreenplain", DDERR_INVALIDOBJECT, TRUE},
9476 window = create_window();
9477 ddraw = create_ddraw();
9478 ok(!!ddraw, "Failed to create a ddraw object.\n");
9479 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9480 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9482 memset(&hal_caps, 0, sizeof(hal_caps));
9483 hal_caps.dwSize = sizeof(hal_caps);
9484 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
9485 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9486 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps
9487 || !(hal_caps.ddsCaps.dwCaps & DDSCAPS2_TEXTUREMANAGE))
9489 skip("Required surface types not supported, skipping test.\n");
9490 goto done;
9493 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
9495 memset(&surface_desc, 0, sizeof(surface_desc));
9496 surface_desc.dwSize = sizeof(surface_desc);
9497 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
9498 surface_desc.dwWidth = 32;
9499 surface_desc.dwHeight = 32;
9500 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
9501 surface_desc.ddsCaps.dwCaps2 = test_data[i].caps2;
9502 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9503 if (is_ddraw64 && (test_data[i].caps & DDSCAPS_TEXTURE))
9505 todo_wine ok(hr == E_NOINTERFACE, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
9506 if (SUCCEEDED(hr))
9507 IDirectDrawSurface7_Release(surface);
9508 continue;
9510 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n", hr, test_data[i].name);
9512 /* Priority == NULL segfaults. */
9513 priority = 0xdeadbeef;
9514 hr = IDirectDrawSurface7_GetPriority(surface, &priority);
9515 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
9516 if (SUCCEEDED(test_data[i].hr))
9517 ok(priority == 0, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
9518 else
9519 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
9521 if (!test_data[i].crash)
9523 hr = IDirectDrawSurface7_SetPriority(surface, 1);
9524 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
9525 hr = IDirectDrawSurface7_GetPriority(surface, &priority);
9526 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
9527 if (SUCCEEDED(test_data[i].hr))
9529 ok(priority == 1, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
9530 hr = IDirectDrawSurface7_SetPriority(surface, 2);
9531 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
9533 else
9534 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
9537 if (test_data[i].caps2 & DDSCAPS2_CUBEMAP)
9539 caps.dwCaps2 = DDSCAPS2_CUBEMAP_NEGATIVEZ;
9540 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
9541 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
9542 /* IDirectDrawSurface7_SetPriority crashes when called on non-positive X surfaces on Windows */
9543 priority = 0xdeadbeef;
9544 hr = IDirectDrawSurface7_GetPriority(mipmap, &priority);
9545 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
9546 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
9548 IDirectDrawSurface7_Release(mipmap);
9551 IDirectDrawSurface7_Release(surface);
9554 if (is_ddraw64)
9555 goto done;
9557 memset(&surface_desc, 0, sizeof(surface_desc));
9558 surface_desc.dwSize = sizeof(surface_desc);
9559 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_MIPMAPCOUNT;
9560 surface_desc.dwWidth = 32;
9561 surface_desc.dwHeight = 32;
9562 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
9563 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
9564 U2(surface_desc).dwMipMapCount = 2;
9565 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9566 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9567 caps.dwCaps2 = 0;
9568 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
9569 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
9571 priority = 0xdeadbeef;
9572 hr = IDirectDrawSurface7_GetPriority(mipmap, &priority);
9573 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type managed mipmap.\n", hr);
9574 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type managed mipmap.\n", priority);
9575 /* SetPriority on the mipmap surface crashes. */
9576 hr = IDirectDrawSurface7_GetPriority(surface, &priority);
9577 ok(SUCCEEDED(hr), "Failed to get priority, hr %#x.\n", hr);
9578 ok(priority == 0, "Got unexpected priority %u, type managed mipmap.\n", priority);
9580 IDirectDrawSurface7_Release(mipmap);
9581 refcount = IDirectDrawSurface7_Release(surface);
9582 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9584 done:
9585 refcount = IDirectDraw7_Release(ddraw);
9586 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9587 DestroyWindow(window);
9590 static void test_surface_desc_lock(void)
9592 IDirectDrawSurface7 *surface;
9593 DDSURFACEDESC2 surface_desc;
9594 IDirectDraw7 *ddraw;
9595 ULONG refcount;
9596 HWND window;
9597 HRESULT hr;
9599 window = create_window();
9600 ddraw = create_ddraw();
9601 ok(!!ddraw, "Failed to create a ddraw object.\n");
9602 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9603 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9605 memset(&surface_desc, 0, sizeof(surface_desc));
9606 surface_desc.dwSize = sizeof(surface_desc);
9607 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
9608 surface_desc.dwWidth = 16;
9609 surface_desc.dwHeight = 16;
9610 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9611 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9612 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9614 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9615 surface_desc.dwSize = sizeof(surface_desc);
9616 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
9617 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
9618 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9620 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9621 surface_desc.dwSize = sizeof(surface_desc);
9622 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, 0, NULL);
9623 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
9624 ok(surface_desc.lpSurface != NULL, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9625 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9626 surface_desc.dwSize = sizeof(surface_desc);
9627 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
9628 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
9629 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9630 hr = IDirectDrawSurface7_Unlock(surface, NULL);
9631 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9633 memset(&surface_desc, 0xaa, sizeof(surface_desc));
9634 surface_desc.dwSize = sizeof(surface_desc);
9635 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
9636 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
9637 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
9639 IDirectDrawSurface7_Release(surface);
9640 refcount = IDirectDraw7_Release(ddraw);
9641 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9642 DestroyWindow(window);
9645 static void test_fog_interpolation(void)
9647 HRESULT hr;
9648 IDirect3DDevice7 *device;
9649 IDirectDrawSurface7 *rt;
9650 ULONG refcount;
9651 HWND window;
9652 D3DCOLOR color;
9653 static struct
9655 struct vec3 position;
9656 D3DCOLOR diffuse;
9657 D3DCOLOR specular;
9659 quad[] =
9661 {{-1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff000000},
9662 {{-1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff000000},
9663 {{ 1.0f, -1.0f, 1.0f}, 0xffff0000, 0x00000000},
9664 {{ 1.0f, 1.0f, 1.0f}, 0xffff0000, 0x00000000},
9666 union
9668 DWORD d;
9669 float f;
9670 } conv;
9671 unsigned int i;
9672 static const struct
9674 D3DFOGMODE vfog, tfog;
9675 D3DSHADEMODE shade;
9676 D3DCOLOR middle_color;
9677 BOOL todo;
9679 tests[] =
9681 {D3DFOG_NONE, D3DFOG_NONE, D3DSHADE_FLAT, 0x00007f80, FALSE},
9682 {D3DFOG_NONE, D3DFOG_NONE, D3DSHADE_GOURAUD, 0x00007f80, FALSE},
9683 {D3DFOG_EXP, D3DFOG_NONE, D3DSHADE_FLAT, 0x00007f80, TRUE},
9684 {D3DFOG_EXP, D3DFOG_NONE, D3DSHADE_GOURAUD, 0x00007f80, TRUE},
9685 {D3DFOG_NONE, D3DFOG_EXP, D3DSHADE_FLAT, 0x0000ea15, FALSE},
9686 {D3DFOG_NONE, D3DFOG_EXP, D3DSHADE_GOURAUD, 0x0000ea15, FALSE},
9687 {D3DFOG_EXP, D3DFOG_EXP, D3DSHADE_FLAT, 0x0000ea15, FALSE},
9688 {D3DFOG_EXP, D3DFOG_EXP, D3DSHADE_GOURAUD, 0x0000ea15, FALSE},
9690 D3DDEVICEDESC7 caps;
9692 window = create_window();
9693 if (!(device = create_device(window, DDSCL_NORMAL)))
9695 skip("Failed to create a 3D device, skipping test.\n");
9696 DestroyWindow(window);
9697 return;
9700 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
9701 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
9702 hr = IDirect3DDevice7_GetCaps(device, &caps);
9703 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
9704 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE))
9705 skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping some fog tests\n");
9707 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
9708 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9709 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
9710 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9711 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
9712 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9713 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x0000ff00);
9714 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9715 conv.f = 5.0;
9716 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGDENSITY, conv.d);
9717 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9719 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
9720 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
9721 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
9722 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
9723 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x000000ff);
9724 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9726 for (i = 0; i < ARRAY_SIZE(tests); ++i)
9728 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE) && tests[i].tfog)
9729 continue;
9731 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00808080, 0.0f, 0);
9732 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
9734 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SHADEMODE, tests[i].shade);
9735 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9736 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, tests[i].vfog);
9737 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9738 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, tests[i].tfog);
9739 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
9740 hr = IDirect3DDevice7_BeginScene(device);
9741 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9742 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
9743 D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR, quad, 4, 0);
9744 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9745 hr = IDirect3DDevice7_EndScene(device);
9746 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9748 color = get_surface_color(rt, 0, 240);
9749 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x, case %u.\n", color, i);
9750 color = get_surface_color(rt, 320, 240);
9751 todo_wine_if (tests[i].todo)
9752 ok(compare_color(color, tests[i].middle_color, 2),
9753 "Got unexpected color 0x%08x, case %u.\n", color, i);
9754 color = get_surface_color(rt, 639, 240);
9755 ok(compare_color(color, 0x0000fd02, 2), "Got unexpected color 0x%08x, case %u.\n", color, i);
9758 IDirectDrawSurface7_Release(rt);
9759 refcount = IDirect3DDevice7_Release(device);
9760 ok(!refcount, "Device has %u references left.\n", refcount);
9761 DestroyWindow(window);
9764 static void test_fog_process_vertices(void)
9766 static D3DMATRIX view_matrix =
9768 1.0f, 0.0f, 0.0f, 0.0f,
9769 0.0f, 1.0f, 0.0f, 0.0f,
9770 0.0f, 0.0f, 0.5f, 0.0f,
9771 0.0f, 0.0f, 0.0f, 1.0f
9773 static D3DMATRIX model_matrix =
9775 1.0f, 0.0f, 0.0f, 0.0f,
9776 0.0f, 1.0f, 0.0f, 0.0f,
9777 0.0f, 0.0f, 0.75f, 0.0f,
9778 0.0f, 0.0f, 0.0f, 1.0f
9780 static D3DMATRIX identity_matrix =
9782 1.0f, 0.0f, 0.0f, 0.0f,
9783 0.0f, 1.0f, 0.0f, 0.0f,
9784 0.0f, 0.0f, 1.0f, 0.0f,
9785 0.0f, 0.0f, 0.0f, 1.0f
9788 static D3DLIGHT7 directional_light =
9790 D3DLIGHT_DIRECTIONAL,
9791 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
9792 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
9793 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
9794 {{0.0f}, {0.0f}, {0.0f}},
9795 {{0.0f}, {0.0f}, {1.0f}},
9798 struct vertex
9800 struct vec3 position;
9801 struct vec3 normal;
9803 static const struct
9805 struct vertex vertex;
9806 D3DFOGMODE fog_vertex_mode, fog_table_mode;
9807 BOOL range_fog;
9808 D3DCOLOR expected_color, expected_broken;
9810 tests[] =
9812 /* Some drivers ignore ranged fog state without an obvious reason, even with D3DPRASTERCAPS_FOGRANGE
9813 * set, while some others (including WARP driver on Windows 10) favour it.
9814 * Vertex fog result does not depend on table fog settings. */
9815 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_NONE, D3DFOG_NONE, FALSE, 0x8000ff00},
9816 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_NONE, D3DFOG_LINEAR, FALSE, 0x8000ff00},
9817 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_EXP, D3DFOG_NONE, FALSE, 0xaf00ff00},
9818 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_EXP2, D3DFOG_NONE, FALSE, 0xde00ff00},
9819 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_LINEAR, D3DFOG_NONE, FALSE, 0x9f00ff00},
9820 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_LINEAR, D3DFOG_LINEAR, FALSE, 0x9f00ff00},
9821 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_NONE, D3DFOG_NONE, TRUE, 0x8000ff00},
9822 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_EXP, D3DFOG_NONE, TRUE, 0x8800ff00, 0xaf00ff00},
9823 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_EXP2, D3DFOG_NONE, TRUE, 0xad00ff00, 0xde00ff00},
9824 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_LINEAR, D3DFOG_NONE, TRUE, 0x6000ff00, 0x9f00ff00},
9825 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_LINEAR, D3DFOG_EXP, TRUE, 0x6000ff00, 0x9f00ff00},
9826 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_EXP, D3DFOG_LINEAR, TRUE, 0x8800ff00, 0xaf00ff00},
9829 struct
9831 struct vec4 position;
9832 D3DCOLOR diffuse, specular;
9834 *dst_data;
9836 IDirect3DVertexBuffer7 *src_vb, *dst_vb;
9837 D3DVERTEXBUFFERDESC vb_desc;
9838 IDirect3DDevice7 *device;
9839 struct vertex *src_data;
9840 D3DMATERIAL7 material;
9841 IDirect3D7 *d3d;
9842 ULONG refcount;
9843 unsigned int i;
9844 HWND window;
9845 HRESULT hr;
9847 window = create_window();
9848 if (!(device = create_device(window, DDSCL_NORMAL)))
9850 skip("Failed to create a 3D device, skipping test.\n");
9851 DestroyWindow(window);
9852 return;
9854 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
9855 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9857 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &model_matrix);
9858 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9859 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &view_matrix);
9860 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9861 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &identity_matrix);
9862 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9864 memset(&vb_desc, 0, sizeof(vb_desc));
9865 vb_desc.dwSize = sizeof(vb_desc);
9866 vb_desc.dwFVF = D3DFVF_XYZ | D3DFVF_NORMAL;
9867 vb_desc.dwNumVertices = 1;
9868 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &src_vb, 0);
9869 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9871 memset(&vb_desc, 0, sizeof(vb_desc));
9872 vb_desc.dwSize = sizeof(vb_desc);
9873 vb_desc.dwFVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR;
9874 vb_desc.dwNumVertices = 1;
9875 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &dst_vb, 0);
9876 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9878 hr = IDirect3DDevice7_LightEnable(device, 0, TRUE);
9879 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9880 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, TRUE);
9881 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9882 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
9883 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9884 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
9885 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9886 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
9887 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9889 hr = IDirect3DDevice7_SetLight(device, 0, &directional_light);
9890 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9892 memset(&material, 0, sizeof(material));
9893 U1(U2(material).specular).r = 0.0f;
9894 U2(U2(material).specular).g = 1.0f;
9895 U3(U2(material).specular).b = 0.0f;
9896 U4(U2(material).specular).a = 0.5f;
9897 U4(material).power = 5.0f;
9898 hr = IDirect3DDevice7_SetMaterial(device, &material);
9899 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9901 for (i = 0; i < ARRAY_SIZE(tests); ++i)
9903 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE,
9904 tests[i].fog_vertex_mode);
9905 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE,
9906 tests[i].fog_table_mode);
9907 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9908 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_RANGEFOGENABLE, tests[i].range_fog);
9909 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9911 hr = IDirect3DVertexBuffer7_Lock(src_vb, 0, (void **)&src_data, NULL);
9912 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9913 *src_data = tests[i].vertex;
9914 hr = IDirect3DVertexBuffer7_Unlock(src_vb);
9915 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9917 hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL);
9918 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9919 memset(dst_data, 0, sizeof(*dst_data));
9920 hr = IDirect3DVertexBuffer7_Unlock(dst_vb);
9921 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9922 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 0,
9923 1, src_vb, 0, device, 0);
9924 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9926 hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL);
9927 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9929 ok(compare_color(dst_data->specular, tests[i].expected_color, 1)
9930 || broken(tests[i].expected_broken
9931 && compare_color(dst_data->specular, tests[i].expected_broken, 1)),
9932 "Expected color 0x%08x, got 0x%08x, test %u.\n",
9933 tests[i].expected_color, dst_data->specular, i);
9935 hr = IDirect3DVertexBuffer7_Unlock(dst_vb);
9936 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
9939 IDirect3DVertexBuffer7_Release(dst_vb);
9940 IDirect3DVertexBuffer7_Release(src_vb);
9941 IDirect3D7_Release(d3d);
9942 refcount = IDirect3DDevice7_Release(device);
9943 ok(!refcount, "Device has %u references left.\n", refcount);
9944 DestroyWindow(window);
9947 static void test_negative_fixedfunction_fog(void)
9949 HRESULT hr;
9950 IDirect3DDevice7 *device;
9951 IDirectDrawSurface7 *rt;
9952 ULONG refcount;
9953 HWND window;
9954 D3DCOLOR color;
9955 static struct
9957 struct vec3 position;
9958 D3DCOLOR diffuse;
9960 quad[] =
9962 {{-1.0f, -1.0f, -0.5f}, 0xffff0000},
9963 {{-1.0f, 1.0f, -0.5f}, 0xffff0000},
9964 {{ 1.0f, -1.0f, -0.5f}, 0xffff0000},
9965 {{ 1.0f, 1.0f, -0.5f}, 0xffff0000},
9967 static struct
9969 struct vec4 position;
9970 D3DCOLOR diffuse;
9972 tquad[] =
9974 {{ 0.0f, 0.0f, -0.5f, 1.0f}, 0xffff0000},
9975 {{640.0f, 0.0f, -0.5f, 1.0f}, 0xffff0000},
9976 {{ 0.0f, 480.0f, -0.5f, 1.0f}, 0xffff0000},
9977 {{640.0f, 480.0f, -0.5f, 1.0f}, 0xffff0000},
9979 unsigned int i;
9980 static D3DMATRIX zero =
9982 1.0f, 0.0f, 0.0f, 0.0f,
9983 0.0f, 1.0f, 0.0f, 0.0f,
9984 0.0f, 0.0f, 0.0f, 0.0f,
9985 0.0f, 0.0f, 0.0f, 1.0f
9987 static D3DMATRIX identity =
9989 1.0f, 0.0f, 0.0f, 0.0f,
9990 0.0f, 1.0f, 0.0f, 0.0f,
9991 0.0f, 0.0f, 1.0f, 0.0f,
9992 0.0f, 0.0f, 0.0f, 1.0f
9994 static const struct
9996 DWORD pos_type;
9997 void *quad;
9998 D3DMATRIX *matrix;
9999 union
10001 float f;
10002 DWORD d;
10003 } start, end;
10004 D3DFOGMODE vfog, tfog;
10005 DWORD color, color_broken, color_broken2;
10007 tests[] =
10009 /* Run the XYZRHW tests first. Depth clamping is broken after RHW draws on the testbot.
10011 * Geforce8+ GPUs on Windows abs() table fog, everything else does not. */
10012 {D3DFVF_XYZRHW, tquad, &identity, { 0.0f}, {1.0f}, D3DFOG_NONE, D3DFOG_LINEAR,
10013 0x00ff0000, 0x00808000, 0x00808000},
10014 /* r200 GPUs and presumably all d3d8 and older HW clamp the fog
10015 * parameters to 0.0 and 1.0 in the table fog case. */
10016 {D3DFVF_XYZRHW, tquad, &identity, {-1.0f}, {0.0f}, D3DFOG_NONE, D3DFOG_LINEAR,
10017 0x00808000, 0x00ff0000, 0x0000ff00},
10018 /* test_fog_interpolation shows that vertex fog evaluates the fog
10019 * equation in the vertex pipeline. Start = -1.0 && end = 0.0 shows
10020 * that the abs happens before the fog equation is evaluated.
10022 * Vertex fog abs() behavior is the same on all GPUs. */
10023 {D3DFVF_XYZ, quad, &zero, { 0.0f}, {1.0f}, D3DFOG_LINEAR, D3DFOG_NONE,
10024 0x00808000, 0x00808000, 0x00808000},
10025 {D3DFVF_XYZ, quad, &zero, {-1.0f}, {0.0f}, D3DFOG_LINEAR, D3DFOG_NONE,
10026 0x0000ff00, 0x0000ff00, 0x0000ff00},
10027 {D3DFVF_XYZ, quad, &zero, { 0.0f}, {1.0f}, D3DFOG_EXP, D3DFOG_NONE,
10028 0x009b6400, 0x009b6400, 0x009b6400},
10030 D3DDEVICEDESC7 caps;
10032 window = create_window();
10033 if (!(device = create_device(window, DDSCL_NORMAL)))
10035 skip("Failed to create a 3D device, skipping test.\n");
10036 DestroyWindow(window);
10037 return;
10040 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
10041 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10042 hr = IDirect3DDevice7_GetCaps(device, &caps);
10043 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10044 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE))
10045 skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping some fog tests.\n");
10047 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
10048 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10049 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
10050 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10051 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
10052 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10053 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x0000ff00);
10054 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10055 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
10056 ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10058 for (i = 0; i < ARRAY_SIZE(tests); ++i)
10060 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE) && tests[i].tfog)
10061 continue;
10063 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0);
10064 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10066 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, tests[i].matrix);
10067 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
10068 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGSTART, tests[i].start.d);
10069 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10070 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGEND, tests[i].end.d);
10071 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10072 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, tests[i].vfog);
10073 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10074 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, tests[i].tfog);
10075 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10077 hr = IDirect3DDevice7_BeginScene(device);
10078 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10079 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
10080 tests[i].pos_type | D3DFVF_DIFFUSE, tests[i].quad, 4, 0);
10081 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10082 hr = IDirect3DDevice7_EndScene(device);
10083 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10085 color = get_surface_color(rt, 0, 240);
10086 ok(compare_color(color, tests[i].color, 2) || broken(compare_color(color, tests[i].color_broken, 2))
10087 || broken(compare_color(color, tests[i].color_broken2, 2)),
10088 "Got unexpected color 0x%08x, case %u.\n", color, i);
10091 IDirectDrawSurface7_Release(rt);
10092 refcount = IDirect3DDevice7_Release(device);
10093 ok(!refcount, "Device has %u references left.\n", refcount);
10094 DestroyWindow(window);
10097 static void test_table_fog_zw(void)
10099 HRESULT hr;
10100 IDirect3DDevice7 *device;
10101 IDirectDrawSurface7 *rt;
10102 ULONG refcount;
10103 HWND window;
10104 D3DCOLOR color;
10105 static struct
10107 struct vec4 position;
10108 D3DCOLOR diffuse;
10110 quad[] =
10112 {{ 0.0f, 0.0f, 0.0f, 0.0f}, 0xffff0000},
10113 {{640.0f, 0.0f, 0.0f, 0.0f}, 0xffff0000},
10114 {{ 0.0f, 480.0f, 0.0f, 0.0f}, 0xffff0000},
10115 {{640.0f, 480.0f, 0.0f, 0.0f}, 0xffff0000},
10117 static D3DMATRIX identity =
10119 1.0f, 0.0f, 0.0f, 0.0f,
10120 0.0f, 1.0f, 0.0f, 0.0f,
10121 0.0f, 0.0f, 1.0f, 0.0f,
10122 0.0f, 0.0f, 0.0f, 1.0f
10124 D3DDEVICEDESC7 caps;
10125 static const struct
10127 float z, w;
10128 D3DZBUFFERTYPE z_test;
10129 D3DCOLOR color;
10131 tests[] =
10133 {0.7f, 0.0f, D3DZB_TRUE, 0x004cb200},
10134 {0.7f, 0.0f, D3DZB_FALSE, 0x004cb200},
10135 {0.7f, 0.3f, D3DZB_TRUE, 0x004cb200},
10136 {0.7f, 0.3f, D3DZB_FALSE, 0x004cb200},
10137 {0.7f, 3.0f, D3DZB_TRUE, 0x004cb200},
10138 {0.7f, 3.0f, D3DZB_FALSE, 0x004cb200},
10139 {0.3f, 0.0f, D3DZB_TRUE, 0x00b24c00},
10140 {0.3f, 0.0f, D3DZB_FALSE, 0x00b24c00},
10142 unsigned int i;
10144 window = create_window();
10145 if (!(device = create_device(window, DDSCL_NORMAL)))
10147 skip("Failed to create a 3D device, skipping test.\n");
10148 DestroyWindow(window);
10149 return;
10152 hr = IDirect3DDevice7_GetCaps(device, &caps);
10153 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10154 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE))
10156 skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping POSITIONT table fog test.\n");
10157 goto done;
10159 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
10160 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10162 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
10163 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10164 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
10165 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10166 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x0000ff00);
10167 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10168 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
10169 ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10170 /* Work around an AMD Windows driver bug. Needs a proj matrix applied redundantly. */
10171 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &identity);
10172 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
10173 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_LINEAR);
10174 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10176 for (i = 0; i < ARRAY_SIZE(tests); ++i)
10178 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x000000ff, 1.0f, 0);
10179 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10181 quad[0].position.z = tests[i].z;
10182 quad[1].position.z = tests[i].z;
10183 quad[2].position.z = tests[i].z;
10184 quad[3].position.z = tests[i].z;
10185 quad[0].position.w = tests[i].w;
10186 quad[1].position.w = tests[i].w;
10187 quad[2].position.w = tests[i].w;
10188 quad[3].position.w = tests[i].w;
10189 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, tests[i].z_test);
10190 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10192 hr = IDirect3DDevice7_BeginScene(device);
10193 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10194 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
10195 D3DFVF_XYZRHW | D3DFVF_DIFFUSE, quad, 4, 0);
10196 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10197 hr = IDirect3DDevice7_EndScene(device);
10198 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10200 color = get_surface_color(rt, 0, 240);
10201 ok(compare_color(color, tests[i].color, 2),
10202 "Got unexpected color 0x%08x, expected 0x%8x, case %u.\n", color, tests[i].color, i);
10205 IDirectDrawSurface7_Release(rt);
10206 done:
10207 refcount = IDirect3DDevice7_Release(device);
10208 ok(!refcount, "Device has %u references left.\n", refcount);
10209 DestroyWindow(window);
10212 static void test_signed_formats(void)
10214 HRESULT hr;
10215 IDirect3DDevice7 *device;
10216 IDirect3D7 *d3d;
10217 IDirectDraw7 *ddraw;
10218 IDirectDrawSurface7 *surface, *rt;
10219 DDSURFACEDESC2 surface_desc;
10220 ULONG refcount;
10221 HWND window;
10222 D3DCOLOR color, expected_color;
10223 static struct
10225 struct vec3 position;
10226 struct vec2 texcoord;
10228 quad[] =
10230 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
10231 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
10232 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
10233 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
10235 /* See test_signed_formats() in dlls/d3d9/tests/visual.c for an explanation
10236 * of these values. */
10237 static const USHORT content_v8u8[4][4] =
10239 {0x0000, 0x7f7f, 0x8880, 0x0000},
10240 {0x0080, 0x8000, 0x7f00, 0x007f},
10241 {0x193b, 0xe8c8, 0x0808, 0xf8f8},
10242 {0x4444, 0xc0c0, 0xa066, 0x22e0},
10244 static const DWORD content_x8l8v8u8[4][4] =
10246 {0x00000000, 0x00ff7f7f, 0x00008880, 0x00ff0000},
10247 {0x00000080, 0x00008000, 0x00007f00, 0x0000007f},
10248 {0x0041193b, 0x0051e8c8, 0x00040808, 0x00fff8f8},
10249 {0x00824444, 0x0000c0c0, 0x00c2a066, 0x009222e0},
10251 static const USHORT content_l6v5u5[4][4] =
10253 {0x0000, 0xfdef, 0x0230, 0xfc00},
10254 {0x0010, 0x0200, 0x01e0, 0x000f},
10255 {0x4067, 0x53b9, 0x0421, 0xffff},
10256 {0x8108, 0x0318, 0xc28c, 0x909c},
10258 static const struct
10260 const char *name;
10261 const void *content;
10262 SIZE_T pixel_size;
10263 BOOL blue;
10264 unsigned int slop, slop_broken;
10265 DDPIXELFORMAT format;
10267 formats[] =
10270 "D3DFMT_V8U8", content_v8u8, sizeof(WORD), FALSE, 1, 0,
10272 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV, 0,
10273 {16}, {0x000000ff}, {0x0000ff00}, {0x00000000}, {0x00000000}
10277 "D3DFMT_X8L8V8U8", content_x8l8v8u8, sizeof(DWORD), TRUE, 1, 0,
10279 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE, 0,
10280 {32}, {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}
10284 "D3DFMT_L6V5U5", content_l6v5u5, sizeof(WORD), TRUE, 4, 7,
10286 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE, 0,
10287 {16}, {0x0000001f}, {0x000003e0}, {0x0000fc00}, {0x00000000}
10291 /* No V16U16 or Q8W8V8U8 support in ddraw. */
10293 static const D3DCOLOR expected_colors[4][4] =
10295 {0x00808080, 0x00fefeff, 0x00010780, 0x008080ff},
10296 {0x00018080, 0x00800180, 0x0080fe80, 0x00fe8080},
10297 {0x00ba98a0, 0x004767a8, 0x00888881, 0x007878ff},
10298 {0x00c3c3c0, 0x003f3f80, 0x00e51fe1, 0x005fa2c8},
10300 unsigned int i, width, x, y;
10301 D3DDEVICEDESC7 device_desc;
10303 window = create_window();
10304 if (!(device = create_device(window, DDSCL_NORMAL)))
10306 skip("Failed to create a 3D device, skipping test.\n");
10307 DestroyWindow(window);
10308 return;
10311 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
10312 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10313 if (!(device_desc.dwTextureOpCaps & D3DTEXOPCAPS_BLENDFACTORALPHA))
10315 skip("D3DTOP_BLENDFACTORALPHA not supported, skipping bumpmap format tests.\n");
10316 goto done;
10319 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
10320 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
10321 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
10322 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
10323 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
10324 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10326 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
10327 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10329 /* dst = tex * 0.5 + 1.0 * (1.0 - 0.5) = tex * 0.5 + 0.5 */
10330 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x80ffffff);
10331 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10332 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_BLENDFACTORALPHA);
10333 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
10334 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
10335 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
10336 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
10337 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
10339 for (i = 0; i < ARRAY_SIZE(formats); ++i)
10341 for (width = 1; width < 5; width += 3)
10343 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
10344 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
10346 memset(&surface_desc, 0, sizeof(surface_desc));
10347 surface_desc.dwSize = sizeof(surface_desc);
10348 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
10349 surface_desc.dwWidth = width;
10350 surface_desc.dwHeight = 4;
10351 U4(surface_desc).ddpfPixelFormat = formats[i].format;
10352 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
10353 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10354 if (FAILED(hr))
10356 skip("%s textures not supported, skipping.\n", formats[i].name);
10357 continue;
10359 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, format %s.\n", hr, formats[i].name);
10360 hr = IDirect3DDevice7_SetTexture(device, 0, surface);
10361 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x, format %s.\n", hr, formats[i].name);
10363 memset(&surface_desc, 0, sizeof(surface_desc));
10364 surface_desc.dwSize = sizeof(surface_desc);
10365 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, 0, NULL);
10366 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, format %s.\n", hr, formats[i].name);
10367 for (y = 0; y < 4; y++)
10369 memcpy((char *)surface_desc.lpSurface + y * U1(surface_desc).lPitch,
10370 (char *)formats[i].content + y * 4 * formats[i].pixel_size,
10371 width * formats[i].pixel_size);
10373 hr = IDirectDrawSurface7_Unlock(surface, NULL);
10374 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, format %s.\n", hr, formats[i].name);
10376 hr = IDirect3DDevice7_BeginScene(device);
10377 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10378 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
10379 D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
10380 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10381 hr = IDirect3DDevice7_EndScene(device);
10382 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10384 for (y = 0; y < 4; y++)
10386 for (x = 0; x < width; x++)
10388 expected_color = expected_colors[y][x];
10389 if (!formats[i].blue)
10390 expected_color |= 0x000000ff;
10392 color = get_surface_color(rt, 80 + 160 * x, 60 + 120 * y);
10393 ok(compare_color(color, expected_color, formats[i].slop)
10394 || broken(compare_color(color, expected_color, formats[i].slop_broken)),
10395 "Expected color 0x%08x, got 0x%08x, format %s, location %ux%u.\n",
10396 expected_color, color, formats[i].name, x, y);
10400 IDirectDrawSurface7_Release(surface);
10405 IDirectDrawSurface7_Release(rt);
10406 IDirectDraw7_Release(ddraw);
10407 IDirect3D7_Release(d3d);
10409 done:
10410 refcount = IDirect3DDevice7_Release(device);
10411 ok(!refcount, "Device has %u references left.\n", refcount);
10412 DestroyWindow(window);
10415 static void test_color_fill(void)
10417 HRESULT hr;
10418 IDirect3DDevice7 *device;
10419 IDirect3D7 *d3d;
10420 IDirectDraw7 *ddraw;
10421 IDirectDrawSurface7 *surface, *surface2;
10422 DDSURFACEDESC2 surface_desc;
10423 DDPIXELFORMAT z_fmt;
10424 ULONG refcount;
10425 HWND window;
10426 unsigned int i;
10427 DDBLTFX fx;
10428 RECT rect = {5, 5, 7, 7};
10429 DWORD *color;
10430 DWORD supported_fmts = 0, num_fourcc_codes, *fourcc_codes;
10431 DDCAPS hal_caps;
10432 static const struct
10434 DWORD caps, caps2;
10435 HRESULT colorfill_hr, depthfill_hr;
10436 BOOL rop_success;
10437 const char *name;
10438 DWORD result;
10439 BOOL check_result;
10440 DDPIXELFORMAT format;
10442 tests[] =
10445 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
10446 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain RGB", 0xdeadbeef, TRUE,
10448 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
10449 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
10453 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0,
10454 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain RGB", 0xdeadbeef, TRUE,
10456 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
10457 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
10461 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0,
10462 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem texture RGB", 0xdeadbeef, TRUE,
10464 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
10465 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
10469 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0,
10470 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem texture RGB", 0xdeadbeef, TRUE,
10472 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
10473 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
10477 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
10478 DD_OK, DDERR_INVALIDPARAMS, TRUE, "managed texture RGB", 0xdeadbeef, TRUE,
10480 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
10481 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
10485 DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY, 0,
10486 DDERR_INVALIDPARAMS, DD_OK, TRUE, "vidmem zbuffer", 0xdeadbeef, TRUE,
10487 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
10490 DDSCAPS_ZBUFFER | DDSCAPS_SYSTEMMEMORY, 0,
10491 DDERR_INVALIDPARAMS, DD_OK, TRUE, "sysmem zbuffer", 0xdeadbeef, TRUE,
10492 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
10495 /* Colorfill on YUV surfaces always returns DD_OK, but the content is
10496 * different afterwards. DX9+ GPUs set one of the two luminance values
10497 * in each block, but AMD and Nvidia GPUs disagree on which luminance
10498 * value they set. r200 (dx8) just sets the entire block to the clear
10499 * value. */
10500 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
10501 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain YUY2", 0, FALSE,
10503 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
10504 {0}, {0}, {0}, {0}, {0}
10508 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
10509 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain UYVY", 0, FALSE,
10511 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
10512 {0}, {0}, {0}, {0}, {0}
10516 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY, 0,
10517 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay YUY2", 0, FALSE,
10519 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
10520 {0}, {0}, {0}, {0}, {0}
10524 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY, 0,
10525 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay UYVY", 0, FALSE,
10527 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
10528 {0}, {0}, {0}, {0}, {0}
10532 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0,
10533 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "vidmem texture DXT1", 0, FALSE,
10535 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
10536 {0}, {0}, {0}, {0}, {0}
10540 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0,
10541 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "sysmem texture DXT1", 0, FALSE,
10543 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
10544 {0}, {0}, {0}, {0}, {0}
10548 /* The testbot fills this with 0x00 instead of the blue channel. The sysmem
10549 * surface works, presumably because it is handled by the runtime instead of
10550 * the driver. */
10551 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
10552 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain P8", 0xefefefef, FALSE,
10554 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
10555 {8}, {0}, {0}, {0}, {0}
10559 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0,
10560 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain P8", 0xefefefef, TRUE,
10562 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
10563 {8}, {0}, {0}, {0}, {0}
10567 static const struct
10569 DWORD rop;
10570 const char *name;
10571 HRESULT hr;
10573 rops[] =
10575 {SRCCOPY, "SRCCOPY", DD_OK},
10576 {SRCPAINT, "SRCPAINT", DDERR_NORASTEROPHW},
10577 {SRCAND, "SRCAND", DDERR_NORASTEROPHW},
10578 {SRCINVERT, "SRCINVERT", DDERR_NORASTEROPHW},
10579 {SRCERASE, "SRCERASE", DDERR_NORASTEROPHW},
10580 {NOTSRCCOPY, "NOTSRCCOPY", DDERR_NORASTEROPHW},
10581 {NOTSRCERASE, "NOTSRCERASE", DDERR_NORASTEROPHW},
10582 {MERGECOPY, "MERGECOPY", DDERR_NORASTEROPHW},
10583 {MERGEPAINT, "MERGEPAINT", DDERR_NORASTEROPHW},
10584 {PATCOPY, "PATCOPY", DDERR_NORASTEROPHW},
10585 {PATPAINT, "PATPAINT", DDERR_NORASTEROPHW},
10586 {PATINVERT, "PATINVERT", DDERR_NORASTEROPHW},
10587 {DSTINVERT, "DSTINVERT", DDERR_NORASTEROPHW},
10588 {BLACKNESS, "BLACKNESS", DD_OK},
10589 {WHITENESS, "WHITENESS", DD_OK},
10590 {0xaa0029, "0xaa0029", DDERR_NORASTEROPHW} /* noop */
10593 window = create_window();
10594 if (!(device = create_device(window, DDSCL_NORMAL)))
10596 skip("Failed to create a 3D device, skipping test.\n");
10597 DestroyWindow(window);
10598 return;
10601 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
10602 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
10603 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
10604 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
10606 memset(&z_fmt, 0, sizeof(z_fmt));
10607 IDirect3D7_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
10608 if (!z_fmt.dwSize)
10609 skip("No Z buffer formats supported, skipping Z buffer colorfill test.\n");
10611 IDirect3DDevice7_EnumTextureFormats(device, test_block_formats_creation_cb, &supported_fmts);
10612 if (!(supported_fmts & SUPPORT_DXT1))
10613 skip("DXT1 textures not supported, skipping DXT1 colorfill test.\n");
10615 IDirect3D7_Release(d3d);
10617 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
10618 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
10619 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
10620 num_fourcc_codes * sizeof(*fourcc_codes));
10621 if (!fourcc_codes)
10622 goto done;
10623 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
10624 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
10625 for (i = 0; i < num_fourcc_codes; i++)
10627 if (fourcc_codes[i] == MAKEFOURCC('Y', 'U', 'Y', '2'))
10628 supported_fmts |= SUPPORT_YUY2;
10629 else if (fourcc_codes[i] == MAKEFOURCC('U', 'Y', 'V', 'Y'))
10630 supported_fmts |= SUPPORT_UYVY;
10632 HeapFree(GetProcessHeap(), 0, fourcc_codes);
10634 memset(&hal_caps, 0, sizeof(hal_caps));
10635 hal_caps.dwSize = sizeof(hal_caps);
10636 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
10637 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
10639 if (!(supported_fmts & (SUPPORT_YUY2 | SUPPORT_UYVY)) || !(hal_caps.dwCaps & DDCAPS_OVERLAY))
10640 skip("Overlays or some YUV formats not supported, skipping YUV colorfill tests.\n");
10642 for (i = 0; i < ARRAY_SIZE(tests); ++i)
10644 DWORD expected_broken = tests[i].result;
10646 /* Some Windows drivers modify dwFillColor when it is used on P8 or FourCC formats. */
10647 memset(&fx, 0, sizeof(fx));
10648 fx.dwSize = sizeof(fx);
10649 U5(fx).dwFillColor = 0xdeadbeef;
10651 memset(&surface_desc, 0, sizeof(surface_desc));
10652 surface_desc.dwSize = sizeof(surface_desc);
10653 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10654 surface_desc.dwWidth = 64;
10655 surface_desc.dwHeight = 64;
10656 U4(surface_desc).ddpfPixelFormat = tests[i].format;
10657 surface_desc.ddsCaps.dwCaps = tests[i].caps;
10658 surface_desc.ddsCaps.dwCaps2 = tests[i].caps2;
10660 if (tests[i].format.dwFourCC == MAKEFOURCC('D','X','T','1') && !(supported_fmts & SUPPORT_DXT1))
10661 continue;
10662 if (tests[i].format.dwFourCC == MAKEFOURCC('Y','U','Y','2') && !(supported_fmts & SUPPORT_YUY2))
10663 continue;
10664 if (tests[i].format.dwFourCC == MAKEFOURCC('U','Y','V','Y') && !(supported_fmts & SUPPORT_UYVY))
10665 continue;
10666 if (tests[i].caps & DDSCAPS_OVERLAY && !(hal_caps.dwCaps & DDCAPS_OVERLAY))
10667 continue;
10669 if (tests[i].caps & DDSCAPS_ZBUFFER)
10671 if (!z_fmt.dwSize)
10672 continue;
10674 U4(surface_desc).ddpfPixelFormat = z_fmt;
10675 /* Some drivers seem to convert depth values incorrectly or not at
10676 * all. Affects at least AMD PALM, 8.17.10.1247. */
10677 if (tests[i].caps & DDSCAPS_VIDEOMEMORY)
10679 DWORD expected;
10680 float f, g;
10682 expected = tests[i].result & U3(z_fmt).dwZBitMask;
10683 f = ceilf(logf(expected + 1.0f) / logf(2.0f));
10684 g = (f + 1.0f) / 2.0f;
10685 g -= (int)g;
10686 expected_broken = (expected / exp2f(f) - g) * 256;
10687 expected_broken *= 0x01010101;
10691 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10692 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, surface %s.\n", hr, tests[i].name);
10694 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10695 todo_wine_if (tests[i].format.dwFourCC)
10696 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
10697 hr, tests[i].colorfill_hr, tests[i].name);
10699 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10700 todo_wine_if (tests[i].format.dwFourCC)
10701 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
10702 hr, tests[i].colorfill_hr, tests[i].name);
10704 if (SUCCEEDED(hr) && tests[i].check_result)
10706 memset(&surface_desc, 0, sizeof(surface_desc));
10707 surface_desc.dwSize = sizeof(surface_desc);
10708 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
10709 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10710 color = surface_desc.lpSurface;
10711 ok(*color == tests[i].result, "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
10712 *color, tests[i].result, tests[i].name);
10713 hr = IDirectDrawSurface7_Unlock(surface, NULL);
10714 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10717 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10718 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
10719 hr, tests[i].depthfill_hr, tests[i].name);
10720 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10721 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
10722 hr, tests[i].depthfill_hr, tests[i].name);
10724 if (SUCCEEDED(hr) && tests[i].check_result)
10726 memset(&surface_desc, 0, sizeof(surface_desc));
10727 surface_desc.dwSize = sizeof(surface_desc);
10728 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
10729 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10730 color = surface_desc.lpSurface;
10731 ok((*color & U3(z_fmt).dwZBitMask) == (tests[i].result & U3(z_fmt).dwZBitMask)
10732 || broken((*color & U3(z_fmt).dwZBitMask) == (expected_broken & U3(z_fmt).dwZBitMask)),
10733 "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
10734 *color & U3(z_fmt).dwZBitMask, tests[i].result & U3(z_fmt).dwZBitMask, tests[i].name);
10735 hr = IDirectDrawSurface7_Unlock(surface, NULL);
10736 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10739 U5(fx).dwFillColor = 0xdeadbeef;
10740 fx.dwROP = BLACKNESS;
10741 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
10742 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
10743 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
10744 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
10745 U5(fx).dwFillColor, tests[i].name);
10747 if (SUCCEEDED(hr) && tests[i].check_result)
10749 memset(&surface_desc, 0, sizeof(surface_desc));
10750 surface_desc.dwSize = sizeof(surface_desc);
10751 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
10752 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10753 color = surface_desc.lpSurface;
10754 ok(*color == 0, "Got clear result 0x%08x, expected 0x00000000, surface %s.\n",
10755 *color, tests[i].name);
10756 hr = IDirectDrawSurface7_Unlock(surface, NULL);
10757 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10760 fx.dwROP = WHITENESS;
10761 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
10762 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
10763 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
10764 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
10765 U5(fx).dwFillColor, tests[i].name);
10767 if (SUCCEEDED(hr) && tests[i].check_result)
10769 memset(&surface_desc, 0, sizeof(surface_desc));
10770 surface_desc.dwSize = sizeof(surface_desc);
10771 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
10772 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10773 color = surface_desc.lpSurface;
10774 /* WHITENESS sets the alpha channel to 0x00. Ignore this for now. */
10775 ok((*color & 0x00ffffff) == 0x00ffffff, "Got clear result 0x%08x, expected 0xffffffff, surface %s.\n",
10776 *color, tests[i].name);
10777 hr = IDirectDrawSurface7_Unlock(surface, NULL);
10778 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
10781 IDirectDrawSurface7_Release(surface);
10784 memset(&fx, 0, sizeof(fx));
10785 fx.dwSize = sizeof(fx);
10786 U5(fx).dwFillColor = 0xdeadbeef;
10787 fx.dwROP = WHITENESS;
10789 memset(&surface_desc, 0, sizeof(surface_desc));
10790 surface_desc.dwSize = sizeof(surface_desc);
10791 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10792 surface_desc.dwWidth = 64;
10793 surface_desc.dwHeight = 64;
10794 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
10795 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
10796 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
10797 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
10798 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
10799 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
10800 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
10801 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10802 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10803 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
10804 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10806 /* No DDBLTFX. */
10807 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, NULL);
10808 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10809 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, NULL);
10810 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10812 /* Unused source rectangle. */
10813 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10814 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10815 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10816 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10818 /* Unused source surface. */
10819 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10820 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10821 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
10822 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10823 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10824 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10825 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10826 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10828 /* Inverted destination or source rectangle. */
10829 SetRect(&rect, 5, 7, 7, 5);
10830 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10831 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10832 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10833 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10834 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10835 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10836 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10837 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10838 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10839 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10841 /* Negative rectangle. */
10842 SetRect(&rect, -1, -1, 5, 5);
10843 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10844 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10845 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10846 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10847 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10848 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10849 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10850 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10851 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10852 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10854 /* Out of bounds rectangle. */
10855 SetRect(&rect, 0, 0, 65, 65);
10856 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
10857 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10858 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
10859 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10861 /* Combine multiple flags. */
10862 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10863 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10864 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
10865 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10866 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
10867 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10869 for (i = 0; i < ARRAY_SIZE(rops); ++i)
10871 fx.dwROP = rops[i].rop;
10872 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
10873 ok(hr == rops[i].hr, "Got unexpected hr %#x for rop %s.\n", hr, rops[i].name);
10876 IDirectDrawSurface7_Release(surface2);
10877 IDirectDrawSurface7_Release(surface);
10879 if (!z_fmt.dwSize)
10880 goto done;
10882 memset(&surface_desc, 0, sizeof(surface_desc));
10883 surface_desc.dwSize = sizeof(surface_desc);
10884 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10885 surface_desc.dwWidth = 64;
10886 surface_desc.dwHeight = 64;
10887 U4(surface_desc).ddpfPixelFormat = z_fmt;
10888 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
10889 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10890 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10891 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
10892 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10894 /* No DDBLTFX. */
10895 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, NULL);
10896 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10898 /* Unused source rectangle. */
10899 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10900 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10902 /* Unused source surface. */
10903 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10904 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10905 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10906 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10908 /* Inverted destination or source rectangle. */
10909 SetRect(&rect, 5, 7, 7, 5);
10910 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10911 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10912 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10913 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10914 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10915 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10916 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10917 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10919 /* Negative rectangle. */
10920 SetRect(&rect, -1, -1, 5, 5);
10921 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10922 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10923 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10924 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
10925 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10926 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10927 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10928 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10930 /* Out of bounds rectangle. */
10931 SetRect(&rect, 0, 0, 65, 65);
10932 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10933 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
10935 /* Combine multiple flags. */
10936 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
10937 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
10939 IDirectDrawSurface7_Release(surface2);
10940 IDirectDrawSurface7_Release(surface);
10942 done:
10943 IDirectDraw7_Release(ddraw);
10944 refcount = IDirect3DDevice7_Release(device);
10945 ok(!refcount, "Device has %u references left.\n", refcount);
10946 DestroyWindow(window);
10949 static void test_texcoordindex(void)
10951 static D3DMATRIX mat =
10953 1.0f, 0.0f, 0.0f, 0.0f,
10954 0.0f, 0.0f, 0.0f, 0.0f,
10955 0.0f, 0.0f, 0.0f, 0.0f,
10956 0.0f, 0.0f, 0.0f, 0.0f,
10958 static struct
10960 struct vec3 pos;
10961 struct vec2 texcoord1;
10962 struct vec2 texcoord2;
10963 struct vec2 texcoord3;
10965 quad[] =
10967 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f}},
10968 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 0.0f}},
10969 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}},
10970 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}},
10972 static const DWORD fvf = D3DFVF_XYZ | D3DFVF_TEX3;
10973 IDirect3DDevice7 *device;
10974 IDirect3D7 *d3d;
10975 IDirectDraw7 *ddraw;
10976 IDirectDrawSurface7 *rt;
10977 HWND window;
10978 HRESULT hr;
10979 IDirectDrawSurface7 *texture1, *texture2;
10980 DDSURFACEDESC2 surface_desc;
10981 ULONG refcount;
10982 D3DCOLOR color;
10983 DWORD *ptr;
10985 window = create_window();
10986 if (!(device = create_device(window, DDSCL_NORMAL)))
10988 skip("Failed to create a 3D device, skipping test.\n");
10989 DestroyWindow(window);
10990 return;
10993 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
10994 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
10995 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
10996 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
10997 IDirect3D7_Release(d3d);
10999 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
11000 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11002 memset(&surface_desc, 0, sizeof(surface_desc));
11003 surface_desc.dwSize = sizeof(surface_desc);
11004 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
11005 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
11006 surface_desc.dwWidth = 2;
11007 surface_desc.dwHeight = 2;
11008 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
11009 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
11010 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
11011 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
11012 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
11013 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
11014 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
11015 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture1, NULL);
11016 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11017 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture2, NULL);
11018 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11020 memset(&surface_desc, 0, sizeof(surface_desc));
11021 surface_desc.dwSize = sizeof(surface_desc);
11022 hr = IDirectDrawSurface7_Lock(texture1, 0, &surface_desc, 0, NULL);
11023 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11024 ptr = surface_desc.lpSurface;
11025 ptr[0] = 0xff000000;
11026 ptr[1] = 0xff00ff00;
11027 ptr += U1(surface_desc).lPitch / sizeof(*ptr);
11028 ptr[0] = 0xff0000ff;
11029 ptr[1] = 0xff00ffff;
11030 hr = IDirectDrawSurface7_Unlock(texture1, NULL);
11031 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11033 memset(&surface_desc, 0, sizeof(surface_desc));
11034 surface_desc.dwSize = sizeof(surface_desc);
11035 hr = IDirectDrawSurface7_Lock(texture2, 0, &surface_desc, 0, NULL);
11036 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11037 ptr = surface_desc.lpSurface;
11038 ptr[0] = 0xff000000;
11039 ptr[1] = 0xff0000ff;
11040 ptr += U1(surface_desc).lPitch / sizeof(*ptr);
11041 ptr[0] = 0xffff0000;
11042 ptr[1] = 0xffff00ff;
11043 hr = IDirectDrawSurface7_Unlock(texture2, 0);
11044 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11046 hr = IDirect3DDevice7_SetTexture(device, 0, texture1);
11047 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
11048 hr = IDirect3DDevice7_SetTexture(device, 1, texture2);
11049 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
11050 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
11051 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
11052 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
11053 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
11054 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
11055 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11056 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_ADD);
11057 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
11058 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
11059 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11060 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
11061 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11062 hr = IDirect3DDevice7_SetTextureStageState(device, 2, D3DTSS_COLOROP, D3DTOP_DISABLE);
11063 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
11065 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_TEXCOORDINDEX, 1);
11066 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
11067 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXCOORDINDEX, 0);
11068 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
11070 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
11071 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
11073 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
11074 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
11076 hr = IDirect3DDevice7_BeginScene(device);
11077 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11078 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
11079 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11080 hr = IDirect3DDevice7_EndScene(device);
11081 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11083 color = get_surface_color(rt, 160, 120);
11084 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
11085 color = get_surface_color(rt, 480, 120);
11086 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
11087 color = get_surface_color(rt, 160, 360);
11088 ok(compare_color(color, 0x00ff0000, 2), "Got unexpected color 0x%08x.\n", color);
11089 color = get_surface_color(rt, 480, 360);
11090 ok(compare_color(color, 0x00ffffff, 2), "Got unexpected color 0x%08x.\n", color);
11092 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
11093 ok(SUCCEEDED(hr), "Failed to set texture transform flags, hr %#x.\n", hr);
11094 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_TEXTURE1, &mat);
11095 ok(SUCCEEDED(hr), "Failed to set transformation matrix, hr %#x.\n", hr);
11097 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
11098 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
11100 hr = IDirect3DDevice7_BeginScene(device);
11101 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11102 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
11103 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11104 hr = IDirect3DDevice7_EndScene(device);
11105 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11107 color = get_surface_color(rt, 160, 120);
11108 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
11109 color = get_surface_color(rt, 480, 120);
11110 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
11111 color = get_surface_color(rt, 160, 360);
11112 ok(compare_color(color, 0x00000000, 2), "Got unexpected color 0x%08x.\n", color);
11113 color = get_surface_color(rt, 480, 360);
11114 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
11116 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
11117 ok(SUCCEEDED(hr), "Failed to set texture transform flags, hr %#x.\n", hr);
11118 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXCOORDINDEX, 2);
11119 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
11121 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
11122 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
11124 hr = IDirect3DDevice7_BeginScene(device);
11125 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11126 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
11127 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11128 hr = IDirect3DDevice7_EndScene(device);
11129 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11131 color = get_surface_color(rt, 160, 120);
11132 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
11133 color = get_surface_color(rt, 480, 120);
11134 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
11135 color = get_surface_color(rt, 160, 360);
11136 ok(compare_color(color, 0x00ff00ff, 2), "Got unexpected color 0x%08x.\n", color);
11137 color = get_surface_color(rt, 480, 360);
11138 ok(compare_color(color, 0x00ffff00, 2), "Got unexpected color 0x%08x.\n", color);
11140 IDirectDrawSurface7_Release(texture1);
11141 IDirectDrawSurface7_Release(texture2);
11143 IDirectDrawSurface7_Release(rt);
11144 IDirectDraw_Release(ddraw);
11145 refcount = IDirect3DDevice7_Release(device);
11146 ok(!refcount, "Device has %u references left.\n", refcount);
11147 DestroyWindow(window);
11150 static void test_colorkey_precision(void)
11152 static struct
11154 struct vec3 pos;
11155 struct vec2 texcoord;
11157 quad[] =
11159 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
11160 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
11161 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
11162 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
11165 static const struct
11167 unsigned int max, shift, bpp, clear;
11168 const char *name;
11169 BOOL skip_nv;
11170 DDPIXELFORMAT fmt;
11172 tests[] =
11175 255, 0, 4, 0x00345678, "D3DFMT_X8R8G8B8", FALSE,
11177 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
11178 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
11183 63, 5, 2, 0x5678, "D3DFMT_R5G6B5, G channel", FALSE,
11185 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
11186 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
11191 31, 0, 2, 0x5678, "D3DFMT_R5G6B5, B channel", FALSE,
11193 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
11194 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
11199 15, 0, 2, 0x0678, "D3DFMT_A4R4G4B4", TRUE,
11201 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
11202 {16}, {0x0f00}, {0x00f0}, {0x000f}, {0xf000}
11207 IDirectDrawSurface7 *src, *dst, *texture;
11208 DDSURFACEDESC2 surface_desc, lock_desc;
11209 DWORD data[4] = {0}, color_mask;
11210 IDirect3DDevice7 *device;
11211 IDirectDrawSurface7 *rt;
11212 IDirectDraw7 *ddraw;
11213 unsigned int t, c;
11214 DDCOLORKEY ckey;
11215 IDirect3D7 *d3d;
11216 BOOL is_nvidia;
11217 ULONG refcount;
11218 D3DCOLOR color;
11219 HWND window;
11220 HRESULT hr;
11221 DDBLTFX fx;
11223 window = create_window();
11224 if (!(device = create_device(window, DDSCL_NORMAL)))
11226 skip("Failed to create a 3D device, skipping test.\n");
11227 DestroyWindow(window);
11228 return;
11231 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
11232 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11233 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
11234 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11235 IDirect3D7_Release(d3d);
11236 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
11237 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11239 is_nvidia = ddraw_is_nvidia(ddraw);
11240 /* The Windows 8 WARP driver has plenty of false negatives in X8R8G8B8
11241 * (color key doesn't match although the values are equal), and a false
11242 * positive when the color key is 0 and the texture contains the value 1.
11243 * Also on random occasions 254 == 255 and 255 != 255.
11244 * Crashes on Windows 10 WARP. */
11245 if (ddraw_is_warp(ddraw))
11247 win_skip("Skipping test on WARP driver.\n");
11248 goto done;
11251 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
11252 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11253 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
11254 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11255 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
11256 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11257 /* Multiply the texture read result with 0, that way the result color if the key doesn't
11258 * match is constant. In theory color keying works without reading the texture result
11259 * (meaning we could just op=arg1, arg1=tfactor), but the Geforce7 Windows driver begs
11260 * to differ. */
11261 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
11262 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11263 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
11264 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11265 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
11266 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11267 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x00000000);
11268 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11270 memset(&fx, 0, sizeof(fx));
11271 fx.dwSize = sizeof(fx);
11272 memset(&lock_desc, 0, sizeof(lock_desc));
11273 lock_desc.dwSize = sizeof(lock_desc);
11275 for (t = 0; t < ARRAY_SIZE(tests); ++t)
11277 if (is_nvidia && tests[t].skip_nv)
11279 win_skip("Skipping test %s on Nvidia Windows drivers.\n", tests[t].name);
11280 continue;
11283 memset(&surface_desc, 0, sizeof(surface_desc));
11284 surface_desc.dwSize = sizeof(surface_desc);
11285 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
11286 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11287 surface_desc.dwWidth = 4;
11288 surface_desc.dwHeight = 1;
11289 U4(surface_desc).ddpfPixelFormat = tests[t].fmt;
11290 /* Windows XP (at least with the r200 driver, other drivers untested) produces
11291 * garbage when doing color keyed texture->texture blits. */
11292 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
11293 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11294 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
11295 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11297 U5(fx).dwFillColor = tests[t].clear;
11298 /* On the w8 testbot (WARP driver) the blit result has different values in the
11299 * X channel. */
11300 color_mask = U2(tests[t].fmt).dwRBitMask
11301 | U3(tests[t].fmt).dwGBitMask
11302 | U4(tests[t].fmt).dwBBitMask;
11304 for (c = 0; c <= tests[t].max; ++c)
11306 /* The idiotic Nvidia Windows driver can't change the color key on a d3d
11307 * texture after it has been set once... */
11308 surface_desc.dwFlags |= DDSD_CKSRCBLT;
11309 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
11310 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = c << tests[t].shift;
11311 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = c << tests[t].shift;
11312 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
11313 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11314 hr = IDirect3DDevice7_SetTexture(device, 0, texture);
11315 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11317 hr = IDirectDrawSurface7_Blt(dst, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11318 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11320 hr = IDirectDrawSurface7_Lock(src, NULL, &lock_desc, DDLOCK_WAIT, NULL);
11321 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11322 switch (tests[t].bpp)
11324 case 4:
11325 ((DWORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
11326 ((DWORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
11327 ((DWORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
11328 ((DWORD *)lock_desc.lpSurface)[3] = 0xffffffff;
11329 break;
11331 case 2:
11332 ((WORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
11333 ((WORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
11334 ((WORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
11335 ((WORD *)lock_desc.lpSurface)[3] = 0xffff;
11336 break;
11338 hr = IDirectDrawSurface7_Unlock(src, 0);
11339 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11340 hr = IDirectDrawSurface7_Blt(texture, NULL, src, NULL, DDBLT_WAIT, NULL);
11341 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11343 ckey.dwColorSpaceLowValue = c << tests[t].shift;
11344 ckey.dwColorSpaceHighValue = c << tests[t].shift;
11345 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
11346 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11348 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_WAIT, NULL);
11349 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11351 /* Don't make this read only, it somehow breaks the detection of the Nvidia bug below. */
11352 hr = IDirectDrawSurface7_Lock(dst, NULL, &lock_desc, DDLOCK_WAIT, NULL);
11353 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11354 switch (tests[t].bpp)
11356 case 4:
11357 data[0] = ((DWORD *)lock_desc.lpSurface)[0] & color_mask;
11358 data[1] = ((DWORD *)lock_desc.lpSurface)[1] & color_mask;
11359 data[2] = ((DWORD *)lock_desc.lpSurface)[2] & color_mask;
11360 data[3] = ((DWORD *)lock_desc.lpSurface)[3] & color_mask;
11361 break;
11363 case 2:
11364 data[0] = ((WORD *)lock_desc.lpSurface)[0] & color_mask;
11365 data[1] = ((WORD *)lock_desc.lpSurface)[1] & color_mask;
11366 data[2] = ((WORD *)lock_desc.lpSurface)[2] & color_mask;
11367 data[3] = ((WORD *)lock_desc.lpSurface)[3] & color_mask;
11368 break;
11370 hr = IDirectDrawSurface7_Unlock(dst, 0);
11371 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11373 if (!c)
11375 ok(data[0] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
11376 tests[t].clear, data[0], tests[t].name, c);
11378 if (data[3] == tests[t].clear)
11380 /* My Geforce GTX 460 on Windows 7 misbehaves when A4R4G4B4 is blitted with color
11381 * keying: The blit takes ~0.5 seconds, and subsequent color keying draws are broken,
11382 * even when a different surface is used. The blit itself doesn't draw anything,
11383 * so we can detect the bug by looking at the otherwise unused 4th texel. It should
11384 * never be masked out by the key.
11386 * On Windows 10 the problem is worse, Blt just hangs. For this reason the ARGB4444
11387 * test is disabled on Nvidia.
11389 * Also appears to affect the testbot in some way with R5G6B5. Color keying is
11390 * terrible on WARP. */
11391 skip("Nvidia A4R4G4B4 color keying blit bug detected, skipping.\n");
11392 IDirectDrawSurface7_Release(texture);
11393 IDirectDrawSurface7_Release(src);
11394 IDirectDrawSurface7_Release(dst);
11395 goto done;
11398 else
11399 ok(data[0] == (c - 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
11400 (c - 1) << tests[t].shift, data[0], tests[t].name, c);
11402 ok(data[1] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
11403 tests[t].clear, data[1], tests[t].name, c);
11405 if (c == tests[t].max)
11406 ok(data[2] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
11407 tests[t].clear, data[2], tests[t].name, c);
11408 else
11409 ok(data[2] == (c + 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
11410 (c + 1) << tests[t].shift, data[2], tests[t].name, c);
11412 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x0000ff00, 1.0f, 0);
11413 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11415 hr = IDirect3DDevice7_BeginScene(device);
11416 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11417 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
11418 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11419 hr = IDirect3DDevice7_EndScene(device);
11420 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
11422 color = get_surface_color(rt, 80, 240);
11424 if (!c)
11425 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x, format %s, c=%u.\n",
11426 color, tests[t].name, c);
11427 else
11428 ok(compare_color(color, 0x00000000, 1), "Got unexpected color 0x%08x, format %s, c=%u.\n",
11429 color, tests[t].name, c);
11431 color = get_surface_color(rt, 240, 240);
11432 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x, format %s, c=%u.\n",
11433 color, tests[t].name, c);
11435 color = get_surface_color(rt, 400, 240);
11436 if (c == tests[t].max)
11437 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x, format %s, c=%u.\n",
11438 color, tests[t].name, c);
11439 else
11440 ok(compare_color(color, 0x00000000, 1), "Got unexpected color 0x%08x, format %s, c=%u.\n",
11441 color, tests[t].name, c);
11443 IDirectDrawSurface7_Release(texture);
11445 IDirectDrawSurface7_Release(src);
11446 IDirectDrawSurface7_Release(dst);
11448 done:
11450 IDirectDrawSurface7_Release(rt);
11451 IDirectDraw7_Release(ddraw);
11452 refcount = IDirect3DDevice7_Release(device);
11453 ok(!refcount, "Device has %u references left.\n", refcount);
11454 DestroyWindow(window);
11457 static void test_range_colorkey(void)
11459 IDirectDraw7 *ddraw;
11460 HWND window;
11461 HRESULT hr;
11462 IDirectDrawSurface7 *surface;
11463 DDSURFACEDESC2 surface_desc;
11464 ULONG refcount;
11465 DDCOLORKEY ckey;
11467 window = create_window();
11468 ddraw = create_ddraw();
11469 ok(!!ddraw, "Failed to create a ddraw object.\n");
11470 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11471 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11473 memset(&surface_desc, 0, sizeof(surface_desc));
11474 surface_desc.dwSize = sizeof(surface_desc);
11475 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
11476 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
11477 surface_desc.dwWidth = 1;
11478 surface_desc.dwHeight = 1;
11479 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
11480 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
11481 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
11482 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
11483 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
11484 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0x00000000;
11486 /* Creating a surface with a range color key fails with DDERR_NOCOLORKEY. */
11487 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
11488 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
11489 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11490 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11492 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
11493 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
11494 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11495 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11497 /* Same for DDSCAPS_OFFSCREENPLAIN. */
11498 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
11499 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
11500 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
11501 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11502 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11504 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
11505 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
11506 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11507 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11509 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
11510 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
11511 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11512 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11514 /* Setting a range color key without DDCKEY_COLORSPACE collapses the key. */
11515 ckey.dwColorSpaceLowValue = 0x00000000;
11516 ckey.dwColorSpaceHighValue = 0x00000001;
11517 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
11518 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
11520 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
11521 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
11522 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
11523 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
11525 ckey.dwColorSpaceLowValue = 0x00000001;
11526 ckey.dwColorSpaceHighValue = 0x00000000;
11527 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
11528 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
11530 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
11531 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
11532 ok(ckey.dwColorSpaceLowValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
11533 ok(ckey.dwColorSpaceHighValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
11535 /* DDCKEY_COLORSPACE is ignored if the key is a single value. */
11536 ckey.dwColorSpaceLowValue = 0x00000000;
11537 ckey.dwColorSpaceHighValue = 0x00000000;
11538 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
11539 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
11541 /* Using it with a range key results in DDERR_NOCOLORKEYHW. */
11542 ckey.dwColorSpaceLowValue = 0x00000001;
11543 ckey.dwColorSpaceHighValue = 0x00000000;
11544 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
11545 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11546 ckey.dwColorSpaceLowValue = 0x00000000;
11547 ckey.dwColorSpaceHighValue = 0x00000001;
11548 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
11549 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11550 /* Range destination keys don't work either. */
11551 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_DESTBLT | DDCKEY_COLORSPACE, &ckey);
11552 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11554 /* Just to show it's not because of A, R, and G having equal values. */
11555 ckey.dwColorSpaceLowValue = 0x00000000;
11556 ckey.dwColorSpaceHighValue = 0x01010101;
11557 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
11558 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
11560 /* None of these operations modified the key. */
11561 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
11562 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
11563 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
11564 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
11566 IDirectDrawSurface7_Release(surface);
11567 refcount = IDirectDraw7_Release(ddraw);
11568 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
11569 DestroyWindow(window);
11572 static void test_shademode(void)
11574 IDirect3DVertexBuffer7 *vb_strip, *vb_list, *buffer;
11575 IDirect3DDevice7 *device;
11576 D3DVERTEXBUFFERDESC desc;
11577 IDirectDrawSurface7 *rt;
11578 DWORD color0, color1;
11579 void *data = NULL;
11580 IDirect3D7 *d3d;
11581 ULONG refcount;
11582 UINT i, count;
11583 HWND window;
11584 HRESULT hr;
11585 static const struct
11587 struct vec3 position;
11588 DWORD diffuse;
11590 quad_strip[] =
11592 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
11593 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
11594 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
11595 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
11597 quad_list[] =
11599 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
11600 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
11601 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
11603 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
11604 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
11605 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
11607 static const struct
11609 DWORD primtype;
11610 DWORD shademode;
11611 DWORD color0, color1;
11613 tests[] =
11615 {D3DPT_TRIANGLESTRIP, D3DSHADE_FLAT, 0x00ff0000, 0x0000ff00},
11616 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
11617 {D3DPT_TRIANGLESTRIP, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
11618 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
11619 {D3DPT_TRIANGLELIST, D3DSHADE_FLAT, 0x00ff0000, 0x000000ff},
11620 {D3DPT_TRIANGLELIST, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
11623 window = create_window();
11624 if (!(device = create_device(window, DDSCL_NORMAL)))
11626 skip("Failed to create a 3D device, skipping test.\n");
11627 DestroyWindow(window);
11628 return;
11631 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
11632 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
11633 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
11634 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11636 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
11637 ok(hr == D3D_OK, "Failed to disable lighting, hr %#x.\n", hr);
11638 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
11639 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
11641 memset(&desc, 0, sizeof(desc));
11642 desc.dwSize = sizeof(desc);
11643 desc.dwCaps = D3DVBCAPS_WRITEONLY;
11644 desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
11645 desc.dwNumVertices = ARRAY_SIZE(quad_strip);
11646 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &vb_strip, 0);
11647 ok(hr == D3D_OK, "Failed to create vertex buffer, hr %#x.\n", hr);
11648 hr = IDirect3DVertexBuffer7_Lock(vb_strip, 0, &data, NULL);
11649 ok(hr == D3D_OK, "Failed to lock vertex buffer, hr %#x.\n", hr);
11650 memcpy(data, quad_strip, sizeof(quad_strip));
11651 hr = IDirect3DVertexBuffer7_Unlock(vb_strip);
11652 ok(hr == D3D_OK, "Failed to unlock vertex buffer, hr %#x.\n", hr);
11654 desc.dwNumVertices = ARRAY_SIZE(quad_list);
11655 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &vb_list, 0);
11656 ok(hr == D3D_OK, "Failed to create vertex buffer, hr %#x.\n", hr);
11657 hr = IDirect3DVertexBuffer7_Lock(vb_list, 0, &data, NULL);
11658 ok(hr == D3D_OK, "Failed to lock vertex buffer, hr %#x.\n", hr);
11659 memcpy(data, quad_list, sizeof(quad_list));
11660 hr = IDirect3DVertexBuffer7_Unlock(vb_list);
11661 ok(hr == D3D_OK, "Failed to unlock vertex buffer, hr %#x.\n", hr);
11663 /* Try it first with a TRIANGLESTRIP. Do it with different geometry because
11664 * the color fixups we have to do for FLAT shading will be dependent on that. */
11666 for (i = 0; i < ARRAY_SIZE(tests); ++i)
11668 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
11669 ok(hr == D3D_OK, "Failed to clear, hr %#x.\n", hr);
11671 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SHADEMODE, tests[i].shademode);
11672 ok(hr == D3D_OK, "Failed to set shade mode, hr %#x.\n", hr);
11674 hr = IDirect3DDevice7_BeginScene(device);
11675 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11676 buffer = tests[i].primtype == D3DPT_TRIANGLESTRIP ? vb_strip : vb_list;
11677 count = tests[i].primtype == D3DPT_TRIANGLESTRIP ? 4 : 6;
11678 hr = IDirect3DDevice7_DrawPrimitiveVB(device, tests[i].primtype, buffer, 0, count, 0);
11679 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11680 hr = IDirect3DDevice7_EndScene(device);
11681 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11683 color0 = get_surface_color(rt, 100, 100); /* Inside first triangle */
11684 color1 = get_surface_color(rt, 500, 350); /* Inside second triangle */
11686 /* For D3DSHADE_FLAT it should take the color of the first vertex of
11687 * each triangle. This requires EXT_provoking_vertex or similar
11688 * functionality being available. */
11689 /* PHONG should be the same as GOURAUD, since no hardware implements
11690 * this. */
11691 ok(compare_color(color0, tests[i].color0, 1), "Test %u shading has color0 %08x, expected %08x.\n",
11692 i, color0, tests[i].color0);
11693 ok(compare_color(color1, tests[i].color1, 1), "Test %u shading has color1 %08x, expected %08x.\n",
11694 i, color1, tests[i].color1);
11697 IDirect3DVertexBuffer7_Release(vb_strip);
11698 IDirect3DVertexBuffer7_Release(vb_list);
11699 IDirectDrawSurface7_Release(rt);
11700 IDirect3D7_Release(d3d);
11701 refcount = IDirect3DDevice7_Release(device);
11702 ok(!refcount, "Device has %u references left.\n", refcount);
11703 DestroyWindow(window);
11706 static void test_lockrect_invalid(void)
11708 unsigned int i, r;
11709 IDirectDraw7 *ddraw;
11710 IDirectDrawSurface7 *surface;
11711 HWND window;
11712 HRESULT hr;
11713 DDSURFACEDESC2 surface_desc;
11714 DDSURFACEDESC2 locked_desc;
11715 DDCAPS hal_caps;
11716 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
11717 static RECT valid[] =
11719 {60, 60, 68, 68},
11720 {60, 60, 60, 68},
11721 {60, 60, 68, 60},
11722 {120, 60, 128, 68},
11723 {60, 120, 68, 128},
11725 static RECT invalid[] =
11727 {68, 60, 60, 68}, /* left > right */
11728 {60, 68, 68, 60}, /* top > bottom */
11729 {-8, 60, 0, 68}, /* left < surface */
11730 {60, -8, 68, 0}, /* top < surface */
11731 {-16, 60, -8, 68}, /* right < surface */
11732 {60, -16, 68, -8}, /* bottom < surface */
11733 {60, 60, 136, 68}, /* right > surface */
11734 {60, 60, 68, 136}, /* bottom > surface */
11735 {136, 60, 144, 68}, /* left > surface */
11736 {60, 136, 68, 144}, /* top > surface */
11738 static const struct
11740 DWORD caps, caps2;
11741 const char *name;
11742 BOOL allowed;
11743 HRESULT hr;
11745 resources[] =
11747 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, "sysmem offscreenplain", TRUE, DDERR_INVALIDPARAMS},
11748 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, "vidmem offscreenplain", TRUE, DDERR_INVALIDPARAMS},
11749 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, "sysmem texture", TRUE, DD_OK},
11750 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, "vidmem texture", TRUE, DDERR_INVALIDPARAMS},
11751 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, "managed texture", TRUE, DD_OK},
11753 /* FWIW the SDK header mentions DDSCAPS_WRITEONLY as being a "READ
11754 * ONLY" flag. */
11755 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_WRITEONLY, 0, "sysmem offscreenplain writeonly", FALSE, DDERR_INVALIDPARAMS},
11756 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_WRITEONLY, 0, "vidmem offscreenplain writeonly", FALSE, DDERR_INVALIDPARAMS},
11757 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_WRITEONLY, 0, "sysmem texture writeonly", FALSE, DD_OK},
11758 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_WRITEONLY, 0, "vidmem texture writeonly", FALSE, DDERR_INVALIDPARAMS},
11759 {DDSCAPS_TEXTURE | DDSCAPS_WRITEONLY, DDSCAPS2_TEXTUREMANAGE, "managed texture writeonly", TRUE, DD_OK},
11762 window = create_window();
11763 ddraw = create_ddraw();
11764 ok(!!ddraw, "Failed to create a ddraw object.\n");
11765 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11766 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11768 memset(&hal_caps, 0, sizeof(hal_caps));
11769 hal_caps.dwSize = sizeof(hal_caps);
11770 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
11771 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
11772 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps
11773 || !(hal_caps.ddsCaps.dwCaps & DDSCAPS2_TEXTUREMANAGE))
11775 skip("Required surface types not supported, skipping test.\n");
11776 goto done;
11779 for (r = 0; r < ARRAY_SIZE(resources); ++r)
11781 memset(&surface_desc, 0, sizeof(surface_desc));
11782 surface_desc.dwSize = sizeof(surface_desc);
11783 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
11784 surface_desc.ddsCaps.dwCaps = resources[r].caps;
11785 surface_desc.ddsCaps.dwCaps2 = resources[r].caps2;
11786 surface_desc.dwWidth = 128;
11787 surface_desc.dwHeight = 128;
11788 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
11789 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
11790 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
11791 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xff0000;
11792 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x00ff00;
11793 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x0000ff;
11795 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11796 if (!resources[r].allowed)
11798 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
11799 continue;
11801 if (is_ddraw64 && (resources[r].caps & DDSCAPS_TEXTURE))
11803 todo_wine ok(hr == E_NOINTERFACE, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
11804 if (SUCCEEDED(hr))
11805 IDirectDrawSurface7_Release(surface);
11806 continue;
11808 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n", hr, resources[r].name);
11810 /* Crashes in ddraw7
11811 hr = IDirectDrawSurface7_Lock(surface, NULL, NULL, DDLOCK_WAIT, NULL);
11812 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
11815 for (i = 0; i < ARRAY_SIZE(valid); ++i)
11817 RECT *rect = &valid[i];
11819 memset(&locked_desc, 0, sizeof(locked_desc));
11820 locked_desc.dwSize = sizeof(locked_desc);
11822 hr = IDirectDrawSurface7_Lock(surface, rect, &locked_desc, DDLOCK_WAIT, NULL);
11823 ok(SUCCEEDED(hr), "Lock failed (%#x) for rect %s, type %s.\n",
11824 hr, wine_dbgstr_rect(rect), resources[r].name);
11826 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11827 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11830 for (i = 0; i < ARRAY_SIZE(invalid); ++i)
11832 RECT *rect = &invalid[i];
11834 memset(&locked_desc, 1, sizeof(locked_desc));
11835 locked_desc.dwSize = sizeof(locked_desc);
11837 hr = IDirectDrawSurface7_Lock(surface, rect, &locked_desc, DDLOCK_WAIT, NULL);
11838 todo_wine_if (SUCCEEDED(resources[r].hr))
11839 ok(hr == resources[r].hr, "Lock returned %#x for rect %s, type %s.\n",
11840 hr, wine_dbgstr_rect(rect), resources[r].name);
11841 if (SUCCEEDED(hr))
11843 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11844 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11846 else
11847 ok(!locked_desc.lpSurface, "Got unexpected lpSurface %p.\n", locked_desc.lpSurface);
11850 hr = IDirectDrawSurface7_Lock(surface, NULL, &locked_desc, DDLOCK_WAIT, NULL);
11851 ok(SUCCEEDED(hr), "Lock(rect = NULL) failed, hr %#x, type %s.\n",
11852 hr, resources[r].name);
11853 hr = IDirectDrawSurface7_Lock(surface, NULL, &locked_desc, DDLOCK_WAIT, NULL);
11854 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = NULL) returned %#x, type %s.\n",
11855 hr, resources[r].name);
11856 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11857 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11859 hr = IDirectDrawSurface7_Lock(surface, &valid[0], &locked_desc, DDLOCK_WAIT, NULL);
11860 ok(SUCCEEDED(hr), "Lock(rect = %s) failed (%#x).\n", wine_dbgstr_rect(&valid[0]), hr);
11861 hr = IDirectDrawSurface7_Lock(surface, &valid[0], &locked_desc, DDLOCK_WAIT, NULL);
11862 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = %s) failed (%#x).\n",
11863 wine_dbgstr_rect(&valid[0]), hr);
11865 /* Locking a different rectangle returns DD_OK, but it seems to break the surface.
11866 * Afterwards unlocking the surface fails(NULL rectangle or both locked rectangles) */
11868 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11869 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
11871 IDirectDrawSurface7_Release(surface);
11874 done:
11875 IDirectDraw7_Release(ddraw);
11876 DestroyWindow(window);
11879 static void test_yv12_overlay(void)
11881 IDirectDrawSurface7 *src_surface, *dst_surface;
11882 RECT rect = {13, 17, 14, 18};
11883 unsigned int offset, y;
11884 DDSURFACEDESC2 desc;
11885 unsigned char *base;
11886 IDirectDraw7 *ddraw;
11887 HWND window;
11888 HRESULT hr;
11890 window = create_window();
11891 ddraw = create_ddraw();
11892 ok(!!ddraw, "Failed to create a ddraw object.\n");
11893 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
11894 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
11896 if (!(src_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
11898 skip("Failed to create a YV12 overlay, skipping test.\n");
11899 goto done;
11902 memset(&desc, 0, sizeof(desc));
11903 desc.dwSize = sizeof(desc);
11904 hr = IDirectDrawSurface7_Lock(src_surface, NULL, &desc, DDLOCK_WAIT, NULL);
11905 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11907 ok(desc.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH),
11908 "Got unexpected flags %#x.\n", desc.dwFlags);
11909 ok(desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_HWCODEC)
11910 || desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
11911 "Got unexpected caps %#x.\n", desc.ddsCaps.dwCaps);
11912 ok(desc.dwWidth == 256, "Got unexpected width %u.\n", desc.dwWidth);
11913 ok(desc.dwHeight == 256, "Got unexpected height %u.\n", desc.dwHeight);
11914 /* The overlay pitch seems to have 256 byte alignment. */
11915 ok(!(U1(desc).lPitch & 0xff), "Got unexpected pitch %u.\n", U1(desc).lPitch);
11917 /* Fill the surface with some data for the blit test. */
11918 base = desc.lpSurface;
11919 /* Luminance */
11920 for (y = 0; y < desc.dwHeight; ++y)
11922 memset(base + U1(desc).lPitch * y, 0x10, desc.dwWidth);
11924 /* V */
11925 for (; y < desc.dwHeight + desc.dwHeight / 4; ++y)
11927 memset(base + U1(desc).lPitch * y, 0x20, desc.dwWidth);
11929 /* U */
11930 for (; y < desc.dwHeight + desc.dwHeight / 2; ++y)
11932 memset(base + U1(desc).lPitch * y, 0x30, desc.dwWidth);
11935 hr = IDirectDrawSurface7_Unlock(src_surface, NULL);
11936 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11938 /* YV12 uses 2x2 blocks with 6 bytes per block (4*Y, 1*U, 1*V). Unlike
11939 * other block-based formats like DXT the entire Y channel is stored in
11940 * one big chunk of memory, followed by the chroma channels. So partial
11941 * locks do not really make sense. Show that they are allowed nevertheless
11942 * and the offset points into the luminance data. */
11943 hr = IDirectDrawSurface7_Lock(src_surface, &rect, &desc, DDLOCK_WAIT, NULL);
11944 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11945 offset = ((const unsigned char *)desc.lpSurface - base);
11946 ok(offset == rect.top * U1(desc).lPitch + rect.left, "Got unexpected offset %u, expected %u.\n",
11947 offset, rect.top * U1(desc).lPitch + rect.left);
11948 hr = IDirectDrawSurface7_Unlock(src_surface, NULL);
11949 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11951 if (!(dst_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
11953 /* Windows XP with a Radeon X1600 GPU refuses to create a second
11954 * overlay surface, DDERR_NOOVERLAYHW, making the blit tests moot. */
11955 skip("Failed to create a second YV12 surface, skipping blit test.\n");
11956 IDirectDrawSurface7_Release(src_surface);
11957 goto done;
11960 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, src_surface, NULL, DDBLT_WAIT, NULL);
11961 /* VMware rejects YV12 blits. This behavior has not been seen on real
11962 * hardware yet, so mark it broken. */
11963 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL), "Failed to blit, hr %#x.\n", hr);
11965 if (SUCCEEDED(hr))
11967 memset(&desc, 0, sizeof(desc));
11968 desc.dwSize = sizeof(desc);
11969 hr = IDirectDrawSurface7_Lock(dst_surface, NULL, &desc, DDLOCK_WAIT, NULL);
11970 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11972 base = desc.lpSurface;
11973 ok(base[0] == 0x10, "Got unexpected Y data 0x%02x.\n", base[0]);
11974 base += desc.dwHeight * U1(desc).lPitch;
11975 todo_wine ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]);
11976 base += desc.dwHeight / 4 * U1(desc).lPitch;
11977 todo_wine ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]);
11979 hr = IDirectDrawSurface7_Unlock(dst_surface, NULL);
11980 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11983 IDirectDrawSurface7_Release(dst_surface);
11984 IDirectDrawSurface7_Release(src_surface);
11985 done:
11986 IDirectDraw7_Release(ddraw);
11987 DestroyWindow(window);
11990 static BOOL dwm_enabled(void)
11992 BOOL ret = FALSE;
11994 if (!strcmp(winetest_platform, "wine"))
11995 return FALSE;
11996 if (!pDwmIsCompositionEnabled)
11997 return FALSE;
11998 if (FAILED(pDwmIsCompositionEnabled(&ret)))
11999 return FALSE;
12000 return ret;
12003 static void test_offscreen_overlay(void)
12005 IDirectDrawSurface7 *overlay, *offscreen, *primary;
12006 DDSURFACEDESC2 surface_desc;
12007 IDirectDraw7 *ddraw;
12008 HWND window;
12009 HRESULT hr;
12010 HDC dc;
12012 window = create_window();
12013 ddraw = create_ddraw();
12014 ok(!!ddraw, "Failed to create a ddraw object.\n");
12015 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12016 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12018 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
12020 skip("Failed to create a UYVY overlay, skipping test.\n");
12021 goto done;
12024 memset(&surface_desc, 0, sizeof(surface_desc));
12025 surface_desc.dwSize = sizeof(surface_desc);
12026 surface_desc.dwFlags = DDSD_CAPS;
12027 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
12028 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
12029 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
12031 /* On Windows 7, and probably Vista, UpdateOverlay() will return
12032 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
12033 * surface prevents this by disabling the dwm. */
12034 hr = IDirectDrawSurface7_GetDC(primary, &dc);
12035 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
12036 hr = IDirectDrawSurface7_ReleaseDC(primary, dc);
12037 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
12039 /* Try to overlay a NULL surface. */
12040 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_SHOW, NULL);
12041 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
12042 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_HIDE, NULL);
12043 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
12045 /* Try to overlay an offscreen surface. */
12046 memset(&surface_desc, 0, sizeof(surface_desc));
12047 surface_desc.dwSize = sizeof(surface_desc);
12048 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
12049 surface_desc.dwWidth = 64;
12050 surface_desc.dwHeight = 64;
12051 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12052 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
12053 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
12054 U4(surface_desc).ddpfPixelFormat.dwFourCC = 0;
12055 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
12056 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
12057 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
12058 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
12059 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
12060 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
12062 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, offscreen, NULL, DDOVER_SHOW, NULL);
12063 ok(SUCCEEDED(hr) || broken(hr == DDERR_OUTOFCAPS && dwm_enabled())
12064 || broken(hr == E_NOTIMPL && ddraw_is_vmware(ddraw)),
12065 "Failed to update overlay, hr %#x.\n", hr);
12067 /* Try to overlay the primary with a non-overlay surface. */
12068 hr = IDirectDrawSurface7_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_SHOW, NULL);
12069 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
12070 hr = IDirectDrawSurface7_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_HIDE, NULL);
12071 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
12073 IDirectDrawSurface7_Release(offscreen);
12074 IDirectDrawSurface7_Release(primary);
12075 IDirectDrawSurface7_Release(overlay);
12076 done:
12077 IDirectDraw7_Release(ddraw);
12078 DestroyWindow(window);
12081 static void test_overlay_rect(void)
12083 IDirectDrawSurface7 *overlay, *primary = NULL;
12084 DDSURFACEDESC2 surface_desc;
12085 RECT rect = {0, 0, 64, 64};
12086 IDirectDraw7 *ddraw;
12087 LONG pos_x, pos_y;
12088 HRESULT hr, hr2;
12089 HWND window;
12090 HDC dc;
12092 window = create_window();
12093 ddraw = create_ddraw();
12094 ok(!!ddraw, "Failed to create a ddraw object.\n");
12095 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12096 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12098 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
12100 skip("Failed to create a UYVY overlay, skipping test.\n");
12101 goto done;
12104 memset(&surface_desc, 0, sizeof(surface_desc));
12105 surface_desc.dwSize = sizeof(surface_desc);
12106 surface_desc.dwFlags = DDSD_CAPS;
12107 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
12108 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
12109 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
12111 /* On Windows 7, and probably Vista, UpdateOverlay() will return
12112 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
12113 * surface prevents this by disabling the dwm. */
12114 hr = IDirectDrawSurface7_GetDC(primary, &dc);
12115 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
12116 hr = IDirectDrawSurface7_ReleaseDC(primary, dc);
12117 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
12119 /* On Windows 8 and newer DWM can't be turned off, making overlays unusable. */
12120 if (dwm_enabled())
12122 win_skip("Cannot disable DWM, skipping overlay test.\n");
12123 goto done;
12126 /* The dx sdk sort of implies that rect must be set when DDOVER_SHOW is
12127 * used. This is not true in Windows Vista and earlier, but changed in
12128 * Windows 7. */
12129 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
12130 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
12131 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_HIDE, NULL);
12132 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
12133 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_SHOW, NULL);
12134 ok(hr == DD_OK || hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
12136 /* Show that the overlay position is the (top, left) coordinate of the
12137 * destination rectangle. */
12138 OffsetRect(&rect, 32, 16);
12139 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
12140 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
12141 pos_x = -1; pos_y = -1;
12142 hr = IDirectDrawSurface7_GetOverlayPosition(overlay, &pos_x, &pos_y);
12143 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
12144 ok(pos_x == rect.left, "Got unexpected pos_x %d, expected %d.\n", pos_x, rect.left);
12145 ok(pos_y == rect.top, "Got unexpected pos_y %d, expected %d.\n", pos_y, rect.top);
12147 /* Passing a NULL dest rect sets the position to 0/0. Visually it can be
12148 * seen that the overlay overlays the whole primary(==screen). */
12149 hr2 = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, NULL, 0, NULL);
12150 ok(hr2 == DD_OK || hr2 == DDERR_INVALIDPARAMS || hr2 == DDERR_OUTOFCAPS, "Got unexpected hr %#x.\n", hr2);
12151 hr = IDirectDrawSurface7_GetOverlayPosition(overlay, &pos_x, &pos_y);
12152 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
12153 if (SUCCEEDED(hr2))
12155 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
12156 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
12158 else
12160 ok(pos_x == 32, "Got unexpected pos_x %d.\n", pos_x);
12161 ok(pos_y == 16, "Got unexpected pos_y %d.\n", pos_y);
12164 /* The position cannot be retrieved when the overlay is not shown. */
12165 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_HIDE, NULL);
12166 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
12167 pos_x = -1; pos_y = -1;
12168 hr = IDirectDrawSurface7_GetOverlayPosition(overlay, &pos_x, &pos_y);
12169 ok(hr == DDERR_OVERLAYNOTVISIBLE, "Got unexpected hr %#x.\n", hr);
12170 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
12171 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
12173 done:
12174 if (primary)
12175 IDirectDrawSurface7_Release(primary);
12176 if (overlay)
12177 IDirectDrawSurface7_Release(overlay);
12178 IDirectDraw7_Release(ddraw);
12179 DestroyWindow(window);
12182 static void test_blt(void)
12184 IDirectDrawSurface7 *surface, *rt;
12185 DDSURFACEDESC2 surface_desc;
12186 IDirect3DDevice7 *device;
12187 IDirectDraw7 *ddraw;
12188 IDirect3D7 *d3d;
12189 unsigned int i;
12190 ULONG refcount;
12191 HWND window;
12192 HRESULT hr;
12194 static struct
12196 RECT src_rect;
12197 RECT dst_rect;
12198 HRESULT hr;
12200 test_data[] =
12202 {{160, 0, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit. */
12203 {{160, 480, 640, 0}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, flipped source. */
12204 {{640, 0, 160, 480}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, mirrored source. */
12205 {{160, 0, 480, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched x. */
12206 {{160, 160, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched y. */
12207 {{ 0, 0, 640, 480}, { 0, 0, 640, 480}, DD_OK}, /* Full surface blit. */
12208 {{ 0, 0, 640, 480}, { 0, 480, 640, 0}, DDERR_INVALIDRECT}, /* Full surface, flipped destination. */
12209 {{ 0, 0, 640, 480}, {640, 0, 0, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored destination. */
12210 {{ 0, 480, 640, 0}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, flipped source. */
12211 {{640, 0, 0, 480}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored source. */
12214 window = create_window();
12215 if (!(device = create_device(window, DDSCL_NORMAL)))
12217 skip("Failed to create a 3D device, skipping test.\n");
12218 DestroyWindow(window);
12219 return;
12222 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
12223 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
12224 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
12225 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
12226 IDirect3D7_Release(d3d);
12227 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
12228 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
12230 memset(&surface_desc, 0, sizeof(surface_desc));
12231 surface_desc.dwSize = sizeof(surface_desc);
12232 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
12233 surface_desc.dwWidth = 640;
12234 surface_desc.dwHeight = 480;
12235 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12236 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12237 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12239 hr = IDirectDrawSurface7_Blt(surface, NULL, surface, NULL, 0, NULL);
12240 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12242 hr = IDirectDrawSurface7_Blt(surface, NULL, rt, NULL, 0, NULL);
12243 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
12245 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
12247 hr = IDirectDrawSurface7_Blt(surface, &test_data[i].dst_rect,
12248 surface, &test_data[i].src_rect, DDBLT_WAIT, NULL);
12249 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
12251 hr = IDirectDrawSurface7_Blt(surface, &test_data[i].dst_rect,
12252 rt, &test_data[i].src_rect, DDBLT_WAIT, NULL);
12253 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
12255 hr = IDirectDrawSurface7_Blt(surface, &test_data[i].dst_rect,
12256 NULL, &test_data[i].src_rect, DDBLT_WAIT, NULL);
12257 ok(hr == DDERR_INVALIDPARAMS, "Test %u: Got unexpected hr %#x.\n", i, hr);
12259 hr = IDirectDrawSurface7_Blt(surface, &test_data[i].dst_rect, NULL, NULL, DDBLT_WAIT, NULL);
12260 ok(hr == DDERR_INVALIDPARAMS, "Test %u: Got unexpected hr %#x.\n", i, hr);
12263 IDirectDrawSurface7_Release(surface);
12264 IDirectDrawSurface7_Release(rt);
12265 IDirectDraw7_Release(ddraw);
12266 refcount = IDirect3DDevice7_Release(device);
12267 ok(!refcount, "Device has %u references left.\n", refcount);
12268 DestroyWindow(window);
12271 static void test_blt_z_alpha(void)
12273 DWORD blt_flags[] =
12275 /* 0 */
12276 DDBLT_ALPHADEST,
12277 DDBLT_ALPHADESTCONSTOVERRIDE,
12278 DDBLT_ALPHADESTNEG,
12279 DDBLT_ALPHADESTSURFACEOVERRIDE,
12280 DDBLT_ALPHAEDGEBLEND,
12281 /* 5 */
12282 DDBLT_ALPHASRC,
12283 DDBLT_ALPHASRCCONSTOVERRIDE,
12284 DDBLT_ALPHASRCNEG,
12285 DDBLT_ALPHASRCSURFACEOVERRIDE,
12286 DDBLT_ZBUFFER,
12287 /* 10 */
12288 DDBLT_ZBUFFERDESTCONSTOVERRIDE,
12289 DDBLT_ZBUFFERDESTOVERRIDE,
12290 DDBLT_ZBUFFERSRCCONSTOVERRIDE,
12291 DDBLT_ZBUFFERSRCOVERRIDE,
12293 IDirectDrawSurface7 *src_surface, *dst_surface;
12294 DDSURFACEDESC2 surface_desc;
12295 IDirectDraw7 *ddraw;
12296 DDPIXELFORMAT pf;
12297 ULONG refcount;
12298 unsigned int i;
12299 D3DCOLOR color;
12300 HWND window;
12301 HRESULT hr;
12302 DDBLTFX fx;
12304 window = create_window();
12305 ddraw = create_ddraw();
12306 ok(!!ddraw, "Failed to create a ddraw object.\n");
12307 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12308 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12310 memset(&pf, 0, sizeof(pf));
12311 pf.dwSize = sizeof(pf);
12312 pf.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
12313 U1(pf).dwRGBBitCount = 32;
12314 U2(pf).dwRBitMask = 0x00ff0000;
12315 U3(pf).dwGBitMask = 0x0000ff00;
12316 U4(pf).dwBBitMask = 0x000000ff;
12317 U5(pf).dwRGBAlphaBitMask = 0xff000000;
12319 memset(&surface_desc, 0, sizeof(surface_desc));
12320 surface_desc.dwSize = sizeof(surface_desc);
12321 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
12322 surface_desc.dwWidth = 64;
12323 surface_desc.dwHeight = 64;
12324 U4(surface_desc).ddpfPixelFormat = pf;
12325 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12327 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
12328 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
12329 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
12330 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
12332 memset(&fx, 0, sizeof(fx));
12333 fx.dwSize = sizeof(fx);
12334 fx.dwZBufferOpCode = D3DCMP_NEVER;
12335 fx.dwZDestConstBitDepth = 32;
12336 U1(fx).dwZDestConst = 0x11111111;
12337 fx.dwZSrcConstBitDepth = 32;
12338 U2(fx).dwZSrcConst = 0xeeeeeeee;
12339 fx.dwAlphaEdgeBlendBitDepth = 8;
12340 fx.dwAlphaEdgeBlend = 0x7f;
12341 fx.dwAlphaDestConstBitDepth = 8;
12342 U3(fx).dwAlphaDestConst = 0xdd;
12343 fx.dwAlphaSrcConstBitDepth = 8;
12344 U4(fx).dwAlphaSrcConst = 0x22;
12346 for (i = 0; i < ARRAY_SIZE(blt_flags); ++i)
12348 U5(fx).dwFillColor = 0x3300ff00;
12349 hr = IDirectDrawSurface7_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
12350 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
12352 U5(fx).dwFillColor = 0xccff0000;
12353 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
12354 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
12356 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, src_surface, NULL, blt_flags[i] | DDBLT_WAIT, &fx);
12357 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
12359 color = get_surface_color(dst_surface, 32, 32);
12360 ok(compare_color(color, 0x0000ff00, 0), "Test %u: Got unexpected color 0x%08x.\n", i, color);
12363 IDirectDrawSurface7_Release(dst_surface);
12364 IDirectDrawSurface7_Release(src_surface);
12365 refcount = IDirectDraw7_Release(ddraw);
12366 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
12367 DestroyWindow(window);
12370 static void test_cross_device_blt(void)
12372 IDirectDrawSurface7 *surface, *surface2, *sysmem_surface;
12373 IDirect3DDevice7 *device, *device2;
12374 IDirectDraw7 *ddraw, *ddraw2;
12375 DDSURFACEDESC2 surface_desc;
12376 HWND window, window2;
12377 IDirect3D7 *d3d;
12378 ULONG refcount;
12379 D3DCOLOR color;
12380 DDBLTFX fx;
12381 HRESULT hr;
12383 window = create_window();
12384 if (!(device = create_device(window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
12386 skip("Failed to create a 3D device.\n");
12387 DestroyWindow(window);
12388 return;
12391 window2 = create_window();
12392 if (!(device2 = create_device(window2, DDSCL_NORMAL)))
12394 skip("Failed to create a 3D device.\n");
12395 IDirect3DDevice7_Release(device);
12396 DestroyWindow(window);
12397 DestroyWindow(window2);
12398 return;
12401 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
12402 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
12403 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
12404 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
12405 IDirect3D7_Release(d3d);
12407 hr = IDirect3DDevice7_GetDirect3D(device2, &d3d);
12408 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
12409 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw2);
12410 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
12411 IDirect3D7_Release(d3d);
12413 memset(&surface_desc, 0, sizeof(surface_desc));
12414 surface_desc.dwSize = sizeof(surface_desc);
12415 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
12416 surface_desc.dwWidth = 640;
12417 surface_desc.dwHeight = 480;
12418 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
12419 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &sysmem_surface, NULL);
12420 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12422 memset(&surface_desc, 0, sizeof(surface_desc));
12423 surface_desc.dwSize = sizeof(surface_desc);
12424 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
12425 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_VIDEOMEMORY;
12426 U5(surface_desc).dwBackBufferCount = 2;
12427 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12428 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12430 memset(&surface_desc, 0, sizeof(surface_desc));
12431 surface_desc.dwSize = sizeof(surface_desc);
12432 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
12433 surface_desc.dwWidth = 640;
12434 surface_desc.dwHeight = 480;
12435 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
12436 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
12437 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
12438 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
12439 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00007c00;
12440 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x000003e0;
12441 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x0000001f;
12442 hr = IDirectDraw7_CreateSurface(ddraw2, &surface_desc, &surface2, NULL);
12443 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12445 memset(&fx, 0, sizeof(fx));
12446 fx.dwSize = sizeof(fx);
12447 U5(fx).dwFillColor = 0xff0000ff;
12448 hr = IDirectDrawSurface7_Blt(surface2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
12449 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
12451 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
12452 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
12453 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
12454 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12455 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
12456 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
12457 color = get_surface_color(surface, 320, 240);
12458 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
12460 hr = IDirectDrawSurface7_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
12461 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
12462 color = get_surface_color(sysmem_surface, 320, 240);
12463 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
12465 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12466 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12467 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
12468 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
12470 hr = IDirectDrawSurface7_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
12471 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
12472 color = get_surface_color(sysmem_surface, 320, 240);
12473 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
12475 IDirectDrawSurface7_Release(surface2);
12476 memset(&surface_desc, 0, sizeof(surface_desc));
12477 surface_desc.dwSize = sizeof(surface_desc);
12478 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
12479 surface_desc.dwWidth = 640;
12480 surface_desc.dwHeight = 480;
12481 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
12482 hr = IDirectDraw7_CreateSurface(ddraw2, &surface_desc, &surface2, NULL);
12483 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12484 hr = IDirectDrawSurface7_Blt(surface2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
12485 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
12487 hr = IDirectDrawSurface7_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
12488 todo_wine ok(hr == D3D_OK, "Failed to blit, hr %#x.\n", hr);
12489 color = get_surface_color(sysmem_surface, 320, 240);
12490 todo_wine ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
12492 IDirectDrawSurface7_Release(surface);
12493 IDirectDrawSurface7_Release(surface2);
12494 IDirectDrawSurface7_Release(sysmem_surface);
12495 IDirectDraw7_Release(ddraw);
12496 IDirectDraw7_Release(ddraw2);
12497 refcount = IDirect3DDevice7_Release(device);
12498 ok(!refcount, "Device has %u references left.\n", refcount);
12499 refcount = IDirect3DDevice7_Release(device2);
12500 ok(!refcount, "Device has %u references left.\n", refcount);
12501 DestroyWindow(window);
12502 DestroyWindow(window2);
12505 static void test_color_clamping(void)
12507 static D3DMATRIX mat =
12509 1.0f, 0.0f, 0.0f, 0.0f,
12510 0.0f, 1.0f, 0.0f, 0.0f,
12511 0.0f, 0.0f, 1.0f, 0.0f,
12512 0.0f, 0.0f, 0.0f, 1.0f,
12514 static struct vec3 quad[] =
12516 {-1.0f, -1.0f, 0.1f},
12517 {-1.0f, 1.0f, 0.1f},
12518 { 1.0f, -1.0f, 0.1f},
12519 { 1.0f, 1.0f, 0.1f},
12521 IDirect3DDevice7 *device;
12522 IDirectDrawSurface7 *rt;
12523 ULONG refcount;
12524 D3DCOLOR color;
12525 HWND window;
12526 HRESULT hr;
12528 window = create_window();
12529 if (!(device = create_device(window, DDSCL_NORMAL)))
12531 skip("Failed to create a 3D device, skipping test.\n");
12532 DestroyWindow(window);
12533 return;
12536 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
12537 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
12539 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
12540 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
12541 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
12542 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
12543 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
12544 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
12545 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
12546 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
12547 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
12548 ok(SUCCEEDED(hr), "Failed to disable Z test, hr %#x.\n", hr);
12549 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
12550 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
12551 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
12552 ok(SUCCEEDED(hr), "Failed to disable stencil test, hr %#x.\n", hr);
12553 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
12554 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
12555 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
12556 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
12558 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0xff404040);
12559 ok(SUCCEEDED(hr), "Failed to set texture factor, hr %#x.\n", hr);
12560 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_ADD);
12561 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
12562 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
12563 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
12564 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_SPECULAR);
12565 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
12566 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_MODULATE);
12567 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
12568 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TFACTOR);
12569 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
12570 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
12571 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
12573 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
12574 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12576 hr = IDirect3DDevice7_BeginScene(device);
12577 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12579 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
12580 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12582 hr = IDirect3DDevice7_EndScene(device);
12583 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12585 color = get_surface_color(rt, 320, 240);
12586 ok(compare_color(color, 0x00404040, 1), "Got unexpected color 0x%08x.\n", color);
12588 IDirectDrawSurface7_Release(rt);
12589 refcount = IDirect3DDevice7_Release(device);
12590 ok(!refcount, "Device has %u references left.\n", refcount);
12591 DestroyWindow(window);
12594 static void test_getdc(void)
12596 DDSCAPS2 caps = {DDSCAPS_COMPLEX, DDSCAPS2_CUBEMAP_NEGATIVEZ, 0, {0}};
12597 IDirectDrawSurface7 *surface, *surface2, *tmp;
12598 DDSURFACEDESC2 surface_desc, map_desc;
12599 IDirectDraw7 *ddraw;
12600 unsigned int i, screen_bpp;
12601 HWND window;
12602 HDC dc, dc2;
12603 HRESULT hr;
12605 static const struct
12607 const char *name;
12608 DDPIXELFORMAT format;
12609 BOOL getdc_supported;
12610 HRESULT alt_result;
12612 test_data[] =
12614 {"D3DFMT_A8R8G8B8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
12615 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}}, TRUE},
12616 {"D3DFMT_X8R8G8B8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
12617 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}}, TRUE},
12618 {"D3DFMT_R5G6B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
12619 {0x0000f800}, {0x000007e0}, {0x0000001f}, {0x00000000}}, TRUE},
12620 {"D3DFMT_X1R5G5B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
12621 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00000000}}, TRUE},
12622 {"D3DFMT_A1R5G5B5", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
12623 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00008000}}, TRUE},
12624 {"D3DFMT_A4R4G4B4", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
12625 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x0000f000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
12626 {"D3DFMT_X4R4G4B4", {sizeof(test_data->format), DDPF_RGB, 0, {16},
12627 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
12628 {"D3DFMT_A2R10G10B10", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
12629 {0xc0000000}, {0x3ff00000}, {0x000ffc00}, {0x000003ff}}, TRUE},
12630 {"D3DFMT_A8B8G8R8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
12631 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0xff000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
12632 {"D3DFMT_X8B8G8R8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
12633 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
12634 {"D3DFMT_R3G3B2", {sizeof(test_data->format), DDPF_RGB, 0, {8},
12635 {0x000000e0}, {0x0000001c}, {0x00000003}, {0x00000000}}, FALSE},
12636 /* GetDC() on a P8 surface fails unless the display mode is 8 bpp.
12637 * This is not implemented in wine yet, so disable the test for now.
12638 * Succeeding P8 GetDC() calls are tested in the ddraw:visual test.
12639 {"D3DFMT_P8", {sizeof(test_data->format), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0, {8 },
12640 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
12642 {"D3DFMT_L8", {sizeof(test_data->format), DDPF_LUMINANCE, 0, {8},
12643 {0x000000ff}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
12644 {"D3DFMT_A8L8", {sizeof(test_data->format), DDPF_ALPHAPIXELS | DDPF_LUMINANCE, 0, {16},
12645 {0x000000ff}, {0x00000000}, {0x00000000}, {0x0000ff00}}, FALSE},
12646 {"D3DFMT_DXT1", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','1'), {0},
12647 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
12648 {"D3DFMT_DXT2", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','2'), {0},
12649 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
12650 {"D3DFMT_DXT3", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','3'), {0},
12651 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
12652 {"D3DFMT_DXT4", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','4'), {0},
12653 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
12654 {"D3DFMT_DXT5", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','5'), {0},
12655 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
12658 window = create_window();
12659 ddraw = create_ddraw();
12660 ok(!!ddraw, "Failed to create a ddraw object.\n");
12661 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12662 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12664 surface_desc.dwSize = sizeof(surface_desc);
12665 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
12666 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr);
12667 screen_bpp = U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount;
12669 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
12671 memset(&surface_desc, 0, sizeof(surface_desc));
12672 surface_desc.dwSize = sizeof(surface_desc);
12673 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
12674 surface_desc.dwWidth = 64;
12675 surface_desc.dwHeight = 64;
12676 U4(surface_desc).ddpfPixelFormat = test_data[i].format;
12677 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12679 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
12681 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
12682 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
12683 if (FAILED(hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
12685 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", test_data[i].name, hr);
12686 continue;
12690 dc = (void *)0x1234;
12691 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12692 if (test_data[i].getdc_supported)
12693 ok(SUCCEEDED(hr) || broken(hr == test_data[i].alt_result),
12694 "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12695 else
12696 ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12698 if (SUCCEEDED(hr))
12700 unsigned int width_bytes;
12701 DIBSECTION dib;
12702 HBITMAP bitmap;
12703 DWORD type;
12704 int size;
12706 type = GetObjectType(dc);
12707 ok(type == OBJ_MEMDC, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
12708 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
12709 type = GetObjectType(bitmap);
12710 ok(type == OBJ_BITMAP, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
12712 size = GetObjectA(bitmap, sizeof(dib), &dib);
12713 ok(size == sizeof(dib), "Got unexpected size %d for format %s.\n", size, test_data[i].name);
12714 ok(!dib.dsBm.bmType, "Got unexpected type %#x for format %s.\n",
12715 dib.dsBm.bmType, test_data[i].name);
12716 ok(dib.dsBm.bmWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
12717 dib.dsBm.bmWidth, test_data[i].name);
12718 ok(dib.dsBm.bmHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
12719 dib.dsBm.bmHeight, test_data[i].name);
12720 width_bytes = ((dib.dsBm.bmWidth * U1(test_data[i].format).dwRGBBitCount + 31) >> 3) & ~3;
12721 ok(dib.dsBm.bmWidthBytes == width_bytes, "Got unexpected width bytes %d for format %s.\n",
12722 dib.dsBm.bmWidthBytes, test_data[i].name);
12723 ok(dib.dsBm.bmPlanes == 1, "Got unexpected plane count %d for format %s.\n",
12724 dib.dsBm.bmPlanes, test_data[i].name);
12725 ok(dib.dsBm.bmBitsPixel == U1(test_data[i].format).dwRGBBitCount,
12726 "Got unexpected bit count %d for format %s.\n",
12727 dib.dsBm.bmBitsPixel, test_data[i].name);
12728 /* Windows XP sets bmBits == NULL for formats that match the screen at least on my r200 GPU. I
12729 * suspect this applies to all HW accelerated pre-WDDM drivers because they can handle gdi access
12730 * to ddraw surfaces themselves instead of going through a sysmem DIB section. */
12731 ok(!!dib.dsBm.bmBits || broken(!pDwmIsCompositionEnabled && dib.dsBm.bmBitsPixel == screen_bpp),
12732 "Got unexpected bits %p for format %s.\n", dib.dsBm.bmBits, test_data[i].name);
12734 ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "Got unexpected size %u for format %s.\n",
12735 dib.dsBmih.biSize, test_data[i].name);
12736 ok(dib.dsBmih.biWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
12737 dib.dsBmih.biHeight, test_data[i].name);
12738 ok(dib.dsBmih.biHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
12739 dib.dsBmih.biHeight, test_data[i].name);
12740 ok(dib.dsBmih.biPlanes == 1, "Got unexpected plane count %u for format %s.\n",
12741 dib.dsBmih.biPlanes, test_data[i].name);
12742 ok(dib.dsBmih.biBitCount == U1(test_data[i].format).dwRGBBitCount,
12743 "Got unexpected bit count %u for format %s.\n",
12744 dib.dsBmih.biBitCount, test_data[i].name);
12745 ok(dib.dsBmih.biCompression == (U1(test_data[i].format).dwRGBBitCount == 16 ? BI_BITFIELDS : BI_RGB)
12746 || broken(U1(test_data[i].format).dwRGBBitCount == 32 && dib.dsBmih.biCompression == BI_BITFIELDS),
12747 "Got unexpected compression %#x for format %s.\n",
12748 dib.dsBmih.biCompression, test_data[i].name);
12749 ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
12750 dib.dsBmih.biSizeImage, test_data[i].name);
12751 ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n",
12752 dib.dsBmih.biXPelsPerMeter, test_data[i].name);
12753 ok(!dib.dsBmih.biYPelsPerMeter, "Got unexpected vertical resolution %d for format %s.\n",
12754 dib.dsBmih.biYPelsPerMeter, test_data[i].name);
12755 ok(!dib.dsBmih.biClrUsed, "Got unexpected used colour count %u for format %s.\n",
12756 dib.dsBmih.biClrUsed, test_data[i].name);
12757 ok(!dib.dsBmih.biClrImportant, "Got unexpected important colour count %u for format %s.\n",
12758 dib.dsBmih.biClrImportant, test_data[i].name);
12760 if (dib.dsBmih.biCompression == BI_BITFIELDS)
12762 ok((dib.dsBitfields[0] == U2(test_data[i].format).dwRBitMask
12763 && dib.dsBitfields[1] == U3(test_data[i].format).dwGBitMask
12764 && dib.dsBitfields[2] == U4(test_data[i].format).dwBBitMask)
12765 || broken(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2]),
12766 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
12767 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
12769 else
12771 ok(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2],
12772 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
12773 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
12775 ok(!dib.dshSection, "Got unexpected section %p for format %s.\n", dib.dshSection, test_data[i].name);
12776 ok(!dib.dsOffset, "Got unexpected offset %u for format %s.\n", dib.dsOffset, test_data[i].name);
12778 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12779 ok(hr == DD_OK, "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12781 else
12783 ok(!dc, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
12786 IDirectDrawSurface7_Release(surface);
12788 if (FAILED(hr))
12789 continue;
12791 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
12792 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_TEXTUREMANAGE;
12793 if (FAILED(hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
12795 skip("Failed to create cube texture for format %s (hr %#x), skipping tests.\n", test_data[i].name, hr);
12796 continue;
12799 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &surface2);
12800 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
12801 hr = IDirectDrawSurface7_GetAttachedSurface(surface2, &caps, &tmp);
12802 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
12803 IDirectDrawSurface7_Release(surface2);
12804 hr = IDirectDrawSurface7_GetAttachedSurface(tmp, &caps, &surface2);
12805 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
12806 IDirectDrawSurface7_Release(tmp);
12808 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12809 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12810 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12811 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12812 hr = IDirectDrawSurface7_GetDC(surface2, &dc);
12813 ok(SUCCEEDED(hr), "Failed to get DC 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_GetDC(surface, &dc);
12818 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12819 dc2 = (void *)0x1234;
12820 hr = IDirectDrawSurface7_GetDC(surface, &dc2);
12821 ok(hr == DDERR_DCALREADYCREATED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12822 ok(dc2 == (void *)0x1234, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
12823 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12824 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12825 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12826 ok(hr == DDERR_NODC, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12828 map_desc.dwSize = sizeof(map_desc);
12829 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12830 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12831 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12832 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12833 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12834 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12835 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12836 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12838 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12839 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12840 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12841 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12842 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12843 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12845 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12846 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12847 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12848 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12849 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12850 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12851 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12852 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12854 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12855 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12856 hr = IDirectDrawSurface7_GetDC(surface2, &dc2);
12857 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12858 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc2);
12859 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12860 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12861 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12863 hr = IDirectDrawSurface7_GetDC(surface2, &dc);
12864 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12865 hr = IDirectDrawSurface7_GetDC(surface, &dc2);
12866 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12867 hr = IDirectDrawSurface7_ReleaseDC(surface, dc2);
12868 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12869 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc);
12870 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12872 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12873 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12874 hr = IDirectDrawSurface7_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12875 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12876 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
12877 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12878 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12879 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12881 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12882 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12883 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12884 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12885 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12886 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12887 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12888 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12890 hr = IDirectDrawSurface7_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12891 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12892 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12893 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12894 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12895 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12896 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
12897 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12899 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12900 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12901 hr = IDirectDrawSurface7_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12902 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12903 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
12904 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12905 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12906 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12908 hr = IDirectDrawSurface7_GetDC(surface2, &dc);
12909 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12910 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
12911 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
12912 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12913 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
12914 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc);
12915 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12917 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12918 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12919 hr = IDirectDrawSurface7_GetDC(surface2, &dc);
12920 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12921 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12922 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12923 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc);
12924 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12925 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12926 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12928 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
12929 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12930 hr = IDirectDrawSurface7_GetDC(surface, &dc);
12931 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
12932 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
12933 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12934 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
12935 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
12936 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
12937 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
12939 IDirectDrawSurface7_Release(surface2);
12940 IDirectDrawSurface7_Release(surface);
12943 IDirectDraw7_Release(ddraw);
12944 DestroyWindow(window);
12947 static void test_draw_primitive(void)
12949 static WORD indices[] = {0, 1, 2, 3};
12950 static struct vec3 quad[] =
12952 {-1.0f, -1.0f, 0.0f},
12953 {-1.0f, 1.0f, 0.0f},
12954 { 1.0f, -1.0f, 0.0f},
12955 { 1.0f, 1.0f, 0.0f},
12957 D3DDRAWPRIMITIVESTRIDEDDATA strided;
12958 D3DVERTEXBUFFERDESC vb_desc;
12959 IDirect3DVertexBuffer7 *vb;
12960 IDirect3DDevice7 *device;
12961 IDirect3D7 *d3d;
12962 IDirectDraw7 *ddraw;
12963 ULONG refcount;
12964 HWND window;
12965 HRESULT hr;
12966 void *data;
12968 window = create_window();
12969 if (!(device = create_device(window, DDSCL_NORMAL)))
12971 skip("Failed to create a 3D device, skipping test.\n");
12972 DestroyWindow(window);
12973 return;
12976 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
12977 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
12978 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
12979 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
12981 memset(&vb_desc, 0, sizeof(vb_desc));
12982 vb_desc.dwSize = sizeof(vb_desc);
12983 vb_desc.dwFVF = D3DFVF_XYZ;
12984 vb_desc.dwNumVertices = 4;
12985 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &vb, 0);
12986 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
12988 IDirect3D7_Release(d3d);
12990 memset(&strided, 0, sizeof(strided));
12992 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, NULL, 0, 0);
12993 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12994 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device,
12995 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, NULL, 0, 0);
12996 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12997 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, NULL, 0, 0);
12998 todo_wine ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
12999 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, NULL, 0, 0);
13000 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13001 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, 0);
13002 /* r200 rejects 0 vertices */
13003 ok(SUCCEEDED(hr) || broken(ddraw_is_amd(ddraw) && hr == E_FAIL), "Failed to draw, hr %#x.\n", hr);
13004 hr = IDirect3DDevice7_DrawPrimitiveStrided(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, 0);
13005 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13006 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, 0);
13007 ok(SUCCEEDED(hr) || broken(ddraw_is_amd(ddraw) && hr == E_FAIL), "Failed to draw, hr %#x.\n", hr);
13009 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, indices, 4, 0);
13010 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13011 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device,
13012 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, indices, 4, 0);
13013 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13014 /* Interestingly r200 rejects this, but not the call with a NULL index buffer and 0 indices. */
13015 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, indices, 4, 0);
13016 ok(SUCCEEDED(hr) || broken(ddraw_is_amd(ddraw) && hr == E_FAIL), "Failed to draw, hr %#x.\n", hr);
13018 strided.position.lpvData = quad;
13019 strided.position.dwStride = sizeof(*quad);
13020 hr = IDirect3DVertexBuffer7_Lock(vb, 0, &data, NULL);
13021 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
13022 memcpy(data, quad, sizeof(quad));
13023 hr = IDirect3DVertexBuffer7_Unlock(vb);
13024 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
13026 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, NULL, 0, 0);
13027 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13028 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device,
13029 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, NULL, 0, 0);
13030 /* r200 again fails this, this time with E_OUTOFMEMORY. */
13031 ok(SUCCEEDED(hr) || broken(ddraw_is_amd(ddraw) && hr == E_OUTOFMEMORY), "Failed to draw, hr %#x.\n", hr);
13032 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, NULL, 0, 0);
13033 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13034 /* Now this draw should work, but r200 rejects it too - presumably earlier tests broke
13035 * driver internal state. */
13036 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
13037 ok(SUCCEEDED(hr) || broken(ddraw_is_amd(ddraw) && hr == E_FAIL), "Failed to draw, hr %#x.\n", hr);
13038 hr = IDirect3DDevice7_DrawPrimitiveStrided(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, 0);
13039 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13040 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, 0);
13041 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13043 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, indices, 4, 0);
13044 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13045 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device,
13046 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, indices, 4, 0);
13047 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13048 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, indices, 4, 0);
13049 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13051 IDirect3DVertexBuffer7_Release(vb);
13052 IDirectDraw7_Release(ddraw);
13053 refcount = IDirect3DDevice7_Release(device);
13054 ok(!refcount, "Device has %u references left.\n", refcount);
13055 DestroyWindow(window);
13058 static void test_edge_antialiasing_blending(void)
13060 IDirectDrawSurface7 *offscreen;
13061 DDSURFACEDESC2 surface_desc;
13062 D3DDEVICEDESC7 device_desc;
13063 IDirect3DDevice7 *device;
13064 IDirectDraw7 *ddraw;
13065 IDirect3D7 *d3d;
13066 ULONG refcount;
13067 D3DCOLOR color;
13068 HWND window;
13069 HRESULT hr;
13071 static D3DMATRIX mat =
13073 1.0f, 0.0f, 0.0f, 0.0f,
13074 0.0f, 1.0f, 0.0f, 0.0f,
13075 0.0f, 0.0f, 1.0f, 0.0f,
13076 0.0f, 0.0f, 0.0f, 1.0f,
13078 static struct
13080 struct vec3 position;
13081 DWORD diffuse;
13083 green_quad[] =
13085 {{-1.0f, -1.0f, 0.1f}, 0x7f00ff00},
13086 {{-1.0f, 1.0f, 0.1f}, 0x7f00ff00},
13087 {{ 1.0f, -1.0f, 0.1f}, 0x7f00ff00},
13088 {{ 1.0f, 1.0f, 0.1f}, 0x7f00ff00},
13090 static struct
13092 struct vec3 position;
13093 DWORD diffuse;
13095 red_quad[] =
13097 {{-1.0f, -1.0f, 0.1f}, 0xccff0000},
13098 {{-1.0f, 1.0f, 0.1f}, 0xccff0000},
13099 {{ 1.0f, -1.0f, 0.1f}, 0xccff0000},
13100 {{ 1.0f, 1.0f, 0.1f}, 0xccff0000},
13103 window = create_window();
13104 if (!(device = create_device(window, DDSCL_NORMAL)))
13106 skip("Failed to create a 3D device.\n");
13107 DestroyWindow(window);
13108 return;
13111 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
13112 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
13113 trace("Line edge antialiasing support: %#x.\n",
13114 device_desc.dpcLineCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
13115 trace("Triangle edge antialiasing support: %#x.\n",
13116 device_desc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
13118 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
13119 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
13120 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
13121 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
13122 IDirect3D7_Release(d3d);
13124 memset(&surface_desc, 0, sizeof(surface_desc));
13125 surface_desc.dwSize = sizeof(surface_desc);
13126 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
13127 surface_desc.dwWidth = 640;
13128 surface_desc.dwHeight = 480;
13129 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
13130 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
13131 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
13132 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
13133 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
13134 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
13135 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
13136 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
13137 ok(hr == D3D_OK, "Creating the offscreen render target failed, hr %#x.\n", hr);
13139 hr = IDirect3DDevice7_SetRenderTarget(device, offscreen, 0);
13140 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
13142 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
13143 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
13144 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
13145 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
13146 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
13147 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
13148 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
13149 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
13150 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
13151 ok(SUCCEEDED(hr), "Failed to disable Z test, hr %#x.\n", hr);
13152 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
13153 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
13154 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
13155 ok(SUCCEEDED(hr), "Failed to disable stencil test, hr %#x.\n", hr);
13156 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
13157 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
13158 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
13159 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
13161 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
13162 ok(SUCCEEDED(hr), "Failed to enable blending, hr %#x.\n", hr);
13163 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
13164 ok(SUCCEEDED(hr), "Failed to set src blend, hr %#x.\n", hr);
13165 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_DESTALPHA);
13166 ok(SUCCEEDED(hr), "Failed to set dest blend, hr %#x.\n", hr);
13168 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
13169 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
13170 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
13171 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
13172 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
13173 ok(SUCCEEDED(hr), "Failed to set alpha op, hr %#x.\n", hr);
13174 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
13175 ok(SUCCEEDED(hr), "Failed to set alpha arg, hr %#x.\n", hr);
13177 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
13178 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13179 hr = IDirect3DDevice7_BeginScene(device);
13180 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
13181 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
13182 green_quad, 4, 0);
13183 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13184 hr = IDirect3DDevice7_EndScene(device);
13185 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
13186 color = get_surface_color(offscreen, 320, 240);
13187 ok(compare_color(color, 0x00cc7f00, 1), "Got unexpected color 0x%08x.\n", color);
13189 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
13190 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13191 hr = IDirect3DDevice7_BeginScene(device);
13192 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
13193 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
13194 red_quad, 4, 0);
13195 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13196 hr = IDirect3DDevice7_EndScene(device);
13197 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
13198 color = get_surface_color(offscreen, 320, 240);
13199 ok(compare_color(color, 0x00cc7f00, 1), "Got unexpected color 0x%08x.\n", color);
13201 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
13202 ok(SUCCEEDED(hr), "Failed to disable blending, hr %#x.\n", hr);
13204 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
13205 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13206 hr = IDirect3DDevice7_BeginScene(device);
13207 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
13208 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
13209 green_quad, 4, 0);
13210 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13211 hr = IDirect3DDevice7_EndScene(device);
13212 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
13213 color = get_surface_color(offscreen, 320, 240);
13214 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
13216 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
13217 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13218 hr = IDirect3DDevice7_BeginScene(device);
13219 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
13220 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
13221 red_quad, 4, 0);
13222 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13223 hr = IDirect3DDevice7_EndScene(device);
13224 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
13225 color = get_surface_color(offscreen, 320, 240);
13226 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
13228 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_EDGEANTIALIAS, TRUE);
13229 ok(SUCCEEDED(hr), "Failed to enable edge antialiasing, hr %#x.\n", hr);
13231 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
13232 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13233 hr = IDirect3DDevice7_BeginScene(device);
13234 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
13235 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
13236 green_quad, 4, 0);
13237 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13238 hr = IDirect3DDevice7_EndScene(device);
13239 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
13240 color = get_surface_color(offscreen, 320, 240);
13241 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
13243 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
13244 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13245 hr = IDirect3DDevice7_BeginScene(device);
13246 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
13247 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
13248 red_quad, 4, 0);
13249 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13250 hr = IDirect3DDevice7_EndScene(device);
13251 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
13252 color = get_surface_color(offscreen, 320, 240);
13253 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
13255 IDirectDrawSurface7_Release(offscreen);
13256 IDirectDraw7_Release(ddraw);
13257 refcount = IDirect3DDevice7_Release(device);
13258 ok(!refcount, "Device has %u references left.\n", refcount);
13259 DestroyWindow(window);
13262 static void test_display_mode_surface_pixel_format(void)
13264 unsigned int width, height, bpp;
13265 IDirectDrawSurface7 *surface;
13266 DDSURFACEDESC2 surface_desc;
13267 IDirectDraw7 *ddraw;
13268 ULONG refcount;
13269 HWND window;
13270 HRESULT hr;
13272 if (!(ddraw = create_ddraw()))
13274 skip("Failed to create ddraw.\n");
13275 return;
13278 surface_desc.dwSize = sizeof(surface_desc);
13279 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
13280 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr);
13281 width = surface_desc.dwWidth;
13282 height = surface_desc.dwHeight;
13284 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
13285 0, 0, width, height, NULL, NULL, NULL, NULL);
13286 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
13287 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13289 bpp = 0;
13290 if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 16, 0, 0)))
13291 bpp = 16;
13292 if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 24, 0, 0)))
13293 bpp = 24;
13294 if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
13295 bpp = 32;
13296 ok(bpp, "Set display mode failed.\n");
13298 surface_desc.dwSize = sizeof(surface_desc);
13299 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
13300 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr);
13301 ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width);
13302 ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height);
13303 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
13304 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
13306 memset(&surface_desc, 0, sizeof(surface_desc));
13307 surface_desc.dwSize = sizeof(surface_desc);
13308 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
13309 U5(surface_desc).dwBackBufferCount = 1;
13310 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE;
13311 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
13312 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
13313 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
13314 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
13315 ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width);
13316 ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height);
13317 ok(U4(surface_desc).ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n",
13318 U4(surface_desc).ddpfPixelFormat.dwFlags);
13319 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
13320 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
13321 IDirectDrawSurface7_Release(surface);
13323 memset(&surface_desc, 0, sizeof(surface_desc));
13324 surface_desc.dwSize = sizeof(surface_desc);
13325 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
13326 surface_desc.dwWidth = width;
13327 surface_desc.dwHeight = height;
13328 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13329 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
13330 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
13331 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
13332 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
13333 ok(U4(surface_desc).ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n",
13334 U4(surface_desc).ddpfPixelFormat.dwFlags);
13335 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
13336 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
13337 IDirectDrawSurface7_Release(surface);
13339 refcount = IDirectDraw7_Release(ddraw);
13340 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
13341 DestroyWindow(window);
13344 static void test_surface_desc_size(void)
13346 union
13348 DWORD dwSize;
13349 DDSURFACEDESC desc1;
13350 DDSURFACEDESC2 desc2;
13351 BYTE blob[1024];
13352 } desc;
13353 IDirectDrawSurface7 *surface7;
13354 IDirectDrawSurface3 *surface3;
13355 IDirectDrawSurface *surface;
13356 DDSURFACEDESC2 surface_desc;
13357 HRESULT expected_hr, hr;
13358 IDirectDraw7 *ddraw;
13359 unsigned int i, j;
13360 ULONG refcount;
13362 static const struct
13364 unsigned int caps;
13365 const char *name;
13367 surface_caps[] =
13369 {DDSCAPS_OFFSCREENPLAIN, "offscreenplain"},
13370 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, "systemmemory texture"},
13371 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, "videomemory texture"},
13373 static const unsigned int desc_sizes[] =
13375 sizeof(DDSURFACEDESC),
13376 sizeof(DDSURFACEDESC2),
13377 sizeof(DDSURFACEDESC) + 1,
13378 sizeof(DDSURFACEDESC2) + 1,
13379 2 * sizeof(DDSURFACEDESC),
13380 2 * sizeof(DDSURFACEDESC2),
13381 sizeof(DDSURFACEDESC) - 1,
13382 sizeof(DDSURFACEDESC2) - 1,
13383 sizeof(DDSURFACEDESC) / 2,
13384 sizeof(DDSURFACEDESC2) / 2,
13388 sizeof(desc) / 2,
13389 sizeof(desc) - 100,
13392 if (!(ddraw = create_ddraw()))
13394 skip("Failed to create ddraw.\n");
13395 return;
13397 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
13398 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13400 for (i = 0; i < ARRAY_SIZE(surface_caps); ++i)
13402 memset(&surface_desc, 0, sizeof(surface_desc));
13403 surface_desc.dwSize = sizeof(surface_desc);
13404 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
13405 surface_desc.ddsCaps.dwCaps = surface_caps[i].caps;
13406 surface_desc.dwHeight = 128;
13407 surface_desc.dwWidth = 128;
13408 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface7, NULL)))
13410 skip("Failed to create surface, type %s.\n", surface_caps[i].name);
13411 continue;
13413 hr = IDirectDrawSurface_QueryInterface(surface7, &IID_IDirectDrawSurface, (void **)&surface);
13414 ok(hr == DD_OK, "Failed to query IDirectDrawSurface, hr %#x, type %s.\n", hr, surface_caps[i].name);
13415 hr = IDirectDrawSurface_QueryInterface(surface7, &IID_IDirectDrawSurface3, (void **)&surface3);
13416 ok(hr == DD_OK, "Failed to query IDirectDrawSurface3, hr %#x, type %s.\n", hr, surface_caps[i].name);
13418 /* GetSurfaceDesc() */
13419 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
13421 memset(&desc, 0, sizeof(desc));
13422 desc.dwSize = desc_sizes[j];
13423 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC) ? DD_OK : DDERR_INVALIDPARAMS;
13424 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &desc.desc1);
13425 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13426 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13428 memset(&desc, 0, sizeof(desc));
13429 desc.dwSize = desc_sizes[j];
13430 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC) ? DD_OK : DDERR_INVALIDPARAMS;
13431 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &desc.desc1);
13432 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13433 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13435 memset(&desc, 0, sizeof(desc));
13436 desc.dwSize = desc_sizes[j];
13437 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC2) ? DD_OK : DDERR_INVALIDPARAMS;
13438 hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &desc.desc2);
13439 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13440 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13443 /* Lock() */
13444 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
13446 const BOOL ignore_size = surface_caps[i].caps & DDSCAPS_TEXTURE
13447 && !(surface_caps[i].caps & DDSCAPS_VIDEOMEMORY);
13448 const BOOL valid_size = desc_sizes[j] == sizeof(DDSURFACEDESC)
13449 || desc_sizes[j] == sizeof(DDSURFACEDESC2);
13450 DWORD expected_texture_stage;
13452 memset(&desc, 0, sizeof(desc));
13453 desc.dwSize = desc_sizes[j];
13454 desc.desc2.dwTextureStage = 0xdeadbeef;
13455 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
13456 hr = IDirectDrawSurface_Lock(surface, NULL, &desc.desc1, 0, 0);
13457 expected_hr = ignore_size || valid_size ? DD_OK : DDERR_INVALIDPARAMS;
13458 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13459 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13460 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
13461 desc_sizes[j], desc.dwSize, surface_caps[i].name);
13462 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
13463 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
13464 if (SUCCEEDED(hr))
13466 ok(desc.desc1.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
13467 desc.desc1.dwWidth, desc_sizes[j], surface_caps[i].name);
13468 ok(desc.desc1.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
13469 desc.desc1.dwHeight, desc_sizes[j], surface_caps[i].name);
13470 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
13471 todo_wine_if(!expected_texture_stage)
13472 ok(desc.desc2.dwTextureStage == expected_texture_stage,
13473 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
13474 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
13475 IDirectDrawSurface_Unlock(surface, NULL);
13478 memset(&desc, 0, sizeof(desc));
13479 desc.dwSize = desc_sizes[j];
13480 desc.desc2.dwTextureStage = 0xdeadbeef;
13481 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
13482 hr = IDirectDrawSurface3_Lock(surface3, NULL, &desc.desc1, 0, 0);
13483 expected_hr = ignore_size || valid_size ? DD_OK : DDERR_INVALIDPARAMS;
13484 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13485 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13486 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
13487 desc_sizes[j], desc.dwSize, surface_caps[i].name);
13488 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
13489 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
13490 if (SUCCEEDED(hr))
13492 ok(desc.desc1.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
13493 desc.desc1.dwWidth, desc_sizes[j], surface_caps[i].name);
13494 ok(desc.desc1.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
13495 desc.desc1.dwHeight, desc_sizes[j], surface_caps[i].name);
13496 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
13497 todo_wine_if(!expected_texture_stage)
13498 ok(desc.desc2.dwTextureStage == expected_texture_stage,
13499 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
13500 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
13501 IDirectDrawSurface3_Unlock(surface3, NULL);
13504 memset(&desc, 0, sizeof(desc));
13505 desc.dwSize = desc_sizes[j];
13506 desc.desc2.dwTextureStage = 0xdeadbeef;
13507 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
13508 hr = IDirectDrawSurface7_Lock(surface7, NULL, &desc.desc2, 0, 0);
13509 expected_hr = ignore_size || valid_size ? DD_OK : DDERR_INVALIDPARAMS;
13510 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
13511 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
13512 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
13513 desc_sizes[j], desc.dwSize, surface_caps[i].name);
13514 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
13515 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
13516 if (SUCCEEDED(hr))
13518 ok(desc.desc2.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
13519 desc.desc2.dwWidth, desc_sizes[j], surface_caps[i].name);
13520 ok(desc.desc2.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
13521 desc.desc2.dwHeight, desc_sizes[j], surface_caps[i].name);
13522 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
13523 ok(desc.desc2.dwTextureStage == expected_texture_stage,
13524 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
13525 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
13526 IDirectDrawSurface7_Unlock(surface7, NULL);
13530 IDirectDrawSurface7_Release(surface7);
13531 IDirectDrawSurface3_Release(surface3);
13532 IDirectDrawSurface_Release(surface);
13535 /* GetDisplayMode() */
13536 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
13538 memset(&desc, 0xcc, sizeof(desc));
13539 desc.dwSize = desc_sizes[j];
13540 expected_hr = (desc.dwSize == sizeof(DDSURFACEDESC) || desc.dwSize == sizeof(DDSURFACEDESC2))
13541 ? DD_OK : DDERR_INVALIDPARAMS;
13542 hr = IDirectDraw7_GetDisplayMode(ddraw, &desc.desc2);
13543 ok(hr == expected_hr, "Got hr %#x, expected %#x, size %u.\n", hr, expected_hr, desc_sizes[j]);
13544 if (SUCCEEDED(hr))
13546 ok(desc.dwSize == sizeof(DDSURFACEDESC2), "Wrong size %u for %u.\n", desc.dwSize, desc_sizes[j]);
13547 ok(desc.blob[desc_sizes[j]] == 0xcc, "Overflow for size %u.\n", desc_sizes[j]);
13548 ok(desc.blob[desc_sizes[j] - 1] != 0xcc, "Struct not cleared for size %u.\n", desc_sizes[j]);
13552 refcount = IDirectDraw7_Release(ddraw);
13553 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
13556 static void test_get_surface_from_dc(void)
13558 IDirectDrawSurface *surface1, *tmp1;
13559 IDirectDrawSurface7 *surface, *tmp;
13560 DDSURFACEDESC2 surface_desc;
13561 IDirectDraw7 *ddraw;
13562 HDC dc, device_dc;
13563 ULONG refcount;
13564 HWND window;
13565 HRESULT hr;
13566 DWORD ret;
13568 window = create_window();
13569 ddraw = create_ddraw();
13570 ok(!!ddraw, "Failed to create a ddraw object.\n");
13571 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
13572 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13574 memset(&surface_desc, 0, sizeof(surface_desc));
13575 surface_desc.dwSize = sizeof(surface_desc);
13576 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
13577 surface_desc.dwWidth = 64;
13578 surface_desc.dwHeight = 64;
13579 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13581 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
13582 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13583 hr = IDirectDrawSurface7_QueryInterface(surface, &IID_IDirectDrawSurface, (void **)&surface1);
13584 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
13586 refcount = get_refcount((IUnknown *)surface1);
13587 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
13588 refcount = get_refcount((IUnknown *)surface);
13589 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
13591 hr = IDirectDrawSurface7_GetDC(surface, &dc);
13592 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
13594 tmp1 = (void *)0xdeadbeef;
13595 device_dc = (void *)0xdeadbeef;
13596 hr = GetSurfaceFromDC(NULL, &tmp1, &device_dc);
13597 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
13598 ok(!tmp1, "Got unexpected surface %p.\n", tmp1);
13599 ok(!device_dc, "Got unexpected device_dc %p.\n", device_dc);
13601 device_dc = (void *)0xdeadbeef;
13602 hr = GetSurfaceFromDC(dc, NULL, &device_dc);
13603 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
13604 ok(device_dc == (void *)0xdeadbeef, "Got unexpected device_dc %p.\n", device_dc);
13606 tmp1 = (void *)0xdeadbeef;
13607 hr = GetSurfaceFromDC(dc, &tmp1, NULL);
13608 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
13609 ok(!tmp1, "Got unexpected surface %p.\n", tmp1);
13611 hr = GetSurfaceFromDC(dc, &tmp1, &device_dc);
13612 ok(SUCCEEDED(hr), "GetSurfaceFromDC failed, hr %#x.\n", hr);
13613 ok(tmp1 == surface1, "Got unexpected surface %p, expected %p.\n", tmp1, surface1);
13614 IDirectDrawSurface_Release(tmp1);
13616 ret = GetObjectType(device_dc);
13617 todo_wine ok(ret == OBJ_DC, "Got unexpected object type %#x.\n", ret);
13618 ret = GetDeviceCaps(device_dc, TECHNOLOGY);
13619 todo_wine ok(ret == DT_RASDISPLAY, "Got unexpected technology %#x.\n", ret);
13621 hr = IDirectDraw7_GetSurfaceFromDC(ddraw, dc, NULL);
13622 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
13624 hr = IDirectDraw7_GetSurfaceFromDC(ddraw, dc, &tmp);
13625 ok(SUCCEEDED(hr), "GetSurfaceFromDC failed, hr %#x.\n", hr);
13626 ok(tmp == surface, "Got unexpected surface %p, expected %p.\n", tmp, surface);
13628 refcount = get_refcount((IUnknown *)surface1);
13629 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
13630 refcount = get_refcount((IUnknown *)surface);
13631 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
13633 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
13634 ok(SUCCEEDED(hr), "ReleaseDC failed, hr %#x.\n", hr);
13636 IDirectDrawSurface_Release(tmp);
13638 dc = CreateCompatibleDC(NULL);
13639 ok(!!dc, "CreateCompatibleDC failed.\n");
13641 tmp1 = (void *)0xdeadbeef;
13642 device_dc = (void *)0xdeadbeef;
13643 hr = GetSurfaceFromDC(dc, &tmp1, &device_dc);
13644 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
13645 ok(!tmp1, "Got unexpected surface %p.\n", tmp1);
13646 ok(!device_dc, "Got unexpected device_dc %p.\n", device_dc);
13648 tmp = (void *)0xdeadbeef;
13649 hr = IDirectDraw7_GetSurfaceFromDC(ddraw, dc, &tmp);
13650 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
13651 ok(!tmp, "Got unexpected surface %p.\n", tmp);
13653 ok(DeleteDC(dc), "DeleteDC failed.\n");
13655 tmp = (void *)0xdeadbeef;
13656 hr = IDirectDraw7_GetSurfaceFromDC(ddraw, NULL, &tmp);
13657 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
13658 ok(!tmp, "Got unexpected surface %p.\n", tmp);
13660 IDirectDrawSurface7_Release(surface);
13661 IDirectDrawSurface_Release(surface1);
13662 IDirectDraw7_Release(ddraw);
13663 DestroyWindow(window);
13666 static void test_ck_operation(void)
13668 IDirectDrawSurface7 *src, *dst;
13669 IDirectDrawSurface *src1, *dst1;
13670 DDSURFACEDESC2 surface_desc;
13671 IDirectDraw7 *ddraw;
13672 ULONG refcount;
13673 HWND window;
13674 HRESULT hr;
13675 D3DCOLOR *color;
13676 unsigned int i;
13677 DDCOLORKEY ckey;
13678 DDBLTFX fx;
13680 window = create_window();
13681 ddraw = create_ddraw();
13682 ok(!!ddraw, "Failed to create a ddraw object.\n");
13683 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
13684 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13686 memset(&surface_desc, 0, sizeof(surface_desc));
13687 surface_desc.dwSize = sizeof(surface_desc);
13688 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
13689 surface_desc.dwWidth = 4;
13690 surface_desc.dwHeight = 1;
13691 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13692 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
13693 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
13694 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
13695 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
13696 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
13697 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
13698 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13700 surface_desc.dwFlags |= DDSD_CKSRCBLT;
13701 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff00ff;
13702 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff00ff;
13703 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
13704 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13706 hr = IDirectDrawSurface7_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13707 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13708 ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n");
13709 color = surface_desc.lpSurface;
13710 color[0] = 0x77010203;
13711 color[1] = 0x00010203;
13712 color[2] = 0x77ff00ff;
13713 color[3] = 0x00ff00ff;
13714 hr = IDirectDrawSurface7_Unlock(src, NULL);
13715 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13717 for (i = 0; i < 2; ++i)
13719 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13720 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13721 color = surface_desc.lpSurface;
13722 color[0] = 0xcccccccc;
13723 color[1] = 0xcccccccc;
13724 color[2] = 0xcccccccc;
13725 color[3] = 0xcccccccc;
13726 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13727 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13729 if (i)
13731 hr = IDirectDrawSurface7_BltFast(dst, 0, 0, src, NULL, DDBLTFAST_SRCCOLORKEY);
13732 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13734 else
13736 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, NULL);
13737 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13740 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT | DDLOCK_READONLY, NULL);
13741 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13742 ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n");
13743 color = surface_desc.lpSurface;
13744 /* Different behavior on some drivers / windows versions. Some versions ignore the X channel when
13745 * color keying, but copy it to the destination surface. Others (sysmem surfaces) apply it for
13746 * color keying, but do not copy it into the destination surface. Nvidia neither uses it for
13747 * color keying nor copies it. */
13748 ok((color[0] == 0x77010203 && color[1] == 0x00010203
13749 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* AMD, Wine */
13750 || broken(color[0] == 0x00010203 && color[1] == 0x00010203
13751 && color[2] == 0x00ff00ff && color[3] == 0xcccccccc) /* Sysmem surfaces? */
13752 || broken(color[0] == 0x00010203 && color[1] == 0x00010203
13753 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Nvidia */
13754 || broken(color[0] == 0xff010203 && color[1] == 0xff010203
13755 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Testbot */,
13756 "Destination data after blitting is %08x %08x %08x %08x, i=%u.\n",
13757 color[0], color[1], color[2], color[3], i);
13758 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13759 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13762 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13763 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
13764 ok(ckey.dwColorSpaceLowValue == 0x00ff00ff && ckey.dwColorSpaceHighValue == 0x00ff00ff,
13765 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13767 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
13768 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13769 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13771 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
13772 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13773 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
13774 ok(ckey.dwColorSpaceLowValue == 0x0000ff00 && ckey.dwColorSpaceHighValue == 0x0000ff00,
13775 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13777 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0;
13778 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0;
13779 hr = IDirectDrawSurface7_GetSurfaceDesc(src, &surface_desc);
13780 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
13781 ok(surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue == 0x0000ff00
13782 && surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue == 0x0000ff00,
13783 "Got unexpected color key low=%08x high=%08x.\n", surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue,
13784 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue);
13786 /* Test SetColorKey with dwColorSpaceHighValue < dwColorSpaceLowValue */
13787 ckey.dwColorSpaceLowValue = 0x000000ff;
13788 ckey.dwColorSpaceHighValue = 0x00000000;
13789 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13790 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13792 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
13793 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13794 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
13795 ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff,
13796 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13798 ckey.dwColorSpaceLowValue = 0x000000ff;
13799 ckey.dwColorSpaceHighValue = 0x00000001;
13800 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13801 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13803 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
13804 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13805 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
13806 ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff,
13807 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13809 ckey.dwColorSpaceLowValue = 0x000000fe;
13810 ckey.dwColorSpaceHighValue = 0x000000fd;
13811 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13812 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13814 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
13815 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
13816 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
13817 ok(ckey.dwColorSpaceLowValue == 0x000000fe && ckey.dwColorSpaceHighValue == 0x000000fe,
13818 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
13820 IDirectDrawSurface7_Release(src);
13821 IDirectDrawSurface7_Release(dst);
13823 /* Test source and destination keys and where they are read from. Use a surface with alpha
13824 * to avoid driver-dependent content in the X channel. */
13825 memset(&surface_desc, 0, sizeof(surface_desc));
13826 surface_desc.dwSize = sizeof(surface_desc);
13827 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
13828 surface_desc.dwWidth = 6;
13829 surface_desc.dwHeight = 1;
13830 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13831 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
13832 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
13833 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
13834 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
13835 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
13836 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
13837 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
13838 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13839 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
13840 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13842 ckey.dwColorSpaceLowValue = 0x0000ff00;
13843 ckey.dwColorSpaceHighValue = 0x0000ff00;
13844 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
13845 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13846 ckey.dwColorSpaceLowValue = 0x00ff0000;
13847 ckey.dwColorSpaceHighValue = 0x00ff0000;
13848 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_DESTBLT, &ckey);
13849 ok(SUCCEEDED(hr) || hr == DDERR_NOCOLORKEYHW, "Failed to set color key, hr %#x.\n", hr);
13850 if (FAILED(hr))
13852 /* Nvidia reject dest keys, AMD allows them. This applies to vidmem and sysmem surfaces. */
13853 skip("Failed to set destination color key, skipping related tests.\n");
13854 goto done;
13857 ckey.dwColorSpaceLowValue = 0x000000ff;
13858 ckey.dwColorSpaceHighValue = 0x000000ff;
13859 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
13860 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13861 ckey.dwColorSpaceLowValue = 0x000000aa;
13862 ckey.dwColorSpaceHighValue = 0x000000aa;
13863 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_DESTBLT, &ckey);
13864 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
13866 memset(&fx, 0, sizeof(fx));
13867 fx.dwSize = sizeof(fx);
13868 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x00110000;
13869 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x00110000;
13870 fx.ddckDestColorkey.dwColorSpaceHighValue = 0x00001100;
13871 fx.ddckDestColorkey.dwColorSpaceLowValue = 0x00001100;
13873 hr = IDirectDrawSurface7_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13874 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13875 color = surface_desc.lpSurface;
13876 color[0] = 0x000000ff; /* Applies to src blt key in src surface. */
13877 color[1] = 0x000000aa; /* Applies to dst blt key in src surface. */
13878 color[2] = 0x00ff0000; /* Dst color key in dst surface. */
13879 color[3] = 0x0000ff00; /* Src color key in dst surface. */
13880 color[4] = 0x00001100; /* Src color key in ddbltfx. */
13881 color[5] = 0x00110000; /* Dst color key in ddbltfx. */
13882 hr = IDirectDrawSurface7_Unlock(src, NULL);
13883 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13885 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13886 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13887 color = surface_desc.lpSurface;
13888 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
13889 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13890 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13892 /* Test a blit without keying. */
13893 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, 0, &fx);
13894 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13896 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13897 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13898 color = surface_desc.lpSurface;
13899 /* Should have copied src data unmodified to dst. */
13900 ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
13901 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
13902 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13903 color[0], color[1], color[2], color[3], color[4], color[5]);
13905 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
13906 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13907 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13909 /* Src key. */
13910 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx);
13911 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13913 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13914 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13915 color = surface_desc.lpSurface;
13916 /* Src key applied to color[0]. It is unmodified, the others are copied. */
13917 ok(color[0] == 0x55555555 && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
13918 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
13919 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13920 color[0], color[1], color[2], color[3], color[4], color[5]);
13922 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
13923 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13924 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13926 /* Src override. */
13927 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, &fx);
13928 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13930 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13931 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13932 color = surface_desc.lpSurface;
13933 /* Override key applied to color[5]. It is unmodified, the others are copied. */
13934 ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
13935 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x55555555,
13936 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13937 color[0], color[1], color[2], color[3], color[4], color[5]);
13939 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
13940 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13941 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13943 /* Src override AND src key. That is not supposed to work. */
13944 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE, &fx);
13945 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13947 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13948 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13949 color = surface_desc.lpSurface;
13950 /* Ensure the destination was not changed. */
13951 ok(color[0] == 0x55555555 && color[1] == 0x55555555 && color[2] == 0x55555555 &&
13952 color[3] == 0x55555555 && color[4] == 0x55555555 && color[5] == 0x55555555,
13953 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13954 color[0], color[1], color[2], color[3], color[4], color[5]);
13956 /* Use different dst colors for the dst key test. */
13957 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13958 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13959 color[2] = 0x00001100; /* Dest key in override. */
13960 color[3] = 0x00001100; /* Dest key in override. */
13961 color[4] = 0x000000aa; /* Dest key in src surface. */
13962 color[5] = 0x000000aa; /* Dest key in src surface. */
13963 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13964 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13966 /* Dest key blit. The key is taken from the DESTINATION surface in v7! */
13967 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
13968 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13970 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
13971 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
13972 color = surface_desc.lpSurface;
13973 /* Dst key applied to color[0,1], they are the only changed pixels. */
13974 todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 &&
13975 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
13976 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
13977 color[0], color[1], color[2], color[3], color[4], color[5]);
13979 color[0] = 0x00ff0000; /* Dest key in dst surface. */
13980 color[1] = 0x00ff0000; /* Dest key in dst surface. */
13981 color[2] = 0x00001100; /* Dest key in override. */
13982 color[3] = 0x00001100; /* Dest key in override. */
13983 color[4] = 0x000000aa; /* Dest key in src surface. */
13984 color[5] = 0x000000aa; /* Dest key in src surface. */
13985 hr = IDirectDrawSurface7_Unlock(dst, NULL);
13986 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
13988 /* What happens with a QI'd older version of the interface? It takes the key
13989 * from the source surface. */
13990 hr = IDirectDrawSurface7_QueryInterface(src, &IID_IDirectDrawSurface, (void **)&src1);
13991 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
13992 hr = IDirectDrawSurface7_QueryInterface(dst, &IID_IDirectDrawSurface, (void **)&dst1);
13993 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
13995 hr = IDirectDrawSurface_Blt(dst1, NULL, src1, NULL, DDBLT_KEYDEST, &fx);
13996 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13998 IDirectDrawSurface_Release(dst1);
13999 IDirectDrawSurface_Release(src1);
14001 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14002 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14003 color = surface_desc.lpSurface;
14004 /* Dst key applied to color[4,5], they are the only changed pixels. */
14005 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
14006 color[3] == 0x00001100 && color[4] == 0x00001100 && color[5] == 0x00110000,
14007 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14008 color[0], color[1], color[2], color[3], color[4], color[5]);
14010 color[0] = 0x00ff0000; /* Dest key in dst surface. */
14011 color[1] = 0x00ff0000; /* Dest key in dst surface. */
14012 color[2] = 0x00001100; /* Dest key in override. */
14013 color[3] = 0x00001100; /* Dest key in override. */
14014 color[4] = 0x000000aa; /* Dest key in src surface. */
14015 color[5] = 0x000000aa; /* Dest key in src surface. */
14016 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14017 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14019 /* Dest override key blit. */
14020 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, &fx);
14021 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14023 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14024 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14025 color = surface_desc.lpSurface;
14026 /* Dst key applied to color[2,3], they are the only changed pixels. */
14027 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00ff0000 &&
14028 color[3] == 0x0000ff00 && color[4] == 0x000000aa && color[5] == 0x000000aa,
14029 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14030 color[0], color[1], color[2], color[3], color[4], color[5]);
14032 color[0] = 0x00ff0000; /* Dest key in dst surface. */
14033 color[1] = 0x00ff0000; /* Dest key in dst surface. */
14034 color[2] = 0x00001100; /* Dest key in override. */
14035 color[3] = 0x00001100; /* Dest key in override. */
14036 color[4] = 0x000000aa; /* Dest key in src surface. */
14037 color[5] = 0x000000aa; /* Dest key in src surface. */
14038 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14039 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14041 /* Dest override together with surface key. Supposed to fail. */
14042 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYDESTOVERRIDE, &fx);
14043 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14045 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14046 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14047 color = surface_desc.lpSurface;
14048 /* Destination is unchanged. */
14049 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
14050 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
14051 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14052 color[0], color[1], color[2], color[3], color[4], color[5]);
14053 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14054 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14056 /* Source and destination key. This is driver dependent. New HW treats it like
14057 * DDBLT_KEYSRC. Older HW and some software renderers apply both keys. */
14058 if (0)
14060 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYSRC, &fx);
14061 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14063 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14064 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14065 color = surface_desc.lpSurface;
14066 /* Color[0] is filtered by the src key, 2-5 are filtered by the dst key, if
14067 * the driver applies it. */
14068 ok(color[0] == 0x00ff0000 && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
14069 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
14070 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14071 color[0], color[1], color[2], color[3], color[4], color[5]);
14073 color[0] = 0x00ff0000; /* Dest key in dst surface. */
14074 color[1] = 0x00ff0000; /* Dest key in dst surface. */
14075 color[2] = 0x00001100; /* Dest key in override. */
14076 color[3] = 0x00001100; /* Dest key in override. */
14077 color[4] = 0x000000aa; /* Dest key in src surface. */
14078 color[5] = 0x000000aa; /* Dest key in src surface. */
14079 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14080 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14083 /* Override keys without ddbltfx parameter fail */
14084 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, NULL);
14085 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14086 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, NULL);
14087 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14089 /* Try blitting without keys in the source surface. */
14090 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, NULL);
14091 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14092 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_DESTBLT, NULL);
14093 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14095 /* That fails now. Do not bother to check that the data is unmodified. */
14096 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx);
14097 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14099 /* Dest key blit still works, the destination surface key is used in v7. */
14100 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
14101 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14103 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14104 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14105 color = surface_desc.lpSurface;
14106 /* Dst key applied to color[0,1], they are the only changed pixels. */
14107 todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 &&
14108 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
14109 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14110 color[0], color[1], color[2], color[3], color[4], color[5]);
14111 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14112 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14114 /* Try blitting without keys in the destination surface. */
14115 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_SRCBLT, NULL);
14116 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14117 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_DESTBLT, NULL);
14118 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14120 /* This fails, as sanity would dictate. */
14121 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
14122 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14124 done:
14125 IDirectDrawSurface7_Release(src);
14126 IDirectDrawSurface7_Release(dst);
14127 refcount = IDirectDraw7_Release(ddraw);
14128 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
14129 DestroyWindow(window);
14132 static void test_vb_refcount(void)
14134 ULONG prev_d3d_refcount, prev_device_refcount;
14135 ULONG cur_d3d_refcount, cur_device_refcount;
14136 IDirect3DVertexBuffer7 *vb, *vb7;
14137 D3DVERTEXBUFFERDESC vb_desc;
14138 IDirect3DVertexBuffer *vb1;
14139 IDirect3DDevice7 *device;
14140 IDirect3D7 *d3d;
14141 ULONG refcount;
14142 IUnknown *unk;
14143 HWND window;
14144 HRESULT hr;
14146 window = create_window();
14147 if (!(device = create_device(window, DDSCL_NORMAL)))
14149 skip("Failed to create a 3D device, skipping test.\n");
14150 DestroyWindow(window);
14151 return;
14154 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
14155 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
14157 prev_d3d_refcount = get_refcount((IUnknown *)d3d);
14158 prev_device_refcount = get_refcount((IUnknown *)device);
14160 memset(&vb_desc, 0, sizeof(vb_desc));
14161 vb_desc.dwSize = sizeof(vb_desc);
14162 vb_desc.dwFVF = D3DFVF_XYZ;
14163 vb_desc.dwNumVertices = 4;
14164 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &vb, 0);
14165 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
14167 cur_d3d_refcount = get_refcount((IUnknown *)d3d);
14168 cur_device_refcount = get_refcount((IUnknown *)device);
14169 ok(cur_d3d_refcount > prev_d3d_refcount, "D3D object refcount didn't change from %u.\n", prev_d3d_refcount);
14170 ok(cur_device_refcount == prev_device_refcount, "Device refcount changed from %u to %u.\n",
14171 prev_device_refcount, cur_device_refcount);
14173 prev_d3d_refcount = cur_d3d_refcount;
14174 hr = IDirect3DVertexBuffer7_QueryInterface(vb, &IID_IDirect3DVertexBuffer7, (void **)&vb7);
14175 ok(hr == DD_OK, "Failed to query IDirect3DVertexBuffer7, hr %#x.\n", hr);
14176 cur_d3d_refcount = get_refcount((IUnknown *)d3d);
14177 ok(cur_d3d_refcount == prev_d3d_refcount, "D3D object refcount changed from %u to %u.\n",
14178 prev_d3d_refcount, cur_d3d_refcount);
14179 IDirect3DVertexBuffer7_Release(vb7);
14181 hr = IDirect3DVertexBuffer7_QueryInterface(vb, &IID_IDirect3DVertexBuffer, (void **)&vb1);
14182 ok(hr == E_NOINTERFACE, "Querying IDirect3DVertexBuffer returned unexpected hr %#x.\n", hr);
14184 hr = IDirect3DVertexBuffer_QueryInterface(vb, &IID_IUnknown, (void **)&unk);
14185 ok(hr == DD_OK, "Failed to query IUnknown, hr %#x.\n", hr);
14186 ok((IUnknown *)vb == unk,
14187 "IDirect3DVertexBuffer7 and IUnknown interface pointers don't match, %p != %p.\n", vb, unk);
14188 IUnknown_Release(unk);
14190 refcount = IDirect3DVertexBuffer7_Release(vb);
14191 ok(!refcount, "Vertex buffer has %u references left.\n", refcount);
14193 IDirect3D7_Release(d3d);
14194 refcount = IDirect3DDevice7_Release(device);
14195 ok(!refcount, "Device has %u references left.\n", refcount);
14196 DestroyWindow(window);
14199 static void test_compute_sphere_visibility(void)
14201 static D3DVALUE clip_plane[4] = {1.0f, 0.0f, 0.0f, 0.5f};
14202 static D3DMATRIX proj_1 =
14204 1.810660f, 0.000000f, 0.000000f, 0.000000f,
14205 0.000000f, 2.414213f, 0.000000f, 0.000000f,
14206 0.000000f, 0.000000f, 1.020408f, 1.000000f,
14207 0.000000f, 0.000000f, -0.102041f, 0.000000f,
14209 static D3DMATRIX proj_2 =
14211 10.0f, 0.0f, 0.0f, 0.0f,
14212 0.0f, 10.0f, 0.0f, 0.0f,
14213 0.0f, 0.0f, 10.0f, 0.0f,
14214 0.0f, 0.0f, 0.0f, 1.0f,
14216 static D3DMATRIX view_1 =
14218 1.000000f, 0.000000f, 0.000000f, 0.000000f,
14219 0.000000f, 0.768221f, -0.640185f, 0.000000f,
14220 -0.000000f, 0.640185f, 0.768221f, 0.000000f,
14221 -14.852037f, 9.857489f, 11.600972f, 1.000000f,
14223 static D3DMATRIX identity =
14225 1.0f, 0.0f, 0.0f, 0.0f,
14226 0.0f, 1.0f, 0.0f, 0.0f,
14227 0.0f, 0.0f, 1.0f, 0.0f,
14228 0.0f, 0.0f, 0.0f, 1.0f,
14230 static struct
14232 D3DMATRIX *view, *proj;
14233 unsigned int sphere_count;
14234 D3DVECTOR center[3];
14235 D3DVALUE radius[3];
14236 DWORD enable_planes;
14237 const DWORD expected[3];
14239 tests[] =
14241 {&view_1, &proj_1, 1, {{{11.461533f}, {-4.761727f}, {-1.171646f}}}, {38.252632f}, 0, {0x3f}},
14242 {&view_1, &proj_1, 3, {{{-3.515620f}, {-1.560661f}, {-12.464638f}},
14243 {{14.290396f}, {-2.981143f}, {-24.311312f}},
14244 {{1.461626f}, {-6.093709f}, {-13.901010f}}},
14245 {4.354097f, 12.500704f, 17.251318f}, 0, {0x103d, 0x3f, 0x3f}},
14246 {&identity, &proj_2, 1, {{{0.0f}, {0.0f}, {0.05f}}}, {0.04f}, 0, {0}},
14247 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.5f}}}, {0.5f}, 0, {0}},
14248 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.0f}}}, {0.0f}, 0, {0}},
14249 {&identity, &identity, 1, {{{-1.0f}, {-1.0f}, {0.5f}}}, {0.25f}, 0, {0x9}}, /* 5 */
14250 {&identity, &identity, 1, {{{-20.0f}, {0.0f}, {0.5f}}}, {3.0f}, 0, {0x103d}},
14251 {&identity, &identity, 1, {{{20.0f}, {0.0f}, {0.5f}}}, {3.0f}, 0, {0x203e}},
14252 {&identity, &identity, 1, {{{0.0f}, {-20.0f}, {0.5f}}}, {3.0f}, 0, {0x803b}},
14253 {&identity, &identity, 1, {{{0.0f}, {20.0f}, {0.5f}}}, {3.0f}, 0, {0x4037}},
14254 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {-20.0f}}}, {3.0f}, 0, {0x1001f}}, /* 10 */
14255 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {20.0f}}}, {3.0f}, 0, {0x2002f}},
14256 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.0f}}}, {5.0f}, 1, {0x7f}},
14257 {&identity, &identity, 1, {{{-0.5f}, {0.0f}, {0.0f}}}, {5.0f}, 1, {0x7f}},
14258 {&identity, &identity, 1, {{{-0.5f}, {0.0f}, {0.0f}}}, {1.0f}, 1, {0x51}},
14259 {&identity, &identity, 1, {{{-2.5f}, {0.0f}, {0.0f}}}, {1.0f}, 1, {0x41051}}, /* 15 */
14261 IDirect3DDevice7 *device;
14262 unsigned int i, j;
14263 DWORD result[3];
14264 ULONG refcount;
14265 HWND window;
14266 HRESULT hr;
14268 window = create_window();
14269 if (!(device = create_device(window, DDSCL_NORMAL)))
14271 skip("Failed to create a 3D device, skipping test.\n");
14272 DestroyWindow(window);
14273 return;
14276 hr = IDirect3DDevice7_SetClipPlane(device, 0, clip_plane);
14277 ok(SUCCEEDED(hr), "Failed to set user clip plane, hr %#x.\n", hr);
14279 IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &identity);
14281 for (i = 0; i < ARRAY_SIZE(tests); ++i)
14283 IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, tests[i].view);
14284 IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, tests[i].proj);
14286 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE,
14287 tests[i].enable_planes);
14288 ok(SUCCEEDED(hr), "Failed to enable / disable user clip planes, hr %#x.\n", hr);
14290 hr = IDirect3DDevice7_ComputeSphereVisibility(device, tests[i].center, tests[i].radius,
14291 tests[i].sphere_count, 0, result);
14292 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14294 for (j = 0; j < tests[i].sphere_count; ++j)
14295 ok(result[j] == tests[i].expected[j], "Test %u sphere %u: expected %#x, got %#x.\n",
14296 i, j, tests[i].expected[j], result[j]);
14299 refcount = IDirect3DDevice7_Release(device);
14300 ok(!refcount, "Device has %u references left.\n", refcount);
14301 DestroyWindow(window);
14304 static void test_clip_planes_limits(void)
14306 IDirect3DDevice7 *device;
14307 D3DDEVICEDESC7 caps;
14308 unsigned int i;
14309 ULONG refcount;
14310 float plane[4];
14311 HWND window;
14312 DWORD state;
14313 HRESULT hr;
14315 window = create_window();
14316 if (!(device = create_device(window, DDSCL_NORMAL)))
14318 skip("Failed to create 3D device.\n");
14319 DestroyWindow(window);
14320 return;
14323 memset(&caps, 0, sizeof(caps));
14324 hr = IDirect3DDevice7_GetCaps(device, &caps);
14325 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
14327 trace("Max user clip planes: %u.\n", caps.wMaxUserClipPlanes);
14329 for (i = 0; i < caps.wMaxUserClipPlanes; ++i)
14331 memset(plane, 0xff, sizeof(plane));
14332 hr = IDirect3DDevice7_GetClipPlane(device, i, plane);
14333 ok(hr == D3D_OK, "Failed to get clip plane %u, hr %#x.\n", i, hr);
14334 ok(!plane[0] && !plane[1] && !plane[2] && !plane[3],
14335 "Got unexpected plane %u: %.8e, %.8e, %.8e, %.8e.\n",
14336 i, plane[0], plane[1], plane[2], plane[3]);
14339 plane[0] = 2.0f;
14340 plane[1] = 8.0f;
14341 plane[2] = 5.0f;
14342 for (i = 0; i < caps.wMaxUserClipPlanes; ++i)
14344 plane[3] = i;
14345 hr = IDirect3DDevice7_SetClipPlane(device, i, plane);
14346 ok(hr == D3D_OK, "Failed to set clip plane %u, hr %#x.\n", i, hr);
14348 for (i = 0; i < caps.wMaxUserClipPlanes; ++i)
14350 memset(plane, 0xff, sizeof(plane));
14351 hr = IDirect3DDevice7_GetClipPlane(device, i, plane);
14352 ok(hr == D3D_OK, "Failed to get clip plane %u, hr %#x.\n", i, hr);
14353 ok(plane[0] == 2.0f && plane[1] == 8.0f && plane[2] == 5.0f && plane[3] == i,
14354 "Got unexpected plane %u: %.8e, %.8e, %.8e, %.8e.\n",
14355 i, plane[0], plane[1], plane[2], plane[3]);
14358 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE, 0xffffffff);
14359 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
14360 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE, &state);
14361 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
14362 ok(state == 0xffffffff, "Got unexpected state %#x.\n", state);
14363 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE, 0x80000000);
14364 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
14365 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE, &state);
14366 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
14367 ok(state == 0x80000000, "Got unexpected state %#x.\n", state);
14369 refcount = IDirect3DDevice7_Release(device);
14370 ok(!refcount, "Device has %u references left.\n", refcount);
14371 DestroyWindow(window);
14374 static void test_texture_stages_limits(void)
14376 IDirectDrawSurface7 *texture;
14377 DDSURFACEDESC2 surface_desc;
14378 IDirect3DDevice7 *device;
14379 IDirectDraw7 *ddraw;
14380 IDirect3D7 *d3d;
14381 unsigned int i;
14382 ULONG refcount;
14383 HWND window;
14384 HRESULT hr;
14386 window = create_window();
14387 if (!(device = create_device(window, DDSCL_NORMAL)))
14389 skip("Failed to create 3D device.\n");
14390 DestroyWindow(window);
14391 return;
14393 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
14394 ok(SUCCEEDED(hr), "Failed to get Direct3D interface, hr %#x.\n", hr);
14395 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
14396 ok(SUCCEEDED(hr), "Failed to get DirectDraw interface, hr %#x.\n", hr);
14397 IDirect3D7_Release(d3d);
14399 memset(&surface_desc, 0, sizeof(surface_desc));
14400 surface_desc.dwSize = sizeof(surface_desc);
14401 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
14402 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
14403 surface_desc.dwWidth = 16;
14404 surface_desc.dwHeight = 16;
14405 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
14406 ok(hr == DD_OK, "Failed to create surface, hr %#x.\n", hr);
14408 for (i = 0; i < 8; ++i)
14410 hr = IDirect3DDevice7_SetTexture(device, i, texture);
14411 ok(hr == D3D_OK, "Failed to set texture %u, hr %#x.\n", i, hr);
14412 hr = IDirect3DDevice7_SetTexture(device, i, NULL);
14413 ok(hr == D3D_OK, "Failed to set texture %u, hr %#x.\n", i, hr);
14414 hr = IDirect3DDevice7_SetTextureStageState(device, i, D3DTSS_COLOROP, D3DTOP_ADD);
14415 ok(hr == D3D_OK, "Failed to set texture stage state %u, hr %#x.\n", i, hr);
14418 IDirectDrawSurface7_Release(texture);
14419 IDirectDraw7_Release(ddraw);
14420 refcount = IDirect3DDevice7_Release(device);
14421 ok(!refcount, "Device has %u references left.\n", refcount);
14422 DestroyWindow(window);
14425 static void test_set_render_state(void)
14427 IDirect3DDevice7 *device;
14428 ULONG refcount;
14429 HWND window;
14430 DWORD state;
14431 HRESULT hr;
14433 window = create_window();
14434 if (!(device = create_device(window, DDSCL_NORMAL)))
14436 skip("Failed to create 3D device.\n");
14437 DestroyWindow(window);
14438 return;
14441 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZVISIBLE, TRUE);
14442 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14443 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZVISIBLE, FALSE);
14444 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
14446 /* States deprecated in D3D7 */
14447 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
14448 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14449 state = 0xdeadbeef;
14450 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, &state);
14451 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14452 ok(state == 0xdeadbeef, "Got unexpected render state %#x.\n", state);
14453 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
14454 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14455 state = 0xdeadbeef;
14456 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, &state);
14457 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14458 ok(state == 0xdeadbeef, "Got unexpected render state %#x.\n", state);
14460 refcount = IDirect3DDevice7_Release(device);
14461 ok(!refcount, "Device has %u references left.\n", refcount);
14462 DestroyWindow(window);
14465 static void test_map_synchronisation(void)
14467 LARGE_INTEGER frequency, diff, ts[3];
14468 IDirect3DVertexBuffer7 *buffer;
14469 unsigned int i, j, tri_count;
14470 D3DVERTEXBUFFERDESC vb_desc;
14471 IDirect3DDevice7 *device;
14472 BOOL unsynchronised, ret;
14473 IDirectDrawSurface7 *rt;
14474 IDirectDraw7 *ddraw;
14475 IDirect3D7 *d3d;
14476 D3DCOLOR colour;
14477 ULONG refcount;
14478 HWND window;
14479 HRESULT hr;
14481 static const struct
14483 unsigned int flags;
14484 BOOL unsynchronised;
14486 tests[] =
14488 {0, FALSE},
14489 {DDLOCK_NOOVERWRITE, TRUE},
14490 {DDLOCK_DISCARDCONTENTS, FALSE},
14491 {DDLOCK_NOOVERWRITE | DDLOCK_DISCARDCONTENTS, TRUE},
14494 static const struct quad
14496 struct
14498 struct vec3 position;
14499 DWORD diffuse;
14500 } strip[4];
14502 quad1 =
14505 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
14506 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
14507 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
14508 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
14511 quad2 =
14514 {{-1.0f, -1.0f, 0.0f}, 0xffffff00},
14515 {{-1.0f, 1.0f, 0.0f}, 0xffffff00},
14516 {{ 1.0f, -1.0f, 0.0f}, 0xffffff00},
14517 {{ 1.0f, 1.0f, 0.0f}, 0xffffff00},
14520 struct quad *quads;
14522 window = create_window();
14523 ok(!!window, "Failed to create a window.\n");
14525 if (!(device = create_device(window, DDSCL_NORMAL)))
14527 skip("Failed to create a D3D device, skipping tests.\n");
14528 DestroyWindow(window);
14529 return;
14532 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
14533 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
14534 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
14535 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
14536 /* Maps are always synchronised on WARP. */
14537 if (ddraw_is_warp(ddraw))
14539 skip("Running on WARP, skipping test.\n");
14540 goto done;
14543 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
14544 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
14546 tri_count = 0x1000;
14548 ret = QueryPerformanceFrequency(&frequency);
14549 ok(ret, "Failed to get performance counter frequency.\n");
14551 vb_desc.dwSize = sizeof(vb_desc);
14552 vb_desc.dwCaps = D3DVBCAPS_WRITEONLY;
14553 vb_desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
14554 vb_desc.dwNumVertices = tri_count + 2;
14555 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &buffer, 0);
14556 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
14557 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&quads, NULL);
14558 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
14559 for (j = 0; j < vb_desc.dwNumVertices / 4; ++j)
14561 quads[j] = quad1;
14563 hr = IDirect3DVertexBuffer7_Unlock(buffer);
14564 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
14566 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
14567 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
14569 /* Initial draw to initialise states, compile shaders, etc. */
14570 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
14571 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14572 hr = IDirect3DDevice7_BeginScene(device);
14573 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14574 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, vb_desc.dwNumVertices, 0);
14575 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14576 hr = IDirect3DDevice7_EndScene(device);
14577 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14578 /* Read the result to ensure the GPU has finished drawing. */
14579 colour = get_surface_color(rt, 320, 240);
14581 /* Time drawing tri_count triangles. */
14582 ret = QueryPerformanceCounter(&ts[0]);
14583 ok(ret, "Failed to read performance counter.\n");
14584 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
14585 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14586 hr = IDirect3DDevice7_BeginScene(device);
14587 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14588 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, vb_desc.dwNumVertices, 0);
14589 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14590 hr = IDirect3DDevice7_EndScene(device);
14591 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14592 colour = get_surface_color(rt, 320, 240);
14593 /* Time drawing a single triangle. */
14594 ret = QueryPerformanceCounter(&ts[1]);
14595 ok(ret, "Failed to read performance counter.\n");
14596 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
14597 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14598 hr = IDirect3DDevice7_BeginScene(device);
14599 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14600 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 3, 0);
14601 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14602 hr = IDirect3DDevice7_EndScene(device);
14603 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14604 colour = get_surface_color(rt, 320, 240);
14605 ret = QueryPerformanceCounter(&ts[2]);
14606 ok(ret, "Failed to read performance counter.\n");
14608 IDirect3DVertexBuffer7_Release(buffer);
14610 /* Estimate the number of triangles we can draw in 100ms. */
14611 diff.QuadPart = ts[1].QuadPart - ts[0].QuadPart + ts[1].QuadPart - ts[2].QuadPart;
14612 tri_count = (tri_count * frequency.QuadPart) / (diff.QuadPart * 10);
14613 tri_count = ((tri_count + 2 + 3) & ~3) - 2;
14614 vb_desc.dwNumVertices = tri_count + 2;
14616 for (i = 0; i < ARRAY_SIZE(tests); ++i)
14618 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &buffer, 0);
14619 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
14620 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&quads, NULL);
14621 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
14622 for (j = 0; j < vb_desc.dwNumVertices / 4; ++j)
14624 quads[j] = quad1;
14626 hr = IDirect3DVertexBuffer7_Unlock(buffer);
14627 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
14629 /* Start a draw operation. */
14630 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
14631 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14632 hr = IDirect3DDevice7_BeginScene(device);
14633 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14634 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, vb_desc.dwNumVertices, 0);
14635 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14636 hr = IDirect3DDevice7_EndScene(device);
14637 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14639 /* Map the last quad while the draw is in progress. */
14640 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_WAIT | tests[i].flags, (void **)&quads, NULL);
14641 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
14642 quads[(vb_desc.dwNumVertices / 4) - 1] = quad2;
14643 hr = IDirect3DVertexBuffer7_Unlock(buffer);
14644 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
14646 colour = get_surface_color(rt, 320, 240);
14647 unsynchronised = compare_color(colour, 0x00ffff00, 1);
14648 ok(tests[i].unsynchronised == unsynchronised, "Expected %s map for flags %#x.\n",
14649 tests[i].unsynchronised ? "unsynchronised" : "synchronised", tests[i].flags);
14651 IDirect3DVertexBuffer7_Release(buffer);
14654 IDirectDrawSurface7_Release(rt);
14655 done:
14656 IDirectDraw7_Release(ddraw);
14657 IDirect3D7_Release(d3d);
14658 refcount = IDirect3DDevice7_Release(device);
14659 ok(!refcount, "Device has %u references left.\n", refcount);
14660 DestroyWindow(window);
14663 static void test_depth_readback(void)
14665 DWORD depth, expected_depth, max_diff, raw_value, passed_fmts = 0;
14666 IDirectDrawSurface7 *rt, *ds;
14667 DDSURFACEDESC2 surface_desc;
14668 IDirect3DDevice7 *device;
14669 unsigned int i, x, y;
14670 IDirectDraw7 *ddraw;
14671 IDirect3D7 *d3d;
14672 ULONG refcount;
14673 HWND window;
14674 HRESULT hr;
14675 RECT r;
14676 BOOL all_zero, all_one, all_pass;
14678 static struct
14680 struct vec3 position;
14681 DWORD diffuse;
14683 quad[] =
14685 {{-1.0f, -1.0f, 0.1f}, 0xff00ff00},
14686 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
14687 {{ 1.0f, -1.0f, 1.0f}, 0xff00ff00},
14688 {{ 1.0f, 1.0f, 0.9f}, 0xff00ff00},
14691 static const struct
14693 unsigned int z_depth, s_depth, z_mask, s_mask;
14694 BOOL todo;
14696 tests[] =
14698 {16, 0, 0x0000ffff, 0x00000000},
14699 {24, 0, 0x00ffffff, 0x00000000},
14700 {32, 0, 0x00ffffff, 0x00000000},
14701 {32, 8, 0x00ffffff, 0xff000000, TRUE},
14702 {32, 0, 0xffffffff, 0x00000000},
14705 window = create_window();
14706 ok(!!window, "Failed to create a window.\n");
14708 if (!(device = create_device(window, DDSCL_NORMAL)))
14710 skip("Failed to create a D3D device, skipping tests.\n");
14711 DestroyWindow(window);
14712 return;
14715 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
14716 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
14717 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
14718 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
14720 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
14721 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
14723 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
14724 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
14726 ds = get_depth_stencil(device);
14727 hr = IDirectDrawSurface7_DeleteAttachedSurface(rt, 0, ds);
14728 ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
14729 IDirectDrawSurface7_Release(ds);
14731 for (i = 0; i < ARRAY_SIZE(tests); ++i)
14733 memset(&surface_desc, 0, sizeof(surface_desc));
14734 surface_desc.dwSize = sizeof(surface_desc);
14735 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
14736 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
14737 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
14738 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
14739 if (tests[i].s_depth)
14740 U4(surface_desc).ddpfPixelFormat.dwFlags |= DDPF_STENCILBUFFER;
14741 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = tests[i].z_depth;
14742 U2(U4(surface_desc).ddpfPixelFormat).dwStencilBitDepth = tests[i].s_depth;
14743 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = tests[i].z_mask;
14744 U4(U4(surface_desc).ddpfPixelFormat).dwStencilBitMask = tests[i].s_mask;
14745 surface_desc.dwWidth = 640;
14746 surface_desc.dwHeight = 480;
14747 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL);
14748 if (FAILED(hr))
14750 skip("Format %u not supported, skipping test.\n", i);
14751 continue;
14754 hr = IDirectDrawSurface_AddAttachedSurface(rt, ds);
14755 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
14756 hr = IDirect3DDevice7_SetRenderTarget(device, rt, 0);
14757 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
14759 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 1.0f, 0);
14760 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14761 hr = IDirect3DDevice7_BeginScene(device);
14762 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14763 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, 4, 0);
14764 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14765 hr = IDirect3DDevice7_EndScene(device);
14766 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14768 all_zero = all_one = all_pass = TRUE;
14769 for (y = 60; y < 480; y += 120)
14771 for (x = 80; x < 640; x += 160)
14773 SetRect(&r, x, y, x + 1, y + 1);
14774 memset(&surface_desc, 0, sizeof(surface_desc));
14775 surface_desc.dwSize = sizeof(surface_desc);
14776 hr = IDirectDrawSurface7_Lock(ds, &r, &surface_desc, DDLOCK_READONLY, NULL);
14777 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14779 raw_value = *((DWORD *)surface_desc.lpSurface);
14780 if (raw_value)
14781 all_zero = FALSE;
14782 if (raw_value != 0x00ffffff)
14783 all_one = FALSE;
14785 depth = raw_value & tests[i].z_mask;
14786 expected_depth = (x * (0.9 / 640.0) + y * (0.1 / 480.0)) * tests[i].z_mask;
14787 max_diff = ((0.5f * 0.9f) / 640.0f) * tests[i].z_mask;
14788 /* This test is very reliably on AMD, but fails in a number of interesting ways on Nvidia GPUs:
14790 * Geforce 7 GPUs work only with D16. D24 and D24S8 return 0, D24X8 broken data.
14792 * Geforce 9 GPUs return broken data for D16 that resembles the expected data in
14793 * the lower 8 bits and has 0xff in the upper 8 bits. D24X8 works, D24 and D24S8 return
14794 * 0x00ffffff.
14796 * Geforce GTX 650 has working D16 and D24, but D24S8 returns 0.
14798 * Arx Fatalis is broken on the Geforce 9 in the same way it was broken in Wine (bug 43654).
14799 * The !tests[i].s_depth is supposed to rule out D16 on GF9 and D24X8 on GF7. */
14800 todo_wine_if(tests[i].todo)
14801 ok(compare_uint(expected_depth, depth, max_diff)
14802 || (ddraw_is_nvidia(ddraw) && (all_zero || all_one || !tests[i].s_depth)),
14803 "Test %u: Got depth 0x%08x (diff %d), expected 0x%08x+/-%u, at %u, %u.\n",
14804 i, depth, expected_depth - depth, expected_depth, max_diff, x, y);
14805 if (!compare_uint(expected_depth, depth, max_diff))
14806 all_pass = FALSE;
14808 hr = IDirectDrawSurface7_Unlock(ds, &r);
14809 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14812 if (all_pass)
14813 passed_fmts++;
14815 hr = IDirectDrawSurface7_DeleteAttachedSurface(rt, 0, ds);
14816 ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
14817 IDirectDrawSurface7_Release(ds);
14820 ok(passed_fmts, "Not a single format passed the tests, this is bad even by Nvidia's standards.\n");
14822 IDirectDrawSurface7_Release(rt);
14823 IDirectDraw7_Release(ddraw);
14824 IDirect3D7_Release(d3d);
14825 refcount = IDirect3DDevice7_Release(device);
14826 ok(!refcount, "Device has %u references left.\n", refcount);
14827 DestroyWindow(window);
14830 static void test_clear(void)
14832 IDirect3DDevice7 *device;
14833 IDirectDrawSurface7 *rt;
14834 D3DVIEWPORT7 vp, old_vp;
14835 IDirectDraw7 *ddraw;
14836 D3DRECT rect_negneg;
14837 IDirect3D7 *d3d;
14838 D3DRECT rect[2];
14839 D3DCOLOR color;
14840 ULONG refcount;
14841 HWND window;
14842 HRESULT hr;
14844 window = create_window();
14845 if (!(device = create_device(window, DDSCL_NORMAL)))
14847 skip("Failed to create 3D device.\n");
14848 DestroyWindow(window);
14849 return;
14852 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
14853 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
14854 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
14855 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
14857 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
14858 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
14860 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
14861 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14863 /* Positive x, negative y. */
14864 U1(rect[0]).x1 = 0;
14865 U2(rect[0]).y1 = 480;
14866 U3(rect[0]).x2 = 320;
14867 U4(rect[0]).y2 = 240;
14869 /* Positive x, positive y. */
14870 U1(rect[1]).x1 = 0;
14871 U2(rect[1]).y1 = 0;
14872 U3(rect[1]).x2 = 320;
14873 U4(rect[1]).y2 = 240;
14875 /* Clear 2 rectangles with one call. Unlike d3d8/9, the refrast does not
14876 * refuse negative rectangles, but it will not clear them either. */
14877 hr = IDirect3DDevice7_Clear(device, 2, rect, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
14878 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14880 color = get_surface_color(rt, 160, 360);
14881 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 3 (pos, neg) has color 0x%08x.\n", color);
14882 color = get_surface_color(rt, 160, 120);
14883 ok(compare_color(color, 0x00ff0000, 0), "Clear rectangle 1 (pos, pos) has color 0x%08x.\n", color);
14884 color = get_surface_color(rt, 480, 360);
14885 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 4 (NULL) has color 0x%08x.\n", color);
14886 color = get_surface_color(rt, 480, 120);
14887 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 4 (neg, neg) has color 0x%08x.\n", color);
14889 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
14890 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14891 /* negative x, negative y.
14892 * Also ignored, except on WARP, which clears the entire screen. */
14893 U1(rect_negneg).x1 = 640;
14894 U2(rect_negneg).y1 = 240;
14895 U3(rect_negneg).x2 = 320;
14896 U4(rect_negneg).y2 = 0;
14897 hr = IDirect3DDevice7_Clear(device, 1, &rect_negneg, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
14898 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14900 color = get_surface_color(rt, 160, 360);
14901 ok(compare_color(color, 0x00ffffff, 0)
14902 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
14903 "Got unexpected color 0x%08x.\n", color);
14904 color = get_surface_color(rt, 160, 120);
14905 ok(compare_color(color, 0x00ffffff, 0)
14906 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
14907 "Got unexpected color 0x%08x.\n", color);
14908 color = get_surface_color(rt, 480, 360);
14909 ok(compare_color(color, 0x00ffffff, 0)
14910 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
14911 "Got unexpected color 0x%08x.\n", color);
14912 color = get_surface_color(rt, 480, 120);
14913 ok(compare_color(color, 0x00ffffff, 0)
14914 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
14915 "Got unexpected color 0x%08x.\n", color);
14917 /* Test how the viewport affects clears. */
14918 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
14919 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14920 hr = IDirect3DDevice7_GetViewport(device, &old_vp);
14921 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
14923 vp.dwX = 160;
14924 vp.dwY = 120;
14925 vp.dwWidth = 160;
14926 vp.dwHeight = 120;
14927 vp.dvMinZ = 0.0f;
14928 vp.dvMaxZ = 1.0f;
14929 hr = IDirect3DDevice7_SetViewport(device, &vp);
14930 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
14931 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
14932 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14934 vp.dwX = 320;
14935 vp.dwY = 240;
14936 vp.dwWidth = 320;
14937 vp.dwHeight = 240;
14938 vp.dvMinZ = 0.0f;
14939 vp.dvMaxZ = 1.0f;
14940 hr = IDirect3DDevice7_SetViewport(device, &vp);
14941 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
14943 U1(rect[0]).x1 = 160;
14944 U2(rect[0]).y1 = 120;
14945 U3(rect[0]).x2 = 480;
14946 U4(rect[0]).y2 = 360;
14947 hr = IDirect3DDevice7_Clear(device, 1, &rect[0], D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
14948 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14950 hr = IDirect3DDevice7_SetViewport(device, &old_vp);
14951 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
14953 color = get_surface_color(rt, 158, 118);
14954 ok(compare_color(color, 0x00ffffff, 0), "(158, 118) has color 0x%08x.\n", color);
14955 color = get_surface_color(rt, 162, 118);
14956 ok(compare_color(color, 0x00ffffff, 0), "(162, 118) has color 0x%08x.\n", color);
14957 color = get_surface_color(rt, 158, 122);
14958 ok(compare_color(color, 0x00ffffff, 0), "(158, 122) has color 0x%08x.\n", color);
14959 color = get_surface_color(rt, 162, 122);
14960 ok(compare_color(color, 0x000000ff, 0), "(162, 122) has color 0x%08x.\n", color);
14962 color = get_surface_color(rt, 318, 238);
14963 ok(compare_color(color, 0x000000ff, 0), "(318, 238) has color 0x%08x.\n", color);
14964 color = get_surface_color(rt, 322, 238);
14965 ok(compare_color(color, 0x00ffffff, 0), "(322, 328) has color 0x%08x.\n", color);
14966 color = get_surface_color(rt, 318, 242);
14967 ok(compare_color(color, 0x00ffffff, 0), "(318, 242) has color 0x%08x.\n", color);
14968 color = get_surface_color(rt, 322, 242);
14969 ok(compare_color(color, 0x0000ff00, 0), "(322, 242) has color 0x%08x.\n", color);
14971 color = get_surface_color(rt, 478, 358);
14972 ok(compare_color(color, 0x0000ff00, 0), "(478, 358) has color 0x%08x.\n", color);
14973 color = get_surface_color(rt, 482, 358);
14974 ok(compare_color(color, 0x00ffffff, 0), "(482, 358) has color 0x%08x.\n", color);
14975 color = get_surface_color(rt, 478, 362);
14976 ok(compare_color(color, 0x00ffffff, 0), "(478, 362) has color 0x%08x.\n", color);
14977 color = get_surface_color(rt, 482, 362);
14978 ok(compare_color(color, 0x00ffffff, 0), "(482, 362) has color 0x%08x.\n", color);
14980 /* COLORWRITEENABLE, SRGBWRITEENABLE and scissor rectangles do not exist
14981 * in d3d7. */
14983 IDirectDrawSurface7_Release(rt);
14984 IDirectDraw7_Release(ddraw);
14985 IDirect3D7_Release(d3d);
14986 refcount = IDirect3DDevice7_Release(device);
14987 ok(!refcount, "Device has %u references left.\n", refcount);
14988 DestroyWindow(window);
14991 struct enum_surfaces_param
14993 IDirectDrawSurface7 *surfaces[8];
14994 unsigned int count;
14997 static HRESULT WINAPI enum_surfaces_cb(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
14999 struct enum_surfaces_param *param = context;
15000 BOOL found = FALSE;
15001 unsigned int i;
15003 for (i = 0; i < ARRAY_SIZE(param->surfaces); ++i)
15005 if (param->surfaces[i] == surface)
15007 found = TRUE;
15008 break;
15012 ok(found, "Unexpected surface %p enumerated.\n", surface);
15013 IDirectDrawSurface7_Release(surface);
15014 ++param->count;
15016 return DDENUMRET_OK;
15019 static void test_enum_surfaces(void)
15021 struct enum_surfaces_param param = {{0}};
15022 DDSURFACEDESC2 desc;
15023 IDirectDraw7 *ddraw;
15024 HRESULT hr;
15026 ddraw = create_ddraw();
15027 ok(!!ddraw, "Failed to create a ddraw object.\n");
15029 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
15030 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
15032 memset(&desc, 0, sizeof(desc));
15033 desc.dwSize = sizeof(desc);
15034 desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
15035 desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
15036 U2(desc).dwMipMapCount = 3;
15037 desc.dwWidth = 32;
15038 desc.dwHeight = 32;
15039 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &desc, &param.surfaces[0], NULL)))
15041 win_skip("Failed to create a texture, skipping tests.\n");
15042 IDirectDraw7_Release(ddraw);
15043 return;
15046 hr = IDirectDrawSurface7_GetAttachedSurface(param.surfaces[0], &desc.ddsCaps, &param.surfaces[1]);
15047 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
15048 hr = IDirectDrawSurface7_GetAttachedSurface(param.surfaces[1], &desc.ddsCaps, &param.surfaces[2]);
15049 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
15050 hr = IDirectDrawSurface7_GetAttachedSurface(param.surfaces[2], &desc.ddsCaps, &param.surfaces[3]);
15051 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
15052 ok(!param.surfaces[3], "Got unexpected pointer %p.\n", param.surfaces[3]);
15054 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
15055 &desc, &param, enum_surfaces_cb);
15056 ok(SUCCEEDED(hr), "Failed to enumerate surfaces, hr %#x.\n", hr);
15057 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
15059 param.count = 0;
15060 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
15061 NULL, &param, enum_surfaces_cb);
15062 ok(SUCCEEDED(hr), "Failed to enumerate surfaces, hr %#x.\n", hr);
15063 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
15065 IDirectDrawSurface7_Release(param.surfaces[2]);
15066 IDirectDrawSurface7_Release(param.surfaces[1]);
15067 IDirectDrawSurface7_Release(param.surfaces[0]);
15068 IDirectDraw7_Release(ddraw);
15071 static void test_viewport(void)
15073 static struct
15075 D3DVIEWPORT7 vp;
15076 float expected_z;
15077 RECT expected_rect;
15078 const char *message;
15080 tests[] =
15082 {{ 0, 0, 640, 480}, 0.001f, { 0, 120, 479, 359}, "Viewport (0, 0) - (640, 480)"},
15083 {{ 0, 0, 320, 240}, 0.001f, { 0, 60, 239, 179}, "Viewport (0, 0) - (320, 240)"},
15084 /* Don't run this right after the other 640x480 test, it breaks r500. */
15085 {{ 0, 0, 640, 480, 0.5f, 0.0f}, 0.501f,
15086 {0, 120, 479, 359}, "Viewport (0, 0, 0.5) - (640, 480, 0.0)"},
15087 {{ 0, 0, 1280, 960}, 0.001f, { 0, 240, 639, 479}, "Viewport (0, 0) - (1280, 960)"},
15088 {{ 0, 0, 2000, 1600}, 0.001f, {-10, -10, -10, -10}, "Viewport (0, 0) - (2000, 1600)"},
15089 {{100, 100, 640, 480}, 0.001f, {100, 220, 579, 459}, "Viewport (100, 100) - (640, 480)"},
15090 {{ 0, 0, 8192, 8192}, 0.001f, {-10, -10, -10, -10}, "Viewport (0, 0) - (8192, 8192)"},
15092 static struct vec3 quad[] =
15094 {-1.5f, -0.5f, 1.0f},
15095 {-1.5f, 0.5f, 1.0f},
15096 { 0.5f, -0.5f, 1.0f},
15097 { 0.5f, 0.5f, 1.0f},
15099 static const struct vec2 rt_sizes[] =
15101 {640, 480}, {1280, 960}, {320, 240}, {800, 600},
15103 IDirectDrawSurface7 *rt, *ds;
15104 DDSURFACEDESC2 surface_desc;
15105 const float z_eps = 0.0001;
15106 IDirect3DDevice7 *device;
15107 IDirectDraw7 *ddraw;
15108 DDPIXELFORMAT z_fmt;
15109 unsigned int i, j;
15110 IDirect3D7 *d3d;
15111 ULONG refcount;
15112 HWND window;
15113 HRESULT hr;
15115 window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
15116 0, 0, 640, 480, 0, 0, 0, 0);
15117 if (!(device = create_device(window, DDSCL_NORMAL)))
15119 skip("Failed to create a 3D device, skipping test.\n");
15120 DestroyWindow(window);
15121 return;
15124 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
15125 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15126 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
15127 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15128 IDirect3D7_Release(d3d);
15130 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
15131 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15133 /* Well, by default the vertices without color info should be white, and without any texture
15134 * ops this should just show up in the output, but the r200 driver begs to differ and draws a
15135 * random color. */
15136 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
15137 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15138 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
15139 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15140 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x00ffffff);
15141 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15143 hr = IDirect3DDevice7_SetViewport(device, NULL);
15144 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
15146 ds = get_depth_stencil(device);
15147 memset(&surface_desc, 0, sizeof(surface_desc));
15148 surface_desc.dwSize = sizeof(surface_desc);
15149 hr = IDirectDrawSurface7_GetSurfaceDesc(ds, &surface_desc);
15150 z_fmt = U4(surface_desc).ddpfPixelFormat;
15152 for (i = 0; i < ARRAY_SIZE(rt_sizes); ++i)
15154 if (i)
15156 memset(&surface_desc, 0, sizeof(surface_desc));
15157 surface_desc.dwSize = sizeof(surface_desc);
15158 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
15159 surface_desc.dwWidth = rt_sizes[i].x;
15160 surface_desc.dwHeight = rt_sizes[i].y;
15161 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
15162 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &rt, NULL);
15163 ok(hr == DD_OK, "Got unexpected hr %#x (i %u).\n", hr, i);
15165 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
15166 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
15167 U4(surface_desc).ddpfPixelFormat = z_fmt;
15168 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL);
15169 ok(hr == DD_OK, "Got unexpected hr %#x (i %u).\n", hr, i);
15170 hr = IDirectDrawSurface7_AddAttachedSurface(rt, ds);
15171 ok(hr == DD_OK, "Got unexpected hr %#x (i %u).\n", hr, i);
15173 hr = IDirect3DDevice7_SetRenderTarget(device, rt, 0);
15174 ok(hr == DD_OK, "Got unexpected hr %#x (i %u).\n", hr, i);
15176 else
15178 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
15179 ok(hr == DD_OK, "Got unexpected hr %#x (i %u).\n", hr, i);
15182 for (j = 0; j < ARRAY_SIZE(tests); ++j)
15184 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff000000,
15185 tests[j].expected_z - z_eps, 0);
15186 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
15187 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_GREATER);
15188 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
15190 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, !i);
15191 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
15193 hr = IDirect3DDevice7_SetViewport(device, &tests[j].vp);
15194 if (tests[j].vp.dwX + tests[j].vp.dwWidth > rt_sizes[i].x
15195 || tests[j].vp.dwY + tests[j].vp.dwHeight > rt_sizes[i].y)
15197 ok(hr == E_INVALIDARG, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
15198 continue;
15200 else
15202 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
15205 hr = IDirect3DDevice7_BeginScene(device);
15206 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
15207 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
15208 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
15209 hr = IDirect3DDevice7_EndScene(device);
15210 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
15212 check_rect(rt, tests[j].expected_rect, tests[j].message);
15214 if (!i)
15216 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff000000,
15217 tests[j].expected_z + z_eps, 0);
15218 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
15219 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESS);
15220 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
15222 hr = IDirect3DDevice7_BeginScene(device);
15223 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
15224 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
15225 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
15226 hr = IDirect3DDevice7_EndScene(device);
15227 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
15229 check_rect(rt, tests[j].expected_rect, tests[j].message);
15233 hr = IDirectDrawSurface7_DeleteAttachedSurface(rt, 0, ds);
15234 ok(hr == DD_OK, "Got unexpected hr %#x (i %u).\n", hr, i);
15235 IDirectDrawSurface7_Release(ds);
15236 IDirectDrawSurface7_Release(rt);
15239 refcount = IDirect3DDevice7_Release(device);
15240 ok(!refcount, "Device has %u references left.\n", refcount);
15241 IDirectDraw7_Release(ddraw);
15242 DestroyWindow(window);
15245 static unsigned int validate_loaded_surface(IDirectDrawSurface7 *surface, unsigned int face,
15246 unsigned int level, const RECT *src_rect, const POINT *dst_point)
15248 DDSURFACEDESC2 surface_desc;
15249 unsigned int diff, x, y;
15250 HRESULT hr;
15252 memset(&surface_desc, 0, sizeof(surface_desc));
15253 surface_desc.dwSize = sizeof(surface_desc);
15254 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
15255 ok(SUCCEEDED(hr), "Failed to map surface, hr %#x.\n", hr);
15257 for (y = 0, diff = 0; y < surface_desc.dwHeight; ++y)
15259 DWORD *texture_row = (DWORD *)((char *)surface_desc.lpSurface + y * U1(surface_desc).lPitch);
15261 for (x = 0; x < surface_desc.dwWidth; ++x)
15263 DWORD colour = texture_row[x];
15264 DWORD r = (colour & 0xff0000) >> 16;
15265 DWORD g = (colour & 0xff00) >> 8;
15266 DWORD b = (colour & 0xff);
15268 if (x < dst_point->x || x >= dst_point->x + src_rect->right - src_rect->left
15269 || y < dst_point->y || y >= dst_point->y + src_rect->bottom - src_rect->top)
15271 if (colour & 0xffffff)
15272 ++diff;
15274 else
15276 if (r != ((face << 4) | level)
15277 || g != x + src_rect->left - dst_point->x
15278 || b != y + src_rect->top - dst_point->y)
15279 ++diff;
15284 hr = IDirectDrawSurface7_Unlock(surface, NULL);
15285 ok(SUCCEEDED(hr), "Failed to unmap surface, hr %#x.\n", hr);
15287 return diff;
15290 static void test_device_load(void)
15292 IDirectDrawSurface7 *src_surface, *dst_surface, *surface, *tmp;
15293 DDSCAPS2 mip_caps = {0, DDSCAPS2_MIPMAPSUBLEVEL, 0, {0}};
15294 IDirectDrawPalette *src_palette, *dst_palette, *palette;
15295 unsigned int i, j, k, l, x, y;
15296 DDSURFACEDESC2 surface_desc;
15297 IDirect3DDevice7 *device;
15298 PALETTEENTRY table1[256];
15299 D3DDEVICEDESC7 d3d_caps;
15300 DDCOLORKEY colour_key;
15301 IDirectDraw7 *ddraw;
15302 BOOL cube_support;
15303 IDirect3D7 *d3d;
15304 ULONG refcount;
15305 HWND window;
15306 DDBLTFX fx;
15307 HRESULT hr;
15309 #define TEX_MIP 0x01
15310 #define TEX_CUBE 0x02
15311 #define NULL_COORDS 0x04
15313 /* Creating partial cube maps (e.g. created with just
15314 * DDSCAPS2_CUBEMAP_POSITIVEX) BSODs some Windows machines. (Radeon X1600,
15315 * Windows XP, Catalyst 10.2 driver, 6.14.10.6925)
15317 * Passing non-toplevel surfaces to IDirect3DDevice7_Load() crashes on
15318 * native. (Windows XP / NVIDIA, Windows 98 / RGB software rasteriser) */
15319 static const struct
15321 unsigned int src_w, src_h, src_mip_count;
15322 RECT src_rect;
15323 DWORD src_flags;
15324 unsigned int dst_w, dst_h, dst_mip_count;
15325 POINT dst_point;
15326 DWORD dst_flags;
15327 HRESULT hr;
15329 tests[] =
15331 {128, 128, 0, { 0, 0, 0, 0}, TEX_MIP, 128, 128, 0, { 0, 0}, TEX_MIP, DDERR_INVALIDPARAMS},
15332 {128, 128, 0, { 0, 0, 100, 100}, TEX_MIP, 128, 128, 0, {50, 50}, TEX_MIP, DDERR_INVALIDPARAMS},
15333 {128, 128, 0, {30, 20, 93, 52}, TEX_MIP, 128, 128, 0, {31, 31}, TEX_MIP, D3D_OK},
15334 {128, 128, 0, { 0, 0, 0, 0}, NULL_COORDS, 128, 128, 0, { 0, 0}, NULL_COORDS, D3D_OK},
15335 {128, 128, 0, { 0, 0, 0, 0}, NULL_COORDS, 256, 128, 0, { 0, 0}, NULL_COORDS, DDERR_INVALIDPARAMS},
15336 {256, 128, 0, { 0, 0, 0, 0}, NULL_COORDS, 128, 128, 0, { 0, 0}, NULL_COORDS, DDERR_INVALIDPARAMS},
15337 {128, 128, 0, {30, 20, 93, 52}, TEX_MIP | TEX_CUBE, 128, 128, 0, {10, 10}, TEX_MIP | TEX_CUBE, D3D_OK},
15338 {128, 128, 0, { 0, 0, 0, 0}, NULL_COORDS, 128, 128, 0, { 0, 0}, TEX_CUBE | NULL_COORDS, DDERR_INVALIDPARAMS},
15339 {128, 128, 0, {30, 20, 93, 52}, TEX_MIP, 128, 128, 4, {31, 31}, TEX_MIP, D3D_OK},
15340 {128, 128, 4, {30, 20, 93, 52}, TEX_MIP, 128, 128, 0, {31, 31}, TEX_MIP, DDERR_INVALIDPARAMS},
15341 {128, 128, 0, {32, 32, 96, 96}, TEX_MIP, 32, 32, 0, {32, 32}, 0, D3D_OK},
15342 {128, 128, 0, { 0, 0, 64, 64}, TEX_MIP, 32, 32, 4, { 0, 0}, TEX_MIP, D3D_OK},
15345 window = create_window();
15346 if (!(device = create_device(window, DDSCL_NORMAL)))
15348 skip("Failed to create a 3D device, skipping test.\n");
15349 DestroyWindow(window);
15350 return;
15353 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
15354 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
15355 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
15356 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
15357 IDirect3D7_Release(d3d);
15359 memset(&d3d_caps, 0, sizeof(d3d_caps));
15360 hr = IDirect3DDevice7_GetCaps(device, &d3d_caps);
15361 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
15362 cube_support = d3d_caps.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP;
15364 for (i = 0; i < ARRAY_SIZE(tests); ++i)
15366 unsigned int src_count, dst_count;
15367 POINT dst_point, dst_point_broken;
15368 RECT src_rect, src_rect_broken;
15370 if ((tests[i].src_flags | tests[i].dst_flags) & TEX_CUBE && !cube_support)
15372 skip("No cubemap support, skipping test %u.\n", i);
15373 continue;
15376 memset(&surface_desc, 0, sizeof(surface_desc));
15377 surface_desc.dwSize = sizeof(surface_desc);
15378 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
15379 if (tests[i].src_mip_count)
15380 surface_desc.dwFlags |= DDSD_MIPMAPCOUNT;
15381 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
15382 if (tests[i].src_flags & (TEX_MIP | TEX_CUBE))
15383 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
15384 if (tests[i].src_flags & TEX_MIP)
15385 surface_desc.ddsCaps.dwCaps |= DDSCAPS_MIPMAP;
15386 if (tests[i].src_flags & TEX_CUBE)
15387 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
15388 surface_desc.dwWidth = tests[i].src_w;
15389 surface_desc.dwHeight = tests[i].src_h;
15390 U2(surface_desc).dwMipMapCount = tests[i].src_mip_count;
15391 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
15392 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
15393 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
15394 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
15395 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
15396 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
15397 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
15398 ok(SUCCEEDED(hr), "Test %u: Failed to create source surface, hr %#x.\n", i, hr);
15400 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
15401 if (tests[i].dst_mip_count)
15402 surface_desc.dwFlags |= DDSD_MIPMAPCOUNT;
15403 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
15404 if (tests[i].dst_flags & (TEX_MIP | TEX_CUBE))
15405 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
15406 if (tests[i].dst_flags & TEX_MIP)
15407 surface_desc.ddsCaps.dwCaps |= DDSCAPS_MIPMAP;
15408 surface_desc.ddsCaps.dwCaps2 = 0;
15409 if (tests[i].dst_flags & TEX_CUBE)
15410 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
15411 surface_desc.dwWidth = tests[i].dst_w;
15412 surface_desc.dwHeight = tests[i].dst_h;
15413 U2(surface_desc).dwMipMapCount = tests[i].dst_mip_count;
15414 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
15415 ok(SUCCEEDED(hr), "Test %u: Failed to create destination surface, hr %#x.\n", i, hr);
15417 src_count = dst_count = 1;
15418 if (tests[i].src_flags & TEX_MIP)
15419 src_count = tests[i].src_mip_count ? tests[i].src_mip_count : 8;
15420 if (tests[i].dst_flags & TEX_MIP)
15421 dst_count = tests[i].dst_mip_count ? tests[i].dst_mip_count : 8;
15423 surface = src_surface;
15424 IDirectDrawSurface7_AddRef(surface);
15425 for (j = 0;;)
15427 DDSCAPS2 face_caps = {0, 0, 0, {0}};
15429 /* Check the number of created mipmaps. */
15430 if (tests[i].src_flags & TEX_MIP)
15432 memset(&surface_desc, 0, sizeof(surface_desc));
15433 surface_desc.dwSize = sizeof(surface_desc);
15434 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
15435 ok(SUCCEEDED(hr), "Test %u: Failed to get surface description, hr %#x.\n", i, hr);
15436 ok(U2(surface_desc).dwMipMapCount == src_count,
15437 "Test %u: Got unexpected mip count %u, expected %u.\n",
15438 i, U2(surface_desc).dwMipMapCount, src_count);
15441 for (k = 0; ; ++k)
15443 memset(&surface_desc, 0, sizeof(surface_desc));
15444 surface_desc.dwSize = sizeof(surface_desc);
15445 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
15446 ok(SUCCEEDED(hr), "Test %u: Failed to map surface, hr %#x.\n", i, hr);
15448 for (y = 0; y < surface_desc.dwHeight; ++y)
15450 DWORD *texture_row = (DWORD *)((BYTE *)surface_desc.lpSurface + y * U1(surface_desc).lPitch);
15452 for (x = 0; x < surface_desc.dwWidth; ++x)
15454 /* The face number is stored in the high 4 bits of the
15455 * red component, the mip-level in the low 4 bits. The
15456 * x-coordinate is stored in the green component, and
15457 * the y-coordinate in the blue component. */
15458 texture_row[x] = (j << 20) | (k << 16) | (x << 8) | y;
15462 hr = IDirectDrawSurface7_Unlock(surface, NULL);
15463 ok(SUCCEEDED(hr), "Test %u: Failed to unmap surface, hr %#x.\n", i, hr);
15465 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &mip_caps, &tmp);
15466 IDirectDrawSurface7_Release(surface);
15467 if (FAILED(hr))
15468 break;
15469 surface = tmp;
15472 if (!(tests[i].src_flags & TEX_CUBE) || ++j >= 6)
15473 break;
15475 face_caps.dwCaps2 = DDSCAPS2_CUBEMAP | (DDSCAPS2_CUBEMAP_POSITIVEX << j);
15476 hr = IDirectDrawSurface7_GetAttachedSurface(src_surface, &face_caps, &surface);
15477 ok(SUCCEEDED(hr), "Test %u: Failed to get face %u.\n", i, j);
15480 surface = dst_surface;
15481 IDirectDrawSurface7_AddRef(surface);
15482 for (j = 0;;)
15484 DDSCAPS2 face_caps = {0, 0, 0, {0}};
15486 /* Check the number of created mipmaps. */
15487 if (tests[i].dst_flags & TEX_MIP)
15489 memset(&surface_desc, 0, sizeof(surface_desc));
15490 surface_desc.dwSize = sizeof(surface_desc);
15491 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
15492 ok(SUCCEEDED(hr), "Test %u: Failed to get surface description, hr %#x.\n", i, hr);
15493 ok(U2(surface_desc).dwMipMapCount == dst_count,
15494 "Test %u: Got unexpected mip count %u, expected %u.\n",
15495 i, U2(surface_desc).dwMipMapCount, dst_count);
15498 for (;;)
15500 memset(&fx, 0, sizeof(fx));
15501 fx.dwSize = sizeof(fx);
15502 U5(fx).dwFillColor = 0x00000000;
15503 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
15504 ok(SUCCEEDED(hr), "Test %u: Failed to clear surface, hr %#x.\n", i, hr);
15506 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &mip_caps, &tmp);
15507 IDirectDrawSurface7_Release(surface);
15508 if (FAILED(hr))
15509 break;
15510 surface = tmp;
15513 if (!(tests[i].dst_flags & TEX_CUBE) || ++j >= 6)
15514 break;
15516 face_caps.dwCaps2 = DDSCAPS2_CUBEMAP | (DDSCAPS2_CUBEMAP_POSITIVEX << j);
15517 hr = IDirectDrawSurface7_GetAttachedSurface(dst_surface, &face_caps, &surface);
15518 ok(SUCCEEDED(hr), "Test %u: Failed to get face %u.\n", i, j);
15521 src_rect = tests[i].src_rect;
15522 dst_point = tests[i].dst_point;
15523 hr = IDirect3DDevice7_Load(device,
15524 dst_surface, tests[i].dst_flags & NULL_COORDS ? NULL : &dst_point,
15525 src_surface, tests[i].src_flags & NULL_COORDS ? NULL : &src_rect,
15526 tests[i].dst_flags & TEX_CUBE ? DDSCAPS2_CUBEMAP_ALLFACES : 0);
15527 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x.\n", i, hr);
15529 if (SUCCEEDED(hr))
15531 unsigned int level_offset, level_offset_broken;
15533 for (level_offset = 0, k = tests[i].src_w; k > tests[i].dst_w; ++level_offset, k /= 2);
15534 level_offset_broken = src_count - dst_count;
15536 surface = dst_surface;
15537 IDirectDrawSurface7_AddRef(surface);
15538 for (j = 0;;)
15540 DDSCAPS2 face_caps = {0, 0, 0, {0}};
15542 if (tests[i].src_flags & NULL_COORDS)
15543 SetRect(&src_rect, 0, 0, tests[i].src_w, tests[i].src_h);
15544 else
15545 src_rect = tests[i].src_rect;
15547 if (tests[i].dst_flags & NULL_COORDS)
15548 dst_point.x = dst_point.y = 0;
15549 else
15550 dst_point = tests[i].dst_point;
15552 for (k = 0; k < level_offset; ++k)
15554 dst_point.x /= 2;
15555 dst_point.y /= 2;
15556 src_rect.top /= 2;
15557 src_rect.left /= 2;
15558 src_rect.right = (src_rect.right + 1) / 2;
15559 src_rect.bottom = (src_rect.bottom + 1) / 2;
15562 for (k = 0; ; ++k)
15564 unsigned int diff, diff2, diff3;
15566 diff = validate_loaded_surface(surface, j, k + level_offset, &src_rect, &dst_point);
15568 /* On some newer (XP+) versions of Windows, it appears the
15569 * source/destination coordinates are divided too often.
15570 * This works correctly on Windows 98 with the RGB
15571 * software rasteriser. */
15572 src_rect_broken = src_rect;
15573 dst_point_broken = dst_point;
15574 for (l = 0; l < level_offset; ++l)
15576 dst_point_broken.x /= 2;
15577 dst_point_broken.y /= 2;
15578 src_rect_broken.top /= 2;
15579 src_rect_broken.left /= 2;
15580 src_rect_broken.right = (src_rect_broken.right + 1) / 2;
15581 src_rect_broken.bottom = (src_rect_broken.bottom + 1) / 2;
15583 diff2 = validate_loaded_surface(surface, j, k + level_offset,
15584 &src_rect_broken, &dst_point_broken);
15586 /* On Windows 8+ things are slightly worse still. Instead
15587 * of applying the correct level offset twice, like on
15588 * XP+, an incorrect offset is applied in addition to the
15589 * correct one. Additionally, on Windows 8+, this offset
15590 * also affects the selected source mip-level, as opposed
15591 * to Windows XP+ where it only affects the
15592 * source/destination coordinates. */
15593 src_rect_broken = src_rect;
15594 dst_point_broken = dst_point;
15595 for (l = 0; l < level_offset_broken; ++l)
15597 dst_point_broken.x /= 2;
15598 dst_point_broken.y /= 2;
15599 src_rect_broken.top /= 2;
15600 src_rect_broken.left /= 2;
15601 src_rect_broken.right = (src_rect_broken.right + 1) / 2;
15602 src_rect_broken.bottom = (src_rect_broken.bottom + 1) / 2;
15604 diff3 = validate_loaded_surface(surface, j, k + level_offset_broken,
15605 &src_rect_broken, &dst_point_broken);
15607 ok(!diff || broken(!diff2 || !diff3), "Test %u, face %u, level %u: "
15608 "Unexpected destination texture level pixels; %u/%u/%u differences.\n",
15609 i, j, k, diff, diff2, diff3);
15611 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &mip_caps, &tmp);
15612 IDirectDrawSurface7_Release(surface);
15613 if (FAILED(hr))
15614 break;
15615 surface = tmp;
15617 dst_point.x /= 2;
15618 dst_point.y /= 2;
15619 src_rect.top /= 2;
15620 src_rect.left /= 2;
15621 src_rect.right = (src_rect.right + 1) / 2;
15622 src_rect.bottom = (src_rect.bottom + 1) / 2;
15625 if (!(tests[i].dst_flags & TEX_CUBE) || ++j >= 6)
15626 break;
15628 face_caps.dwCaps2 = DDSCAPS2_CUBEMAP | (DDSCAPS2_CUBEMAP_POSITIVEX << j);
15629 hr = IDirectDrawSurface7_GetAttachedSurface(dst_surface, &face_caps, &surface);
15630 ok(SUCCEEDED(hr), "Test %u: Failed to get face %u.\n", i, j);
15634 IDirectDrawSurface7_Release(dst_surface);
15635 IDirectDrawSurface7_Release(src_surface);
15637 #undef TEX_MIP
15638 #undef TEX_CUBE
15639 #undef NULL_COORDS
15641 memset(&surface_desc, 0, sizeof(surface_desc));
15642 surface_desc.dwSize = sizeof(surface_desc);
15643 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
15644 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
15645 surface_desc.dwWidth = 128;
15646 surface_desc.dwHeight = 128;
15647 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
15648 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
15649 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
15650 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
15651 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
15652 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
15653 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
15654 hr = IDirectDrawSurface7_GetAttachedSurface(src_surface, &mip_caps, &surface);
15655 ok(SUCCEEDED(hr), "Failed to get surface, hr %#x.\n", hr);
15657 /* Test palette copying. */
15658 memset(table1, 0, sizeof(table1));
15659 table1[0].peBlue = 1;
15660 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &src_palette, NULL);
15661 ok(SUCCEEDED(hr), "Failed to create source palette, hr %#x.\n", hr);
15662 table1[0].peBlue = 3;
15663 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &dst_palette, NULL);
15664 ok(SUCCEEDED(hr), "Failed to create destination palette, hr %#x.\n", hr);
15666 hr = IDirectDrawSurface7_SetPalette(src_surface, src_palette);
15667 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
15669 hr = IDirect3DDevice7_Load(device, dst_surface, NULL, src_surface, NULL, 0);
15670 ok(SUCCEEDED(hr), "Failed to load texture, hr %#x.\n", hr);
15672 hr = IDirectDrawSurface7_GetPalette(surface, &palette);
15673 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
15674 hr = IDirectDrawSurface7_GetPalette(dst_surface, &palette);
15675 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
15677 hr = IDirectDrawSurface7_SetPalette(surface, src_palette);
15678 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x.\n", hr);
15679 hr = IDirectDrawSurface7_SetPalette(dst_surface, dst_palette);
15680 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
15682 hr = IDirect3DDevice7_Load(device, dst_surface, NULL, src_surface, NULL, 0);
15683 ok(SUCCEEDED(hr), "Failed to load texture, hr %#x.\n", hr);
15685 hr = IDirectDrawSurface7_GetPalette(dst_surface, &palette);
15686 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
15687 ok(palette == dst_palette, "Got unexpected palette %p, expected %p.\n", palette, dst_palette);
15688 memset(table1, 0, sizeof(table1));
15689 hr = IDirectDrawPalette_GetEntries(palette, 0, 0, 256, table1);
15690 ok(SUCCEEDED(hr), "Failed to retrieve palette entries, hr %#x.\n", hr);
15691 ok(table1[0].peBlue == 1, "Got unexpected palette colour %#x.\n", (unsigned int)table1[0].peBlue);
15692 IDirectDrawPalette_Release(palette);
15694 IDirectDrawPalette_Release(dst_palette);
15695 IDirectDrawPalette_Release(src_palette);
15697 /* Test colour-key copying. */
15698 colour_key.dwColorSpaceLowValue = 32;
15699 colour_key.dwColorSpaceHighValue = 64;
15700 hr = IDirectDrawSurface7_SetColorKey(src_surface, DDCKEY_SRCBLT, &colour_key);
15701 ok(SUCCEEDED(hr), "Failed to set colour-key, hr %#x.\n", hr);
15702 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &colour_key);
15703 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x.\n", hr);
15705 hr = IDirectDrawSurface7_GetColorKey(dst_surface, DDCKEY_SRCBLT, &colour_key);
15706 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
15708 hr = IDirect3DDevice7_Load(device, dst_surface, NULL, src_surface, NULL, 0);
15709 ok(SUCCEEDED(hr), "Failed to load texture, hr %#x.\n", hr);
15711 hr = IDirectDrawSurface7_GetColorKey(dst_surface, DDCKEY_SRCBLT, &colour_key);
15712 ok(SUCCEEDED(hr), "Failed to get colour-key, hr %#x.\n", hr);
15713 ok(colour_key.dwColorSpaceLowValue == 32, "Got unexpected value %u.\n", colour_key.dwColorSpaceLowValue);
15714 ok(colour_key.dwColorSpaceHighValue == 32, "Got unexpected value %u.\n", colour_key.dwColorSpaceHighValue);
15716 IDirectDrawSurface7_Release(surface);
15717 IDirectDrawSurface7_Release(dst_surface);
15718 IDirectDrawSurface7_Release(src_surface);
15720 IDirectDraw7_Release(ddraw);
15721 refcount = IDirect3DDevice7_Release(device);
15722 ok(!refcount, "Device has %u references left.\n", refcount);
15723 DestroyWindow(window);
15726 static void test_color_vertex(void)
15728 IDirect3DDevice7 *device;
15729 IDirectDrawSurface7 *rt;
15730 D3DMATERIAL7 material;
15731 D3DCOLOR colour;
15732 unsigned int i;
15733 ULONG refcount;
15734 HWND window;
15735 HRESULT hr;
15737 static struct
15739 struct vec3 position;
15740 DWORD diffuse;
15741 DWORD specular;
15743 quad_2c[] =
15745 {{-1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff00ff00},
15746 {{-1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff00ff00},
15747 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff00ff00},
15748 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff00ff00},
15750 static struct
15752 struct vec3 position;
15753 DWORD colour;
15755 quad_1c[] =
15757 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
15758 {{-1.0f, 1.0f, 0.0f}, 0xffff0000},
15759 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000},
15760 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000},
15762 static struct
15764 struct vec3 position;
15766 quad_0c[] =
15768 {{-1.0f, -1.0f, 0.0f}},
15769 {{-1.0f, 1.0f, 0.0f}},
15770 {{ 1.0f, -1.0f, 0.0f}},
15771 {{ 1.0f, 1.0f, 0.0f}},
15774 /* The idea here is to set up ambient light parameters in a way that the
15775 * ambient colour from the material is just passed through. The emissive
15776 * colour is just passed through anyway. The sum of ambient + emissive
15777 * should allow deduction of where the material colour came from. */
15778 static const struct
15780 DWORD fvf, color_vertex, ambient, emissive, result;
15781 void *vtx;
15783 tests[] =
15785 {D3DFVF_DIFFUSE | D3DFVF_SPECULAR, FALSE, D3DMCS_COLOR1, D3DMCS_COLOR2, 0x000000c0, quad_2c},
15787 {D3DFVF_DIFFUSE | D3DFVF_SPECULAR, TRUE, D3DMCS_COLOR1, D3DMCS_COLOR2, 0x00ffff00, quad_2c},
15788 {D3DFVF_DIFFUSE | D3DFVF_SPECULAR, TRUE, D3DMCS_MATERIAL, D3DMCS_COLOR2, 0x0000ff80, quad_2c},
15789 {D3DFVF_DIFFUSE | D3DFVF_SPECULAR, TRUE, D3DMCS_COLOR1, D3DMCS_MATERIAL, 0x00ff0040, quad_2c},
15790 {D3DFVF_DIFFUSE | D3DFVF_SPECULAR, TRUE, D3DMCS_COLOR1, D3DMCS_COLOR1, 0x00ff0000, quad_2c},
15791 {D3DFVF_DIFFUSE | D3DFVF_SPECULAR, TRUE, D3DMCS_COLOR2, D3DMCS_COLOR2, 0x0000ff00, quad_2c},
15793 {D3DFVF_SPECULAR, TRUE, D3DMCS_COLOR1, D3DMCS_COLOR2, 0x00ff0080, quad_1c},
15794 {D3DFVF_SPECULAR, TRUE, D3DMCS_COLOR1, D3DMCS_MATERIAL, 0x000000c0, quad_1c},
15795 {D3DFVF_SPECULAR, TRUE, D3DMCS_MATERIAL, D3DMCS_COLOR2, 0x00ff0080, quad_1c},
15796 {D3DFVF_DIFFUSE, TRUE, D3DMCS_COLOR1, D3DMCS_COLOR2, 0x00ff0040, quad_1c},
15797 {D3DFVF_DIFFUSE, TRUE, D3DMCS_COLOR1, D3DMCS_MATERIAL, 0x00ff0040, quad_1c},
15798 {D3DFVF_DIFFUSE, TRUE, D3DMCS_COLOR2, D3DMCS_MATERIAL, 0x000000c0, quad_1c},
15800 {0, TRUE, D3DMCS_COLOR1, D3DMCS_COLOR2, 0x000000c0, quad_0c},
15803 window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
15804 0, 0, 640, 480, 0, 0, 0, 0);
15805 if (!(device = create_device(window, DDSCL_NORMAL)))
15807 skip("Failed to create a 3D device, skipping test.\n");
15808 DestroyWindow(window);
15809 return;
15811 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
15812 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
15814 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
15815 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
15816 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_AMBIENT, 0xffffffff);
15817 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
15819 memset(&material, 0, sizeof(material));
15820 U3(U1(material).ambient).b = 0.5f;
15821 U3(U3(material).emissive).b = 0.25f;
15822 hr = IDirect3DDevice7_SetMaterial(device, &material);
15823 ok(SUCCEEDED(hr), "Failed to set material, hr %#x\n", hr);
15825 for (i = 0; i < ARRAY_SIZE(tests); ++i)
15827 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORVERTEX, tests[i].color_vertex);
15828 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
15829 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_AMBIENTMATERIALSOURCE, tests[i].ambient);
15830 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
15831 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_EMISSIVEMATERIALSOURCE, tests[i].emissive);
15832 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
15833 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
15834 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
15836 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x77777777, 0.0f, 0);
15837 ok(SUCCEEDED(hr), "Failed to clear depth/stencil, hr %#x.\n", hr);
15839 hr = IDirect3DDevice7_BeginScene(device);
15840 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
15841 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
15842 D3DFVF_XYZ | tests[i].fvf, tests[i].vtx, 4, 0);
15843 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
15844 hr = IDirect3DDevice7_EndScene(device);
15845 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
15847 colour = get_surface_color(rt, 320, 240);
15848 ok(compare_color(colour, tests[i].result, 1),
15849 "Expected colour 0x%08x for test %u, got 0x%08x.\n",
15850 tests[i].result, i, colour);
15853 IDirectDrawSurface7_Release(rt);
15854 refcount = IDirect3DDevice7_Release(device);
15855 ok(!refcount, "Device has %u references left.\n", refcount);
15856 DestroyWindow(window);
15859 static IDirectDraw7 *killfocus_ddraw;
15860 static IDirectDrawSurface7 *killfocus_surface;
15862 static LRESULT CALLBACK killfocus_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
15864 ULONG ref;
15866 if (message == WM_KILLFOCUS)
15868 ref = IDirectDrawSurface7_Release(killfocus_surface);
15869 ok(!ref, "Unexpected surface refcount %u.\n", ref);
15870 ref = IDirectDraw7_Release(killfocus_ddraw);
15871 ok(!ref, "Unexpected ddraw refcount %u.\n", ref);
15872 killfocus_ddraw = NULL;
15875 return DefWindowProcA(window, message, wparam, lparam);
15878 static void test_killfocus(void)
15880 DDSURFACEDESC2 surface_desc;
15881 HRESULT hr;
15882 HWND window;
15883 WNDCLASSA wc = {0};
15885 wc.lpfnWndProc = killfocus_proc;
15886 wc.lpszClassName = "ddraw_killfocus_wndproc_wc";
15887 ok(RegisterClassA(&wc), "Failed to register window class.\n");
15889 window = CreateWindowA("ddraw_killfocus_wndproc_wc", "d3d7_test", WS_OVERLAPPEDWINDOW,
15890 0, 0, 640, 480, 0, 0, 0, 0);
15892 killfocus_ddraw = create_ddraw();
15893 ok(!!killfocus_ddraw, "Failed to create a ddraw object.\n");
15895 hr = IDirectDraw7_SetCooperativeLevel(killfocus_ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
15896 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
15898 memset(&surface_desc, 0, sizeof(surface_desc));
15899 surface_desc.dwSize = sizeof(surface_desc);
15900 surface_desc.dwFlags = DDSD_CAPS;
15901 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
15902 hr = IDirectDraw7_CreateSurface(killfocus_ddraw, &surface_desc, &killfocus_surface, NULL);
15903 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
15905 SetForegroundWindow(GetDesktopWindow());
15906 ok(!killfocus_ddraw, "WM_KILLFOCUS was not received.\n");
15908 DestroyWindow(window);
15909 UnregisterClassA("ddraw_killfocus_wndproc_wc", GetModuleHandleA(NULL));
15912 static void test_sysmem_draw(void)
15914 IDirectDrawSurface7 *rt, *texture;
15915 DDSURFACEDESC2 surface_desc;
15916 D3DVERTEXBUFFERDESC vb_desc;
15917 IDirect3DVertexBuffer7 *vb;
15918 IDirect3DDevice7 *device;
15919 IDirectDraw7 *ddraw;
15920 IDirect3D7 *d3d;
15921 D3DCOLOR colour;
15922 ULONG refcount;
15923 HWND window;
15924 HRESULT hr;
15925 BYTE *data;
15927 static const struct
15929 struct vec3 position;
15930 DWORD diffuse;
15932 quad[] =
15934 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
15935 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
15936 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
15937 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
15939 static WORD indices[] = {0, 1, 2, 3};
15941 window = create_window();
15942 ok(!!window, "Failed to create a window.\n");
15944 if (!(device = create_device(window, DDSCL_NORMAL)))
15946 skip("Failed to create a 3D device, skipping test.\n");
15947 DestroyWindow(window);
15948 return;
15951 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
15952 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15953 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
15954 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15955 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
15956 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15958 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
15959 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15961 vb_desc.dwSize = sizeof(vb_desc);
15962 vb_desc.dwCaps = D3DVBCAPS_SYSTEMMEMORY;
15963 vb_desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
15964 vb_desc.dwNumVertices = 4;
15965 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &vb, 0);
15966 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15968 hr = IDirect3DVertexBuffer7_Lock(vb, 0, (void **)&data, NULL);
15969 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15970 memcpy(data, quad, sizeof(quad));
15971 hr = IDirect3DVertexBuffer7_Unlock(vb);
15972 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15974 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x77777777, 0.0f, 0);
15975 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15977 hr = IDirect3DDevice7_BeginScene(device);
15978 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15979 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, 0);
15980 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15981 hr = IDirect3DDevice7_EndScene(device);
15982 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15984 colour = get_surface_color(rt, 320, 240);
15985 ok(compare_color(colour, 0x00007f7f, 1), "Got unexpected colour 0x%08x.\n", colour);
15987 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x77777777, 0.0f, 0);
15988 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15990 hr = IDirect3DDevice7_BeginScene(device);
15991 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15992 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, indices, 4, 0);
15993 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15994 hr = IDirect3DDevice7_EndScene(device);
15995 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
15997 colour = get_surface_color(rt, 320, 240);
15998 ok(compare_color(colour, 0x00007f7f, 1), "Got unexpected colour 0x%08x.\n", colour);
16000 memset(&surface_desc, 0, sizeof(surface_desc));
16001 surface_desc.dwSize = sizeof(surface_desc);
16002 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
16003 surface_desc.dwHeight = 2;
16004 surface_desc.dwWidth = 2;
16005 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
16006 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
16007 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
16008 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
16009 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
16010 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
16011 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
16012 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
16013 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
16014 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16015 hr = IDirect3DDevice7_SetTexture(device, 0, texture);
16016 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16018 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x77777777, 0.0f, 0);
16019 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16021 hr = IDirect3DDevice7_BeginScene(device);
16022 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16023 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, 0);
16024 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16025 hr = IDirect3DDevice7_EndScene(device);
16026 ok(hr == D3D_OK || hr == D3DERR_SCENE_END_FAILED, "Got unexpected hr %#x.\n", hr);
16028 IDirectDrawSurface7_Release(texture);
16029 IDirect3DVertexBuffer7_Release(vb);
16030 IDirectDrawSurface7_Release(rt);
16031 IDirectDraw7_Release(ddraw);
16032 IDirect3D7_Release(d3d);
16033 refcount = IDirect3DDevice7_Release(device);
16034 ok(!refcount, "Device has %u references left.\n", refcount);
16035 DestroyWindow(window);
16038 static void test_gdi_surface(void)
16040 IDirectDrawSurface7 *primary, *backbuffer, *gdi_surface;
16041 DDSCAPS2 caps = {DDSCAPS_BACKBUFFER, 0, 0, {0}};
16042 DDSURFACEDESC2 surface_desc;
16043 IDirectDraw7 *ddraw;
16044 ULONG refcount;
16045 HWND window;
16046 HRESULT hr;
16048 window = create_window();
16049 ddraw = create_ddraw();
16050 ok(!!ddraw, "Failed to create a ddraw object.\n");
16051 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
16052 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16054 /* Retrieving the GDI surface requires a primary surface to exist. */
16055 gdi_surface = (void *)0xc0dec0de;
16056 hr = IDirectDraw7_GetGDISurface(ddraw, &gdi_surface);
16057 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
16058 ok(!gdi_surface, "Got unexpected surface %p.\n", gdi_surface);
16060 hr = IDirectDraw7_FlipToGDISurface(ddraw);
16061 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
16063 memset(&surface_desc, 0, sizeof(surface_desc));
16064 surface_desc.dwSize = sizeof(surface_desc);
16065 surface_desc.dwFlags = DDSD_CAPS;
16066 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
16067 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
16068 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16070 hr = IDirectDraw7_GetGDISurface(ddraw, &gdi_surface);
16071 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16072 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
16073 IDirectDrawSurface7_Release(gdi_surface);
16075 /* Flipping to the GDI surface requires the primary surface to be
16076 * flippable. */
16077 hr = IDirectDraw7_FlipToGDISurface(ddraw);
16078 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
16080 IDirectDrawSurface7_Release(primary);
16082 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
16083 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16085 memset(&surface_desc, 0, sizeof(surface_desc));
16086 surface_desc.dwSize = sizeof(surface_desc);
16087 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
16088 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
16089 U5(surface_desc).dwBackBufferCount = 1;
16090 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
16091 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16092 hr = IDirectDrawSurface7_GetAttachedSurface(primary, &caps, &backbuffer);
16093 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16094 ok(backbuffer != primary, "Got unexpected backbuffer %p.\n", backbuffer);
16096 hr = IDirectDraw7_GetGDISurface(ddraw, &gdi_surface);
16097 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16098 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
16099 IDirectDrawSurface7_Release(gdi_surface);
16101 hr = IDirectDrawSurface7_Flip(primary, NULL, DDFLIP_WAIT);
16102 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16103 hr = IDirectDraw7_GetGDISurface(ddraw, &gdi_surface);
16104 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16105 ok(gdi_surface == backbuffer || broken(gdi_surface == primary),
16106 "Got unexpected surface %p, expected %p.\n", gdi_surface, backbuffer);
16107 IDirectDrawSurface7_Release(gdi_surface);
16109 hr = IDirectDraw7_FlipToGDISurface(ddraw);
16110 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16112 hr = IDirectDraw7_GetGDISurface(ddraw, &gdi_surface);
16113 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16114 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
16115 IDirectDrawSurface7_Release(gdi_surface);
16117 hr = IDirectDraw7_FlipToGDISurface(ddraw);
16118 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16120 IDirectDrawSurface7_Release(backbuffer);
16121 IDirectDrawSurface7_Release(primary);
16123 refcount = IDirectDraw7_Release(ddraw);
16124 ok(!refcount, "%u references left.\n", refcount);
16125 DestroyWindow(window);
16128 static void test_multiply_transform(void)
16130 IDirect3DDevice7 *device;
16131 D3DMATRIX ret_mat;
16132 DWORD stateblock;
16133 unsigned int i;
16134 ULONG refcount;
16135 HWND window;
16136 HRESULT hr;
16138 static const D3DTRANSFORMSTATETYPE tests[] =
16140 D3DTRANSFORMSTATE_WORLD,
16141 D3DTRANSFORMSTATE_VIEW,
16142 D3DTRANSFORMSTATE_PROJECTION,
16143 D3DTRANSFORMSTATE_WORLD1,
16144 D3DTRANSFORMSTATE_WORLD2,
16145 D3DTRANSFORMSTATE_WORLD3,
16146 D3DTRANSFORMSTATE_TEXTURE0,
16147 D3DTRANSFORMSTATE_TEXTURE1,
16148 D3DTRANSFORMSTATE_TEXTURE2,
16149 D3DTRANSFORMSTATE_TEXTURE3,
16150 D3DTRANSFORMSTATE_TEXTURE4,
16151 D3DTRANSFORMSTATE_TEXTURE5,
16152 D3DTRANSFORMSTATE_TEXTURE6,
16153 D3DTRANSFORMSTATE_TEXTURE7,
16156 D3DMATRIX mat1 =
16158 1.0f, 0.0f, 0.0f, 0.0f,
16159 0.0f, 1.0f, 0.0f, 0.0f,
16160 0.0f, 0.0f, 1.0f, 0.0f,
16161 0.0f, 0.0f, 0.0f, 1.0f,
16163 mat2 =
16165 2.0f, 0.0f, 0.0f, 0.0f,
16166 0.0f, 2.0f, 0.0f, 0.0f,
16167 0.0f, 0.0f, 2.0f, 0.0f,
16168 0.0f, 0.0f, 0.0f, 2.0f,
16171 window = create_window();
16172 if (!(device = create_device(window, DDSCL_NORMAL)))
16174 skip("Failed to create 3D device.\n");
16175 DestroyWindow(window);
16176 return;
16179 for (i = 0; i < ARRAY_SIZE(tests); ++i)
16181 hr = IDirect3DDevice7_GetTransform(device, tests[i], &ret_mat);
16182 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
16183 ok(!memcmp(&ret_mat, &mat1, sizeof(mat1)), "Test %u: Got unexpected transform matrix.\n", i);
16185 hr = IDirect3DDevice7_MultiplyTransform(device, tests[i], &mat2);
16186 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
16188 hr = IDirect3DDevice7_GetTransform(device, tests[i], &ret_mat);
16189 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
16190 ok(!memcmp(&ret_mat, &mat2, sizeof(mat2)), "Test %u: Got unexpected transform matrix.\n", i);
16192 /* MultiplyTransform() goes directly into the primary stateblock. */
16194 hr = IDirect3DDevice7_SetTransform(device, tests[i], &mat1);
16195 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
16197 hr = IDirect3DDevice7_BeginStateBlock(device);
16198 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
16200 hr = IDirect3DDevice7_MultiplyTransform(device, tests[i], &mat2);
16201 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
16203 hr = IDirect3DDevice7_EndStateBlock(device, &stateblock);
16204 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
16206 hr = IDirect3DDevice7_GetTransform(device, tests[i], &ret_mat);
16207 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
16208 ok(!memcmp(&ret_mat, &mat2, sizeof(mat2)), "Test %u: Got unexpected transform matrix.\n", i);
16210 hr = IDirect3DDevice7_CaptureStateBlock(device, stateblock);
16211 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
16213 hr = IDirect3DDevice7_SetTransform(device, tests[i], &mat1);
16214 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
16216 hr = IDirect3DDevice7_ApplyStateBlock(device, stateblock);
16217 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
16219 hr = IDirect3DDevice7_GetTransform(device, tests[i], &ret_mat);
16220 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
16221 ok(!memcmp(&ret_mat, &mat1, sizeof(mat1)), "Test %u: Got unexpected transform matrix.\n", i);
16223 IDirect3DDevice7_DeleteStateBlock(device, stateblock);
16226 refcount = IDirect3DDevice7_Release(device);
16227 ok(!refcount, "Device has %u references left.\n", refcount);
16228 DestroyWindow(window);
16231 static void test_alphatest(void)
16233 #define ALPHATEST_PASSED 0x0000ff00
16234 #define ALPHATEST_FAILED 0x00ff0000
16235 IDirect3DDevice7 *device;
16236 IDirectDrawSurface7 *rt;
16237 unsigned int i;
16238 D3DCOLOR color;
16239 ULONG refcount;
16240 HWND window;
16241 DWORD value;
16242 HRESULT hr;
16244 static const struct
16246 D3DCMPFUNC func;
16247 D3DCOLOR color_less;
16248 D3DCOLOR color_equal;
16249 D3DCOLOR color_greater;
16251 test_data[] =
16253 {D3DCMP_NEVER, ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_FAILED},
16254 {D3DCMP_LESS, ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_FAILED},
16255 {D3DCMP_EQUAL, ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_FAILED},
16256 {D3DCMP_LESSEQUAL, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_FAILED},
16257 {D3DCMP_GREATER, ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_PASSED},
16258 {D3DCMP_NOTEQUAL, ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_PASSED},
16259 {D3DCMP_GREATEREQUAL, ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_PASSED},
16260 {D3DCMP_ALWAYS, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_PASSED},
16262 static struct
16264 struct vec3 position;
16265 DWORD diffuse;
16267 quad[] =
16269 {{-1.0f, -1.0f, 0.1f}, ALPHATEST_PASSED | 0x80000000},
16270 {{-1.0f, 1.0f, 0.1f}, ALPHATEST_PASSED | 0x80000000},
16271 {{ 1.0f, -1.0f, 0.1f}, ALPHATEST_PASSED | 0x80000000},
16272 {{ 1.0f, 1.0f, 0.1f}, ALPHATEST_PASSED | 0x80000000},
16275 window = create_window();
16276 if (!(device = create_device(window, DDSCL_NORMAL)))
16278 skip("Failed to create a 3D device.\n");
16279 DestroyWindow(window);
16280 return;
16282 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
16283 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16285 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
16286 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16287 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
16288 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16289 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
16290 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16291 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHATESTENABLE, TRUE);
16292 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16294 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
16296 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHAFUNC, test_data[i].func);
16297 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16299 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, ALPHATEST_FAILED, 0.0f, 0);
16300 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16301 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHAREF, 0x70);
16302 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16303 hr = IDirect3DDevice7_BeginScene(device);
16304 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16305 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
16306 D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, ARRAY_SIZE(quad), 0);
16307 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16308 hr = IDirect3DDevice7_EndScene(device);
16309 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16310 color = get_surface_color(rt, 320, 240);
16311 ok(compare_color(color, test_data[i].color_greater, 0),
16312 "Alphatest failed, color 0x%08x, expected 0x%08x, alpha > ref, func %u.\n",
16313 color, test_data[i].color_greater, test_data[i].func);
16315 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, ALPHATEST_FAILED, 0.0f, 0);
16316 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16317 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHAREF, 0xff70);
16318 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16319 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ALPHAREF, &value);
16320 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16321 ok(value == 0xff70, "Got unexpected value %#x.\n", value);
16322 hr = IDirect3DDevice7_BeginScene(device);
16323 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16324 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
16325 D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, ARRAY_SIZE(quad), 0);
16326 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16327 hr = IDirect3DDevice7_EndScene(device);
16328 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16329 color = get_surface_color(rt, 320, 240);
16330 ok(compare_color(color, test_data[i].color_greater, 0),
16331 "Alphatest failed, color 0x%08x, expected 0x%08x, alpha > ref, func %u.\n",
16332 color, test_data[i].color_greater, test_data[i].func);
16335 IDirectDrawSurface7_Release(rt);
16336 refcount = IDirect3DDevice7_Release(device);
16337 ok(!refcount, "Device has %u references left.\n", refcount);
16338 DestroyWindow(window);
16341 static void test_clipper_refcount(void)
16343 IDirectDrawSurface7 *surface;
16344 IDirectDrawClipper *clipper, *clipper2;
16345 DDSURFACEDESC2 surface_desc;
16346 IDirectDraw7 *ddraw;
16347 IDirectDraw *ddraw1;
16348 ULONG refcount;
16349 HWND window;
16350 HRESULT hr;
16351 BOOL changed;
16352 const IDirectDrawClipperVtbl *orig_vtbl;
16354 window = create_window();
16355 ddraw = create_ddraw();
16356 ok(!!ddraw, "Failed to create a ddraw object.\n");
16357 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
16358 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16360 memset(&surface_desc, 0, sizeof(surface_desc));
16361 surface_desc.dwSize = sizeof(surface_desc);
16362 surface_desc.dwFlags = DDSD_CAPS;
16363 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
16364 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
16365 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16367 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
16368 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
16369 refcount = get_refcount((IUnknown *)clipper);
16370 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
16372 /* Show that clipper validation doesn't somehow happen through per-clipper vtable
16373 * pointers. */
16374 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper2, NULL);
16375 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
16376 ok(clipper->lpVtbl == clipper2->lpVtbl, "Got different clipper vtables %p and %p.\n",
16377 clipper->lpVtbl, clipper2->lpVtbl);
16378 orig_vtbl = clipper->lpVtbl;
16379 IDirectDrawClipper_Release(clipper2);
16381 /* Surfaces hold a reference to clippers. No surprises there. */
16382 hr = IDirectDrawSurface7_SetClipper(surface, clipper);
16383 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
16384 refcount = get_refcount((IUnknown *)clipper);
16385 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
16387 hr = IDirectDrawSurface7_GetClipper(surface, &clipper2);
16388 ok(SUCCEEDED(hr), "Failed to get clipper, hr %#x.\n", hr);
16389 ok(clipper == clipper2, "Got clipper %p, expected %p.\n", clipper2, clipper);
16390 refcount = IDirectDrawClipper_Release(clipper2);
16391 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
16393 hr = IDirectDrawSurface7_SetClipper(surface, NULL);
16394 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
16395 refcount = get_refcount((IUnknown *)clipper);
16396 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
16398 hr = IDirectDrawSurface7_SetClipper(surface, clipper);
16399 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
16400 refcount = get_refcount((IUnknown *)clipper);
16401 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
16403 refcount = IDirectDrawSurface7_Release(surface);
16404 ok(!refcount, "%u references left.\n", refcount);
16405 refcount = get_refcount((IUnknown *)clipper);
16406 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
16408 /* SetClipper with an invalid pointer crashes. */
16410 /* Clipper methods work with a broken vtable, with the exception of Release. */
16411 clipper->lpVtbl = (void *)0xdeadbeef;
16412 refcount = orig_vtbl->AddRef(clipper);
16413 todo_wine ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
16414 refcount = orig_vtbl->Release(clipper);
16415 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
16417 clipper->lpVtbl = orig_vtbl;
16418 refcount = orig_vtbl->Release(clipper);
16419 todo_wine ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
16421 /* Fix the refcount difference because Wine did not increase the ref in the
16422 * AddRef call above. */
16423 if (refcount)
16425 refcount = IDirectDrawClipper_Release(clipper);
16426 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
16429 /* Steal the reference and see what happens - releasing the surface works fine.
16430 * The clipper is destroyed and not kept alive by a hidden refcount - trying to
16431 * release it after the GetClipper call is likely to crash, and certain to crash
16432 * if we allocate and zero as much heap memory as we can get. */
16433 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
16434 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16435 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
16436 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
16437 hr = IDirectDrawSurface7_SetClipper(surface, clipper);
16438 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
16440 IDirectDrawClipper_Release(clipper);
16441 IDirectDrawClipper_Release(clipper);
16443 if (0)
16445 /* Disabled because it causes heap corruption (HeapValidate fails and random
16446 * hangs in a later HeapFree) on Windows on one of my Machines: MacbookPro 10,1
16447 * running Windows 10 18363.535 and Nvidia driver 425.31. Driver version 441.66
16448 * is affected too. Some testbot machines have crashes directly in GetClipper
16449 * or proceed with a corrupted heap too.
16451 * The same Windows and driver versions run the test without heap corruption on
16452 * a Geforce 1060 GTX card. I have not seen the problem on AMD GPUs either. */
16453 hr = IDirectDrawSurface7_GetClipper(surface, &clipper2);
16454 ok(SUCCEEDED(hr), "Failed to get clipper, hr %#x.\n", hr);
16455 ok(clipper == clipper2, "Got clipper %p, expected %p.\n", clipper2, clipper);
16458 /* Show that invoking the Release method does not crash, but don't get the
16459 * vtable through the clipper pointer because it is no longer pointing to
16460 * valid memory. */
16461 refcount = orig_vtbl->Release(clipper);
16462 ok(!refcount, "%u references left.\n", refcount);
16464 refcount = IDirectDrawSurface7_Release(surface);
16465 ok(!refcount, "%u references left.\n", refcount);
16467 /* It looks like the protection against invalid thispointers is part of
16468 * the IDirectDrawClipper method implementation, not IDirectDrawSurface. */
16469 clipper = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 0x1000);
16470 ok(!!clipper, "failed to allocate memory\n");
16472 /* Assigning the vtable to our fake clipper does NOT make a difference on
16473 * native - there is a different member of the clipper implementation struct
16474 * that is used to determine if a clipper is valid. */
16475 clipper->lpVtbl = orig_vtbl;
16477 refcount = orig_vtbl->AddRef(clipper);
16478 todo_wine ok(!refcount, "Got refcount %u.\n", refcount);
16479 refcount = orig_vtbl->AddRef((IDirectDrawClipper *)(ULONG_PTR)0xdeadbeef);
16480 ok(!refcount, "Got refcount %u.\n", refcount);
16482 changed = 0x1234;
16483 hr = orig_vtbl->IsClipListChanged(clipper, &changed);
16484 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
16485 todo_wine ok(changed == 0x1234, "'changed' changed: %x.\n", changed);
16487 changed = 0x1234;
16488 hr = orig_vtbl->IsClipListChanged((IDirectDrawClipper *)(ULONG_PTR)0xdeadbeef, &changed);
16489 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
16490 ok(changed == 0x1234, "'changed' changed: %x.\n", changed);
16492 /* Nope, we can't initialize our fake clipper. */
16493 hr = IDirectDraw7_QueryInterface(ddraw, &IID_IDirectDraw, (void **)&ddraw1);
16494 ok(SUCCEEDED(hr), "Failed to get ddraw1 interface, hr %#x.\n", hr);
16496 hr = orig_vtbl->Initialize(clipper, ddraw1, 0);
16497 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
16499 IDirectDraw_Release(ddraw1);
16501 HeapFree(GetProcessHeap(), 0, clipper);
16503 refcount = IDirectDraw7_Release(ddraw);
16504 ok(!refcount, "%u references left.\n", refcount);
16505 DestroyWindow(window);
16508 static void test_begin_end_state_block(void)
16510 DWORD stateblock, stateblock2;
16511 IDirect3DDevice7 *device;
16512 ULONG refcount;
16513 DWORD value;
16514 HWND window;
16515 HRESULT hr;
16517 window = create_window();
16518 if (!(device = create_device(window, DDSCL_NORMAL)))
16520 skip("Failed to create 3D device.\n");
16521 DestroyWindow(window);
16522 return;
16525 hr = IDirect3DDevice7_BeginStateBlock(device);
16526 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16528 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
16529 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16531 stateblock = 0xdeadbeef;
16532 hr = IDirect3DDevice7_EndStateBlock(device, &stateblock);
16533 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16534 ok(!!stateblock && stateblock != 0xdeadbeef, "Got unexpected stateblock %#x.\n", stateblock);
16536 stateblock2 = 0xdeadbeef;
16537 hr = IDirect3DDevice7_EndStateBlock(device, &stateblock2);
16538 ok(hr == D3DERR_NOTINBEGINSTATEBLOCK, "Got unexpected hr %#x.\n", hr);
16539 ok(stateblock2 == 0xdeadbeef, "Got unexpected stateblock %#x.\n", stateblock2);
16541 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &value);
16542 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16543 ok(value == TRUE, "Got unexpected value %#x.\n", value);
16545 hr = IDirect3DDevice7_BeginStateBlock(device);
16546 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16548 hr = IDirect3DDevice7_BeginStateBlock(device);
16549 ok(hr == D3DERR_INBEGINSTATEBLOCK, "Got unexpected hr %#x.\n", hr);
16551 hr = IDirect3DDevice7_ApplyStateBlock(device, stateblock);
16552 ok(hr == D3DERR_INBEGINSTATEBLOCK, "Got unexpected hr %#x.\n", hr);
16554 hr = IDirect3DDevice7_CaptureStateBlock(device, stateblock);
16555 ok(hr == D3DERR_INBEGINSTATEBLOCK, "Got unexpected hr %#x.\n", hr);
16557 hr = IDirect3DDevice7_CreateStateBlock(device, D3DSBT_ALL, &stateblock2);
16558 ok(hr == D3DERR_INBEGINSTATEBLOCK, "Got unexpected hr %#x.\n", hr);
16560 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &value);
16561 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16562 ok(value == TRUE, "Got unexpected value %#x.\n", value);
16564 hr = IDirect3DDevice7_EndStateBlock(device, &stateblock2);
16565 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16567 hr = IDirect3DDevice7_ApplyStateBlock(device, stateblock2);
16568 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16570 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &value);
16571 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16572 ok(value == TRUE, "Got unexpected value %#x.\n", value);
16574 refcount = IDirect3DDevice7_Release(device);
16575 ok(!refcount, "Device has %u references left.\n", refcount);
16576 DestroyWindow(window);
16579 static void test_caps(void)
16581 DWORD caps_never, caps_always, caps_hal;
16582 DDCAPS hal_caps, hel_caps;
16583 IDirectDraw7 *ddraw;
16584 HRESULT hr;
16585 BOOL no3d;
16587 caps_never = DDSCAPS_RESERVED1
16588 | DDSCAPS_ALPHA
16589 | DDSCAPS_PRIMARYSURFACELEFT
16590 | DDSCAPS_SYSTEMMEMORY
16591 | DDSCAPS_VISIBLE
16592 | DDSCAPS_WRITEONLY
16593 | DDSCAPS_LIVEVIDEO
16594 | DDSCAPS_HWCODEC
16595 | DDSCAPS_MODEX
16596 | DDSCAPS_RESERVED2
16597 | 0x01000000u
16598 | 0x02000000u
16599 | DDSCAPS_ALLOCONLOAD
16600 | DDSCAPS_VIDEOPORT
16601 | DDSCAPS_STANDARDVGAMODE
16602 | DDSCAPS_OPTIMIZED;
16604 caps_always = DDSCAPS_FLIP
16605 | DDSCAPS_OFFSCREENPLAIN
16606 | DDSCAPS_PRIMARYSURFACE
16607 | DDSCAPS_TEXTURE
16608 | DDSCAPS_ZBUFFER
16609 | DDSCAPS_MIPMAP;
16611 caps_hal = DDSCAPS_BACKBUFFER
16612 | DDSCAPS_COMPLEX
16613 | DDSCAPS_FRONTBUFFER
16614 | DDSCAPS_3DDEVICE
16615 | DDSCAPS_VIDEOMEMORY
16616 | DDSCAPS_LOCALVIDMEM
16617 | DDSCAPS_NONLOCALVIDMEM;
16619 ddraw = create_ddraw();
16620 ok(!!ddraw, "Failed to create a ddraw object.\n");
16622 memset(&hal_caps, 0, sizeof(hal_caps));
16623 memset(&hel_caps, 0, sizeof(hel_caps));
16624 hal_caps.dwSize = sizeof(hal_caps);
16625 hel_caps.dwSize = sizeof(hel_caps);
16626 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, &hel_caps);
16627 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16628 ok(hal_caps.ddsOldCaps.dwCaps == hal_caps.ddsCaps.dwCaps,
16629 "Got unexpected caps %#x, expected %#x.\n",
16630 hal_caps.ddsOldCaps.dwCaps, hal_caps.ddsCaps.dwCaps);
16631 ok(hel_caps.ddsOldCaps.dwCaps == hel_caps.ddsCaps.dwCaps,
16632 "Got unexpected caps %#x, expected %#x.\n",
16633 hel_caps.ddsOldCaps.dwCaps, hel_caps.ddsCaps.dwCaps);
16635 no3d = !(hal_caps.ddsCaps.dwCaps & DDSCAPS_3DDEVICE);
16636 if (hal_caps.ddsCaps.dwCaps)
16638 ok(!(hal_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
16639 ok(!(~hal_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
16640 todo_wine_if(no3d) ok(!(~hal_caps.ddsCaps.dwCaps & caps_hal),
16641 "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
16643 ok(!(hel_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
16644 ok(!(~hel_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
16645 todo_wine_if(!no3d) ok(!(hel_caps.ddsCaps.dwCaps & caps_hal),
16646 "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
16648 IDirectDraw7_Release(ddraw);
16650 if (hal_caps.ddsCaps.dwCaps)
16652 hr = pDirectDrawCreateEx((GUID *)DDCREATE_HARDWAREONLY, (void **)&ddraw, &IID_IDirectDraw7, NULL);
16653 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16655 memset(&hal_caps, 0, sizeof(hal_caps));
16656 memset(&hel_caps, 0, sizeof(hel_caps));
16657 hal_caps.dwSize = sizeof(hal_caps);
16658 hel_caps.dwSize = sizeof(hel_caps);
16659 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, &hel_caps);
16660 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16661 ok(hal_caps.ddsOldCaps.dwCaps == hal_caps.ddsCaps.dwCaps,
16662 "Got unexpected caps %#x, expected %#x.\n",
16663 hal_caps.ddsOldCaps.dwCaps, hal_caps.ddsCaps.dwCaps);
16664 ok(hel_caps.ddsOldCaps.dwCaps == hel_caps.ddsCaps.dwCaps,
16665 "Got unexpected caps %#x, expected %#x.\n",
16666 hel_caps.ddsOldCaps.dwCaps, hel_caps.ddsCaps.dwCaps);
16668 ok(!(hal_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
16669 ok(!(~hal_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
16670 todo_wine_if(no3d) ok(!(~hal_caps.ddsCaps.dwCaps & caps_hal),
16671 "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
16672 todo_wine ok(!hel_caps.ddsCaps.dwCaps, "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
16674 IDirectDraw7_Release(ddraw);
16677 hr = pDirectDrawCreateEx((GUID *)DDCREATE_EMULATIONONLY, (void **)&ddraw, &IID_IDirectDraw7, NULL);
16678 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16680 memset(&hal_caps, 0, sizeof(hal_caps));
16681 memset(&hel_caps, 0, sizeof(hel_caps));
16682 hal_caps.dwSize = sizeof(hal_caps);
16683 hel_caps.dwSize = sizeof(hel_caps);
16684 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, &hel_caps);
16685 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16686 ok(hal_caps.ddsOldCaps.dwCaps == hal_caps.ddsCaps.dwCaps,
16687 "Got unexpected caps %#x, expected %#x.\n",
16688 hal_caps.ddsOldCaps.dwCaps, hal_caps.ddsCaps.dwCaps);
16689 ok(hel_caps.ddsOldCaps.dwCaps == hel_caps.ddsCaps.dwCaps,
16690 "Got unexpected caps %#x, expected %#x.\n",
16691 hel_caps.ddsOldCaps.dwCaps, hel_caps.ddsCaps.dwCaps);
16693 todo_wine ok(!hal_caps.ddsCaps.dwCaps, "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
16694 ok(!(hel_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
16695 ok(!(~hel_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
16696 todo_wine_if(!no3d) ok(!(hel_caps.ddsCaps.dwCaps & caps_hal),
16697 "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
16699 IDirectDraw7_Release(ddraw);
16702 static void test_d32_support(void)
16704 IDirectDrawSurface7 *surface;
16705 DDSURFACEDESC2 surface_desc;
16706 IDirectDraw7 *ddraw;
16707 ULONG refcount;
16708 HWND window;
16709 HRESULT hr;
16711 window = create_window();
16712 ddraw = create_ddraw();
16713 ok(!!ddraw, "Failed to create a ddraw object.\n");
16714 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
16715 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16717 memset(&surface_desc, 0, sizeof(surface_desc));
16718 surface_desc.dwSize = sizeof(surface_desc);
16719 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
16720 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
16721 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
16722 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
16723 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = 32;
16724 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = 0xffffffff;
16725 surface_desc.dwWidth = 64;
16726 surface_desc.dwHeight = 64;
16727 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
16728 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16730 memset(&surface_desc, 0, sizeof(surface_desc));
16731 surface_desc.dwSize = sizeof(surface_desc);
16732 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
16733 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16734 ok((surface_desc.dwFlags & DDSD_PIXELFORMAT), "Got unexpected flags %#x.\n", surface_desc.dwFlags);
16735 ok(U4(surface_desc).ddpfPixelFormat.dwFlags & DDPF_ZBUFFER,
16736 "Got unexpected format flags %#x.\n", U4(surface_desc).ddpfPixelFormat.dwFlags);
16737 ok(U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth == 32,
16738 "Got unexpected dwZBufferBitDepth %u.\n", U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth);
16739 ok(U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask == 0xffffffff,
16740 "Got unexpected Z mask 0x%08x.\n", U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask);
16741 ok(!(surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY),
16742 "Got unexpected surface caps %#x.\n", surface_desc.ddsCaps.dwCaps);
16743 IDirectDrawSurface7_Release(surface);
16745 refcount = IDirectDraw7_Release(ddraw);
16746 ok(!refcount, "%u references left.\n", refcount);
16747 DestroyWindow(window);
16750 static void test_surface_format_conversion_alpha(void)
16752 static const unsigned int rgba_data[4 * 4] =
16754 0xff00ff00, 0xff0000ff, 0xff0000ff, 0xff0000ff,
16755 0xff0000ff, 0xff00ff00, 0xff0000ff, 0xff0000ff,
16756 0xff00ff00, 0xff0000ff, 0xff00ff00, 0xff0000ff,
16757 0xff00ff00, 0xff0000ff, 0xff0000ff, 0xff00ff00,
16759 static const unsigned int rgbx_data[4 * 4] =
16761 0x0000ff00, 0x000000ff, 0x000000ff, 0x000000ff,
16762 0x000000ff, 0x0000ff00, 0x000000ff, 0x000000ff,
16763 0x0000ff00, 0x000000ff, 0x0000ff00, 0x000000ff,
16764 0x0000ff00, 0x000000ff, 0x000000ff, 0x0000ff00,
16766 static const unsigned short int r5g6b5_data[4 * 4] =
16768 0x07e0, 0x001f, 0x001f, 0x001f,
16769 0x001f, 0x07e0, 0x001f, 0x001f,
16770 0x07e0, 0x001f, 0x07e0, 0x001f,
16771 0x07e0, 0x001f, 0x001f, 0x07e0,
16773 static const unsigned short int r5g5b5x1_data[4 * 4] =
16775 0x03e0, 0x001f, 0x001f, 0x001f,
16776 0x001f, 0x03e0, 0x001f, 0x001f,
16777 0x03e0, 0x001f, 0x03e0, 0x001f,
16778 0x03e0, 0x001f, 0x001f, 0x03e0,
16780 static const unsigned short int r5g5b5a1_data[4 * 4] =
16782 0x83e0, 0x801f, 0x801f, 0x801f,
16783 0x801f, 0x83e0, 0x801f, 0x801f,
16784 0x83e0, 0x801f, 0x83e0, 0x801f,
16785 0x83e0, 0x801f, 0x801f, 0x83e0,
16787 static const unsigned int dxt1_data[8] =
16789 0x001f07e0, 0x14445154,
16791 static const unsigned int dxt2_data[16] =
16793 0xffffffff, 0xffffffff, 0x001f07e0, 0x14445154,
16796 enum test_format_id
16798 FMT_RGBA,
16799 FMT_RGBX,
16800 FMT_R5G6B5,
16801 FMT_R5G5B5X1,
16802 FMT_R5G5B5A1,
16803 FMT_DXT1,
16804 FMT_DXT2,
16805 FMT_DXT3,
16808 static const struct test_format
16810 DDPIXELFORMAT fmt;
16811 const char *name;
16812 unsigned int block_size, x_blocks, y_blocks;
16813 DWORD support_flag;
16814 BOOL broken_software_blit, broken_hardware_blit;
16816 formats[] =
16820 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
16821 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
16823 "RGBA", 4, 4, 4,
16827 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
16828 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
16830 "RGBX", 4, 4, 4,
16834 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
16835 {16}, {0x0000f800}, {0x000007e0}, {0x0000001f}, {0x00000000}
16837 "R5G6B5", 2, 4, 4, 0, TRUE,
16838 /* Looks broken for sysmem texture conversions on Windows (at
16839 * least with hardware device), the result is either error from
16840 * _Blt() or a copy of the source data without any conversion. */
16844 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
16845 {16}, {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00000000}
16847 "R5G5B5X1", 2, 4, 4,
16851 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
16852 {16}, {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00008000}
16854 "R5G5B5A1", 2, 4, 4, 0, FALSE, TRUE,
16858 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
16859 {0}, {0}, {0}, {0}, {0}
16861 "DXT1", 8, 1, 1, SUPPORT_DXT1,
16865 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '2'),
16866 {0}, {0}, {0}, {0}, {0}
16868 "DXT2", 16, 1, 1, SUPPORT_DXT2,
16872 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '3'),
16873 {0}, {0}, {0}, {0}, {0}
16875 "DXT3", 16, 1, 1, SUPPORT_DXT3,
16879 static const struct
16881 DWORD src_caps, dst_caps;
16883 test_caps[] =
16885 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY},
16886 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY},
16887 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY},
16888 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY},
16891 static const struct
16893 enum test_format_id src_format;
16894 const void *src_data;
16895 enum test_format_id dst_format;
16896 const void *expected_data;
16897 BOOL todo;
16899 tests[] =
16901 #if 0
16902 /* The following 3 tests give different results on AMD and NVIDIA on Windows, disabling. */
16903 {FMT_RGBX, rgbx_data, FMT_RGBA, rgba_data},
16904 {FMT_RGBA, rgba_data, FMT_RGBX, rgbx_data},
16905 {FMT_R5G5B5X1, r5g5b5x1_data, FMT_RGBA, rgba_data},
16906 #endif
16907 {FMT_R5G6B5, r5g6b5_data, FMT_RGBA, rgba_data},
16908 {FMT_R5G6B5, r5g6b5_data, FMT_R5G5B5A1, r5g5b5a1_data},
16909 {FMT_R5G5B5X1, r5g5b5x1_data, FMT_R5G5B5A1, r5g5b5x1_data, TRUE},
16910 {FMT_R5G5B5A1, r5g5b5a1_data, FMT_R5G6B5, r5g6b5_data},
16911 {FMT_RGBA, rgba_data, FMT_DXT1, dxt1_data},
16912 {FMT_RGBX, rgbx_data, FMT_DXT1, dxt1_data},
16913 {FMT_RGBA, rgba_data, FMT_DXT2, dxt2_data},
16914 {FMT_RGBX, rgbx_data, FMT_DXT2, dxt2_data},
16915 {FMT_RGBA, rgba_data, FMT_DXT3, dxt2_data},
16916 {FMT_RGBX, rgbx_data, FMT_DXT3, dxt2_data},
16917 {FMT_DXT1, dxt1_data, FMT_DXT2, dxt2_data},
16918 {FMT_DXT1, dxt1_data, FMT_RGBA, rgba_data},
16919 {FMT_DXT1, dxt1_data, FMT_RGBX, rgba_data},
16920 {FMT_DXT3, dxt2_data, FMT_RGBA, rgba_data},
16921 {FMT_DXT3, dxt2_data, FMT_RGBX, rgba_data},
16924 const struct test_format *src_format, *dst_format;
16925 IDirectDrawSurface7 *src_surf, *dst_surf;
16926 DDSURFACEDESC2 surface_desc, lock;
16927 unsigned int i, j, x, y, pitch;
16928 IDirect3DDevice7 *device;
16929 DWORD supported_fmts;
16930 IDirectDraw7 *ddraw;
16931 ULONG refcount;
16932 BOOL is_wine;
16933 HWND window;
16934 BOOL passed;
16935 HRESULT hr;
16937 window = create_window();
16938 if (!(device = create_device(window, DDSCL_NORMAL)))
16940 skip("Failed to create a 3D device, skipping test.\n");
16941 DestroyWindow(window);
16942 return;
16945 ddraw = create_ddraw();
16946 ok(!!ddraw, "Failed to create a ddraw object.\n");
16947 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
16948 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16950 hr = IDirect3DDevice7_EnumTextureFormats(device, test_block_formats_creation_cb,
16951 &supported_fmts);
16952 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16954 is_wine = !strcmp(winetest_platform, "wine");
16956 memset(&surface_desc, 0, sizeof(surface_desc));
16957 surface_desc.dwSize = sizeof(surface_desc);
16958 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
16959 surface_desc.dwWidth = 4;
16960 surface_desc.dwHeight = 4;
16962 for (i = 0; i < ARRAY_SIZE(tests); ++i)
16964 src_format = &formats[tests[i].src_format];
16965 dst_format = &formats[tests[i].dst_format];
16967 if (~supported_fmts & dst_format->support_flag)
16969 skip("%s format is not supported, skipping test %u.\n", dst_format->name, i);
16970 continue;
16972 if (~supported_fmts & src_format->support_flag)
16974 skip("%s format is not supported, skipping test %u.\n", src_format->name, i);
16975 continue;
16978 for (j = 0; j < ARRAY_SIZE(test_caps); ++j)
16980 if (!is_wine && ((test_caps[j].src_caps | test_caps[j].dst_caps) & DDSCAPS_SYSTEMMEMORY)
16981 && (src_format->broken_software_blit || dst_format->broken_software_blit))
16982 continue;
16983 if (!is_wine && (test_caps[j].dst_caps & DDSCAPS_VIDEOMEMORY)
16984 && dst_format->broken_hardware_blit)
16985 continue;
16987 U4(surface_desc).ddpfPixelFormat = src_format->fmt;
16988 surface_desc.ddsCaps.dwCaps = test_caps[j].src_caps;
16989 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surf, NULL);
16990 ok(hr == DD_OK, "Test (%u, %u), got unexpected hr %#x.\n", j, i, hr);
16992 U4(surface_desc).ddpfPixelFormat = dst_format->fmt;
16993 surface_desc.ddsCaps.dwCaps = test_caps[j].dst_caps;
16994 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surf, NULL);
16995 ok(hr == DD_OK, "Test (%u, %u), got unexpected hr %#x.\n", j, i, hr);
16997 memset(&lock, 0, sizeof(lock));
16998 lock.dwSize = sizeof(lock);
16999 hr = IDirectDrawSurface7_Lock(src_surf, NULL, &lock, 0, NULL);
17000 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17001 pitch = U1(lock).lPitch;
17002 for (y = 0; y < src_format->y_blocks; ++y)
17004 memcpy((BYTE *)lock.lpSurface + y * pitch,
17005 (BYTE *)tests[i].src_data + y * src_format->x_blocks * src_format->block_size,
17006 src_format->block_size * src_format->x_blocks);
17008 hr = IDirectDrawSurface7_Unlock(src_surf, NULL);
17009 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17011 hr = IDirectDrawSurface7_Blt(dst_surf, NULL, src_surf, NULL, DDBLT_WAIT, NULL);
17012 if (!is_wine && FAILED(hr))
17014 /* Some software blits are rejected on Windows. */
17015 IDirectDrawSurface7_Release(dst_surf);
17016 IDirectDrawSurface7_Release(src_surf);
17017 skip("Skipping test (%u, %u), cannot blit %s -> %s, hr %#x.\n", j, i,
17018 src_format->name, dst_format->name, hr);
17019 continue;
17021 ok(hr == DD_OK, "Test (%u, %s -> %s), got unexpected hr %#x.\n", j,
17022 src_format->name, dst_format->name, hr);
17024 memset(&lock, 0, sizeof(lock));
17025 lock.dwSize = sizeof(lock);
17026 hr = IDirectDrawSurface7_Lock(dst_surf, NULL, &lock, 0, NULL);
17027 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17028 pitch = U1(lock).lPitch;
17030 for (y = 0; y < dst_format->y_blocks; ++y)
17032 const void *expected_data = tests[i].expected_data;
17034 passed = !memcmp((BYTE*)lock.lpSurface + y * pitch,
17035 (BYTE *)expected_data + y * dst_format->x_blocks * dst_format->block_size,
17036 dst_format->block_size * dst_format->x_blocks);
17037 todo_wine_if(tests[i].todo)
17038 ok(passed, "Test (%u, %s -> %s), row %u, unexpected surface data.\n", j,
17039 src_format->name, dst_format->name, y);
17041 if (!passed && !(is_wine && tests[i].todo))
17043 for (x = 0; x < dst_format->x_blocks * dst_format->block_size / 4; ++x)
17045 trace("Test (%u, %u), x %u, y %u, got 0x%08x, expected 0x%08x.\n", j, i, x, y,
17046 *(unsigned int *)((BYTE *)lock.lpSurface + y * pitch + x * 4),
17047 *(unsigned int *)((BYTE *)expected_data + y * dst_format->x_blocks
17048 * dst_format->block_size + x * 4));
17051 if (!passed)
17052 break;
17054 hr = IDirectDrawSurface7_Unlock(dst_surf, NULL);
17055 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17057 IDirectDrawSurface7_Release(dst_surf);
17058 IDirectDrawSurface7_Release(src_surf);
17062 IDirect3DDevice7_Release(device);
17063 refcount = IDirectDraw7_Release(ddraw);
17064 ok(!refcount, "%u references left.\n", refcount);
17065 DestroyWindow(window);
17068 static void test_compressed_surface_stretch(void)
17070 static const struct
17072 unsigned int src_width, src_height;
17073 unsigned int dst_width, dst_height;
17074 unsigned int src_x, src_y;
17075 unsigned int dst_x, dst_y;
17076 BOOL todo_src, todo_dst;
17078 test_sizes[] =
17080 {4, 4, 8, 8},
17081 {8, 8, 4, 4},
17082 {4, 4, 2, 2, 0, 0, 0, 0, FALSE, TRUE},
17083 {4, 4, 6, 6, 0, 0, 0, 0, FALSE, TRUE},
17084 {4, 4, 8, 8, 2, 2, 2, 2, TRUE, TRUE},
17087 static const struct
17089 DWORD src_caps, dst_caps;
17091 test_caps[] =
17093 #if 0
17094 /* Broken on Windows. */
17095 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY},
17096 #endif
17097 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY},
17098 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY},
17099 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY},
17102 static struct
17104 DDPIXELFORMAT fmt;
17105 const char *name;
17106 DWORD support_flag;
17108 test_formats[] =
17112 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
17113 {16}, {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00008000}
17115 "R5G5B5A1",
17119 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
17120 {0}, {0}, {0}, {0}, {0}
17122 "DXT1", SUPPORT_DXT1,
17126 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '3'),
17127 {0}, {0}, {0}, {0}, {0}
17129 "DXT3", SUPPORT_DXT3,
17133 unsigned int i, j, k, l, x, y, pitch;
17134 DDSURFACEDESC2 rb_surface_desc, src_surface_desc, dst_surface_desc, lock;
17135 IDirectDrawSurface7 *src_surf, *dst_surf, *rb_surf;
17136 IDirect3DDevice7 *device;
17137 RECT src_rect, dst_rect;
17138 DWORD supported_fmts;
17139 unsigned short *data;
17140 IDirectDraw7 *ddraw;
17141 ULONG refcount;
17142 HWND window;
17143 BOOL passed;
17144 DDBLTFX fx;
17145 HRESULT hr;
17147 window = create_window();
17148 if (!(device = create_device(window, DDSCL_NORMAL)))
17150 skip("Failed to create a 3D device, skipping test.\n");
17151 DestroyWindow(window);
17152 return;
17155 ddraw = create_ddraw();
17156 ok(!!ddraw, "Failed to create a ddraw object.\n");
17157 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
17158 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17160 hr = IDirect3DDevice7_EnumTextureFormats(device, test_block_formats_creation_cb,
17161 &supported_fmts);
17162 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17164 memset(&src_surface_desc, 0, sizeof(src_surface_desc));
17165 src_surface_desc.dwSize = sizeof(src_surface_desc);
17166 src_surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
17167 dst_surface_desc = src_surface_desc;
17169 memset(&rb_surface_desc, 0, sizeof(rb_surface_desc));
17170 rb_surface_desc.dwSize = sizeof(rb_surface_desc);
17171 rb_surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
17172 U4(rb_surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(rb_surface_desc).ddpfPixelFormat);
17173 U4(rb_surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
17174 U1(U4(rb_surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
17175 U2(U4(rb_surface_desc).ddpfPixelFormat).dwRBitMask = 0x00007c00;
17176 U3(U4(rb_surface_desc).ddpfPixelFormat).dwGBitMask = 0x000003e0;
17177 U4(U4(rb_surface_desc).ddpfPixelFormat).dwBBitMask = 0x0000001f;
17178 U5(U4(rb_surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0x00008000;
17179 rb_surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
17181 memset(&fx, 0, sizeof(fx));
17182 fx.dwSize = sizeof(fx);
17184 memset(&lock, 0, sizeof(lock));
17185 lock.dwSize = sizeof(lock);
17187 for (i = 0; i < ARRAY_SIZE(test_caps); ++i)
17189 src_surface_desc.ddsCaps.dwCaps = test_caps[i].src_caps;
17190 dst_surface_desc.ddsCaps.dwCaps = test_caps[i].dst_caps;
17192 for (j = 0; j < ARRAY_SIZE(test_sizes); ++j)
17194 SetRect(&src_rect, test_sizes[j].src_x, test_sizes[j].src_y,
17195 test_sizes[j].src_width, test_sizes[j].src_height);
17196 SetRect(&dst_rect, test_sizes[j].dst_x, test_sizes[j].dst_y,
17197 test_sizes[j].dst_width, test_sizes[j].dst_height);
17199 src_surface_desc.dwWidth = test_sizes[j].src_width;
17200 src_surface_desc.dwHeight = test_sizes[j].src_height;
17202 dst_surface_desc.dwWidth = (test_sizes[j].dst_width + 3) & ~3;
17203 dst_surface_desc.dwHeight = (test_sizes[j].dst_height + 3) & ~3;
17205 rb_surface_desc.dwWidth = max(src_surface_desc.dwWidth, dst_surface_desc.dwWidth);
17206 rb_surface_desc.dwHeight = max(src_surface_desc.dwHeight, dst_surface_desc.dwHeight);
17208 hr = IDirectDraw7_CreateSurface(ddraw, &rb_surface_desc, &rb_surf, NULL);
17209 ok(hr == DD_OK, "Test (%u, %u), got unexpected hr %#x.\n", i, j, hr);
17211 for (k = 0; k < ARRAY_SIZE(test_formats); ++k)
17213 U4(src_surface_desc).ddpfPixelFormat = test_formats[k].fmt;
17214 hr = IDirectDraw7_CreateSurface(ddraw, &src_surface_desc, &src_surf, NULL);
17215 ok(hr == DD_OK, "Test (%u, %u, %u), got unexpected hr %#x.\n", i, j, k, hr);
17217 U5(fx).dwFillColor = 0x801f;
17218 hr = IDirectDrawSurface7_Blt(rb_surf, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
17219 ok(hr == DD_OK, "Test (%u, %u, %u), got unexpected hr %#x.\n", i, j, k, hr);
17221 hr = IDirectDrawSurface7_Blt(src_surf, &src_rect, rb_surf, &src_rect, DDBLT_WAIT, NULL);
17223 todo_wine_if(test_formats[k].fmt.dwFlags == DDPF_FOURCC && test_sizes[j].todo_src)
17224 ok(hr == DD_OK, "Test (%u, %u, %u), got unexpected hr %#x.\n", i, j, k, hr);
17225 if (FAILED(hr))
17227 IDirectDrawSurface7_Release(src_surf);
17228 continue;
17231 for (l = 0; l < ARRAY_SIZE(test_formats); ++l)
17233 if (~supported_fmts & test_formats[l].support_flag)
17235 skip("%s format is not supported, skipping test %u.\n", test_formats[l].name, i);
17236 continue;
17239 U4(dst_surface_desc).ddpfPixelFormat = test_formats[l].fmt;
17241 hr = IDirectDraw7_CreateSurface(ddraw, &dst_surface_desc, &dst_surf, NULL);
17242 ok(hr == DD_OK, "Test (%u, %u, %u, %u), got unexpected hr %#x.\n", i, j, k, l, hr);
17244 memset(&lock, 0, sizeof(lock));
17245 lock.dwSize = sizeof(lock);
17247 /* r200 does not init vidmem DXT3 surfaces to 0 correctly. Do it manually.
17248 * We can't use DDBLT_COLORFILL on compressed surfaces, so we need memset.
17250 * Locking alone is not enough, so this isn't an accidental workaround that
17251 * forces a different codepath because the destination is currently in sysmem. */
17252 if (test_formats[l].fmt.dwFourCC == MAKEFOURCC('D', 'X', 'T', '3'))
17254 hr = IDirectDrawSurface7_Lock(dst_surf, NULL, &lock, 0, NULL);
17255 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17256 memset(lock.lpSurface, 0, U1(lock).dwLinearSize);
17257 hr = IDirectDrawSurface7_Unlock(dst_surf, NULL);
17258 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17261 hr = IDirectDrawSurface7_Blt(dst_surf, &dst_rect, src_surf, &src_rect, DDBLT_WAIT, NULL);
17262 todo_wine_if(test_formats[l].fmt.dwFlags == DDPF_FOURCC && test_sizes[j].todo_dst)
17263 ok(hr == DD_OK, "Test (%u, %u, %u, %u), got unexpected hr %#x.\n", i, j, k, l, hr);
17264 if (FAILED(hr))
17266 IDirectDrawSurface7_Release(dst_surf);
17267 continue;
17270 U5(fx).dwFillColor = 0xffffffff;
17271 hr = IDirectDrawSurface7_Blt(rb_surf, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
17272 ok(hr == DD_OK, "Test (%u, %u, %u, %u), got unexpected hr %#x.\n", i, j, k, l, hr);
17274 hr = IDirectDrawSurface7_Blt(rb_surf, &dst_rect, dst_surf, &dst_rect, DDBLT_WAIT, NULL);
17275 ok(hr == DD_OK, "Test (%u, %u, %u, %u), got unexpected hr %#x.\n", i, j, k, l, hr);
17276 hr = IDirectDrawSurface7_Lock(rb_surf, NULL, &lock, 0, NULL);
17277 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17278 pitch = U1(lock).lPitch;
17280 passed = TRUE;
17281 for (y = dst_rect.top; y < dst_rect.bottom && passed; ++y)
17283 data = (unsigned short *)((BYTE *)lock.lpSurface + y * pitch);
17285 for (x = dst_rect.left; x < dst_rect.right && passed; ++x)
17287 passed = data[x] == 0x801f;
17288 ok(passed, "Test (%u, %u, %u, %u), x %u, y %u, "
17289 "got unexpected colour 0x%04x.\n", i, j, k, l, x, y, data[x]);
17292 hr = IDirectDrawSurface7_Unlock(rb_surf, NULL);
17293 IDirectDrawSurface7_Release(dst_surf);
17295 IDirectDrawSurface7_Release(src_surf);
17297 IDirectDrawSurface7_Release(rb_surf);
17301 IDirect3DDevice7_Release(device);
17302 refcount = IDirectDraw7_Release(ddraw);
17303 ok(!refcount, "%u references left.\n", refcount);
17304 DestroyWindow(window);
17307 START_TEST(ddraw7)
17309 DDDEVICEIDENTIFIER2 identifier;
17310 HMODULE module, dwmapi;
17311 DEVMODEW current_mode;
17312 IDirectDraw7 *ddraw;
17314 module = GetModuleHandleA("ddraw.dll");
17315 if (!(pDirectDrawCreateEx = (void *)GetProcAddress(module, "DirectDrawCreateEx")))
17317 win_skip("DirectDrawCreateEx not available, skipping tests.\n");
17318 return;
17321 if (!(ddraw = create_ddraw()))
17323 skip("Failed to create a ddraw object, skipping tests.\n");
17324 return;
17327 if (ddraw_get_identifier(ddraw, &identifier))
17329 trace("Driver string: \"%s\"\n", identifier.szDriver);
17330 trace("Description string: \"%s\"\n", identifier.szDescription);
17331 trace("Driver version %d.%d.%d.%d\n",
17332 HIWORD(U(identifier.liDriverVersion).HighPart), LOWORD(U(identifier.liDriverVersion).HighPart),
17333 HIWORD(U(identifier.liDriverVersion).LowPart), LOWORD(U(identifier.liDriverVersion).LowPart));
17335 IDirectDraw7_Release(ddraw);
17337 memset(&current_mode, 0, sizeof(current_mode));
17338 current_mode.dmSize = sizeof(current_mode);
17339 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
17340 registry_mode.dmSize = sizeof(registry_mode);
17341 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
17342 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
17343 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
17345 skip("Current mode does not match registry mode, skipping test.\n");
17346 return;
17349 if ((dwmapi = LoadLibraryA("dwmapi.dll")))
17350 pDwmIsCompositionEnabled = (void *)GetProcAddress(dwmapi, "DwmIsCompositionEnabled");
17352 test_process_vertices();
17353 test_coop_level_create_device_window();
17354 test_clipper_blt();
17355 test_coop_level_d3d_state();
17356 test_surface_interface_mismatch();
17357 test_coop_level_threaded();
17358 test_depth_blit();
17359 test_texture_load_ckey();
17360 test_zenable();
17361 test_ck_rgba();
17362 test_ck_default();
17363 test_ck_complex();
17364 test_surface_qi();
17365 test_device_qi();
17366 test_wndproc();
17367 test_window_style();
17368 test_redundant_mode_set();
17369 test_coop_level_mode_set();
17370 test_coop_level_mode_set_multi();
17371 test_initialize();
17372 test_coop_level_surf_create();
17373 test_vb_discard();
17374 test_coop_level_multi_window();
17375 test_draw_strided();
17376 test_lighting();
17377 test_specular_lighting();
17378 test_clear_rect_count();
17379 test_coop_level_versions();
17380 test_fog_special();
17381 test_lighting_interface_versions();
17382 test_coop_level_activateapp();
17383 test_texturemanage();
17384 test_block_formats_creation();
17385 test_unsupported_formats();
17386 test_rt_caps();
17387 test_primary_caps();
17388 test_surface_lock();
17389 test_surface_discard();
17390 test_flip();
17391 test_set_surface_desc();
17392 test_user_memory_getdc();
17393 test_sysmem_overlay();
17394 test_primary_palette();
17395 test_surface_attachment();
17396 test_private_data();
17397 test_pixel_format();
17398 test_create_surface_pitch();
17399 test_mipmap();
17400 test_palette_complex();
17401 test_p8_blit();
17402 test_material();
17403 test_palette_gdi();
17404 test_palette_alpha();
17405 test_vb_writeonly();
17406 test_lost_device();
17407 test_resource_priority();
17408 test_surface_desc_lock();
17409 test_fog_interpolation();
17410 test_fog_process_vertices();
17411 test_negative_fixedfunction_fog();
17412 test_table_fog_zw();
17413 test_signed_formats();
17414 test_color_fill();
17415 test_texcoordindex();
17416 test_colorkey_precision();
17417 test_range_colorkey();
17418 test_shademode();
17419 test_lockrect_invalid();
17420 test_yv12_overlay();
17421 test_offscreen_overlay();
17422 test_overlay_rect();
17423 test_blt();
17424 test_blt_z_alpha();
17425 test_cross_device_blt();
17426 test_color_clamping();
17427 test_getdc();
17428 test_draw_primitive();
17429 test_edge_antialiasing_blending();
17430 test_display_mode_surface_pixel_format();
17431 test_surface_desc_size();
17432 test_get_surface_from_dc();
17433 test_ck_operation();
17434 test_vb_refcount();
17435 test_compute_sphere_visibility();
17436 test_clip_planes_limits();
17437 test_texture_stages_limits();
17438 test_set_render_state();
17439 test_map_synchronisation();
17440 test_depth_readback();
17441 test_clear();
17442 test_enum_surfaces();
17443 test_viewport();
17444 test_device_load();
17445 test_color_vertex();
17446 test_killfocus();
17447 test_sysmem_draw();
17448 test_gdi_surface();
17449 test_multiply_transform();
17450 test_alphatest();
17451 test_clipper_refcount();
17452 test_begin_end_state_block();
17453 test_caps();
17454 test_d32_support();
17455 test_surface_format_conversion_alpha();
17456 test_compressed_surface_stretch();