version/tests: Enable compilation with long types.
[wine.git] / dlls / ddraw / tests / ddraw7.c
blob84789e8f1777a4a7f0bc2c104e4f1669510379b8
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;
33 static const GUID *hw_device_guid = &IID_IDirect3DHALDevice;
35 static HRESULT (WINAPI *pDwmIsCompositionEnabled)(BOOL *);
37 struct vec2
39 float x, y;
42 struct vec3
44 float x, y, z;
47 struct vec4
49 float x, y, z, w;
52 struct create_window_thread_param
54 HWND window;
55 HANDLE window_created;
56 HANDLE destroy_window;
57 HANDLE thread;
60 static BOOL compare_float(float f, float g, unsigned int ulps)
62 int x = *(int *)&f;
63 int y = *(int *)&g;
65 if (x < 0)
66 x = INT_MIN - x;
67 if (y < 0)
68 y = INT_MIN - y;
70 if (abs(x - y) > ulps)
71 return FALSE;
73 return TRUE;
76 static BOOL compare_vec3(struct vec3 *vec, float x, float y, float z, unsigned int ulps)
78 return compare_float(vec->x, x, ulps)
79 && compare_float(vec->y, y, ulps)
80 && compare_float(vec->z, z, ulps);
83 static BOOL compare_vec4(const struct vec4 *vec, float x, float y, float z, float w, unsigned int ulps)
85 return compare_float(vec->x, x, ulps)
86 && compare_float(vec->y, y, ulps)
87 && compare_float(vec->z, z, ulps)
88 && compare_float(vec->w, w, ulps);
91 static BOOL compare_uint(unsigned int x, unsigned int y, unsigned int max_diff)
93 unsigned int diff = x > y ? x - y : y - x;
95 return diff <= max_diff;
98 static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
100 return compare_uint(c1 & 0xff, c2 & 0xff, max_diff)
101 && compare_uint((c1 >> 8) & 0xff, (c2 >> 8) & 0xff, max_diff)
102 && compare_uint((c1 >> 16) & 0xff, (c2 >> 16) & 0xff, max_diff)
103 && compare_uint((c1 >> 24) & 0xff, (c2 >> 24) & 0xff, max_diff);
106 static BOOL compare_mode_rect(const DEVMODEW *mode1, const DEVMODEW *mode2)
108 return mode1->dmPosition.x == mode2->dmPosition.x
109 && mode1->dmPosition.y == mode2->dmPosition.y
110 && mode1->dmPelsWidth == mode2->dmPelsWidth
111 && mode1->dmPelsHeight == mode2->dmPelsHeight;
114 static ULONG get_refcount(IUnknown *iface)
116 IUnknown_AddRef(iface);
117 return IUnknown_Release(iface);
120 static void get_virtual_rect(RECT *rect)
122 rect->left = GetSystemMetrics(SM_XVIRTUALSCREEN);
123 rect->top = GetSystemMetrics(SM_YVIRTUALSCREEN);
124 rect->right = rect->left + GetSystemMetrics(SM_CXVIRTUALSCREEN);
125 rect->bottom = rect->top + GetSystemMetrics(SM_CYVIRTUALSCREEN);
128 /* Try to make sure pending X events have been processed before continuing */
129 static void flush_events(void)
131 int diff = 200;
132 DWORD time;
133 MSG msg;
135 time = GetTickCount() + diff;
136 while (diff > 0)
138 if (MsgWaitForMultipleObjects(0, NULL, FALSE, 100, QS_ALLINPUT) == WAIT_TIMEOUT)
139 break;
140 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
141 DispatchMessageA(&msg);
142 diff = time - GetTickCount();
146 static BOOL ddraw_get_identifier(IDirectDraw7 *ddraw, DDDEVICEIDENTIFIER2 *identifier)
148 HRESULT hr;
150 hr = IDirectDraw7_GetDeviceIdentifier(ddraw, identifier, 0);
151 ok(SUCCEEDED(hr), "Failed to get device identifier, hr %#x.\n", hr);
153 return SUCCEEDED(hr);
156 static BOOL ddraw_is_warp(IDirectDraw7 *ddraw)
158 DDDEVICEIDENTIFIER2 identifier;
160 return strcmp(winetest_platform, "wine")
161 && ddraw_get_identifier(ddraw, &identifier)
162 && strstr(identifier.szDriver, "warp");
165 static BOOL ddraw_is_vendor(IDirectDraw7 *ddraw, DWORD vendor)
167 DDDEVICEIDENTIFIER2 identifier;
169 return strcmp(winetest_platform, "wine")
170 && ddraw_get_identifier(ddraw, &identifier)
171 && identifier.dwVendorId == vendor;
174 static BOOL ddraw_is_intel(IDirectDraw7 *ddraw)
176 return ddraw_is_vendor(ddraw, 0x8086);
179 static BOOL ddraw_is_nvidia(IDirectDraw7 *ddraw)
181 return ddraw_is_vendor(ddraw, 0x10de);
184 static BOOL ddraw_is_vmware(IDirectDraw7 *ddraw)
186 return ddraw_is_vendor(ddraw, 0x15ad);
189 static BOOL ddraw_is_amd(IDirectDraw7 *ddraw)
191 return ddraw_is_vendor(ddraw, 0x1002);
194 static BOOL is_software_device_type(const GUID *device_guid)
196 return device_guid != &IID_IDirect3DTnLHalDevice && device_guid != &IID_IDirect3DHALDevice;
199 static IDirectDrawSurface7 *create_overlay(IDirectDraw7 *ddraw,
200 unsigned int width, unsigned int height, DWORD format)
202 IDirectDrawSurface7 *surface;
203 DDSURFACEDESC2 desc;
205 memset(&desc, 0, sizeof(desc));
206 desc.dwSize = sizeof(desc);
207 desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
208 desc.dwWidth = width;
209 desc.dwHeight = height;
210 desc.ddsCaps.dwCaps = DDSCAPS_OVERLAY;
211 U4(desc).ddpfPixelFormat.dwSize = sizeof(U4(desc).ddpfPixelFormat);
212 U4(desc).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
213 U4(desc).ddpfPixelFormat.dwFourCC = format;
215 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &desc, &surface, NULL)))
216 return NULL;
217 return surface;
220 static HWND create_window(void)
222 RECT r = {0, 0, 640, 480};
224 AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
226 return CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
227 CW_USEDEFAULT, CW_USEDEFAULT, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL);
230 static DWORD WINAPI create_window_thread_proc(void *param)
232 struct create_window_thread_param *p = param;
233 DWORD res;
234 BOOL ret;
236 p->window = create_window();
237 ret = SetEvent(p->window_created);
238 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
240 for (;;)
242 MSG msg;
244 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
245 DispatchMessageA(&msg);
246 res = WaitForSingleObject(p->destroy_window, 100);
247 if (res == WAIT_OBJECT_0)
248 break;
249 if (res != WAIT_TIMEOUT)
251 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
252 break;
256 DestroyWindow(p->window);
258 return 0;
261 static void create_window_thread(struct create_window_thread_param *p)
263 DWORD res, tid;
265 p->window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
266 ok(!!p->window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
267 p->destroy_window = CreateEventA(NULL, FALSE, FALSE, NULL);
268 ok(!!p->destroy_window, "CreateEvent failed, last error %#x.\n", GetLastError());
269 p->thread = CreateThread(NULL, 0, create_window_thread_proc, p, 0, &tid);
270 ok(!!p->thread, "Failed to create thread, last error %#x.\n", GetLastError());
271 res = WaitForSingleObject(p->window_created, INFINITE);
272 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
275 static void destroy_window_thread(struct create_window_thread_param *p)
277 SetEvent(p->destroy_window);
278 WaitForSingleObject(p->thread, INFINITE);
279 CloseHandle(p->destroy_window);
280 CloseHandle(p->window_created);
281 CloseHandle(p->thread);
284 static IDirectDrawSurface7 *get_depth_stencil(IDirect3DDevice7 *device)
286 IDirectDrawSurface7 *rt, *ret;
287 DDSCAPS2 caps = {DDSCAPS_ZBUFFER, 0, 0, {0}};
288 HRESULT hr;
290 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
291 ok(SUCCEEDED(hr), "Failed to get the render target, hr %#x.\n", hr);
292 hr = IDirectDrawSurface7_GetAttachedSurface(rt, &caps, &ret);
293 ok(SUCCEEDED(hr) || hr == DDERR_NOTFOUND, "Failed to get the z buffer, hr %#x.\n", hr);
294 IDirectDrawSurface7_Release(rt);
295 return ret;
298 /* Free original_modes after finished using it */
299 static BOOL save_display_modes(DEVMODEW **original_modes, unsigned int *display_count)
301 unsigned int number, size = 2, count = 0, index = 0;
302 DISPLAY_DEVICEW display_device;
303 DEVMODEW *modes, *tmp;
305 if (!(modes = heap_alloc(size * sizeof(*modes))))
306 return FALSE;
308 display_device.cb = sizeof(display_device);
309 while (EnumDisplayDevicesW(NULL, index++, &display_device, 0))
311 /* Skip software devices */
312 if (swscanf(display_device.DeviceName, L"\\\\.\\DISPLAY%u", &number) != 1)
313 continue;
315 if (!(display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
316 continue;
318 if (count >= size)
320 size *= 2;
321 if (!(tmp = heap_realloc(modes, size * sizeof(*modes))))
323 heap_free(modes);
324 return FALSE;
326 modes = tmp;
329 memset(&modes[count], 0, sizeof(modes[count]));
330 modes[count].dmSize = sizeof(modes[count]);
331 if (!EnumDisplaySettingsW(display_device.DeviceName, ENUM_CURRENT_SETTINGS, &modes[count]))
333 heap_free(modes);
334 return FALSE;
337 lstrcpyW(modes[count++].dmDeviceName, display_device.DeviceName);
340 *original_modes = modes;
341 *display_count = count;
342 return TRUE;
345 static BOOL restore_display_modes(DEVMODEW *modes, unsigned int count)
347 unsigned int index;
348 LONG ret;
350 for (index = 0; index < count; ++index)
352 ret = ChangeDisplaySettingsExW(modes[index].dmDeviceName, &modes[index], NULL,
353 CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
354 if (ret != DISP_CHANGE_SUCCESSFUL)
355 return FALSE;
357 ret = ChangeDisplaySettingsExW(NULL, NULL, NULL, 0, NULL);
358 return ret == DISP_CHANGE_SUCCESSFUL;
361 static HRESULT set_display_mode(IDirectDraw7 *ddraw, DWORD width, DWORD height)
363 if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
364 return DD_OK;
365 return IDirectDraw7_SetDisplayMode(ddraw, width, height, 24, 0, 0);
368 static D3DCOLOR get_surface_color(IDirectDrawSurface7 *surface, UINT x, UINT y)
370 RECT rect = {x, y, x + 1, y + 1};
371 DDSURFACEDESC2 surface_desc;
372 D3DCOLOR color;
373 HRESULT hr;
375 memset(&surface_desc, 0, sizeof(surface_desc));
376 surface_desc.dwSize = sizeof(surface_desc);
378 hr = IDirectDrawSurface7_Lock(surface, &rect, &surface_desc, DDLOCK_READONLY, NULL);
379 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
380 if (FAILED(hr))
381 return 0xdeadbeef;
383 color = *((DWORD *)surface_desc.lpSurface) & 0x00ffffff;
385 hr = IDirectDrawSurface7_Unlock(surface, &rect);
386 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
388 return color;
391 static void fill_surface(IDirectDrawSurface7 *surface, D3DCOLOR color)
393 DDSURFACEDESC2 surface_desc = {sizeof(surface_desc)};
394 HRESULT hr;
395 unsigned int x, y;
396 DWORD *ptr;
398 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
399 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
401 for (y = 0; y < surface_desc.dwHeight; ++y)
403 ptr = (DWORD *)((BYTE *)surface_desc.lpSurface + y * U1(surface_desc).lPitch);
404 for (x = 0; x < surface_desc.dwWidth; ++x)
406 ptr[x] = color;
410 hr = IDirectDrawSurface7_Unlock(surface, NULL);
411 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
414 #define check_rect(a, b, c) check_rect_(__LINE__, a, b, c)
415 static void check_rect_(unsigned int line, IDirectDrawSurface7 *surface, RECT r, const char *message)
417 LONG x_coords[2][2] =
419 {r.left - 1, r.left + 1},
420 {r.right + 1, r.right - 1},
422 LONG y_coords[2][2] =
424 {r.top - 1, r.top + 1},
425 {r.bottom + 1, r.bottom - 1}
427 unsigned int i, j, x_side, y_side;
428 DWORD color;
429 LONG x, y;
431 for (i = 0; i < 2; ++i)
433 for (j = 0; j < 2; ++j)
435 for (x_side = 0; x_side < 2; ++x_side)
437 for (y_side = 0; y_side < 2; ++y_side)
439 DWORD expected = (x_side == 1 && y_side == 1) ? 0x00ffffff : 0x00000000;
441 x = x_coords[i][x_side];
442 y = y_coords[j][y_side];
443 if (x < 0 || x >= 640 || y < 0 || y >= 480)
444 continue;
445 color = get_surface_color(surface, x, y);
446 ok_(__FILE__, line)(color == expected, "%s: Pixel (%d, %d) has color %08x, expected %08x.\n",
447 message, x, y, color, expected);
454 static HRESULT CALLBACK enum_z_fmt(DDPIXELFORMAT *format, void *ctx)
456 DDPIXELFORMAT *z_fmt = ctx;
458 if (U1(*format).dwZBufferBitDepth > U1(*z_fmt).dwZBufferBitDepth)
459 *z_fmt = *format;
461 return DDENUMRET_OK;
464 static IDirectDraw7 *create_ddraw(void)
466 IDirectDraw7 *ddraw;
468 if (FAILED(pDirectDrawCreateEx(NULL, (void **)&ddraw, &IID_IDirectDraw7, NULL)))
469 return NULL;
471 return ddraw;
474 static HRESULT WINAPI enum_devtype_cb(char *desc_str, char *name, D3DDEVICEDESC7 *desc, void *ctx)
476 BOOL *hal_ok = ctx;
477 if (IsEqualGUID(&desc->deviceGUID, &IID_IDirect3DTnLHalDevice))
479 *hal_ok = TRUE;
480 return DDENUMRET_CANCEL;
482 return DDENUMRET_OK;
485 static IDirect3DDevice7 *create_device_ex(HWND window, DWORD coop_level, const GUID *device_guid)
487 IDirectDrawSurface7 *surface, *ds;
488 IDirect3DDevice7 *device = NULL;
489 DDSURFACEDESC2 surface_desc;
490 DDPIXELFORMAT z_fmt;
491 IDirectDraw7 *ddraw;
492 IDirect3D7 *d3d7;
493 HRESULT hr;
495 if (!(ddraw = create_ddraw()))
496 return NULL;
498 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, coop_level);
499 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
501 memset(&surface_desc, 0, sizeof(surface_desc));
502 surface_desc.dwSize = sizeof(surface_desc);
503 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
504 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
505 if (is_software_device_type(device_guid))
506 surface_desc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
507 surface_desc.dwWidth = 640;
508 surface_desc.dwHeight = 480;
510 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
511 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
513 if (coop_level & DDSCL_NORMAL)
515 IDirectDrawClipper *clipper;
517 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
518 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
519 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
520 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
521 hr = IDirectDrawSurface7_SetClipper(surface, clipper);
522 ok(SUCCEEDED(hr), "Failed to set surface clipper, hr %#x.\n", hr);
523 IDirectDrawClipper_Release(clipper);
526 hr = IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d7);
527 IDirectDraw7_Release(ddraw);
528 if (FAILED(hr))
530 IDirectDrawSurface7_Release(surface);
531 return NULL;
534 memset(&z_fmt, 0, sizeof(z_fmt));
535 hr = IDirect3D7_EnumZBufferFormats(d3d7, device_guid, enum_z_fmt, &z_fmt);
536 if (FAILED(hr) || !z_fmt.dwSize)
538 IDirect3D7_Release(d3d7);
539 IDirectDrawSurface7_Release(surface);
540 return NULL;
543 memset(&surface_desc, 0, sizeof(surface_desc));
544 surface_desc.dwSize = sizeof(surface_desc);
545 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
546 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
547 if (is_software_device_type(device_guid))
548 surface_desc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
549 U4(surface_desc).ddpfPixelFormat = z_fmt;
550 surface_desc.dwWidth = 640;
551 surface_desc.dwHeight = 480;
552 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL);
553 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
554 if (FAILED(hr))
556 IDirect3D7_Release(d3d7);
557 IDirectDrawSurface7_Release(surface);
558 return NULL;
561 hr = IDirectDrawSurface_AddAttachedSurface(surface, ds);
562 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
563 IDirectDrawSurface7_Release(ds);
564 if (FAILED(hr))
566 IDirect3D7_Release(d3d7);
567 IDirectDrawSurface7_Release(surface);
568 return NULL;
571 hr = IDirect3D7_CreateDevice(d3d7, device_guid, surface, &device);
572 IDirect3D7_Release(d3d7);
573 IDirectDrawSurface7_Release(surface);
574 if (FAILED(hr))
575 return NULL;
577 return device;
580 static IDirect3DDevice7 *create_device(HWND window, DWORD coop_level)
582 const GUID *device_guid = &IID_IDirect3DHALDevice;
583 IDirectDraw7 *ddraw;
584 BOOL hal_ok = FALSE;
585 IDirect3D7 *d3d7;
586 HRESULT hr;
588 if (!(ddraw = create_ddraw()))
589 return NULL;
590 hr = IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d7);
591 IDirectDraw7_Release(ddraw);
592 if (FAILED(hr))
593 return NULL;
595 hr = IDirect3D7_EnumDevices(d3d7, enum_devtype_cb, &hal_ok);
596 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
597 if (hal_ok)
598 device_guid = &IID_IDirect3DTnLHalDevice;
600 IDirect3D7_Release(d3d7);
602 return create_device_ex(window, coop_level, device_guid);
605 struct message
607 UINT message;
608 BOOL check_wparam;
609 WPARAM expect_wparam;
610 HRESULT ddraw_state;
613 static const struct message *expect_messages;
614 static IDirectDraw7 *focus_test_ddraw;
616 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
618 HRESULT hr;
620 if (expect_messages && message == expect_messages->message)
622 if (expect_messages->check_wparam)
623 ok (wparam == expect_messages->expect_wparam,
624 "Got unexpected wparam %lx for message %x, expected %lx.\n",
625 wparam, message, expect_messages->expect_wparam);
627 if (focus_test_ddraw)
629 hr = IDirectDraw7_TestCooperativeLevel(focus_test_ddraw);
630 ok(hr == expect_messages->ddraw_state, "Got ddraw state %#x on message %#x, expected %#x.\n",
631 hr, message, expect_messages->ddraw_state);
634 ++expect_messages;
637 return DefWindowProcA(hwnd, message, wparam, lparam);
640 /* Set the wndproc back to what ddraw expects it to be, and release the ddraw
641 * interface. This prevents subsequent SetCooperativeLevel() calls on a
642 * different window from failing with DDERR_HWNDALREADYSET. */
643 static void fix_wndproc(HWND window, LONG_PTR proc)
645 IDirectDraw7 *ddraw;
646 HRESULT hr;
648 if (!(ddraw = create_ddraw()))
649 return;
651 SetWindowLongPtrA(window, GWLP_WNDPROC, proc);
652 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
653 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
654 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
655 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
657 IDirectDraw7_Release(ddraw);
660 static void test_process_vertices(void)
662 IDirect3DVertexBuffer7 *src_vb, *dst_vb1, *dst_vb2;
663 D3DVERTEXBUFFERDESC vb_desc;
664 IDirect3DDevice7 *device;
665 struct vec4 *dst_data;
666 struct vec3 *dst_data2;
667 struct vec3 *src_data;
668 IDirect3D7 *d3d7;
669 D3DVIEWPORT7 vp;
670 HWND window;
671 HRESULT hr;
673 static D3DMATRIX world =
675 0.0f, 1.0f, 0.0f, 0.0f,
676 1.0f, 0.0f, 0.0f, 0.0f,
677 0.0f, 0.0f, 0.0f, 1.0f,
678 0.0f, 1.0f, 1.0f, 1.0f,
680 static D3DMATRIX view =
682 2.0f, 0.0f, 0.0f, 0.0f,
683 0.0f, -1.0f, 0.0f, 0.0f,
684 0.0f, 0.0f, 1.0f, 0.0f,
685 0.0f, 0.0f, 0.0f, 3.0f,
687 static D3DMATRIX proj =
689 1.0f, 0.0f, 0.0f, 1.0f,
690 0.0f, 1.0f, 1.0f, 0.0f,
691 0.0f, 1.0f, 1.0f, 0.0f,
692 1.0f, 0.0f, 0.0f, 1.0f,
695 window = create_window();
696 if (!(device = create_device(window, DDSCL_NORMAL)))
698 skip("Failed to create a 3D device, skipping test.\n");
699 DestroyWindow(window);
700 return;
703 hr = IDirect3DDevice7_GetDirect3D(device, &d3d7);
704 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
706 memset(&vb_desc, 0, sizeof(vb_desc));
707 vb_desc.dwSize = sizeof(vb_desc);
708 vb_desc.dwFVF = D3DFVF_XYZ;
709 vb_desc.dwNumVertices = 4;
710 hr = IDirect3D7_CreateVertexBuffer(d3d7, &vb_desc, &src_vb, 0);
711 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
713 hr = IDirect3DVertexBuffer7_Lock(src_vb, 0, (void **)&src_data, NULL);
714 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
715 src_data[0].x = 0.0f;
716 src_data[0].y = 0.0f;
717 src_data[0].z = 0.0f;
718 src_data[1].x = 1.0f;
719 src_data[1].y = 1.0f;
720 src_data[1].z = 1.0f;
721 src_data[2].x = -1.0f;
722 src_data[2].y = -1.0f;
723 src_data[2].z = 0.5f;
724 src_data[3].x = 0.5f;
725 src_data[3].y = -0.5f;
726 src_data[3].z = 0.25f;
727 hr = IDirect3DVertexBuffer7_Unlock(src_vb);
728 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
730 memset(&vb_desc, 0, sizeof(vb_desc));
731 vb_desc.dwSize = sizeof(vb_desc);
732 vb_desc.dwFVF = D3DFVF_XYZRHW;
733 vb_desc.dwNumVertices = 4;
734 /* MSDN says that the last parameter must be 0 - check that. */
735 hr = IDirect3D7_CreateVertexBuffer(d3d7, &vb_desc, &dst_vb1, 4);
736 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
738 memset(&vb_desc, 0, sizeof(vb_desc));
739 vb_desc.dwSize = sizeof(vb_desc);
740 vb_desc.dwFVF = D3DFVF_XYZ;
741 vb_desc.dwNumVertices = 5;
742 /* MSDN says that the last parameter must be 0 - check that. */
743 hr = IDirect3D7_CreateVertexBuffer(d3d7, &vb_desc, &dst_vb2, 12345678);
744 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
746 memset(&vp, 0, sizeof(vp));
747 vp.dwX = 64;
748 vp.dwY = 64;
749 vp.dwWidth = 128;
750 vp.dwHeight = 128;
751 vp.dvMinZ = 0.0f;
752 vp.dvMaxZ = 1.0f;
753 hr = IDirect3DDevice7_SetViewport(device, &vp);
754 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
756 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
757 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
758 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb2, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
759 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
761 hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
762 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
763 ok(compare_vec4(&dst_data[0], +1.280e+2f, +1.280e+2f, +0.000e+0f, +1.000e+0f, 4096),
764 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
765 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
766 ok(compare_vec4(&dst_data[1], +1.920e+2f, +6.400e+1f, +1.000e+0f, +1.000e+0f, 4096),
767 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
768 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
769 ok(compare_vec4(&dst_data[2], +6.400e+1f, +1.920e+2f, +5.000e-1f, +1.000e+0f, 4096),
770 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
771 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
772 ok(compare_vec4(&dst_data[3], +1.600e+2f, +1.600e+2f, +2.500e-1f, +1.000e+0f, 4096),
773 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
774 dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
775 hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
776 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
778 hr = IDirect3DVertexBuffer7_Lock(dst_vb2, 0, (void **)&dst_data2, NULL);
779 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
780 /* Small thing without much practical meaning, but I stumbled upon it,
781 * so let's check for it: If the output vertex buffer has no RHW value,
782 * the RHW value of the last vertex is written into the next vertex. */
783 ok(compare_vec3(&dst_data2[4], +1.000e+0f, +0.000e+0f, +0.000e+0f, 4096),
784 "Got unexpected vertex 4 {%.8e, %.8e, %.8e}.\n",
785 dst_data2[4].x, dst_data2[4].y, dst_data2[4].z);
786 hr = IDirect3DVertexBuffer7_Unlock(dst_vb2);
787 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
789 /* Test degenerate viewport z ranges. */
790 vp.dvMinZ = 0.0f;
791 vp.dvMaxZ = 0.0f;
792 hr = IDirect3DDevice7_SetViewport(device, &vp);
793 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
795 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
796 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
797 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb2, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
798 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
800 hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
801 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
802 ok(compare_vec4(&dst_data[0], +1.280e+2f, +1.280e+2f, +0.000e+0f, +1.000e+0f, 4096),
803 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
804 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
805 ok(compare_vec4(&dst_data[1], +1.920e+2f, +6.400e+1f, +1.000e-3f, +1.000e+0f, 4096),
806 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
807 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
808 ok(compare_vec4(&dst_data[2], +6.400e+1f, +1.920e+2f, +5.000e-4f, +1.000e+0f, 4096),
809 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
810 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
811 ok(compare_vec4(&dst_data[3], +1.600e+2f, +1.600e+2f, +2.500e-4f, +1.000e+0f, 4096),
812 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
813 dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
814 hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
815 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
817 vp.dvMinZ = 1.0f;
818 vp.dvMaxZ = 0.0f;
819 hr = IDirect3DDevice7_SetViewport(device, &vp);
820 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
822 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
823 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
824 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb2, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
825 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
827 hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
828 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
829 ok(compare_vec4(&dst_data[0], +1.280e+2f, +1.280e+2f, +1.000e+0f, +1.000e+0f, 4096),
830 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
831 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
832 ok(compare_vec4(&dst_data[1], +1.920e+2f, +6.400e+1f, +1.001e+0f, +1.000e+0f, 4096),
833 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
834 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
835 ok(compare_vec4(&dst_data[2], +6.400e+1f, +1.920e+2f, +1.0005e+0f, +1.000e+0f, 4096),
836 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
837 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
838 ok(compare_vec4(&dst_data[3], +1.600e+2f, +1.600e+2f, +1.00025e+0f, +1.000e+0f, 4096),
839 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
840 dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
841 hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
842 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
844 /* Try a more complicated viewport, same vertices. */
845 memset(&vp, 0, sizeof(vp));
846 vp.dwX = 10;
847 vp.dwY = 5;
848 vp.dwWidth = 246;
849 vp.dwHeight = 130;
850 vp.dvMinZ = -2.0f;
851 vp.dvMaxZ = 4.0f;
852 hr = IDirect3DDevice7_SetViewport(device, &vp);
853 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
855 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
856 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
858 hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
859 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
860 ok(compare_vec4(&dst_data[0], +1.330e+2f, +7.000e+1f, -2.000e+0f, +1.000e+0f, 4096),
861 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
862 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
863 ok(compare_vec4(&dst_data[1], +2.560e+2f, +5.000e+0f, +4.000e+0f, +1.000e+0f, 4096),
864 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
865 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
866 ok(compare_vec4(&dst_data[2], +1.000e+1f, +1.350e+2f, +1.000e+0f, +1.000e+0f, 4096),
867 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
868 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
869 ok(compare_vec4(&dst_data[3], +1.945e+2f, +1.025e+2f, -5.000e-1f, +1.000e+0f, 4096),
870 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
871 dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
872 hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
873 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
875 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &world);
876 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
877 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &view);
878 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
879 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &proj);
880 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
882 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb1, D3DVOP_TRANSFORM, 0, 4, src_vb, 0, device, 0);
883 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
885 hr = IDirect3DVertexBuffer7_Lock(dst_vb1, 0, (void **)&dst_data, NULL);
886 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
887 ok(compare_vec4(&dst_data[0], +2.560e+2f, +7.000e+1f, -2.000e+0f, +3.333e-1f, 4096),
888 "Got unexpected vertex 0 {%.8e, %.8e, %.8e, %.8e}.\n",
889 dst_data[0].x, dst_data[0].y, dst_data[0].z, dst_data[0].w);
890 ok(compare_vec4(&dst_data[1], +2.560e+2f, +7.813e+1f, -2.750e+0f, +1.250e-1f, 4096),
891 "Got unexpected vertex 1 {%.8e, %.8e, %.8e, %.8e}.\n",
892 dst_data[1].x, dst_data[1].y, dst_data[1].z, dst_data[1].w);
893 ok(compare_vec4(&dst_data[2], +2.560e+2f, +4.400e+1f, +4.000e-1f, +4.000e-1f, 4096),
894 "Got unexpected vertex 2 {%.8e, %.8e, %.8e, %.8e}.\n",
895 dst_data[2].x, dst_data[2].y, dst_data[2].z, dst_data[2].w);
896 ok(compare_vec4(&dst_data[3], +2.560e+2f, +8.182e+1f, -3.091e+0f, +3.636e-1f, 4096),
897 "Got unexpected vertex 3 {%.8e, %.8e, %.8e, %.8e}.\n",
898 dst_data[3].x, dst_data[3].y, dst_data[3].z, dst_data[3].w);
899 hr = IDirect3DVertexBuffer7_Unlock(dst_vb1);
900 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
902 IDirect3DVertexBuffer7_Release(dst_vb2);
903 IDirect3DVertexBuffer7_Release(dst_vb1);
904 IDirect3DVertexBuffer7_Release(src_vb);
905 IDirect3D7_Release(d3d7);
906 IDirect3DDevice7_Release(device);
907 DestroyWindow(window);
910 static void test_coop_level_create_device_window(void)
912 HWND focus_window, device_window;
913 IDirectDraw7 *ddraw;
914 HRESULT hr;
916 focus_window = create_window();
917 ddraw = create_ddraw();
918 ok(!!ddraw, "Failed to create a ddraw object.\n");
920 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
921 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
922 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
923 ok(!device_window, "Unexpected device window found.\n");
924 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW);
925 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
926 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
927 ok(!device_window, "Unexpected device window found.\n");
928 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL);
929 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
930 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
931 ok(!device_window, "Unexpected device window found.\n");
932 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_NORMAL | DDSCL_FULLSCREEN);
933 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
934 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
935 ok(!device_window, "Unexpected device window found.\n");
936 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
937 ok(hr == DDERR_NOFOCUSWINDOW || broken(hr == DDERR_INVALIDPARAMS), "Got unexpected hr %#x.\n", hr);
938 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
939 ok(!device_window, "Unexpected device window found.\n");
941 /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
942 if (broken(hr == DDERR_INVALIDPARAMS))
944 win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
945 IDirectDraw7_Release(ddraw);
946 DestroyWindow(focus_window);
947 return;
950 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
951 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
952 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
953 ok(!device_window, "Unexpected device window found.\n");
954 hr = IDirectDraw7_SetCooperativeLevel(ddraw, focus_window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
955 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
956 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
957 ok(!device_window, "Unexpected device window found.\n");
959 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
960 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
961 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
962 ok(!device_window, "Unexpected device window found.\n");
963 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_SETFOCUSWINDOW
964 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
965 ok(hr == DDERR_NOHWND, "Got unexpected hr %#x.\n", hr);
966 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
967 ok(!!device_window, "Device window not found.\n");
969 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
970 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
971 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
972 ok(!device_window, "Unexpected device window found.\n");
973 hr = IDirectDraw7_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW
974 | DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
975 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
976 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
977 ok(!!device_window, "Device window not found.\n");
979 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
980 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
981 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
982 ok(!device_window, "Unexpected device window found.\n");
983 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
984 ok(hr == DDERR_NOFOCUSWINDOW, "Got unexpected hr %#x.\n", hr);
985 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
986 ok(!device_window, "Unexpected device window found.\n");
987 hr = IDirectDraw7_SetCooperativeLevel(ddraw, focus_window, DDSCL_SETFOCUSWINDOW);
988 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
989 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
990 ok(!device_window, "Unexpected device window found.\n");
991 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_CREATEDEVICEWINDOW | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
992 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
993 device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
994 ok(!!device_window, "Device window not found.\n");
996 IDirectDraw7_Release(ddraw);
997 DestroyWindow(focus_window);
1000 static void test_clipper_blt(void)
1002 IDirectDrawSurface7 *src_surface, *dst_surface;
1003 RECT client_rect, src_rect;
1004 IDirectDrawClipper *clipper;
1005 DDSURFACEDESC2 surface_desc;
1006 unsigned int i, j, x, y;
1007 IDirectDraw7 *ddraw;
1008 RGNDATA *rgn_data;
1009 D3DCOLOR color;
1010 ULONG refcount;
1011 HRGN r1, r2;
1012 HWND window;
1013 DDBLTFX fx;
1014 HRESULT hr;
1015 DWORD *ptr;
1016 DWORD ret;
1018 static const DWORD src_data[] =
1020 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
1021 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
1022 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffffffff, 0xffffffff,
1024 static const D3DCOLOR expected1[] =
1026 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
1027 0x000000ff, 0x0000ff00, 0x00000000, 0x00000000,
1028 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
1029 0x00000000, 0x00000000, 0x00ff0000, 0x00ffffff,
1031 /* Nvidia on Windows seems to have an off-by-one error
1032 * when processing source rectangles. Our left = 1 and
1033 * right = 5 input reads from x = {1, 2, 3}. x = 4 is
1034 * read as well, but only for the edge pixels on the
1035 * output image. The bug happens on the y axis as well,
1036 * but we only read one row there, and all source rows
1037 * contain the same data. This bug is not dependent on
1038 * the presence of a clipper. */
1039 static const D3DCOLOR expected1_broken[] =
1041 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
1042 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
1043 0x00000000, 0x00000000, 0x00ff0000, 0x00ff0000,
1044 0x00000000, 0x00000000, 0x0000ff00, 0x00ff0000,
1046 static const D3DCOLOR expected2[] =
1048 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
1049 0x000000ff, 0x000000ff, 0x00000000, 0x00000000,
1050 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
1051 0x00000000, 0x00000000, 0x000000ff, 0x000000ff,
1054 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
1055 10, 10, 640, 480, 0, 0, 0, 0);
1056 ShowWindow(window, SW_SHOW);
1057 ddraw = create_ddraw();
1058 ok(!!ddraw, "Failed to create a ddraw object.\n");
1060 ret = GetClientRect(window, &client_rect);
1061 ok(ret, "Failed to get client rect.\n");
1062 ret = MapWindowPoints(window, NULL, (POINT *)&client_rect, 2);
1063 ok(ret, "Failed to map client rect.\n");
1065 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1066 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1068 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
1069 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
1070 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1071 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
1072 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
1073 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
1074 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1075 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
1076 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
1077 hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret);
1078 ok(SUCCEEDED(hr), "Failed to get clip list, hr %#x.\n", hr);
1079 ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#x.\n", rgn_data->rdh.dwSize);
1080 ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#x.\n", rgn_data->rdh.iType);
1081 ok(rgn_data->rdh.nCount >= 1, "Got unexpected count %u.\n", rgn_data->rdh.nCount);
1082 ok(EqualRect(&rgn_data->rdh.rcBound, &client_rect),
1083 "Got unexpected bounding rect %s, expected %s.\n",
1084 wine_dbgstr_rect(&rgn_data->rdh.rcBound), wine_dbgstr_rect(&client_rect));
1085 HeapFree(GetProcessHeap(), 0, rgn_data);
1087 r1 = CreateRectRgn(0, 0, 320, 240);
1088 ok(!!r1, "Failed to create region.\n");
1089 r2 = CreateRectRgn(320, 240, 640, 480);
1090 ok(!!r2, "Failed to create region.\n");
1091 CombineRgn(r1, r1, r2, RGN_OR);
1092 ret = GetRegionData(r1, 0, NULL);
1093 rgn_data = HeapAlloc(GetProcessHeap(), 0, ret);
1094 ret = GetRegionData(r1, ret, rgn_data);
1095 ok(!!ret, "Failed to get region data.\n");
1097 DeleteObject(r2);
1098 DeleteObject(r1);
1100 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
1101 ok(hr == DDERR_CLIPPERISUSINGHWND, "Got unexpected hr %#x.\n", hr);
1102 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
1103 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
1104 hr = IDirectDrawClipper_SetClipList(clipper, rgn_data, 0);
1105 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
1107 HeapFree(GetProcessHeap(), 0, rgn_data);
1109 memset(&surface_desc, 0, sizeof(surface_desc));
1110 surface_desc.dwSize = sizeof(surface_desc);
1111 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1112 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
1113 surface_desc.dwWidth = 640;
1114 surface_desc.dwHeight = 480;
1115 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1116 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
1117 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1118 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1119 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1120 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1122 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
1123 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
1124 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
1125 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
1127 memset(&fx, 0, sizeof(fx));
1128 fx.dwSize = sizeof(fx);
1129 hr = IDirectDrawSurface7_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1130 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
1131 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1132 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
1134 hr = IDirectDrawSurface7_Lock(src_surface, NULL, &surface_desc, 0, NULL);
1135 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
1136 ok(U1(surface_desc).lPitch == 2560, "Got unexpected surface pitch %u.\n", U1(surface_desc).lPitch);
1137 ptr = surface_desc.lpSurface;
1138 memcpy(&ptr[ 0], &src_data[ 0], 6 * sizeof(DWORD));
1139 memcpy(&ptr[ 640], &src_data[ 6], 6 * sizeof(DWORD));
1140 memcpy(&ptr[1280], &src_data[12], 6 * sizeof(DWORD));
1141 hr = IDirectDrawSurface7_Unlock(src_surface, NULL);
1142 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
1144 hr = IDirectDrawSurface7_SetClipper(dst_surface, clipper);
1145 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
1147 SetRect(&src_rect, 1, 1, 5, 2);
1148 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, src_surface, &src_rect, DDBLT_WAIT, NULL);
1149 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
1150 for (i = 0; i < 4; ++i)
1152 for (j = 0; j < 4; ++j)
1154 x = 80 * ((2 * j) + 1);
1155 y = 60 * ((2 * i) + 1);
1156 color = get_surface_color(dst_surface, x, y);
1157 ok(compare_color(color, expected1[i * 4 + j], 1)
1158 || broken(compare_color(color, expected1_broken[i * 4 + j], 1)),
1159 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected1[i * 4 + j], x, y, color);
1163 U5(fx).dwFillColor = 0xff0000ff;
1164 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1165 ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
1166 for (i = 0; i < 4; ++i)
1168 for (j = 0; j < 4; ++j)
1170 x = 80 * ((2 * j) + 1);
1171 y = 60 * ((2 * i) + 1);
1172 color = get_surface_color(dst_surface, x, y);
1173 ok(compare_color(color, expected2[i * 4 + j], 1),
1174 "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected2[i * 4 + j], x, y, color);
1178 hr = IDirectDrawSurface7_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
1179 ok(hr == DDERR_BLTFASTCANTCLIP, "Got unexpected hr %#x.\n", hr);
1181 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
1182 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
1183 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1184 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
1185 DestroyWindow(window);
1186 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1187 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
1188 hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL);
1189 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
1190 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1191 ok(SUCCEEDED(hr), "Failed to get clip list size, hr %#x.\n", hr);
1192 hr = IDirectDrawClipper_SetClipList(clipper, NULL, 0);
1193 ok(SUCCEEDED(hr), "Failed to set clip list, hr %#x.\n", hr);
1194 hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret);
1195 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
1196 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1197 ok(hr == DDERR_NOCLIPLIST, "Got unexpected hr %#x.\n", hr);
1199 IDirectDrawSurface7_Release(dst_surface);
1200 IDirectDrawSurface7_Release(src_surface);
1201 refcount = IDirectDrawClipper_Release(clipper);
1202 ok(!refcount, "Clipper has %u references left.\n", refcount);
1203 IDirectDraw7_Release(ddraw);
1206 static void test_coop_level_d3d_state(void)
1208 IDirectDrawSurface7 *rt, *surface;
1209 IDirect3DDevice7 *device;
1210 IDirectDraw7 *ddraw;
1211 DDSURFACEDESC2 lock;
1212 IDirect3D7 *d3d;
1213 D3DCOLOR color;
1214 DDSCAPS2 caps;
1215 DWORD value;
1216 HWND window;
1217 HRESULT hr;
1219 static struct
1221 struct vec3 position;
1222 DWORD diffuse;
1224 quad[] =
1226 {{-1.0f, -1.0f, 0.1f}, 0x800000ff},
1227 {{-1.0f, 1.0f, 0.1f}, 0x800000ff},
1228 {{ 1.0f, -1.0f, 0.1f}, 0x800000ff},
1229 {{ 1.0f, 1.0f, 0.1f}, 0x800000ff},
1232 window = create_window();
1233 if (!(device = create_device(window, DDSCL_NORMAL)))
1235 skip("Failed to create a 3D device, skipping test.\n");
1236 DestroyWindow(window);
1237 return;
1240 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
1241 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1242 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1243 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1244 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_DESTALPHA);
1245 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1247 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1248 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1249 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
1250 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1251 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
1252 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
1253 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1254 ok(!value, "Got unexpected alpha blend enable state %#x.\n", value);
1255 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
1256 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1257 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
1258 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1259 color = get_surface_color(rt, 320, 240);
1260 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1262 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1263 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1264 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1265 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1266 IDirect3D7_Release(d3d);
1267 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1268 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1269 hr = IDirectDrawSurface7_IsLost(rt);
1270 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
1272 memset(&lock, 0, sizeof(lock));
1273 lock.dwSize = sizeof(lock);
1274 lock.lpSurface = (void *)0xdeadbeef;
1275 hr = IDirectDrawSurface7_Lock(rt, NULL, &lock, DDLOCK_READONLY, NULL);
1276 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
1277 ok(lock.lpSurface == (void *)0xdeadbeef, "Got unexpected lock.lpSurface %p.\n", lock.lpSurface);
1279 memset(&caps, 0, sizeof(caps));
1280 caps.dwCaps = DDSCAPS_ZBUFFER;
1281 hr = IDirectDrawSurface7_GetAttachedSurface(rt, &caps, &surface);
1282 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
1283 caps.dwCaps = DDSCAPS_FLIP;
1284 hr = IDirectDrawSurface7_GetAttachedSurface(rt, &caps, &surface);
1285 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
1287 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
1288 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1290 hr = IDirectDrawSurface7_Lock(rt, NULL, &lock, DDLOCK_READONLY, NULL);
1291 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1292 hr = IDirectDrawSurface7_Unlock(rt, NULL);
1293 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1295 caps.dwCaps = DDSCAPS_ZBUFFER;
1296 hr = IDirectDrawSurface7_GetAttachedSurface(rt, &caps, &surface);
1297 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1298 IDirectDrawSurface7_Release(surface);
1300 caps.dwCaps = DDSCAPS_FLIP;
1301 hr = IDirectDrawSurface7_GetAttachedSurface(rt, &caps, &surface);
1302 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
1304 IDirectDraw7_Release(ddraw);
1306 hr = IDirect3DDevice7_GetRenderTarget(device, &surface);
1307 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1308 ok(surface == rt, "Got unexpected surface %p.\n", surface);
1309 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ZENABLE, &value);
1310 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1311 ok(!!value, "Got unexpected z-enable state %#x.\n", value);
1312 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, &value);
1313 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1314 ok(!!value, "Got unexpected alpha blend enable state %#x.\n", value);
1315 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff00ff00, 1.0f, 0);
1316 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1317 color = get_surface_color(rt, 320, 240);
1318 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
1320 hr = IDirect3DDevice7_BeginScene(device);
1321 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1322 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
1323 D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, ARRAY_SIZE(quad), 0);
1324 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1325 hr = IDirect3DDevice7_EndScene(device);
1326 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1327 color = get_surface_color(rt, 320, 240);
1328 ok(compare_color(color, 0x0000ff80, 1), "Got unexpected color 0x%08x.\n", color);
1330 IDirectDrawSurface7_Release(surface);
1331 IDirectDrawSurface7_Release(rt);
1332 IDirect3DDevice7_Release(device);
1333 DestroyWindow(window);
1336 static void test_surface_interface_mismatch(void)
1338 IDirectDraw7 *ddraw = NULL;
1339 IDirect3D7 *d3d = NULL;
1340 IDirectDrawSurface7 *surface = NULL, *ds;
1341 IDirectDrawSurface3 *surface3 = NULL;
1342 IDirect3DDevice7 *device = NULL;
1343 DDSURFACEDESC2 surface_desc;
1344 DDPIXELFORMAT z_fmt;
1345 ULONG refcount;
1346 HRESULT hr;
1347 D3DCOLOR color;
1348 HWND window;
1350 window = create_window();
1351 ddraw = create_ddraw();
1352 ok(!!ddraw, "Failed to create a ddraw object.\n");
1353 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
1354 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1356 memset(&surface_desc, 0, sizeof(surface_desc));
1357 surface_desc.dwSize = sizeof(surface_desc);
1358 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1359 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
1360 surface_desc.dwWidth = 640;
1361 surface_desc.dwHeight = 480;
1363 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1364 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1366 hr = IDirectDrawSurface7_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **)&surface3);
1367 ok(SUCCEEDED(hr), "Failed to QI IDirectDrawSurface3, hr %#x.\n", hr);
1369 if (FAILED(IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d)))
1371 skip("D3D interface is not available, skipping test.\n");
1372 goto cleanup;
1375 memset(&z_fmt, 0, sizeof(z_fmt));
1376 hr = IDirect3D7_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
1377 if (FAILED(hr) || !z_fmt.dwSize)
1379 skip("No depth buffer formats available, skipping test.\n");
1380 goto cleanup;
1383 memset(&surface_desc, 0, sizeof(surface_desc));
1384 surface_desc.dwSize = sizeof(surface_desc);
1385 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
1386 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1387 U4(surface_desc).ddpfPixelFormat = z_fmt;
1388 surface_desc.dwWidth = 640;
1389 surface_desc.dwHeight = 480;
1390 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL);
1391 ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x.\n", hr);
1392 if (FAILED(hr))
1393 goto cleanup;
1395 /* Using a different surface interface version still works */
1396 hr = IDirectDrawSurface3_AddAttachedSurface(surface3, (IDirectDrawSurface3 *)ds);
1397 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
1398 refcount = IDirectDrawSurface7_Release(ds);
1399 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
1400 if (FAILED(hr))
1401 goto cleanup;
1403 /* Here too */
1404 hr = IDirect3D7_CreateDevice(d3d, &IID_IDirect3DHALDevice, (IDirectDrawSurface7 *)surface3, &device);
1405 ok(SUCCEEDED(hr), "Failed to create d3d device.\n");
1406 if (FAILED(hr))
1407 goto cleanup;
1409 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
1410 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
1411 color = get_surface_color(surface, 320, 240);
1412 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
1414 cleanup:
1415 if (surface3) IDirectDrawSurface3_Release(surface3);
1416 if (surface) IDirectDrawSurface7_Release(surface);
1417 if (device) IDirect3DDevice7_Release(device);
1418 if (d3d) IDirect3D7_Release(d3d);
1419 if (ddraw) IDirectDraw7_Release(ddraw);
1420 DestroyWindow(window);
1423 static void test_coop_level_threaded(void)
1425 struct create_window_thread_param p;
1426 IDirectDraw7 *ddraw;
1427 HRESULT hr;
1429 ddraw = create_ddraw();
1430 ok(!!ddraw, "Failed to create a ddraw object.\n");
1431 create_window_thread(&p);
1433 hr = IDirectDraw7_SetCooperativeLevel(ddraw, p.window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1434 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
1436 destroy_window_thread(&p);
1437 IDirectDraw7_Release(ddraw);
1440 static void test_depth_blit(const GUID *device_guid)
1442 IDirect3DDevice7 *device;
1443 static struct
1445 float x, y, z;
1446 DWORD color;
1448 quad1[] =
1450 { -1.0, 1.0, 0.50f, 0xff00ff00},
1451 { 1.0, 1.0, 0.50f, 0xff00ff00},
1452 { -1.0, -1.0, 0.50f, 0xff00ff00},
1453 { 1.0, -1.0, 0.50f, 0xff00ff00},
1455 static const D3DCOLOR expected_colors[4][4] =
1457 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1458 {0x00ff0000, 0x00ff0000, 0x0000ff00, 0x0000ff00},
1459 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1460 {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1462 DDSURFACEDESC2 ddsd_new, ddsd_existing;
1464 IDirectDrawSurface7 *ds1, *ds2, *ds3, *rt;
1465 RECT src_rect, dst_rect;
1466 unsigned int i, j;
1467 D3DCOLOR color;
1468 HRESULT hr;
1469 IDirect3D7 *d3d;
1470 IDirectDraw7 *ddraw;
1471 DDBLTFX fx;
1472 HWND window;
1474 window = create_window();
1475 if (!(device = create_device_ex(window, DDSCL_NORMAL, device_guid)))
1477 skip("Failed to create a 3D device, skipping test.\n");
1478 DestroyWindow(window);
1479 return;
1482 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1483 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
1484 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1485 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
1486 IDirect3D7_Release(d3d);
1488 ds1 = get_depth_stencil(device);
1490 memset(&ddsd_new, 0, sizeof(ddsd_new));
1491 ddsd_new.dwSize = sizeof(ddsd_new);
1492 memset(&ddsd_existing, 0, sizeof(ddsd_existing));
1493 ddsd_existing.dwSize = sizeof(ddsd_existing);
1494 hr = IDirectDrawSurface7_GetSurfaceDesc(ds1, &ddsd_existing);
1495 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1496 ddsd_new.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1497 ddsd_new.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1498 if (is_software_device_type(device_guid))
1499 ddsd_new.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
1500 ddsd_new.dwWidth = ddsd_existing.dwWidth;
1501 ddsd_new.dwHeight = ddsd_existing.dwHeight;
1502 U4(ddsd_new).ddpfPixelFormat = U4(ddsd_existing).ddpfPixelFormat;
1503 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd_new, &ds2, NULL);
1504 ok(SUCCEEDED(hr), "Failed to create a z buffer, hr %#x.\n", hr);
1505 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd_new, &ds3, NULL);
1506 ok(SUCCEEDED(hr), "Failed to create a z buffer, hr %#x.\n", hr);
1507 IDirectDraw7_Release(ddraw);
1509 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_TRUE);
1510 ok(SUCCEEDED(hr), "Failed to enable z testing, hr %#x.\n", hr);
1511 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
1512 ok(SUCCEEDED(hr), "Failed to set the z function, hr %#x.\n", hr);
1513 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
1514 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
1516 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
1517 ok(SUCCEEDED(hr), "Failed to clear the z buffer, hr %#x.\n", hr);
1519 /* Partial blit. */
1520 SetRect(&src_rect, 0, 0, 320, 240);
1521 SetRect(&dst_rect, 0, 0, 320, 240);
1522 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1523 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1524 /* Different locations. */
1525 SetRect(&src_rect, 0, 0, 320, 240);
1526 SetRect(&dst_rect, 320, 240, 640, 480);
1527 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1528 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1529 /* Stretched. */
1530 SetRect(&src_rect, 0, 0, 320, 240);
1531 SetRect(&dst_rect, 0, 0, 640, 480);
1532 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1533 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1534 /* Flipped. */
1535 SetRect(&src_rect, 0, 480, 640, 0);
1536 SetRect(&dst_rect, 0, 0, 640, 480);
1537 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1538 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1539 SetRect(&src_rect, 0, 0, 640, 480);
1540 SetRect(&dst_rect, 0, 480, 640, 0);
1541 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1542 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
1543 /* Full, explicit. */
1544 SetRect(&src_rect, 0, 0, 640, 480);
1545 SetRect(&dst_rect, 0, 0, 640, 480);
1546 hr = IDirectDrawSurface7_Blt(ds2, &dst_rect, ds1, &src_rect, DDBLT_WAIT, NULL);
1547 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1548 /* Depth -> color blit: Succeeds on Win7 + Radeon HD 5700, fails on WinXP + Radeon X1600 */
1550 /* Depth blit inside a BeginScene / EndScene pair */
1551 hr = IDirect3DDevice7_BeginScene(device);
1552 ok(SUCCEEDED(hr), "Failed to start scene, hr %#x.\n", hr);
1553 /* From the current depth stencil */
1554 hr = IDirectDrawSurface7_Blt(ds2, NULL, ds1, NULL, DDBLT_WAIT, NULL);
1555 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1556 /* To the current depth stencil */
1557 hr = IDirectDrawSurface7_Blt(ds1, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1558 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1559 /* Between unbound surfaces */
1560 hr = IDirectDrawSurface7_Blt(ds3, NULL, ds2, NULL, DDBLT_WAIT, NULL);
1561 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1562 hr = IDirect3DDevice7_EndScene(device);
1563 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
1565 /* Avoid changing the depth stencil, it doesn't work properly on Windows.
1566 * Instead use DDBLT_DEPTHFILL to clear the depth stencil. Unfortunately
1567 * drivers disagree on the meaning of dwFillDepth. Only 0 seems to produce
1568 * a reliable result(z = 0.0) */
1569 memset(&fx, 0, sizeof(fx));
1570 fx.dwSize = sizeof(fx);
1571 hr = IDirectDrawSurface7_Blt(ds2, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
1572 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1574 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET, 0xffff0000, 1.0f, 0);
1575 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1577 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1578 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1579 color = get_surface_color(rt, 80, 60);
1581 /* For some reason clears and colour fill blits randomly fail with software render target. */
1582 ok(color == 0x00ff0000 || broken(is_software_device_type(device_guid) && !color),
1583 "Got unexpected colour 0x%08x.\n", color);
1584 if (!color)
1586 fill_surface(rt, 0xffff0000);
1588 color = get_surface_color(rt, 80, 60);
1589 ok(color == 0x00ff0000, "Got unexpected colour 0x%08x.\n", color);
1592 SetRect(&dst_rect, 0, 0, 320, 240);
1593 hr = IDirectDrawSurface7_Blt(ds1, &dst_rect, ds2, NULL, DDBLT_WAIT, NULL);
1594 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1595 IDirectDrawSurface7_Release(ds3);
1596 IDirectDrawSurface7_Release(ds2);
1597 IDirectDrawSurface7_Release(ds1);
1599 hr = IDirect3DDevice7_BeginScene(device);
1600 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1601 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
1602 quad1, 4, 0);
1603 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1604 hr = IDirect3DDevice7_EndScene(device);
1605 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1607 for (i = 0; i < 4; ++i)
1609 for (j = 0; j < 4; ++j)
1611 unsigned int x = 80 * ((2 * j) + 1);
1612 unsigned int y = 60 * ((2 * i) + 1);
1613 color = get_surface_color(rt, x, y);
1614 ok(compare_color(color, expected_colors[i][j], 1),
1615 "Expected color 0x%08x at %u,%u, got 0x%08x, software device %#x.\n",
1616 expected_colors[i][j], x, y, color, is_software_device_type(device_guid));
1620 IDirectDrawSurface7_Release(rt);
1621 IDirect3DDevice7_Release(device);
1622 DestroyWindow(window);
1625 static void test_texture_load_ckey(void)
1627 HWND window;
1628 IDirect3DDevice7 *device;
1629 IDirectDraw7 *ddraw;
1630 IDirectDrawSurface7 *src;
1631 IDirectDrawSurface7 *dst;
1632 DDSURFACEDESC2 ddsd;
1633 HRESULT hr;
1634 DDCOLORKEY ckey;
1635 IDirect3D7 *d3d;
1637 window = create_window();
1638 if (!(device = create_device(window, DDSCL_NORMAL)))
1640 skip("Failed to create a 3D device, skipping test.\n");
1641 DestroyWindow(window);
1642 return;
1645 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1646 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
1647 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1648 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
1649 IDirect3D7_Release(d3d);
1651 memset(&ddsd, 0, sizeof(ddsd));
1652 ddsd.dwSize = sizeof(ddsd);
1653 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
1654 ddsd.dwHeight = 128;
1655 ddsd.dwWidth = 128;
1656 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
1657 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &src, NULL);
1658 ok(SUCCEEDED(hr), "Failed to create source texture, hr %#x.\n", hr);
1659 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1660 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &dst, NULL);
1661 ok(SUCCEEDED(hr), "Failed to create destination texture, hr %#x.\n", hr);
1663 /* No surface has a color key */
1664 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1665 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1666 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0xdeadbeef;
1667 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1668 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1669 ok(ckey.dwColorSpaceLowValue == 0xdeadbeef, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1670 ok(ckey.dwColorSpaceHighValue == 0xdeadbeef, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1672 /* Source surface has a color key */
1673 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
1674 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
1675 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1676 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1677 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1678 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1679 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1680 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1681 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1683 /* Both surfaces have a color key: Dest ckey is overwritten */
1684 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x000000ff;
1685 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1686 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1687 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1688 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1689 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1690 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1691 ok(ckey.dwColorSpaceLowValue == 0x0000ff00, "dwColorSpaceLowValue is %#x.\n", ckey.dwColorSpaceLowValue);
1692 ok(ckey.dwColorSpaceHighValue == 0x0000ff00, "dwColorSpaceHighValue is %#x.\n", ckey.dwColorSpaceHighValue);
1694 /* Only the destination has a color key: It is deleted. This behavior differs from
1695 * IDirect3DTexture(2)::Load */
1696 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, NULL);
1697 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
1698 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
1699 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1700 hr = IDirect3DDevice7_Load(device, dst, NULL, src, NULL, 0);
1701 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1702 hr = IDirectDrawSurface7_GetColorKey(dst, DDCKEY_SRCBLT, &ckey);
1703 todo_wine ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
1705 IDirectDrawSurface7_Release(dst);
1706 IDirectDrawSurface7_Release(src);
1707 IDirectDraw7_Release(ddraw);
1708 IDirect3DDevice7_Release(device);
1709 DestroyWindow(window);
1712 static void test_zenable(const GUID *device_guid)
1714 static struct
1716 struct vec4 position;
1717 D3DCOLOR diffuse;
1719 tquad[] =
1721 {{ 0.0f, 480.0f, -0.5f, 1.0f}, 0xff00ff00},
1722 {{ 0.0f, 0.0f, -0.5f, 1.0f}, 0xff00ff00},
1723 {{640.0f, 480.0f, 1.5f, 1.0f}, 0xff00ff00},
1724 {{640.0f, 0.0f, 1.5f, 1.0f}, 0xff00ff00},
1726 IDirect3DDevice7 *device;
1727 IDirectDrawSurface7 *rt;
1728 D3DCOLOR color;
1729 HWND window;
1730 HRESULT hr;
1731 UINT x, y;
1732 UINT i, j;
1734 window = create_window();
1735 if (!(device = create_device_ex(window, DDSCL_NORMAL, device_guid)))
1737 skip("Failed to create a 3D device, skipping test.\n");
1738 DestroyWindow(window);
1739 return;
1742 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
1743 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1745 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 0.0f, 0);
1746 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1748 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1749 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1751 color = get_surface_color(rt, 80, 60);
1752 /* For some reason clears and colour fill blits randomly fail with software render target. */
1753 ok(color == 0x00ff0000 || broken(is_software_device_type(device_guid) && !color),
1754 "Got unexpected colour 0x%08x.\n", color);
1755 if (!color)
1757 fill_surface(rt, 0xffff0000);
1759 color = get_surface_color(rt, 80, 60);
1760 ok(color == 0x00ff0000, "Got unexpected colour 0x%08x.\n", color);
1763 hr = IDirect3DDevice7_BeginScene(device);
1764 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1765 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_DIFFUSE, tquad, 4, 0);
1766 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1767 hr = IDirect3DDevice7_EndScene(device);
1768 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1770 for (i = 0; i < 4; ++i)
1772 for (j = 0; j < 4; ++j)
1774 x = 80 * ((2 * j) + 1);
1775 y = 60 * ((2 * i) + 1);
1776 color = get_surface_color(rt, x, y);
1777 ok(compare_color(color, 0x0000ff00, 1),
1778 "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
1781 IDirectDrawSurface7_Release(rt);
1783 IDirect3DDevice7_Release(device);
1784 DestroyWindow(window);
1787 static void test_ck_rgba(const GUID *device_guid)
1789 static struct
1791 struct vec4 position;
1792 struct vec2 texcoord;
1794 tquad[] =
1796 {{ 0.0f, 480.0f, 0.25f, 1.0f}, {0.0f, 0.0f}},
1797 {{ 0.0f, 0.0f, 0.25f, 1.0f}, {0.0f, 1.0f}},
1798 {{640.0f, 480.0f, 0.25f, 1.0f}, {1.0f, 0.0f}},
1799 {{640.0f, 0.0f, 0.25f, 1.0f}, {1.0f, 1.0f}},
1800 {{ 0.0f, 480.0f, 0.75f, 1.0f}, {0.0f, 0.0f}},
1801 {{ 0.0f, 0.0f, 0.75f, 1.0f}, {0.0f, 1.0f}},
1802 {{640.0f, 480.0f, 0.75f, 1.0f}, {1.0f, 0.0f}},
1803 {{640.0f, 0.0f, 0.75f, 1.0f}, {1.0f, 1.0f}},
1805 static const struct
1807 D3DCOLOR fill_color;
1808 BOOL color_key;
1809 BOOL blend;
1810 D3DCOLOR result1, result1_broken;
1811 D3DCOLOR result2, result2_broken;
1813 tests[] =
1815 /* r200 on Windows doesn't check the alpha component when applying the color
1816 * key, so the key matches on every texel. */
1817 {0xff00ff00, TRUE, TRUE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1818 {0xff00ff00, TRUE, FALSE, 0x00ff0000, 0x00ff0000, 0x000000ff, 0x000000ff},
1819 {0xff00ff00, FALSE, TRUE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1820 {0xff00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1821 {0x7f00ff00, TRUE, TRUE, 0x00807f00, 0x00ff0000, 0x00807f00, 0x000000ff},
1822 {0x7f00ff00, TRUE, FALSE, 0x0000ff00, 0x00ff0000, 0x0000ff00, 0x000000ff},
1823 {0x7f00ff00, FALSE, TRUE, 0x00807f00, 0x00807f00, 0x00807f00, 0x00807f00},
1824 {0x7f00ff00, FALSE, FALSE, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00},
1827 IDirectDrawSurface7 *texture;
1828 DDSURFACEDESC2 surface_desc;
1829 IDirect3DDevice7 *device;
1830 IDirectDrawSurface7 *rt;
1831 IDirectDraw7 *ddraw;
1832 IDirect3D7 *d3d;
1833 D3DCOLOR color;
1834 HWND window;
1835 DDBLTFX fx;
1836 HRESULT hr;
1837 UINT i;
1839 window = create_window();
1840 if (!(device = create_device_ex(window, DDSCL_NORMAL, device_guid)))
1842 skip("Failed to create a 3D device, skipping test.\n");
1843 DestroyWindow(window);
1844 return;
1847 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1848 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1849 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1850 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1851 IDirect3D7_Release(d3d);
1853 memset(&surface_desc, 0, sizeof(surface_desc));
1854 surface_desc.dwSize = sizeof(surface_desc);
1855 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1856 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1857 if (is_software_device_type(device_guid))
1858 surface_desc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
1859 surface_desc.dwWidth = 256;
1860 surface_desc.dwHeight = 256;
1861 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1862 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1863 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1864 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1865 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1866 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1867 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
1868 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff00;
1869 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff00;
1870 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
1871 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1873 hr = IDirect3DDevice7_SetTexture(device, 0, texture);
1874 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1875 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
1876 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1877 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
1878 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1880 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1881 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1883 for (i = 0; i < ARRAY_SIZE(tests); ++i)
1885 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, tests[i].color_key);
1886 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1887 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, tests[i].blend);
1888 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1890 memset(&fx, 0, sizeof(fx));
1891 fx.dwSize = sizeof(fx);
1892 U5(fx).dwFillColor = tests[i].fill_color;
1893 hr = IDirectDrawSurface7_Blt(texture, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1894 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1896 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 1.0f, 0);
1897 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1898 /* RT clears are broken on Windows for software render target. */
1899 if (is_software_device_type(device_guid))
1900 fill_surface(rt, 0xffff0000);
1902 hr = IDirect3DDevice7_BeginScene(device);
1903 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1904 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
1905 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1906 hr = IDirect3DDevice7_EndScene(device);
1907 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1909 color = get_surface_color(rt, 320, 240);
1910 ok(compare_color(color, tests[i].result1, 2) || compare_color(color, tests[i].result1_broken, 1),
1911 "Expected color 0x%08x for test %u, got 0x%08x.\n",
1912 tests[i].result1, i, color);
1914 U5(fx).dwFillColor = 0xff0000ff;
1915 hr = IDirectDrawSurface7_Blt(texture, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
1916 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
1918 hr = IDirect3DDevice7_BeginScene(device);
1919 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1920 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[4], 4, 0);
1921 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1922 hr = IDirect3DDevice7_EndScene(device);
1923 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1925 /* This tests that fragments that are masked out by the color key are
1926 * discarded, instead of just fully transparent. */
1927 color = get_surface_color(rt, 320, 240);
1928 ok(compare_color(color, tests[i].result2, 2) || compare_color(color, tests[i].result2_broken, 1),
1929 "Expected color 0x%08x for test %u, got 0x%08x.\n",
1930 tests[i].result2, i, color);
1933 IDirectDrawSurface7_Release(rt);
1934 IDirectDrawSurface7_Release(texture);
1935 IDirectDraw7_Release(ddraw);
1936 IDirect3DDevice7_Release(device);
1937 DestroyWindow(window);
1940 static void test_ck_default(void)
1942 static struct
1944 struct vec4 position;
1945 struct vec2 texcoord;
1947 tquad[] =
1949 {{ 0.0f, 480.0f, 0.0f, 1.0f}, {0.0f, 0.0f}},
1950 {{ 0.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 1.0f}},
1951 {{640.0f, 480.0f, 0.0f, 1.0f}, {1.0f, 0.0f}},
1952 {{640.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
1954 IDirectDrawSurface7 *surface, *rt;
1955 DDSURFACEDESC2 surface_desc;
1956 IDirect3DDevice7 *device;
1957 IDirectDraw7 *ddraw;
1958 IDirect3D7 *d3d;
1959 D3DCOLOR color;
1960 DWORD value;
1961 HWND window;
1962 DDBLTFX fx;
1963 HRESULT hr;
1965 window = create_window();
1966 if (!(device = create_device(window, DDSCL_NORMAL)))
1968 skip("Failed to create a 3D device, skipping test.\n");
1969 DestroyWindow(window);
1970 return;
1973 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
1974 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
1975 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
1976 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
1977 IDirect3D7_Release(d3d);
1979 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
1980 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
1982 memset(&surface_desc, 0, sizeof(surface_desc));
1983 surface_desc.dwSize = sizeof(surface_desc);
1984 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
1985 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1986 surface_desc.dwWidth = 256;
1987 surface_desc.dwHeight = 256;
1988 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
1989 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
1990 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
1991 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
1992 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
1993 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
1994 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x000000ff;
1995 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x000000ff;
1996 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
1997 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1998 hr = IDirect3DDevice7_SetTexture(device, 0, surface);
1999 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
2001 memset(&fx, 0, sizeof(fx));
2002 fx.dwSize = sizeof(fx);
2003 U5(fx).dwFillColor = 0x000000ff;
2004 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
2005 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
2007 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
2008 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
2009 hr = IDirect3DDevice7_BeginScene(device);
2010 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
2011 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
2012 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
2013 ok(!value, "Got unexpected color keying state %#x.\n", value);
2014 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
2015 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
2016 hr = IDirect3DDevice7_EndScene(device);
2017 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
2018 color = get_surface_color(rt, 320, 240);
2019 ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
2021 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 1.0f, 0);
2022 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
2023 hr = IDirect3DDevice7_BeginScene(device);
2024 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
2025 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
2026 ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
2027 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_TEX1, &tquad[0], 4, 0);
2028 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
2029 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, &value);
2030 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
2031 ok(!!value, "Got unexpected color keying state %#x.\n", value);
2032 hr = IDirect3DDevice7_EndScene(device);
2033 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
2034 color = get_surface_color(rt, 320, 240);
2035 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
2037 IDirectDrawSurface7_Release(surface);
2038 IDirectDrawSurface7_Release(rt);
2039 IDirect3DDevice7_Release(device);
2040 IDirectDraw7_Release(ddraw);
2041 DestroyWindow(window);
2044 static void test_ck_complex(void)
2046 IDirectDrawSurface7 *surface, *mipmap, *tmp;
2047 D3DDEVICEDESC7 device_desc;
2048 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
2049 DDSURFACEDESC2 surface_desc;
2050 IDirect3DDevice7 *device;
2051 DDCOLORKEY color_key;
2052 IDirectDraw7 *ddraw;
2053 IDirect3D7 *d3d;
2054 unsigned int i;
2055 ULONG refcount;
2056 HWND window;
2057 HRESULT hr;
2059 window = create_window();
2060 if (!(device = create_device(window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
2062 skip("Failed to create a 3D device, skipping test.\n");
2063 DestroyWindow(window);
2064 return;
2066 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
2067 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
2068 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
2069 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
2070 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
2071 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
2072 IDirect3D7_Release(d3d);
2074 memset(&surface_desc, 0, sizeof(surface_desc));
2075 surface_desc.dwSize = sizeof(surface_desc);
2076 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2077 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2078 surface_desc.dwWidth = 128;
2079 surface_desc.dwHeight = 128;
2080 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2081 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
2083 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2084 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
2085 color_key.dwColorSpaceLowValue = 0x0000ff00;
2086 color_key.dwColorSpaceHighValue = 0x0000ff00;
2087 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2088 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
2089 memset(&color_key, 0, sizeof(color_key));
2090 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2091 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
2092 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2093 color_key.dwColorSpaceLowValue);
2094 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2095 color_key.dwColorSpaceHighValue);
2097 mipmap = surface;
2098 IDirectDrawSurface_AddRef(mipmap);
2099 for (i = 0; i < 7; ++i)
2101 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
2102 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
2103 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2104 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
2106 color_key.dwColorSpaceLowValue = 0x000000ff;
2107 color_key.dwColorSpaceHighValue = 0x000000ff;
2108 hr = IDirectDrawSurface7_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2109 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x, i %u.\n", hr, i);
2111 IDirectDrawSurface_Release(mipmap);
2112 mipmap = tmp;
2115 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
2116 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
2117 IDirectDrawSurface_Release(mipmap);
2118 refcount = IDirectDrawSurface7_Release(surface);
2119 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
2121 memset(&surface_desc, 0, sizeof(surface_desc));
2122 surface_desc.dwSize = sizeof(surface_desc);
2123 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
2124 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
2125 U5(surface_desc).dwBackBufferCount = 1;
2126 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2127 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
2129 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2130 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
2131 color_key.dwColorSpaceLowValue = 0x0000ff00;
2132 color_key.dwColorSpaceHighValue = 0x0000ff00;
2133 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2134 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
2135 memset(&color_key, 0, sizeof(color_key));
2136 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2137 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
2138 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2139 color_key.dwColorSpaceLowValue);
2140 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2141 color_key.dwColorSpaceHighValue);
2143 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &tmp);
2144 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
2146 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2147 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
2148 color_key.dwColorSpaceLowValue = 0x0000ff00;
2149 color_key.dwColorSpaceHighValue = 0x0000ff00;
2150 hr = IDirectDrawSurface7_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2151 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
2152 memset(&color_key, 0, sizeof(color_key));
2153 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2154 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
2155 ok(color_key.dwColorSpaceLowValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2156 color_key.dwColorSpaceLowValue);
2157 ok(color_key.dwColorSpaceHighValue == 0x0000ff00, "Got unexpected value 0x%08x.\n",
2158 color_key.dwColorSpaceHighValue);
2160 IDirectDrawSurface_Release(tmp);
2162 refcount = IDirectDrawSurface7_Release(surface);
2163 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
2165 if (!(device_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP))
2167 skip("Device does not support cubemaps.\n");
2168 goto cleanup;
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 | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
2174 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
2175 surface_desc.dwWidth = 128;
2176 surface_desc.dwHeight = 128;
2177 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2178 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
2180 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2181 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
2182 color_key.dwColorSpaceLowValue = 0x0000ff00;
2183 color_key.dwColorSpaceHighValue = 0x0000ff00;
2184 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &color_key);
2185 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
2187 caps.dwCaps2 = DDSCAPS2_CUBEMAP_NEGATIVEZ;
2188 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
2189 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
2191 hr = IDirectDrawSurface7_GetColorKey(mipmap, DDCKEY_SRCBLT, &color_key);
2192 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
2193 color_key.dwColorSpaceLowValue = 0x000000ff;
2194 color_key.dwColorSpaceHighValue = 0x000000ff;
2195 hr = IDirectDrawSurface7_SetColorKey(mipmap, DDCKEY_SRCBLT, &color_key);
2196 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
2198 color_key.dwColorSpaceLowValue = 0;
2199 color_key.dwColorSpaceHighValue = 0;
2200 hr = IDirectDrawSurface7_GetColorKey(mipmap, DDCKEY_SRCBLT, &color_key);
2201 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
2202 ok(color_key.dwColorSpaceLowValue == 0x000000ff, "Got unexpected value 0x%08x.\n",
2203 color_key.dwColorSpaceLowValue);
2204 ok(color_key.dwColorSpaceHighValue == 0x000000ff, "Got unexpected value 0x%08x.\n",
2205 color_key.dwColorSpaceHighValue);
2207 IDirectDrawSurface_AddRef(mipmap);
2208 for (i = 0; i < 7; ++i)
2210 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
2211 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
2212 hr = IDirectDrawSurface7_GetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2213 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x, i %u.\n", hr, i);
2215 color_key.dwColorSpaceLowValue = 0x000000ff;
2216 color_key.dwColorSpaceHighValue = 0x000000ff;
2217 hr = IDirectDrawSurface7_SetColorKey(tmp, DDCKEY_SRCBLT, &color_key);
2218 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x, i %u.\n", hr, i);
2220 IDirectDrawSurface_Release(mipmap);
2221 mipmap = tmp;
2224 IDirectDrawSurface7_Release(mipmap);
2226 refcount = IDirectDrawSurface7_Release(surface);
2227 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
2229 cleanup:
2230 IDirectDraw7_Release(ddraw);
2231 refcount = IDirect3DDevice7_Release(device);
2232 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
2233 DestroyWindow(window);
2236 struct qi_test
2238 REFIID iid;
2239 REFIID refcount_iid;
2240 HRESULT hr;
2243 static void test_qi(const char *test_name, IUnknown *base_iface,
2244 REFIID refcount_iid, const struct qi_test *tests, UINT entry_count)
2246 ULONG refcount, expected_refcount;
2247 IUnknown *iface1, *iface2;
2248 HRESULT hr;
2249 UINT i, j;
2251 for (i = 0; i < entry_count; ++i)
2253 hr = IUnknown_QueryInterface(base_iface, tests[i].iid, (void **)&iface1);
2254 ok(hr == tests[i].hr, "Got hr %#x for test \"%s\" %u.\n", hr, test_name, i);
2255 if (SUCCEEDED(hr))
2257 for (j = 0; j < entry_count; ++j)
2259 hr = IUnknown_QueryInterface(iface1, tests[j].iid, (void **)&iface2);
2260 ok(hr == tests[j].hr, "Got hr %#x for test \"%s\" %u, %u.\n", hr, test_name, i, j);
2261 if (SUCCEEDED(hr))
2263 expected_refcount = 0;
2264 if (IsEqualGUID(refcount_iid, tests[j].refcount_iid))
2265 ++expected_refcount;
2266 if (IsEqualGUID(tests[i].refcount_iid, tests[j].refcount_iid))
2267 ++expected_refcount;
2268 refcount = IUnknown_Release(iface2);
2269 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, %u, expected %u.\n",
2270 refcount, test_name, i, j, expected_refcount);
2274 expected_refcount = 0;
2275 if (IsEqualGUID(refcount_iid, tests[i].refcount_iid))
2276 ++expected_refcount;
2277 refcount = IUnknown_Release(iface1);
2278 ok(refcount == expected_refcount, "Got refcount %u for test \"%s\" %u, expected %u.\n",
2279 refcount, test_name, i, expected_refcount);
2284 static void test_surface_qi(void)
2286 static const struct qi_test tests[] =
2288 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
2289 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
2290 {&IID_IDirectDrawGammaControl, &IID_IDirectDrawGammaControl, S_OK },
2291 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2292 {&IID_IDirectDrawSurface7, &IID_IDirectDrawSurface7, S_OK },
2293 {&IID_IDirectDrawSurface4, &IID_IDirectDrawSurface4, S_OK },
2294 {&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3, S_OK },
2295 {&IID_IDirectDrawSurface2, &IID_IDirectDrawSurface2, S_OK },
2296 {&IID_IDirectDrawSurface, &IID_IDirectDrawSurface, S_OK },
2297 {&IID_IDirect3DDevice7, NULL, E_NOINTERFACE},
2298 {&IID_IDirect3DDevice3, NULL, E_NOINTERFACE},
2299 {&IID_IDirect3DDevice2, NULL, E_NOINTERFACE},
2300 {&IID_IDirect3DDevice, NULL, E_NOINTERFACE},
2301 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
2302 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
2303 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
2304 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
2305 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
2306 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
2307 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
2308 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
2309 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
2310 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
2311 {&IID_IDirect3D, NULL, E_NOINTERFACE},
2312 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
2313 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
2314 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
2315 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
2316 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
2317 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
2318 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
2319 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
2320 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
2321 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
2322 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
2323 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
2324 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
2325 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
2326 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
2327 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
2328 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
2329 {&IID_IUnknown, &IID_IDirectDrawSurface, S_OK },
2330 {NULL, NULL, E_INVALIDARG },
2333 IDirectDrawSurface7 *surface;
2334 DDSURFACEDESC2 surface_desc;
2335 IDirect3DDevice7 *device;
2336 IDirectDraw7 *ddraw;
2337 HWND window;
2338 HRESULT hr;
2340 window = create_window();
2341 /* Try to create a D3D device to see if the ddraw implementation supports
2342 * D3D. 64-bit ddraw in particular doesn't seem to support D3D, and
2343 * doesn't support e.g. the IDirect3DTexture interfaces. */
2344 if (!(device = create_device(window, DDSCL_NORMAL)))
2346 skip("Failed to create a 3D device, skipping test.\n");
2347 DestroyWindow(window);
2348 return;
2350 IDirect3DDevice_Release(device);
2351 ddraw = create_ddraw();
2352 ok(!!ddraw, "Failed to create a ddraw object.\n");
2353 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2354 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
2356 memset(&surface_desc, 0, sizeof(surface_desc));
2357 surface_desc.dwSize = sizeof(surface_desc);
2358 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2359 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2360 surface_desc.dwWidth = 512;
2361 surface_desc.dwHeight = 512;
2362 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, (IDirectDrawSurface7 **)0xdeadbeef, NULL);
2363 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
2364 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
2365 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
2367 test_qi("surface_qi", (IUnknown *)surface, &IID_IDirectDrawSurface7, tests, ARRAY_SIZE(tests));
2369 IDirectDrawSurface7_Release(surface);
2370 IDirectDraw7_Release(ddraw);
2371 DestroyWindow(window);
2374 static void test_device_qi(void)
2376 static const struct qi_test tests[] =
2378 {&IID_IDirect3DTexture2, NULL, E_NOINTERFACE},
2379 {&IID_IDirect3DTexture, NULL, E_NOINTERFACE},
2380 {&IID_IDirectDrawGammaControl, NULL, E_NOINTERFACE},
2381 {&IID_IDirectDrawColorControl, NULL, E_NOINTERFACE},
2382 {&IID_IDirectDrawSurface7, NULL, E_NOINTERFACE},
2383 {&IID_IDirectDrawSurface4, NULL, E_NOINTERFACE},
2384 {&IID_IDirectDrawSurface3, NULL, E_NOINTERFACE},
2385 {&IID_IDirectDrawSurface2, NULL, E_NOINTERFACE},
2386 {&IID_IDirectDrawSurface, NULL, E_NOINTERFACE},
2387 {&IID_IDirect3DDevice7, &IID_IDirect3DDevice7, S_OK },
2388 {&IID_IDirect3DDevice3, NULL, E_NOINTERFACE},
2389 {&IID_IDirect3DDevice2, NULL, E_NOINTERFACE},
2390 {&IID_IDirect3DDevice, NULL, E_NOINTERFACE},
2391 {&IID_IDirect3DRampDevice, NULL, E_NOINTERFACE},
2392 {&IID_IDirect3DRGBDevice, NULL, E_NOINTERFACE},
2393 {&IID_IDirect3DHALDevice, NULL, E_NOINTERFACE},
2394 {&IID_IDirect3DMMXDevice, NULL, E_NOINTERFACE},
2395 {&IID_IDirect3DRefDevice, NULL, E_NOINTERFACE},
2396 {&IID_IDirect3DTnLHalDevice, NULL, E_NOINTERFACE},
2397 {&IID_IDirect3DNullDevice, NULL, E_NOINTERFACE},
2398 {&IID_IDirect3D7, NULL, E_NOINTERFACE},
2399 {&IID_IDirect3D3, NULL, E_NOINTERFACE},
2400 {&IID_IDirect3D2, NULL, E_NOINTERFACE},
2401 {&IID_IDirect3D, NULL, E_NOINTERFACE},
2402 {&IID_IDirectDraw7, NULL, E_NOINTERFACE},
2403 {&IID_IDirectDraw4, NULL, E_NOINTERFACE},
2404 {&IID_IDirectDraw3, NULL, E_NOINTERFACE},
2405 {&IID_IDirectDraw2, NULL, E_NOINTERFACE},
2406 {&IID_IDirectDraw, NULL, E_NOINTERFACE},
2407 {&IID_IDirect3DLight, NULL, E_NOINTERFACE},
2408 {&IID_IDirect3DMaterial, NULL, E_NOINTERFACE},
2409 {&IID_IDirect3DMaterial2, NULL, E_NOINTERFACE},
2410 {&IID_IDirect3DMaterial3, NULL, E_NOINTERFACE},
2411 {&IID_IDirect3DExecuteBuffer, NULL, E_NOINTERFACE},
2412 {&IID_IDirect3DViewport, NULL, E_NOINTERFACE},
2413 {&IID_IDirect3DViewport2, NULL, E_NOINTERFACE},
2414 {&IID_IDirect3DViewport3, NULL, E_NOINTERFACE},
2415 {&IID_IDirect3DVertexBuffer, NULL, E_NOINTERFACE},
2416 {&IID_IDirect3DVertexBuffer7, NULL, E_NOINTERFACE},
2417 {&IID_IDirectDrawPalette, NULL, E_NOINTERFACE},
2418 {&IID_IDirectDrawClipper, NULL, E_NOINTERFACE},
2419 {&IID_IUnknown, &IID_IDirect3DDevice7, S_OK },
2422 IDirect3DDevice7 *device;
2423 HWND window;
2425 window = create_window();
2426 if (!(device = create_device(window, DDSCL_NORMAL)))
2428 skip("Failed to create a 3D device, skipping test.\n");
2429 DestroyWindow(window);
2430 return;
2433 test_qi("device_qi", (IUnknown *)device, &IID_IDirect3DDevice7, tests, ARRAY_SIZE(tests));
2435 IDirect3DDevice7_Release(device);
2436 DestroyWindow(window);
2439 static void test_wndproc(void)
2441 LONG_PTR proc, ddraw_proc;
2442 IDirectDraw7 *ddraw;
2443 WNDCLASSA wc = {0};
2444 HWND window;
2445 HRESULT hr;
2446 ULONG ref;
2448 static struct message messages[] =
2450 {WM_WINDOWPOSCHANGING, FALSE, 0},
2451 {WM_MOVE, FALSE, 0},
2452 {WM_SIZE, FALSE, 0},
2453 {WM_WINDOWPOSCHANGING, FALSE, 0},
2454 {WM_ACTIVATE, FALSE, 0},
2455 {WM_SETFOCUS, FALSE, 0},
2456 {0, FALSE, 0},
2459 /* DDSCL_EXCLUSIVE replaces the window's window proc. */
2460 ddraw = create_ddraw();
2461 ok(!!ddraw, "Failed to create a ddraw object.\n");
2463 wc.lpfnWndProc = test_proc;
2464 wc.lpszClassName = "ddraw_test_wndproc_wc";
2465 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2467 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
2468 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
2470 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2471 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2472 (LONG_PTR)test_proc, proc);
2473 expect_messages = messages;
2474 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2475 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2476 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2477 expect_messages = NULL;
2478 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2479 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2480 (LONG_PTR)test_proc, proc);
2481 ref = IDirectDraw7_Release(ddraw);
2482 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2483 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2484 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2485 (LONG_PTR)test_proc, proc);
2487 /* DDSCL_NORMAL doesn't. */
2488 ddraw = create_ddraw();
2489 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2490 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2491 (LONG_PTR)test_proc, proc);
2492 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
2493 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2494 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2495 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2496 (LONG_PTR)test_proc, proc);
2497 ref = IDirectDraw7_Release(ddraw);
2498 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2499 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2500 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2501 (LONG_PTR)test_proc, proc);
2503 /* The original window proc is only restored by ddraw if the current
2504 * window proc matches the one ddraw set. This also affects switching
2505 * from DDSCL_NORMAL to DDSCL_EXCLUSIVE. */
2506 ddraw = create_ddraw();
2507 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2508 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2509 (LONG_PTR)test_proc, proc);
2510 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2511 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2512 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2513 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2514 (LONG_PTR)test_proc, proc);
2515 ddraw_proc = proc;
2516 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2517 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2518 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2519 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2520 (LONG_PTR)test_proc, proc);
2521 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2522 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2523 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2524 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2525 (LONG_PTR)test_proc, proc);
2526 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2527 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2528 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2529 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2530 (LONG_PTR)DefWindowProcA, proc);
2531 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2532 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2533 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, ddraw_proc);
2534 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2535 (LONG_PTR)DefWindowProcA, proc);
2536 ref = IDirectDraw7_Release(ddraw);
2537 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2538 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2539 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2540 (LONG_PTR)test_proc, proc);
2542 ddraw = create_ddraw();
2543 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2544 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2545 (LONG_PTR)test_proc, proc);
2546 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2547 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2548 proc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2549 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2550 (LONG_PTR)test_proc, proc);
2551 ref = IDirectDraw7_Release(ddraw);
2552 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2553 proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
2554 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2555 (LONG_PTR)DefWindowProcA, proc);
2557 fix_wndproc(window, (LONG_PTR)test_proc);
2558 expect_messages = NULL;
2559 DestroyWindow(window);
2560 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
2563 static void test_window_style(void)
2565 LONG style, exstyle, tmp, expected_style;
2566 RECT fullscreen_rect, r;
2567 HWND window, window2;
2568 IDirectDraw7 *ddraw;
2569 HRESULT hr;
2570 ULONG ref;
2571 BOOL ret;
2573 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2574 0, 0, 100, 100, 0, 0, 0, 0);
2575 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2576 0, 0, 50, 50, 0, 0, 0, 0);
2577 ddraw = create_ddraw();
2578 ok(!!ddraw, "Failed to create a ddraw object.\n");
2580 style = GetWindowLongA(window, GWL_STYLE);
2581 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
2582 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2584 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2585 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2587 tmp = GetWindowLongA(window, GWL_STYLE);
2588 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2589 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2590 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2592 GetWindowRect(window, &r);
2593 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
2594 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
2595 GetClientRect(window, &r);
2596 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2598 ret = SetForegroundWindow(GetDesktopWindow());
2599 ok(ret, "Failed to set foreground window.\n");
2601 tmp = GetWindowLongA(window, GWL_STYLE);
2602 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2603 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2604 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2606 ret = SetForegroundWindow(window);
2607 ok(ret, "Failed to set foreground window.\n");
2608 /* Windows 7 (but not Vista and XP) shows the window when it receives focus. Hide it again,
2609 * the next tests expect this. */
2610 ShowWindow(window, SW_HIDE);
2612 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2613 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2615 tmp = GetWindowLongA(window, GWL_STYLE);
2616 ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2617 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2618 ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2620 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_NOWINDOWCHANGES);
2621 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2623 tmp = GetWindowLongA(window, GWL_STYLE);
2624 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2625 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2626 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2628 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2629 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2631 tmp = GetWindowLongA(window, GWL_STYLE);
2632 expected_style = style | WS_VISIBLE;
2633 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2634 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2635 expected_style = exstyle | WS_EX_TOPMOST;
2636 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2638 ShowWindow(window, SW_HIDE);
2639 tmp = GetWindowLongA(window, GWL_STYLE);
2640 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2641 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2642 expected_style = exstyle | WS_EX_TOPMOST;
2643 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2645 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_NOWINDOWCHANGES);
2646 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2648 tmp = GetWindowLongA(window, GWL_STYLE);
2649 ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2650 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2651 expected_style = exstyle | WS_EX_TOPMOST;
2652 ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2654 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2655 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2657 tmp = GetWindowLongA(window, GWL_STYLE);
2658 ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2659 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2660 expected_style = exstyle | WS_EX_TOPMOST;
2661 ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2663 ret = SetForegroundWindow(window);
2664 ok(ret, "Failed to set foreground window.\n");
2666 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2667 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2669 tmp = GetWindowLongA(window, GWL_STYLE);
2670 expected_style = style | WS_VISIBLE;
2671 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2672 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2673 expected_style = exstyle | WS_EX_TOPMOST;
2674 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2676 ShowWindow(window, SW_HIDE);
2677 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2678 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2680 tmp = GetWindowLongA(window, GWL_STYLE);
2681 ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2682 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2683 ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2685 ShowWindow(window, SW_SHOW);
2686 ret = SetForegroundWindow(GetDesktopWindow());
2687 ok(ret, "Failed to set foreground window.\n");
2688 SetActiveWindow(window);
2689 ok(GetActiveWindow() == window, "Unexpected active window.\n");
2690 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2691 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2693 tmp = GetWindowLongA(window, GWL_STYLE);
2694 expected_style = style | WS_VISIBLE;
2695 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2696 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2697 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2699 GetWindowRect(window, &r);
2700 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
2701 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
2703 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2704 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2706 SetWindowPos(window, NULL, 0, 0, 100, 100, SWP_NOZORDER | SWP_NOACTIVATE);
2707 GetWindowRect(window, &r);
2708 ok(!EqualRect(&r, &fullscreen_rect), "Window resize failed? got %s.\n",
2709 wine_dbgstr_rect(&r));
2711 ret = SetForegroundWindow(window2);
2712 ok(ret, "Failed to set foreground window.\n");
2713 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2714 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2716 tmp = GetWindowLongA(window, GWL_STYLE);
2717 expected_style = style | WS_VISIBLE;
2718 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2719 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2720 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2722 GetWindowRect(window, &r);
2723 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
2724 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
2726 ret = SetForegroundWindow(window);
2727 ok(ret, "Failed to set foreground window.\n");
2728 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2729 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2731 tmp = GetWindowLongA(window, GWL_STYLE);
2732 expected_style = style | WS_VISIBLE;
2733 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2734 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2735 expected_style = exstyle | WS_EX_TOPMOST;
2736 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2738 ShowWindow(window, SW_HIDE);
2739 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2740 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2742 tmp = GetWindowLongA(window, GWL_STYLE);
2743 ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2744 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2745 ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2747 ShowWindow(window, SW_SHOW);
2748 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2749 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2751 tmp = GetWindowLongA(window, GWL_STYLE);
2752 expected_style = style | WS_VISIBLE;
2753 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2754 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2755 expected_style = exstyle | WS_EX_TOPMOST;
2756 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2758 ret = SetForegroundWindow(GetDesktopWindow());
2759 ok(ret, "Failed to set foreground window.\n");
2760 tmp = GetWindowLongA(window, GWL_STYLE);
2761 expected_style = style | WS_VISIBLE | WS_MINIMIZE;
2762 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2763 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2764 expected_style = exstyle | WS_EX_TOPMOST;
2765 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2767 ref = IDirectDraw7_Release(ddraw);
2768 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2770 DestroyWindow(window2);
2771 DestroyWindow(window);
2774 static void test_redundant_mode_set(void)
2776 DDSURFACEDESC2 surface_desc = {0};
2777 IDirectDraw7 *ddraw;
2778 RECT q, r, s;
2779 HWND window;
2780 HRESULT hr;
2781 ULONG ref;
2783 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2784 0, 0, 100, 100, 0, 0, 0, 0);
2785 ddraw = create_ddraw();
2786 ok(!!ddraw, "Failed to create a ddraw object.\n");
2787 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2788 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2790 surface_desc.dwSize = sizeof(surface_desc);
2791 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
2792 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
2794 hr = IDirectDraw7_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2795 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
2796 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2798 GetWindowRect(window, &q);
2799 r = q;
2800 r.right /= 2;
2801 r.bottom /= 2;
2802 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
2803 GetWindowRect(window, &s);
2804 ok(EqualRect(&r, &s), "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2806 hr = IDirectDraw7_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2807 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
2808 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2810 GetWindowRect(window, &s);
2811 ok(EqualRect(&r, &s) || broken(EqualRect(&q, &s) /* Windows 10 */),
2812 "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2814 ref = IDirectDraw7_Release(ddraw);
2815 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2817 DestroyWindow(window);
2820 static SIZE screen_size, screen_size2;
2822 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2824 if (message == WM_SIZE)
2826 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2827 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2830 return test_proc(hwnd, message, wparam, lparam);
2833 static LRESULT CALLBACK mode_set_proc2(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2835 if (message == WM_SIZE)
2837 screen_size2.cx = GetSystemMetrics(SM_CXSCREEN);
2838 screen_size2.cy = GetSystemMetrics(SM_CYSCREEN);
2841 return test_proc(hwnd, message, wparam, lparam);
2844 struct test_coop_level_mode_set_enum_param
2846 DWORD ddraw_width, ddraw_height, user32_width, user32_height;
2849 static HRESULT CALLBACK test_coop_level_mode_set_enum_cb(DDSURFACEDESC2 *surface_desc, void *context)
2851 struct test_coop_level_mode_set_enum_param *param = context;
2853 if (U1(U4(*surface_desc).ddpfPixelFormat).dwRGBBitCount != registry_mode.dmBitsPerPel)
2854 return DDENUMRET_OK;
2855 if (surface_desc->dwWidth == registry_mode.dmPelsWidth
2856 && surface_desc->dwHeight == registry_mode.dmPelsHeight)
2857 return DDENUMRET_OK;
2859 if (!param->ddraw_width)
2861 param->ddraw_width = surface_desc->dwWidth;
2862 param->ddraw_height = surface_desc->dwHeight;
2863 return DDENUMRET_OK;
2865 if (surface_desc->dwWidth == param->ddraw_width && surface_desc->dwHeight == param->ddraw_height)
2866 return DDENUMRET_OK;
2868 param->user32_width = surface_desc->dwWidth;
2869 param->user32_height = surface_desc->dwHeight;
2870 return DDENUMRET_CANCEL;
2873 static void test_coop_level_mode_set(void)
2875 DEVMODEW *original_modes = NULL, devmode, devmode2;
2876 unsigned int display_count = 0;
2877 IDirectDrawSurface7 *primary;
2878 RECT registry_rect, ddraw_rect, user32_rect, r;
2879 IDirectDraw7 *ddraw;
2880 DDSURFACEDESC2 ddsd;
2881 WNDCLASSA wc = {0};
2882 HWND window, window2;
2883 HRESULT hr;
2884 ULONG ref;
2885 MSG msg;
2886 struct test_coop_level_mode_set_enum_param param;
2887 BOOL ret;
2888 LONG change_ret;
2890 static const struct message exclusive_messages[] =
2892 {WM_WINDOWPOSCHANGING, FALSE, 0},
2893 {WM_WINDOWPOSCHANGED, FALSE, 0},
2894 {WM_SIZE, FALSE, 0},
2895 {WM_DISPLAYCHANGE, FALSE, 0},
2896 {0, FALSE, 0},
2898 static const struct message exclusive_focus_loss_messages[] =
2900 {WM_ACTIVATE, TRUE, WA_INACTIVE, DD_OK},
2901 {WM_WINDOWPOSCHANGING, FALSE, 0, DD_OK}, /* Window resize due to mode change. */
2902 {WM_WINDOWPOSCHANGED, FALSE, 0, DD_OK},
2903 {WM_SIZE, TRUE, SIZE_RESTORED, DD_OK}, /* Generated by DefWindowProc. */
2904 {WM_DISPLAYCHANGE, FALSE, 0, DD_OK},
2905 {WM_KILLFOCUS, FALSE, 0, DDERR_NOEXCLUSIVEMODE},
2906 {WM_WINDOWPOSCHANGING, FALSE, 0, DDERR_NOEXCLUSIVEMODE}, /* Window minimized. */
2907 /* Like d3d8 and d3d9 ddraw seems to use SW_SHOWMINIMIZED instead of
2908 * SW_MINIMIZED, causing a recursive window activation that does not
2909 * produce the same result in Wine yet. Ignore the difference for now.
2910 * {WM_ACTIVATE, TRUE, 0x200000 | WA_ACTIVE}, */
2911 {WM_WINDOWPOSCHANGED, FALSE, 0, DDERR_NOEXCLUSIVEMODE},
2912 {WM_MOVE, FALSE, 0, DDERR_NOEXCLUSIVEMODE},
2913 {WM_SIZE, TRUE, SIZE_MINIMIZED, DDERR_NOEXCLUSIVEMODE},
2914 {WM_ACTIVATEAPP, TRUE, FALSE, DDERR_NOEXCLUSIVEMODE},
2915 {0, FALSE, 0, 0},
2917 static const struct message exclusive_focus_restore_messages[] =
2919 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* From the ShowWindow(SW_RESTORE). */
2920 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Generated by ddraw, matches d3d9 behavior. */
2921 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching previous message. */
2922 {WM_SIZE, FALSE, 0}, /* DefWindowProc. */
2923 {WM_DISPLAYCHANGE, FALSE, 0}, /* Ddraw restores mode. */
2924 /* Native redundantly sets the window size here. */
2925 {WM_ACTIVATEAPP, TRUE, TRUE}, /* End of ddraw's hooks. */
2926 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching the one from ShowWindow. */
2927 {WM_MOVE, FALSE, 0}, /* DefWindowProc. */
2928 {WM_SIZE, TRUE, SIZE_RESTORED}, /* DefWindowProc. */
2929 {0, FALSE, 0},
2931 static const struct message sc_restore_messages[] =
2933 {WM_SYSCOMMAND, TRUE, SC_RESTORE},
2934 {WM_WINDOWPOSCHANGING, FALSE, 0},
2935 {WM_WINDOWPOSCHANGED, FALSE, 0},
2936 {WM_SIZE, TRUE, SIZE_RESTORED},
2937 {0, FALSE, 0},
2939 static const struct message sc_minimize_messages[] =
2941 {WM_SYSCOMMAND, TRUE, SC_MINIMIZE},
2942 {WM_WINDOWPOSCHANGING, FALSE, 0},
2943 {WM_WINDOWPOSCHANGED, FALSE, 0},
2944 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2945 {0, FALSE, 0},
2947 static const struct message sc_maximize_messages[] =
2949 {WM_SYSCOMMAND, TRUE, SC_MAXIMIZE},
2950 {WM_WINDOWPOSCHANGING, FALSE, 0},
2951 {WM_WINDOWPOSCHANGED, FALSE, 0},
2952 {WM_SIZE, TRUE, SIZE_MAXIMIZED},
2953 {0, FALSE, 0},
2956 static const struct message normal_messages[] =
2958 {WM_DISPLAYCHANGE, FALSE, 0},
2959 {0, FALSE, 0},
2962 memset(&devmode, 0, sizeof(devmode));
2963 devmode.dmSize = sizeof(devmode);
2964 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2965 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
2966 ok(compare_mode_rect(&devmode, &registry_mode), "Got a different mode.\n");
2967 ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
2968 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
2969 ok(compare_mode_rect(&devmode, &registry_mode), "Got a different mode.\n");
2971 ret = save_display_modes(&original_modes, &display_count);
2972 ok(ret, "Failed to save original display modes.\n");
2974 ddraw = create_ddraw();
2975 ok(!!ddraw, "Failed to create a ddraw object.\n");
2977 memset(&param, 0, sizeof(param));
2978 hr = IDirectDraw7_EnumDisplayModes(ddraw, 0, NULL, &param, test_coop_level_mode_set_enum_cb);
2979 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
2980 ref = IDirectDraw7_Release(ddraw);
2981 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2983 if (!param.user32_height)
2985 skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
2986 heap_free(original_modes);
2987 return;
2990 SetRect(&registry_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2991 SetRect(&ddraw_rect, 0, 0, param.ddraw_width, param.ddraw_height);
2992 SetRect(&user32_rect, 0, 0, param.user32_width, param.user32_height);
2994 memset(&devmode, 0, sizeof(devmode));
2995 devmode.dmSize = sizeof(devmode);
2996 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2997 devmode.dmPelsWidth = param.user32_width;
2998 devmode.dmPelsHeight = param.user32_height;
2999 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3000 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3002 ddraw = create_ddraw();
3003 ok(!!ddraw, "Failed to create a ddraw object.\n");
3005 wc.lpfnWndProc = mode_set_proc;
3006 wc.lpszClassName = "ddraw_test_wndproc_wc";
3007 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3008 wc.lpfnWndProc = mode_set_proc2;
3009 wc.lpszClassName = "ddraw_test_wndproc_wc2";
3010 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3012 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
3013 0, 0, 100, 100, 0, 0, 0, 0);
3014 window2 = CreateWindowA("ddraw_test_wndproc_wc2", "ddraw_test", WS_OVERLAPPEDWINDOW,
3015 0, 0, 100, 100, 0, 0, 0, 0);
3017 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3018 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3020 GetWindowRect(window, &r);
3021 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
3022 wine_dbgstr_rect(&r));
3024 memset(&ddsd, 0, sizeof(ddsd));
3025 ddsd.dwSize = sizeof(ddsd);
3026 ddsd.dwFlags = DDSD_CAPS;
3027 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3029 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3030 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3031 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3032 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3033 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
3034 param.user32_width, ddsd.dwWidth);
3035 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
3036 param.user32_height, ddsd.dwHeight);
3038 GetWindowRect(window, &r);
3039 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
3040 wine_dbgstr_rect(&r));
3042 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3043 expect_messages = exclusive_messages;
3044 screen_size.cx = 0;
3045 screen_size.cy = 0;
3047 hr = IDirectDrawSurface7_IsLost(primary);
3048 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3049 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3050 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3051 hr = IDirectDrawSurface7_IsLost(primary);
3052 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3054 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3055 expect_messages = NULL;
3056 ok(screen_size.cx == param.ddraw_width && screen_size.cy == param.ddraw_height,
3057 "Expected screen size %ux%u, got %ux%u.\n",
3058 param.ddraw_width, param.ddraw_height, screen_size.cx, screen_size.cy);
3060 GetWindowRect(window, &r);
3061 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3062 wine_dbgstr_rect(&r));
3064 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3065 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3066 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
3067 param.user32_width, ddsd.dwWidth);
3068 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
3069 param.user32_height, ddsd.dwHeight);
3070 IDirectDrawSurface7_Release(primary);
3072 memset(&ddsd, 0, sizeof(ddsd));
3073 ddsd.dwSize = sizeof(ddsd);
3074 ddsd.dwFlags = DDSD_CAPS;
3075 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3077 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3078 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3079 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3080 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3081 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3082 param.ddraw_width, ddsd.dwWidth);
3083 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3084 param.ddraw_height, ddsd.dwHeight);
3086 GetWindowRect(window, &r);
3087 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3088 wine_dbgstr_rect(&r));
3090 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3091 expect_messages = exclusive_messages;
3092 screen_size.cx = 0;
3093 screen_size.cy = 0;
3095 hr = IDirectDrawSurface7_IsLost(primary);
3096 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3097 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3098 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3099 hr = IDirectDrawSurface7_IsLost(primary);
3100 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3102 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3103 expect_messages = NULL;
3104 ok(screen_size.cx == param.user32_width && screen_size.cy == param.user32_height,
3105 "Expected screen size %ux%u, got %ux%u.\n",
3106 param.user32_width, param.user32_height, screen_size.cx, screen_size.cy);
3108 GetWindowRect(window, &r);
3109 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
3110 wine_dbgstr_rect(&r));
3112 expect_messages = exclusive_focus_loss_messages;
3113 focus_test_ddraw = ddraw;
3114 ret = SetForegroundWindow(GetDesktopWindow());
3115 ok(ret, "Failed to set foreground window.\n");
3116 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3117 focus_test_ddraw = NULL;
3119 memset(&devmode, 0, sizeof(devmode));
3120 devmode.dmSize = sizeof(devmode);
3121 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3122 ok(ret, "Failed to get display mode.\n");
3123 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3124 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpected screen size %ux%u.\n",
3125 devmode.dmPelsWidth, devmode.dmPelsHeight);
3127 expect_messages = exclusive_focus_restore_messages;
3128 ShowWindow(window, SW_RESTORE);
3129 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3131 GetWindowRect(window, &r);
3132 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3133 wine_dbgstr_rect(&r));
3134 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3135 ok(ret, "Failed to get display mode.\n");
3136 ok(devmode.dmPelsWidth == param.ddraw_width
3137 && devmode.dmPelsHeight == param.ddraw_height, "Got unexpected screen size %ux%u.\n",
3138 devmode.dmPelsWidth, devmode.dmPelsHeight);
3140 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3141 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3142 /* Normally the primary should be restored here. Unfortunately this causes the
3143 * GetSurfaceDesc call after the next display mode change to crash on the Windows 8
3144 * testbot. Another Restore call would presumably avoid the crash, but it also moots
3145 * the point of the GetSurfaceDesc call. */
3147 expect_messages = sc_minimize_messages;
3148 SendMessageA(window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
3149 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3150 expect_messages = NULL;
3152 expect_messages = sc_restore_messages;
3153 SendMessageA(window, WM_SYSCOMMAND, SC_RESTORE, 0);
3154 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3155 expect_messages = NULL;
3157 expect_messages = sc_maximize_messages;
3158 SendMessageA(window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
3159 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3160 expect_messages = NULL;
3162 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3163 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3165 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3166 expect_messages = exclusive_messages;
3167 screen_size.cx = 0;
3168 screen_size.cy = 0;
3170 hr = IDirectDrawSurface7_IsLost(primary);
3171 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3172 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
3173 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3174 hr = IDirectDrawSurface7_IsLost(primary);
3175 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3177 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3178 expect_messages = NULL;
3179 ok(screen_size.cx == registry_mode.dmPelsWidth
3180 && screen_size.cy == registry_mode.dmPelsHeight,
3181 "Expected screen size %ux%u, got %ux%u.\n",
3182 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size.cx, screen_size.cy);
3184 GetWindowRect(window, &r);
3185 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3186 wine_dbgstr_rect(&r));
3188 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3189 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3190 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3191 param.ddraw_width, ddsd.dwWidth);
3192 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3193 param.ddraw_height, ddsd.dwHeight);
3194 IDirectDrawSurface7_Release(primary);
3196 /* For Wine. */
3197 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3198 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3200 memset(&ddsd, 0, sizeof(ddsd));
3201 ddsd.dwSize = sizeof(ddsd);
3202 ddsd.dwFlags = DDSD_CAPS;
3203 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3205 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3206 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3207 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3208 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3209 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3210 registry_mode.dmPelsWidth, ddsd.dwWidth);
3211 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3212 registry_mode.dmPelsHeight, ddsd.dwHeight);
3214 GetWindowRect(window, &r);
3215 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3216 wine_dbgstr_rect(&r));
3218 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3219 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3221 GetWindowRect(window, &r);
3222 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3223 wine_dbgstr_rect(&r));
3225 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3226 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3227 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3228 registry_mode.dmPelsWidth, ddsd.dwWidth);
3229 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3230 registry_mode.dmPelsHeight, ddsd.dwHeight);
3231 IDirectDrawSurface7_Release(primary);
3233 memset(&ddsd, 0, sizeof(ddsd));
3234 ddsd.dwSize = sizeof(ddsd);
3235 ddsd.dwFlags = DDSD_CAPS;
3236 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3238 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3239 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3240 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3241 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3242 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3243 registry_mode.dmPelsWidth, ddsd.dwWidth);
3244 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3245 registry_mode.dmPelsHeight, ddsd.dwHeight);
3247 GetWindowRect(window, &r);
3248 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3249 wine_dbgstr_rect(&r));
3251 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3252 expect_messages = normal_messages;
3253 screen_size.cx = 0;
3254 screen_size.cy = 0;
3256 hr = IDirectDrawSurface7_IsLost(primary);
3257 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3258 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3259 devmode.dmPelsWidth = param.user32_width;
3260 devmode.dmPelsHeight = param.user32_height;
3261 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3262 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3263 hr = IDirectDrawSurface7_IsLost(primary);
3264 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3266 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3267 expect_messages = NULL;
3268 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3270 GetWindowRect(window, &r);
3271 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3272 wine_dbgstr_rect(&r));
3274 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3275 expect_messages = normal_messages;
3276 screen_size.cx = 0;
3277 screen_size.cy = 0;
3279 hr = IDirectDrawSurface7_Restore(primary);
3280 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3281 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3282 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3283 hr = IDirectDrawSurface7_Restore(primary);
3284 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3285 hr = IDirectDrawSurface7_IsLost(primary);
3286 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3288 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3289 expect_messages = NULL;
3290 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3292 GetWindowRect(window, &r);
3293 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3294 wine_dbgstr_rect(&r));
3296 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3297 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3298 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3299 registry_mode.dmPelsWidth, ddsd.dwWidth);
3300 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3301 registry_mode.dmPelsHeight, ddsd.dwHeight);
3302 IDirectDrawSurface7_Release(primary);
3304 memset(&ddsd, 0, sizeof(ddsd));
3305 ddsd.dwSize = sizeof(ddsd);
3306 ddsd.dwFlags = DDSD_CAPS;
3307 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3309 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3310 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3311 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3312 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3313 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3314 param.ddraw_width, ddsd.dwWidth);
3315 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3316 param.ddraw_height, ddsd.dwHeight);
3318 GetWindowRect(window, &r);
3319 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3320 wine_dbgstr_rect(&r));
3322 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3323 expect_messages = normal_messages;
3324 screen_size.cx = 0;
3325 screen_size.cy = 0;
3327 hr = IDirectDrawSurface7_IsLost(primary);
3328 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3329 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
3330 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3331 hr = IDirectDrawSurface7_IsLost(primary);
3332 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3334 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3335 expect_messages = NULL;
3336 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3338 GetWindowRect(window, &r);
3339 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3340 wine_dbgstr_rect(&r));
3342 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3343 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3344 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3345 param.ddraw_width, ddsd.dwWidth);
3346 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3347 param.ddraw_height, ddsd.dwHeight);
3348 IDirectDrawSurface7_Release(primary);
3350 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3351 ok(ret, "Failed to get display mode.\n");
3352 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3353 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3354 "Expected resolution %ux%u, got %ux%u.\n",
3355 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3356 devmode.dmPelsWidth, devmode.dmPelsHeight);
3357 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3358 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3360 memset(&ddsd, 0, sizeof(ddsd));
3361 ddsd.dwSize = sizeof(ddsd);
3362 ddsd.dwFlags = DDSD_CAPS;
3363 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3365 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3366 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3367 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3368 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3369 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3370 registry_mode.dmPelsWidth, ddsd.dwWidth);
3371 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3372 registry_mode.dmPelsHeight, ddsd.dwHeight);
3374 GetWindowRect(window, &r);
3375 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3376 wine_dbgstr_rect(&r));
3378 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
3379 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
3380 * not DDSCL_FULLSCREEN. */
3381 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3382 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3384 GetWindowRect(window, &r);
3385 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3386 wine_dbgstr_rect(&r));
3388 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3389 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3390 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3391 registry_mode.dmPelsWidth, ddsd.dwWidth);
3392 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3393 registry_mode.dmPelsHeight, ddsd.dwHeight);
3394 IDirectDrawSurface7_Release(primary);
3396 memset(&ddsd, 0, sizeof(ddsd));
3397 ddsd.dwSize = sizeof(ddsd);
3398 ddsd.dwFlags = DDSD_CAPS;
3399 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3401 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3402 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3403 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3404 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3405 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3406 registry_mode.dmPelsWidth, ddsd.dwWidth);
3407 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3408 registry_mode.dmPelsHeight, ddsd.dwHeight);
3410 GetWindowRect(window, &r);
3411 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3412 wine_dbgstr_rect(&r));
3414 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3415 expect_messages = normal_messages;
3416 screen_size.cx = 0;
3417 screen_size.cy = 0;
3419 hr = IDirectDrawSurface7_IsLost(primary);
3420 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3421 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3422 devmode.dmPelsWidth = param.user32_width;
3423 devmode.dmPelsHeight = param.user32_height;
3424 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3425 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3426 hr = IDirectDrawSurface7_IsLost(primary);
3427 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3429 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3430 expect_messages = NULL;
3431 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3433 GetWindowRect(window, &r);
3434 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3435 wine_dbgstr_rect(&r));
3437 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3438 expect_messages = normal_messages;
3439 screen_size.cx = 0;
3440 screen_size.cy = 0;
3442 hr = IDirectDrawSurface7_Restore(primary);
3443 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3444 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3445 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3446 hr = IDirectDrawSurface7_Restore(primary);
3447 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3448 hr = IDirectDrawSurface7_IsLost(primary);
3449 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3451 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3452 expect_messages = NULL;
3453 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3455 GetWindowRect(window, &r);
3456 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3457 wine_dbgstr_rect(&r));
3459 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3460 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3461 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3462 registry_mode.dmPelsWidth, ddsd.dwWidth);
3463 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3464 registry_mode.dmPelsHeight, ddsd.dwHeight);
3465 IDirectDrawSurface7_Release(primary);
3467 memset(&ddsd, 0, sizeof(ddsd));
3468 ddsd.dwSize = sizeof(ddsd);
3469 ddsd.dwFlags = DDSD_CAPS;
3470 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3472 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3473 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3474 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3475 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3476 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3477 param.ddraw_width, ddsd.dwWidth);
3478 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3479 param.ddraw_height, ddsd.dwHeight);
3481 GetWindowRect(window, &r);
3482 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3483 wine_dbgstr_rect(&r));
3485 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3486 expect_messages = normal_messages;
3487 screen_size.cx = 0;
3488 screen_size.cy = 0;
3490 hr = IDirectDrawSurface7_IsLost(primary);
3491 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3492 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
3493 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3494 hr = IDirectDrawSurface7_IsLost(primary);
3495 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3497 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3498 expect_messages = NULL;
3499 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3501 GetWindowRect(window, &r);
3502 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3503 wine_dbgstr_rect(&r));
3505 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3506 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3507 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3508 param.ddraw_width, ddsd.dwWidth);
3509 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3510 param.ddraw_height, ddsd.dwHeight);
3511 IDirectDrawSurface7_Release(primary);
3513 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3514 ok(ret, "Failed to get display mode.\n");
3515 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3516 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3517 "Expected resolution %ux%u, got %ux%u.\n",
3518 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3519 devmode.dmPelsWidth, devmode.dmPelsHeight);
3520 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3521 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3523 memset(&ddsd, 0, sizeof(ddsd));
3524 ddsd.dwSize = sizeof(ddsd);
3525 ddsd.dwFlags = DDSD_CAPS;
3526 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3528 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3529 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3530 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3531 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3532 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3533 registry_mode.dmPelsWidth, ddsd.dwWidth);
3534 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3535 registry_mode.dmPelsHeight, ddsd.dwHeight);
3536 IDirectDrawSurface7_Release(primary);
3538 GetWindowRect(window, &r);
3539 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3540 wine_dbgstr_rect(&r));
3542 /* Changing the coop level from EXCLUSIVE to NORMAL restores the screen resolution */
3543 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3544 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3545 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3546 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3548 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3549 expect_messages = exclusive_messages;
3550 screen_size.cx = 0;
3551 screen_size.cy = 0;
3553 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3554 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3556 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3557 expect_messages = NULL;
3558 ok(screen_size.cx == registry_mode.dmPelsWidth
3559 && screen_size.cy == registry_mode.dmPelsHeight,
3560 "Expected screen size %ux%u, got %ux%u.\n",
3561 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3562 screen_size.cx, screen_size.cy);
3564 GetWindowRect(window, &r);
3565 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3566 wine_dbgstr_rect(&r));
3568 memset(&ddsd, 0, sizeof(ddsd));
3569 ddsd.dwSize = sizeof(ddsd);
3570 ddsd.dwFlags = DDSD_CAPS;
3571 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3573 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3574 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3575 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3576 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3577 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3578 registry_mode.dmPelsWidth, ddsd.dwWidth);
3579 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3580 registry_mode.dmPelsHeight, ddsd.dwHeight);
3581 IDirectDrawSurface7_Release(primary);
3583 /* The screen restore is a property of DDSCL_EXCLUSIVE */
3584 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3585 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3586 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3587 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3589 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3590 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3592 memset(&ddsd, 0, sizeof(ddsd));
3593 ddsd.dwSize = sizeof(ddsd);
3594 ddsd.dwFlags = DDSD_CAPS;
3595 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3597 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3598 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3599 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3600 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3601 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3602 param.ddraw_width, ddsd.dwWidth);
3603 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3604 param.ddraw_height, ddsd.dwHeight);
3605 IDirectDrawSurface7_Release(primary);
3607 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
3608 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3610 /* If the window is changed at the same time, messages are sent to the new window. */
3611 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3612 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3613 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3614 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3616 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3617 expect_messages = exclusive_messages;
3618 screen_size.cx = 0;
3619 screen_size.cy = 0;
3620 screen_size2.cx = 0;
3621 screen_size2.cy = 0;
3623 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3624 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3626 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3627 expect_messages = NULL;
3628 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n",
3629 screen_size.cx, screen_size.cy);
3630 ok(screen_size2.cx == registry_mode.dmPelsWidth && screen_size2.cy == registry_mode.dmPelsHeight,
3631 "Expected screen size 2 %ux%u, got %ux%u.\n",
3632 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size2.cx, screen_size2.cy);
3634 GetWindowRect(window, &r);
3635 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3636 wine_dbgstr_rect(&r));
3637 GetWindowRect(window2, &r);
3638 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3639 wine_dbgstr_rect(&r));
3641 memset(&ddsd, 0, sizeof(ddsd));
3642 ddsd.dwSize = sizeof(ddsd);
3643 ddsd.dwFlags = DDSD_CAPS;
3644 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3646 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3647 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3648 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3649 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3650 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3651 registry_mode.dmPelsWidth, ddsd.dwWidth);
3652 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3653 registry_mode.dmPelsHeight, ddsd.dwHeight);
3654 IDirectDrawSurface7_Release(primary);
3656 ref = IDirectDraw7_Release(ddraw);
3657 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3659 GetWindowRect(window, &r);
3660 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3661 wine_dbgstr_rect(&r));
3663 ret = restore_display_modes(original_modes, display_count);
3664 ok(ret, "Failed to restore display modes.\n");
3666 /* Test that no mode restorations if no mode changes happened */
3667 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3668 devmode.dmPelsWidth = param.user32_width;
3669 devmode.dmPelsHeight = param.user32_height;
3670 change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
3671 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
3673 ddraw = create_ddraw();
3674 ok(!!ddraw, "Failed to create a ddraw object.\n");
3675 ref = IDirectDraw7_Release(ddraw);
3676 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3678 memset(&devmode2, 0, sizeof(devmode2));
3679 devmode2.dmSize = sizeof(devmode2);
3680 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
3681 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3682 ok(compare_mode_rect(&devmode2, &registry_mode), "Got a different mode.\n");
3683 ret = restore_display_modes(original_modes, display_count);
3684 ok(ret, "Failed to restore display modes.\n");
3686 /* Test that no mode restorations if no mode changes happened with fullscreen ddraw objects */
3687 change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
3688 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
3690 ddraw = create_ddraw();
3691 ok(!!ddraw, "Failed to create a ddraw object.\n");
3692 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3693 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
3694 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3695 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
3696 ref = IDirectDraw7_Release(ddraw);
3697 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3699 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
3700 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3701 ok(compare_mode_rect(&devmode2, &registry_mode), "Got a different mode.\n");
3702 ret = restore_display_modes(original_modes, display_count);
3703 ok(ret, "Failed to restore display modes.\n");
3705 /* Test that mode restorations use display settings in the registry after ddraw object releases
3706 * if SetDisplayMode() was called */
3707 ddraw = create_ddraw();
3708 ok(!!ddraw, "Failed to create a ddraw object.\n");
3709 hr = set_display_mode(ddraw, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
3710 ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
3712 change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
3713 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
3715 ref = IDirectDraw7_Release(ddraw);
3716 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3718 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
3719 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3720 ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
3721 ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
3722 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3723 ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
3724 ret = restore_display_modes(original_modes, display_count);
3725 ok(ret, "Failed to restore display modes.\n");
3727 /* Test that mode restorations use display settings in the registry after RestoreDisplayMode() */
3728 ddraw = create_ddraw();
3729 ok(!!ddraw, "Failed to create a ddraw object.\n");
3730 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3731 ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
3733 change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
3734 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
3736 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
3737 ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
3739 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
3740 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3741 ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
3742 ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
3743 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3744 ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
3746 ref = IDirectDraw7_Release(ddraw);
3747 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3749 expect_messages = NULL;
3750 DestroyWindow(window);
3751 DestroyWindow(window2);
3752 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
3753 UnregisterClassA("ddraw_test_wndproc_wc2", GetModuleHandleA(NULL));
3754 ret = restore_display_modes(original_modes, display_count);
3755 ok(ret, "Failed to restore display modes.\n");
3756 heap_free(original_modes);
3759 static void test_coop_level_mode_set_multi(void)
3761 DEVMODEW old_devmode, devmode, devmode2, devmode3, *original_modes = NULL;
3762 unsigned int mode_idx = 0, display_idx, display_count = 0;
3763 WCHAR second_monitor_name[CCHDEVICENAME];
3764 IDirectDraw7 *ddraw1, *ddraw2;
3765 LONG change_ret;
3766 UINT w, h;
3767 HWND window;
3768 HRESULT hr;
3769 ULONG ref;
3770 BOOL ret;
3772 memset(&devmode, 0, sizeof(devmode));
3773 devmode.dmSize = sizeof(devmode);
3774 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3775 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3776 ok(compare_mode_rect(&devmode, &registry_mode), "Got a different mode.\n");
3777 ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
3778 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3779 ok(compare_mode_rect(&devmode, &registry_mode), "Got a different mode.\n");
3781 ret = save_display_modes(&original_modes, &display_count);
3782 ok(ret, "Failed to save original display modes.\n");
3784 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3785 0, 0, 100, 100, 0, 0, 0, 0);
3786 ddraw1 = create_ddraw();
3787 ok(!!ddraw1, "Failed to create a ddraw object.\n");
3789 /* With just a single ddraw object, the display mode is restored on
3790 * release. */
3791 hr = set_display_mode(ddraw1, 800, 600);
3792 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3793 w = GetSystemMetrics(SM_CXSCREEN);
3794 ok(w == 800, "Got unexpected screen width %u.\n", w);
3795 h = GetSystemMetrics(SM_CYSCREEN);
3796 ok(h == 600, "Got unexpected screen height %u.\n", h);
3798 ref = IDirectDraw7_Release(ddraw1);
3799 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3800 w = GetSystemMetrics(SM_CXSCREEN);
3801 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3802 h = GetSystemMetrics(SM_CYSCREEN);
3803 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3805 /* When there are multiple ddraw objects, the display mode is restored to
3806 * the initial mode, before the first SetDisplayMode() call. */
3807 ddraw1 = create_ddraw();
3808 hr = set_display_mode(ddraw1, 800, 600);
3809 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3810 w = GetSystemMetrics(SM_CXSCREEN);
3811 ok(w == 800, "Got unexpected screen width %u.\n", w);
3812 h = GetSystemMetrics(SM_CYSCREEN);
3813 ok(h == 600, "Got unexpected screen height %u.\n", h);
3815 ddraw2 = create_ddraw();
3816 hr = set_display_mode(ddraw2, 640, 480);
3817 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3818 w = GetSystemMetrics(SM_CXSCREEN);
3819 ok(w == 640, "Got unexpected screen width %u.\n", w);
3820 h = GetSystemMetrics(SM_CYSCREEN);
3821 ok(h == 480, "Got unexpected screen height %u.\n", h);
3823 ref = IDirectDraw7_Release(ddraw2);
3824 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3825 w = GetSystemMetrics(SM_CXSCREEN);
3826 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3827 h = GetSystemMetrics(SM_CYSCREEN);
3828 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3830 ref = IDirectDraw7_Release(ddraw1);
3831 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3832 w = GetSystemMetrics(SM_CXSCREEN);
3833 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3834 h = GetSystemMetrics(SM_CYSCREEN);
3835 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3837 /* Regardless of release ordering. */
3838 ddraw1 = create_ddraw();
3839 hr = set_display_mode(ddraw1, 800, 600);
3840 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3841 w = GetSystemMetrics(SM_CXSCREEN);
3842 ok(w == 800, "Got unexpected screen width %u.\n", w);
3843 h = GetSystemMetrics(SM_CYSCREEN);
3844 ok(h == 600, "Got unexpected screen height %u.\n", h);
3846 ddraw2 = create_ddraw();
3847 hr = set_display_mode(ddraw2, 640, 480);
3848 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3849 w = GetSystemMetrics(SM_CXSCREEN);
3850 ok(w == 640, "Got unexpected screen width %u.\n", w);
3851 h = GetSystemMetrics(SM_CYSCREEN);
3852 ok(h == 480, "Got unexpected screen height %u.\n", h);
3854 ref = IDirectDraw7_Release(ddraw1);
3855 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3856 w = GetSystemMetrics(SM_CXSCREEN);
3857 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3858 h = GetSystemMetrics(SM_CYSCREEN);
3859 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3861 ref = IDirectDraw7_Release(ddraw2);
3862 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3863 w = GetSystemMetrics(SM_CXSCREEN);
3864 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3865 h = GetSystemMetrics(SM_CYSCREEN);
3866 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3868 /* But only for ddraw objects that called SetDisplayMode(). */
3869 ddraw1 = create_ddraw();
3870 ddraw2 = create_ddraw();
3871 hr = set_display_mode(ddraw2, 640, 480);
3872 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3873 w = GetSystemMetrics(SM_CXSCREEN);
3874 ok(w == 640, "Got unexpected screen width %u.\n", w);
3875 h = GetSystemMetrics(SM_CYSCREEN);
3876 ok(h == 480, "Got unexpected screen height %u.\n", h);
3878 ref = IDirectDraw7_Release(ddraw1);
3879 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3880 w = GetSystemMetrics(SM_CXSCREEN);
3881 ok(w == 640, "Got unexpected screen width %u.\n", w);
3882 h = GetSystemMetrics(SM_CYSCREEN);
3883 ok(h == 480, "Got unexpected screen height %u.\n", h);
3885 ref = IDirectDraw7_Release(ddraw2);
3886 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3887 w = GetSystemMetrics(SM_CXSCREEN);
3888 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3889 h = GetSystemMetrics(SM_CYSCREEN);
3890 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3892 /* If there's a ddraw object that's currently in exclusive mode, it blocks
3893 * restoring the display mode. */
3894 ddraw1 = create_ddraw();
3895 hr = set_display_mode(ddraw1, 800, 600);
3896 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3897 w = GetSystemMetrics(SM_CXSCREEN);
3898 ok(w == 800, "Got unexpected screen width %u.\n", w);
3899 h = GetSystemMetrics(SM_CYSCREEN);
3900 ok(h == 600, "Got unexpected screen height %u.\n", h);
3902 ddraw2 = create_ddraw();
3903 hr = set_display_mode(ddraw2, 640, 480);
3904 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3905 w = GetSystemMetrics(SM_CXSCREEN);
3906 ok(w == 640, "Got unexpected screen width %u.\n", w);
3907 h = GetSystemMetrics(SM_CYSCREEN);
3908 ok(h == 480, "Got unexpected screen height %u.\n", h);
3910 hr = IDirectDraw7_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3911 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3913 ref = IDirectDraw7_Release(ddraw1);
3914 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3915 w = GetSystemMetrics(SM_CXSCREEN);
3916 ok(w == 640, "Got unexpected screen width %u.\n", w);
3917 h = GetSystemMetrics(SM_CYSCREEN);
3918 ok(h == 480, "Got unexpected screen height %u.\n", h);
3920 ref = IDirectDraw7_Release(ddraw2);
3921 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3922 w = GetSystemMetrics(SM_CXSCREEN);
3923 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3924 h = GetSystemMetrics(SM_CYSCREEN);
3925 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3927 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
3928 ddraw1 = create_ddraw();
3929 hr = set_display_mode(ddraw1, 800, 600);
3930 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3931 w = GetSystemMetrics(SM_CXSCREEN);
3932 ok(w == 800, "Got unexpected screen width %u.\n", w);
3933 h = GetSystemMetrics(SM_CYSCREEN);
3934 ok(h == 600, "Got unexpected screen height %u.\n", h);
3936 hr = IDirectDraw7_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3937 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3939 ddraw2 = create_ddraw();
3940 hr = set_display_mode(ddraw2, 640, 480);
3941 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
3943 ref = IDirectDraw7_Release(ddraw1);
3944 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3945 w = GetSystemMetrics(SM_CXSCREEN);
3946 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3947 h = GetSystemMetrics(SM_CYSCREEN);
3948 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3950 ref = IDirectDraw7_Release(ddraw2);
3951 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3952 w = GetSystemMetrics(SM_CXSCREEN);
3953 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3954 h = GetSystemMetrics(SM_CYSCREEN);
3955 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3957 if (display_count < 2)
3959 skip("Following tests require two monitors.\n");
3960 goto done;
3963 ret = restore_display_modes(original_modes, display_count);
3964 ok(ret, "Failed to restore display modes.\n");
3966 second_monitor_name[0] = '\0';
3967 for (display_idx = 0; display_idx < display_count; ++display_idx)
3969 if (original_modes[display_idx].dmPosition.x || original_modes[display_idx].dmPosition.y)
3971 lstrcpyW(second_monitor_name, original_modes[display_idx].dmDeviceName);
3972 break;
3975 ok(lstrlenW(second_monitor_name), "Got an empty second monitor name.\n");
3976 memset(&old_devmode, 0, sizeof(old_devmode));
3977 old_devmode.dmSize = sizeof(old_devmode);
3978 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &old_devmode);
3979 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3981 devmode = old_devmode;
3982 while (EnumDisplaySettingsW(second_monitor_name, mode_idx++, &devmode))
3984 if (devmode.dmPelsWidth != old_devmode.dmPelsWidth
3985 || devmode.dmPelsHeight != old_devmode.dmPelsHeight)
3986 break;
3988 ok(devmode.dmPelsWidth != old_devmode.dmPelsWidth
3989 || devmode.dmPelsHeight != old_devmode.dmPelsHeight,
3990 "Failed to find a different mode for the second monitor.\n");
3992 /* Test that no mode restorations for non-primary monitors if SetDisplayMode() was not called */
3993 ddraw1 = create_ddraw();
3994 ok(!!ddraw1, "Failed to create a ddraw object.\n");
3995 hr = IDirectDraw7_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3996 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
3998 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
3999 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
4001 memset(&devmode2, 0, sizeof(devmode2));
4002 devmode2.dmSize = sizeof(devmode2);
4003 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4004 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
4005 if (compare_mode_rect(&devmode2, &old_devmode))
4007 skip("Failed to change display settings of the second monitor.\n");
4008 ref = IDirectDraw7_Release(ddraw1);
4009 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
4010 goto done;
4013 hr = IDirectDraw7_SetCooperativeLevel(ddraw1, window, DDSCL_NORMAL);
4014 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
4015 ref = IDirectDraw7_Release(ddraw1);
4016 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
4018 memset(&devmode3, 0, sizeof(devmode3));
4019 devmode3.dmSize = sizeof(devmode3);
4020 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode3);
4021 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
4022 ok(compare_mode_rect(&devmode3, &devmode2), "Got a different mode.\n");
4023 ret = restore_display_modes(original_modes, display_count);
4024 ok(ret, "Failed to restore display modes.\n");
4026 /* Test that mode restorations happen for non-primary monitors on ddraw releases if
4027 * SetDisplayMode() was called */
4028 ddraw1 = create_ddraw();
4029 ok(!!ddraw1, "Failed to create a ddraw object.\n");
4030 hr = set_display_mode(ddraw1, 800, 600);
4031 ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
4033 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
4034 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
4036 ref = IDirectDraw7_Release(ddraw1);
4037 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
4039 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4040 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
4041 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4042 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4043 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
4044 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4045 ret = restore_display_modes(original_modes, display_count);
4046 ok(ret, "Failed to restore display modes.\n");
4048 /* Test that mode restorations happen for non-primary monitors as well */
4049 ddraw1 = create_ddraw();
4050 ok(!!ddraw1, "Failed to create a ddraw object.\n");
4051 hr = set_display_mode(ddraw1, 800, 600);
4052 ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
4054 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
4055 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
4057 hr = IDirectDraw7_RestoreDisplayMode(ddraw1);
4058 ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
4060 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4061 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
4062 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4063 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4064 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
4065 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4067 ref = IDirectDraw7_Release(ddraw1);
4068 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
4069 ret = restore_display_modes(original_modes, display_count);
4070 ok(ret, "Failed to restore display modes.\n");
4072 /* Test that mode restorations for non-primary monitors use display settings in the registry */
4073 ddraw1 = create_ddraw();
4074 ok(!!ddraw1, "Failed to create a ddraw object.\n");
4075 hr = set_display_mode(ddraw1, 800, 600);
4076 ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
4078 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL,
4079 CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
4080 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
4082 ref = IDirectDraw7_Release(ddraw1);
4083 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
4085 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4086 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
4087 ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
4088 "Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
4089 devmode2.dmPelsWidth, devmode2.dmPelsHeight);
4090 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4091 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
4092 ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
4093 "Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
4094 devmode2.dmPelsWidth, devmode2.dmPelsHeight);
4095 ret = restore_display_modes(original_modes, display_count);
4096 ok(ret, "Failed to restore display modes.\n");
4098 /* Test mode restorations for non-primary monitors when there are multiple fullscreen ddraw
4099 * objects and one of them restores display mode */
4100 ddraw1 = create_ddraw();
4101 ok(!!ddraw1, "Failed to create a ddraw object.\n");
4102 ddraw2 = create_ddraw();
4103 ok(!!ddraw2, "Failed to create a ddraw object.\n");
4104 hr = set_display_mode(ddraw1, 800, 600);
4105 ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
4106 hr = set_display_mode(ddraw2, 640, 480);
4107 ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
4109 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
4110 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
4112 hr = IDirectDraw7_RestoreDisplayMode(ddraw2);
4113 ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
4115 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4116 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
4117 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4118 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4119 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
4120 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4122 ref = IDirectDraw7_Release(ddraw2);
4123 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
4124 ref = IDirectDraw7_Release(ddraw1);
4125 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
4126 ret = restore_display_modes(original_modes, display_count);
4127 ok(ret, "Failed to restore display modes.\n");
4129 /* Test mode restorations for non-primary monitors when there are multiple fullscreen ddraw
4130 * objects and one of them got released */
4131 ddraw1 = create_ddraw();
4132 ok(!!ddraw1, "Failed to create a ddraw object.\n");
4133 ddraw2 = create_ddraw();
4134 ok(!!ddraw2, "Failed to create a ddraw object.\n");
4135 hr = set_display_mode(ddraw1, 800, 600);
4136 ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
4137 hr = set_display_mode(ddraw2, 640, 480);
4138 ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
4140 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
4141 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
4143 ref = IDirectDraw7_Release(ddraw2);
4144 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
4146 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4147 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
4148 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4149 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4150 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
4151 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4153 ref = IDirectDraw7_Release(ddraw1);
4154 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
4156 done:
4157 DestroyWindow(window);
4158 ret = restore_display_modes(original_modes, display_count);
4159 ok(ret, "Failed to restore display modes.\n");
4160 heap_free(original_modes);
4163 static void test_initialize(void)
4165 IDirectDraw7 *ddraw;
4166 HRESULT hr;
4168 ddraw = create_ddraw();
4169 ok(!!ddraw, "Failed to create a ddraw object.\n");
4171 hr = IDirectDraw7_Initialize(ddraw, NULL);
4172 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
4173 IDirectDraw7_Release(ddraw);
4175 CoInitialize(NULL);
4176 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw7, (void **)&ddraw);
4177 ok(SUCCEEDED(hr), "Failed to create IDirectDraw7 instance, hr %#x.\n", hr);
4178 hr = IDirectDraw7_Initialize(ddraw, NULL);
4179 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
4180 hr = IDirectDraw7_Initialize(ddraw, NULL);
4181 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
4182 IDirectDraw7_Release(ddraw);
4183 CoUninitialize();
4186 static void test_coop_level_surf_create(void)
4188 IDirectDrawSurface7 *surface;
4189 IDirectDraw7 *ddraw;
4190 DDSURFACEDESC2 ddsd;
4191 HRESULT hr;
4193 ddraw = create_ddraw();
4194 ok(!!ddraw, "Failed to create a ddraw object.\n");
4196 memset(&ddsd, 0, sizeof(ddsd));
4197 ddsd.dwSize = sizeof(ddsd);
4198 ddsd.dwFlags = DDSD_CAPS;
4199 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4200 surface = (void *)0xdeadbeef;
4201 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
4202 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
4203 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
4205 surface = (void *)0xdeadbeef;
4206 hr = IDirectDraw7_CreateSurface(ddraw, NULL, &surface, NULL);
4207 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
4208 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
4210 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4211 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4213 surface = (void *)0xdeadbeef;
4214 hr = IDirectDraw7_CreateSurface(ddraw, NULL, &surface, NULL);
4215 ok(hr == DDERR_INVALIDPARAMS, "Unexpected hr %#x.\n", hr);
4216 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
4218 IDirectDraw7_Release(ddraw);
4221 static void test_vb_discard(void)
4223 static const struct vec4 quad[] =
4225 { 0.0f, 480.0f, 0.0f, 1.0f},
4226 { 0.0f, 0.0f, 0.0f, 1.0f},
4227 {640.0f, 480.0f, 0.0f, 1.0f},
4228 {640.0f, 0.0f, 0.0f, 1.0f},
4231 IDirect3DDevice7 *device;
4232 IDirect3D7 *d3d;
4233 IDirect3DVertexBuffer7 *buffer;
4234 HWND window;
4235 HRESULT hr;
4236 D3DVERTEXBUFFERDESC desc;
4237 BYTE *data;
4238 static const unsigned int vbsize = 16;
4239 unsigned int i;
4241 window = create_window();
4242 if (!(device = create_device(window, DDSCL_NORMAL)))
4244 skip("Failed to create a 3D device, skipping test.\n");
4245 DestroyWindow(window);
4246 return;
4249 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
4250 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
4252 memset(&desc, 0, sizeof(desc));
4253 desc.dwSize = sizeof(desc);
4254 desc.dwCaps = D3DVBCAPS_WRITEONLY;
4255 desc.dwFVF = D3DFVF_XYZRHW;
4256 desc.dwNumVertices = vbsize;
4257 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &buffer, 0);
4258 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
4260 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
4261 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
4262 memcpy(data, quad, sizeof(quad));
4263 hr = IDirect3DVertexBuffer7_Unlock(buffer);
4264 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
4266 hr = IDirect3DDevice7_BeginScene(device);
4267 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4268 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
4269 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4270 hr = IDirect3DDevice7_EndScene(device);
4271 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4273 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
4274 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
4275 memset(data, 0xaa, sizeof(struct vec4) * vbsize);
4276 hr = IDirect3DVertexBuffer7_Unlock(buffer);
4277 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
4279 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
4280 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
4281 for (i = 0; i < sizeof(struct vec4) * vbsize; i++)
4283 if (data[i] != 0xaa)
4285 ok(FALSE, "Vertex buffer data byte %u is 0x%02x, expected 0xaa\n", i, data[i]);
4286 break;
4289 hr = IDirect3DVertexBuffer7_Unlock(buffer);
4290 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
4292 IDirect3DVertexBuffer7_Release(buffer);
4293 IDirect3D7_Release(d3d);
4294 IDirect3DDevice7_Release(device);
4295 DestroyWindow(window);
4298 static void test_coop_level_multi_window(void)
4300 HWND window1, window2;
4301 IDirectDraw7 *ddraw;
4302 HRESULT hr;
4304 window1 = create_window();
4305 window2 = create_window();
4306 ddraw = create_ddraw();
4307 ok(!!ddraw, "Failed to create a ddraw object.\n");
4309 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
4310 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4311 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
4312 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4313 ok(IsWindow(window1), "Window 1 was destroyed.\n");
4314 ok(IsWindow(window2), "Window 2 was destroyed.\n");
4316 IDirectDraw7_Release(ddraw);
4317 DestroyWindow(window2);
4318 DestroyWindow(window1);
4321 static void test_draw_strided(void)
4323 static struct vec3 position[] =
4325 {-1.0, -1.0, 0.0},
4326 {-1.0, 1.0, 0.0},
4327 { 1.0, 1.0, 0.0},
4328 { 1.0, -1.0, 0.0},
4330 static DWORD diffuse[] =
4332 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
4334 static WORD indices[] =
4336 0, 1, 2, 2, 3, 0
4339 IDirectDrawSurface7 *rt;
4340 IDirect3DDevice7 *device;
4341 D3DCOLOR color;
4342 HWND window;
4343 HRESULT hr;
4344 D3DDRAWPRIMITIVESTRIDEDDATA strided;
4346 window = create_window();
4347 if (!(device = create_device(window, DDSCL_NORMAL)))
4349 skip("Failed to create a 3D device, skipping test.\n");
4350 DestroyWindow(window);
4351 return;
4354 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
4355 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4357 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
4358 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
4359 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 1.0f, 0);
4360 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4361 hr = IDirect3DDevice7_BeginScene(device);
4362 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4364 memset(&strided, 0x55, sizeof(strided));
4365 strided.position.lpvData = position;
4366 strided.position.dwStride = sizeof(*position);
4367 strided.diffuse.lpvData = diffuse;
4368 strided.diffuse.dwStride = sizeof(*diffuse);
4369 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device, D3DPT_TRIANGLELIST, D3DFVF_XYZ | D3DFVF_DIFFUSE,
4370 &strided, 4, indices, 6, 0);
4371 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4373 hr = IDirect3DDevice7_EndScene(device);
4374 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4376 color = get_surface_color(rt, 320, 240);
4377 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
4379 IDirectDrawSurface7_Release(rt);
4380 IDirect3DDevice7_Release(device);
4381 DestroyWindow(window);
4384 static void test_lighting(void)
4386 static D3DMATRIX mat =
4388 1.0f, 0.0f, 0.0f, 0.0f,
4389 0.0f, 1.0f, 0.0f, 0.0f,
4390 0.0f, 0.0f, 1.0f, 0.0f,
4391 0.0f, 0.0f, 0.0f, 1.0f,
4393 mat_singular =
4395 1.0f, 0.0f, 1.0f, 0.0f,
4396 0.0f, 1.0f, 0.0f, 0.0f,
4397 1.0f, 0.0f, 1.0f, 0.0f,
4398 0.0f, 0.0f, 0.5f, 1.0f,
4400 mat_transf =
4402 0.0f, 0.0f, 1.0f, 0.0f,
4403 0.0f, 1.0f, 0.0f, 0.0f,
4404 -1.0f, 0.0f, 0.0f, 0.0f,
4405 10.f, 10.0f, 10.0f, 1.0f,
4407 mat_nonaffine =
4409 1.0f, 0.0f, 0.0f, 0.0f,
4410 0.0f, 1.0f, 0.0f, 0.0f,
4411 0.0f, 0.0f, 1.0f, -1.0f,
4412 10.f, 10.0f, 10.0f, 0.0f,
4414 static struct vertex
4416 struct vec3 position;
4417 DWORD diffuse;
4419 unlitquad[] =
4421 {{-1.0f, -1.0f, 0.1f}, 0xffff0000},
4422 {{-1.0f, 0.0f, 0.1f}, 0xffff0000},
4423 {{ 0.0f, 0.0f, 0.1f}, 0xffff0000},
4424 {{ 0.0f, -1.0f, 0.1f}, 0xffff0000},
4426 litquad[] =
4428 {{-1.0f, 0.0f, 0.1f}, 0xff00ff00},
4429 {{-1.0f, 1.0f, 0.1f}, 0xff00ff00},
4430 {{ 0.0f, 1.0f, 0.1f}, 0xff00ff00},
4431 {{ 0.0f, 0.0f, 0.1f}, 0xff00ff00},
4433 static struct vertex_normal
4435 struct vec3 position;
4436 struct vec3 normal;
4437 DWORD diffuse;
4439 unlitnquad[] =
4441 {{0.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
4442 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
4443 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
4444 {{1.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
4446 litnquad[] =
4448 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
4449 {{0.0f, 1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
4450 {{1.0f, 1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
4451 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
4453 nquad[] =
4455 {{-1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4456 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4457 {{ 1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4458 {{ 1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4460 rotatedquad[] =
4462 {{-10.0f, -11.0f, 11.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
4463 {{-10.0f, -9.0f, 11.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
4464 {{-10.0f, -9.0f, 9.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
4465 {{-10.0f, -11.0f, 9.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
4467 translatedquad[] =
4469 {{-11.0f, -11.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4470 {{-11.0f, -9.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4471 {{ -9.0f, -9.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4472 {{ -9.0f, -11.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4474 static WORD indices[] = {0, 1, 2, 2, 3, 0};
4475 static const struct
4477 D3DMATRIX *world_matrix;
4478 void *quad;
4479 DWORD expected, expected_process_vertices;
4480 const char *message;
4481 BOOL process_vertices_todo;
4483 tests[] =
4485 {&mat, nquad, 0x000000ff, 0xff0000ff, "Lit quad with light"},
4486 {&mat_singular, nquad, 0x000000ff, 0xff000000, "Lit quad with singular world matrix", TRUE},
4487 {&mat_transf, rotatedquad, 0x000000ff, 0xff0000ff, "Lit quad with transformation matrix"},
4488 {&mat_nonaffine, translatedquad, 0x00000000, 0xff000000, "Lit quad with non-affine matrix"},
4491 DWORD nfvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL;
4492 IDirect3DVertexBuffer7 *src_vb1, *src_vb2, *dst_vb;
4493 DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
4494 struct vertex_normal *src_data2;
4495 D3DVERTEXBUFFERDESC vb_desc;
4496 struct vertex *src_data1;
4497 IDirect3DDevice7 *device;
4498 IDirectDrawSurface7 *rt;
4499 IDirectDraw7 *ddraw;
4500 IDirect3D7 *d3d;
4501 D3DCOLOR color;
4502 ULONG refcount;
4503 unsigned int i;
4504 BOOL is_warp;
4505 HWND window;
4506 HRESULT hr;
4507 struct
4509 struct vec4 position;
4510 DWORD diffuse;
4511 DWORD specular;
4513 *dst_data;
4515 window = create_window();
4516 if (!(device = create_device(window, DDSCL_NORMAL)))
4518 skip("Failed to create a 3D device, skipping test.\n");
4519 DestroyWindow(window);
4520 return;
4522 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
4523 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4524 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
4525 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4527 is_warp = ddraw_is_warp(ddraw);
4529 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
4530 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4532 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
4533 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4535 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
4536 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4537 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
4538 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4539 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
4540 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4541 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
4542 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4543 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
4544 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4545 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
4546 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4547 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
4548 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4549 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
4550 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4552 hr = IDirect3DDevice7_BeginScene(device);
4553 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4555 memset(&vb_desc, 0, sizeof(vb_desc));
4556 vb_desc.dwSize = sizeof(vb_desc);
4557 vb_desc.dwFVF = fvf;
4558 vb_desc.dwNumVertices = 2;
4559 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &src_vb1, 0);
4560 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4561 vb_desc.dwSize = sizeof(vb_desc);
4562 vb_desc.dwFVF = nfvf;
4563 vb_desc.dwNumVertices = 2;
4564 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &src_vb2, 0);
4565 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4567 memset(&vb_desc, 0, sizeof(vb_desc));
4568 vb_desc.dwSize = sizeof(vb_desc);
4569 vb_desc.dwFVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR;
4570 vb_desc.dwNumVertices = 4;
4571 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &dst_vb, 0);
4572 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4574 hr = IDirect3DVertexBuffer7_Lock(src_vb1, 0, (void **)&src_data1, NULL);
4575 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4576 memcpy(src_data1, unlitquad, sizeof(*src_data1));
4577 memcpy(&src_data1[1], litquad, sizeof(*src_data1));
4578 hr = IDirect3DVertexBuffer7_Unlock(src_vb1);
4579 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4581 hr = IDirect3DVertexBuffer7_Lock(src_vb2, 0, (void **)&src_data2, NULL);
4582 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4583 memcpy(src_data2, unlitnquad, sizeof(*src_data2));
4584 memcpy(&src_data2[1], litnquad, sizeof(*src_data2));
4585 hr = IDirect3DVertexBuffer7_Unlock(src_vb2);
4586 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4588 /* No lights are defined... That means, lit vertices should be entirely black. */
4589 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
4590 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4591 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0,
4592 1, src_vb1, 0, device, 0);
4593 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4594 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, unlitquad, 4,
4595 indices, 6, 0);
4596 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4598 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
4599 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4600 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 1,
4601 1, src_vb1, 1, device, 0);
4602 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4603 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, litquad, 4,
4604 indices, 6, 0);
4605 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4607 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
4608 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4609 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 2,
4610 1, src_vb2, 0, device, 0);
4611 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4612 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, unlitnquad, 4,
4613 indices, 6, 0);
4614 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4616 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
4617 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4618 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 3,
4619 1, src_vb2, 1, device, 0);
4620 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4621 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, litnquad, 4,
4622 indices, 6, 0);
4623 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4625 hr = IDirect3DDevice7_EndScene(device);
4626 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4628 hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL);
4629 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4631 color = get_surface_color(rt, 160, 360);
4632 ok(color == 0x00ff0000, "Unlit quad without normals has color 0x%08x, expected 0x00ff0000.\n", color);
4633 ok(dst_data[0].diffuse == 0xffff0000,
4634 "Unlit quad without normals has color 0x%08x, expected 0xffff0000.\n", dst_data[0].diffuse);
4635 ok(!dst_data[0].specular,
4636 "Unexpected specular color 0x%08x.\n", dst_data[0].specular);
4637 color = get_surface_color(rt, 160, 120);
4638 /* Broken on some of WARP drivers. */
4639 ok(color == 0x00000000 || broken(is_warp && (color == 0x000000ff || color == 0x00ff00ff)),
4640 "Lit quad without normals has color 0x%08x, expected 0x00000000.\n", color);
4641 ok(dst_data[1].diffuse == 0xff000000,
4642 "Lit quad without normals has color 0x%08x, expected 0xff000000.\n", dst_data[1].diffuse);
4643 ok(!dst_data[1].specular,
4644 "Unexpected specular color 0x%08x.\n", dst_data[1].specular);
4645 color = get_surface_color(rt, 480, 360);
4646 ok(color == 0x000000ff, "Unlit quad with normals has color 0x%08x, expected 0x000000ff.\n", color);
4647 ok(dst_data[2].diffuse == 0xff0000ff,
4648 "Unlit quad with normals has color 0x%08x, expected 0xff0000ff.\n", dst_data[2].diffuse);
4649 ok(!dst_data[2].specular,
4650 "Unexpected specular color 0x%08x.\n", dst_data[2].specular);
4651 color = get_surface_color(rt, 480, 120);
4652 ok(color == 0x00000000 || broken(is_warp && (color == 0x000000ff || color == 0x00ff00ff)),
4653 "Lit quad with normals has color 0x%08x, expected 0x00000000.\n", color);
4654 ok(dst_data[3].diffuse == 0xff000000,
4655 "Lit quad with normals has color 0x%08x, expected 0xff000000.\n", dst_data[3].diffuse);
4656 ok(!dst_data[3].specular,
4657 "Unexpected specular color 0x%08x.\n", dst_data[3].specular);
4659 hr = IDirect3DVertexBuffer7_Unlock(dst_vb);
4660 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4662 hr = IDirect3DDevice7_LightEnable(device, 0, TRUE);
4663 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4665 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4667 hr = IDirect3DVertexBuffer7_Lock(src_vb2, 0, (void **)&src_data2, NULL);
4668 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4669 memcpy(src_data2, tests[i].quad, sizeof(*src_data2));
4670 hr = IDirect3DVertexBuffer7_Unlock(src_vb2);
4671 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4673 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, tests[i].world_matrix);
4674 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4676 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
4677 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4679 hr = IDirect3DDevice7_BeginScene(device);
4680 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4682 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 0,
4683 1, src_vb2, 0, device, 0);
4684 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4686 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, tests[i].quad,
4687 4, indices, 6, 0);
4688 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4690 hr = IDirect3DDevice7_EndScene(device);
4691 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4693 hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL);
4694 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4696 color = get_surface_color(rt, 320, 240);
4697 ok(color == tests[i].expected || broken(is_warp && (color == 0x000000ff || color == 0x00ff00ff)),
4698 "%s has color 0x%08x.\n", tests[i].message, color);
4699 todo_wine_if(tests[i].process_vertices_todo)
4700 ok(dst_data[0].diffuse == tests[i].expected_process_vertices,
4701 "%s has color 0x%08x.\n", tests[i].message, dst_data[0].diffuse);
4702 ok(!dst_data[0].specular,
4703 "%s has specular color 0x%08x.\n", tests[i].message, dst_data[0].specular);
4705 hr = IDirect3DVertexBuffer7_Unlock(dst_vb);
4706 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4709 IDirect3DVertexBuffer7_Release(src_vb1);
4710 IDirect3DVertexBuffer7_Release(src_vb2);
4711 IDirect3DVertexBuffer7_Release(dst_vb);
4713 IDirectDrawSurface7_Release(rt);
4715 IDirectDraw7_Release(ddraw);
4716 IDirect3D7_Release(d3d);
4717 refcount = IDirect3DDevice7_Release(device);
4718 ok(!refcount, "Device has %u references left.\n", refcount);
4719 DestroyWindow(window);
4722 static void test_specular_lighting(void)
4724 static const unsigned int vertices_side = 5;
4725 const unsigned int indices_count = (vertices_side - 1) * (vertices_side - 1) * 2 * 3;
4726 static const DWORD fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
4727 static D3DMATRIX mat =
4729 1.0f, 0.0f, 0.0f, 0.0f,
4730 0.0f, 1.0f, 0.0f, 0.0f,
4731 0.0f, 0.0f, 1.0f, 0.0f,
4732 0.0f, 0.0f, 0.0f, 1.0f,
4734 static const struct vertex
4736 struct vec3 position;
4737 struct vec3 normal;
4739 vertices[] =
4741 {{-0.5f, -0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4742 {{ 0.0f, -0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4743 {{ 0.5f, -0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4744 {{-0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4745 {{ 0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4746 {{ 0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4747 {{-0.5f, 0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4748 {{ 0.0f, 0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4749 {{ 0.5f, 0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4752 static D3DLIGHT7 directional =
4754 D3DLIGHT_DIRECTIONAL,
4755 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4756 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4757 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4758 {{0.0f}, {0.0f}, {0.0f}},
4759 {{0.0f}, {0.0f}, {1.0f}},
4761 point =
4763 D3DLIGHT_POINT,
4764 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4765 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4766 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4767 {{0.0f}, {0.0f}, {0.0f}},
4768 {{0.0f}, {0.0f}, {0.0f}},
4769 100.0f,
4770 0.0f,
4771 0.0f, 0.0f, 1.0f,
4773 spot =
4775 D3DLIGHT_SPOT,
4776 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4777 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4778 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4779 {{0.0f}, {0.0f}, {0.0f}},
4780 {{0.0f}, {0.0f}, {1.0f}},
4781 100.0f,
4782 1.0f,
4783 0.0f, 0.0f, 1.0f,
4784 M_PI / 12.0f, M_PI / 3.0f
4786 /* The chosen range value makes the test fail when using a manhattan
4787 * distance metric vs the correct euclidean distance. */
4788 point_range =
4790 D3DLIGHT_POINT,
4791 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4792 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4793 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4794 {{0.0f}, {0.0f}, {0.0f}},
4795 {{0.0f}, {0.0f}, {0.0f}},
4796 1.2f,
4797 0.0f,
4798 0.0f, 0.0f, 1.0f,
4800 point_side =
4802 D3DLIGHT_POINT,
4803 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4804 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4805 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4806 {{-1.1f}, {0.0f}, {1.1f}},
4807 {{0.0f}, {0.0f}, {0.0f}},
4808 100.0f,
4809 0.0f,
4810 1.0f, 0.0f, 0.0f,
4812 static const struct expected_color
4814 unsigned int x, y;
4815 D3DCOLOR color;
4817 expected_directional[] =
4819 {160, 120, 0x00ffffff},
4820 {320, 120, 0x00ffffff},
4821 {480, 120, 0x00ffffff},
4822 {160, 240, 0x00ffffff},
4823 {320, 240, 0x00ffffff},
4824 {480, 240, 0x00ffffff},
4825 {160, 360, 0x00ffffff},
4826 {320, 360, 0x00ffffff},
4827 {480, 360, 0x00ffffff},
4829 expected_directional_local[] =
4831 {160, 120, 0x003c3c3c},
4832 {320, 120, 0x00717171},
4833 {480, 120, 0x003c3c3c},
4834 {160, 240, 0x00717171},
4835 {320, 240, 0x00ffffff},
4836 {480, 240, 0x00717171},
4837 {160, 360, 0x003c3c3c},
4838 {320, 360, 0x00717171},
4839 {480, 360, 0x003c3c3c},
4841 expected_point[] =
4843 {160, 120, 0x00282828},
4844 {320, 120, 0x005a5a5a},
4845 {480, 120, 0x00282828},
4846 {160, 240, 0x005a5a5a},
4847 {320, 240, 0x00ffffff},
4848 {480, 240, 0x005a5a5a},
4849 {160, 360, 0x00282828},
4850 {320, 360, 0x005a5a5a},
4851 {480, 360, 0x00282828},
4853 expected_point_local[] =
4855 {160, 120, 0x00000000},
4856 {320, 120, 0x00070707},
4857 {480, 120, 0x00000000},
4858 {160, 240, 0x00070707},
4859 {320, 240, 0x00ffffff},
4860 {480, 240, 0x00070707},
4861 {160, 360, 0x00000000},
4862 {320, 360, 0x00070707},
4863 {480, 360, 0x00000000},
4865 expected_spot[] =
4867 {160, 120, 0x00000000},
4868 {320, 120, 0x00141414},
4869 {480, 120, 0x00000000},
4870 {160, 240, 0x00141414},
4871 {320, 240, 0x00ffffff},
4872 {480, 240, 0x00141414},
4873 {160, 360, 0x00000000},
4874 {320, 360, 0x00141414},
4875 {480, 360, 0x00000000},
4877 expected_spot_local[] =
4879 {160, 120, 0x00000000},
4880 {320, 120, 0x00020202},
4881 {480, 120, 0x00000000},
4882 {160, 240, 0x00020202},
4883 {320, 240, 0x00ffffff},
4884 {480, 240, 0x00020202},
4885 {160, 360, 0x00000000},
4886 {320, 360, 0x00020202},
4887 {480, 360, 0x00000000},
4889 expected_point_range[] =
4891 {160, 120, 0x00000000},
4892 {320, 120, 0x005a5a5a},
4893 {480, 120, 0x00000000},
4894 {160, 240, 0x005a5a5a},
4895 {320, 240, 0x00ffffff},
4896 {480, 240, 0x005a5a5a},
4897 {160, 360, 0x00000000},
4898 {320, 360, 0x005a5a5a},
4899 {480, 360, 0x00000000},
4901 expected_point_side[] =
4903 {160, 120, 0x00000000},
4904 {320, 120, 0x00000000},
4905 {480, 120, 0x00000000},
4906 {160, 240, 0x00000000},
4907 {320, 240, 0x00000000},
4908 {480, 240, 0x00000000},
4909 {160, 360, 0x00000000},
4910 {320, 360, 0x00000000},
4911 {480, 360, 0x00000000},
4913 expected_directional_local_0[] =
4915 {160, 120, 0x00ffffff},
4916 {320, 120, 0x00ffffff},
4917 {480, 120, 0x00ffffff},
4918 {160, 240, 0x00ffffff},
4919 {320, 240, 0x00ffffff},
4920 {480, 240, 0x00ffffff},
4921 {160, 360, 0x00ffffff},
4922 {320, 360, 0x00ffffff},
4923 {480, 360, 0x00ffffff},
4925 expected_point_0[] =
4927 {160, 120, 0x00aaaaaa},
4928 {320, 120, 0x00cccccc},
4929 {480, 120, 0x00aaaaaa},
4930 {160, 240, 0x00cccccc},
4931 {320, 240, 0x00ffffff},
4932 {480, 240, 0x00cccccc},
4933 {160, 360, 0x00aaaaaa},
4934 {320, 360, 0x00cccccc},
4935 {480, 360, 0x00aaaaaa},
4937 expected_spot_0[] =
4939 {160, 120, 0x00000000},
4940 {320, 120, 0x002e2e2e},
4941 {480, 120, 0x00000000},
4942 {160, 240, 0x002e2e2e},
4943 {320, 240, 0x00ffffff},
4944 {480, 240, 0x002e2e2e},
4945 {160, 360, 0x00000000},
4946 {320, 360, 0x002e2e2e},
4947 {480, 360, 0x00000000},
4949 expected_point_range_0[] =
4951 {160, 120, 0x00000000},
4952 {320, 120, 0x00cccccc},
4953 {480, 120, 0x00000000},
4954 {160, 240, 0x00cccccc},
4955 {320, 240, 0x00ffffff},
4956 {480, 240, 0x00cccccc},
4957 {160, 360, 0x00000000},
4958 {320, 360, 0x00cccccc},
4959 {480, 360, 0x00000000},
4961 static const struct
4963 D3DLIGHT7 *light;
4964 BOOL local_viewer;
4965 float specular_power;
4966 const struct expected_color *expected, *expected_process_vertices;
4967 unsigned int expected_count;
4968 BOOL todo_process_vertices;
4970 tests[] =
4972 {&directional, FALSE, 30.0f, expected_directional, expected_directional,
4973 ARRAY_SIZE(expected_directional)},
4974 {&directional, TRUE, 30.0f, expected_directional_local, expected_directional_local,
4975 ARRAY_SIZE(expected_directional_local)},
4976 {&point, FALSE, 30.0f, expected_point, expected_point, ARRAY_SIZE(expected_point)},
4977 {&point, TRUE, 30.0f, expected_point_local, expected_point_local, ARRAY_SIZE(expected_point_local)},
4978 {&spot, FALSE, 30.0f, expected_spot, expected_spot, ARRAY_SIZE(expected_spot)},
4979 {&spot, TRUE, 30.0f, expected_spot_local, expected_spot_local, ARRAY_SIZE(expected_spot_local)},
4980 {&point_range, FALSE, 30.0f, expected_point_range, expected_point_range,
4981 ARRAY_SIZE(expected_point_range)},
4983 /* For zero material shininess _ProcessVertices() seem to keep non-zero material shininess set previously. */
4984 {&point_side, TRUE, 0.0f, expected_point_side, expected_point_side, ARRAY_SIZE(expected_point_side), TRUE},
4985 {&directional, FALSE, 0.0f, expected_directional, expected_directional,
4986 ARRAY_SIZE(expected_directional), TRUE},
4987 {&directional, TRUE, 0.0f, expected_directional_local_0, expected_directional_local,
4988 ARRAY_SIZE(expected_directional_local_0), TRUE},
4989 {&point, FALSE, 0.0f, expected_point_0, expected_point, ARRAY_SIZE(expected_point_0), TRUE},
4990 {&point, TRUE, 0.0f, expected_point_0, expected_point_local, ARRAY_SIZE(expected_point_0), TRUE},
4991 {&spot, FALSE, 0.0f, expected_spot_0, expected_spot, ARRAY_SIZE(expected_spot_0), TRUE},
4992 {&spot, TRUE, 0.0f, expected_spot_0, expected_spot_local, ARRAY_SIZE(expected_spot_0), TRUE},
4993 {&point_range, FALSE, 0.0f, expected_point_range_0, expected_point_range, ARRAY_SIZE(expected_point_range_0), TRUE},
4996 IDirect3DVertexBuffer7 *src_vb, *dst_vb;
4997 D3DCOLOR color, expected_color;
4998 D3DVERTEXBUFFERDESC vb_desc;
4999 IDirect3DDevice7 *device;
5000 unsigned int i, j, x, y;
5001 IDirectDrawSurface7 *rt;
5002 D3DMATERIAL7 material;
5003 struct vec3 *src_data;
5004 struct vertex *quad;
5005 IDirect3D7 *d3d;
5006 ULONG refcount;
5007 WORD *indices;
5008 HWND window;
5009 HRESULT hr;
5010 struct
5012 struct vec4 position;
5013 DWORD diffuse;
5014 DWORD specular;
5015 } *dst_data;
5017 window = create_window();
5018 if (!(device = create_device(window, DDSCL_NORMAL)))
5020 skip("Failed to create a 3D device, skipping test.\n");
5021 DestroyWindow(window);
5022 return;
5024 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
5025 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5027 quad = heap_alloc(vertices_side * vertices_side * sizeof(*quad));
5028 indices = heap_alloc(indices_count * sizeof(*indices));
5029 for (i = 0, y = 0; y < vertices_side; ++y)
5031 for (x = 0; x < vertices_side; ++x)
5033 quad[i].position.x = x * 2.0f / (vertices_side - 1) - 1.0f;
5034 quad[i].position.y = y * 2.0f / (vertices_side - 1) - 1.0f;
5035 quad[i].position.z = 1.0f;
5036 quad[i].normal.x = 0.0f;
5037 quad[i].normal.y = 0.0f;
5038 quad[i++].normal.z = -1.0f;
5041 for (i = 0, y = 0; y < (vertices_side - 1); ++y)
5043 for (x = 0; x < (vertices_side - 1); ++x)
5045 indices[i++] = y * vertices_side + x + 1;
5046 indices[i++] = y * vertices_side + x;
5047 indices[i++] = (y + 1) * vertices_side + x;
5048 indices[i++] = y * vertices_side + x + 1;
5049 indices[i++] = (y + 1) * vertices_side + x;
5050 indices[i++] = (y + 1) * vertices_side + x + 1;
5054 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
5055 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5057 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
5058 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5059 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
5060 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5061 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
5062 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5063 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
5064 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5065 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
5066 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5067 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
5068 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5070 hr = IDirect3DDevice7_LightEnable(device, 0, TRUE);
5071 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5072 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, TRUE);
5073 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5075 memset(&vb_desc, 0, sizeof(vb_desc));
5076 vb_desc.dwSize = sizeof(vb_desc);
5077 vb_desc.dwFVF = fvf;
5078 vb_desc.dwNumVertices = ARRAY_SIZE(vertices);
5079 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &src_vb, 0);
5080 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5081 hr = IDirect3DVertexBuffer7_Lock(src_vb, 0, (void **)&src_data, NULL);
5082 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5083 memcpy(src_data, vertices, sizeof(vertices));
5084 hr = IDirect3DVertexBuffer7_Unlock(src_vb);
5085 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5087 memset(&vb_desc, 0, sizeof(vb_desc));
5088 vb_desc.dwSize = sizeof(vb_desc);
5089 vb_desc.dwFVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR;
5090 vb_desc.dwNumVertices = ARRAY_SIZE(vertices);
5091 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &dst_vb, 0);
5092 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5094 for (i = 0; i < ARRAY_SIZE(tests); ++i)
5096 hr = IDirect3DDevice7_SetLight(device, 0, tests[i].light);
5097 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5099 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LOCALVIEWER, tests[i].local_viewer);
5100 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5102 memset(&material, 0, sizeof(material));
5103 U1(U2(material).specular).r = 1.0f;
5104 U2(U2(material).specular).g = 1.0f;
5105 U3(U2(material).specular).b = 1.0f;
5106 U4(U2(material).specular).a = 0.5f;
5107 U4(material).power = tests[i].specular_power;
5108 hr = IDirect3DDevice7_SetMaterial(device, &material);
5109 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5111 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
5112 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5114 hr = IDirect3DDevice7_BeginScene(device);
5115 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5117 hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL);
5118 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5119 memset(dst_data, 0, sizeof(*dst_data) * ARRAY_SIZE(vertices));
5120 hr = IDirect3DVertexBuffer7_Unlock(dst_vb);
5121 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5123 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 0,
5124 ARRAY_SIZE(vertices), src_vb, 0, device, 0);
5125 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5127 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, quad,
5128 vertices_side * vertices_side, indices, indices_count, 0);
5129 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5131 hr = IDirect3DDevice7_EndScene(device);
5132 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5134 hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL);
5135 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5137 ok(tests[i].expected_count == ARRAY_SIZE(vertices), "Array size mismatch.\n");
5138 for (j = 0; j < tests[i].expected_count; ++j)
5140 color = get_surface_color(rt, tests[i].expected[j].x, tests[i].expected[j].y);
5141 ok(compare_color(color, tests[i].expected[j].color, 1),
5142 "Expected color 0x%08x at location (%u, %u), got 0x%08x, case %u.\n",
5143 tests[i].expected[j].color, tests[i].expected[j].x,
5144 tests[i].expected[j].y, color, i);
5145 ok(!dst_data[j].diffuse, "Expected color 0x00000000 for vertex %u, got 0x%08x, case %u.\n",
5146 j, dst_data[j].diffuse, i);
5147 expected_color = tests[i].expected_process_vertices[j].color | 0x80000000;
5148 todo_wine_if(tests[i].todo_process_vertices && dst_data[j].specular != expected_color)
5149 ok(compare_color(dst_data[j].specular, expected_color, 1),
5150 "Expected color 0x%08x for vertex %u, got 0x%08x, case %u.\n",
5151 expected_color, j, dst_data[j].specular, i);
5153 hr = IDirect3DVertexBuffer7_Unlock(dst_vb);
5154 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5157 IDirect3DVertexBuffer7_Release(dst_vb);
5158 IDirect3DVertexBuffer7_Release(src_vb);
5159 IDirectDrawSurface7_Release(rt);
5161 IDirect3D7_Release(d3d);
5162 refcount = IDirect3DDevice7_Release(device);
5163 ok(!refcount, "Device has %u references left.\n", refcount);
5164 DestroyWindow(window);
5165 heap_free(indices);
5166 heap_free(quad);
5169 static void test_clear_rect_count(void)
5171 IDirectDrawSurface7 *rt;
5172 IDirect3DDevice7 *device;
5173 D3DCOLOR color;
5174 HWND window;
5175 HRESULT hr;
5176 D3DRECT rect = {{0}, {0}, {640}, {480}};
5178 window = create_window();
5179 if (!(device = create_device(window, DDSCL_NORMAL)))
5181 skip("Failed to create a 3D device, skipping test.\n");
5182 DestroyWindow(window);
5183 return;
5186 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
5187 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
5189 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ffffff, 1.0f, 0);
5190 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
5191 hr = IDirect3DDevice7_Clear(device, 0, &rect, D3DCLEAR_TARGET, 0x00ff0000, 1.0f, 0);
5192 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
5194 color = get_surface_color(rt, 320, 240);
5195 ok(compare_color(color, 0x00ffffff, 1) || broken(compare_color(color, 0x00ff0000, 1)),
5196 "Clear with count = 0, rect != NULL has color %#08x.\n", color);
5198 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ffffff, 1.0f, 0);
5199 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
5200 hr = IDirect3DDevice7_Clear(device, 1, NULL, D3DCLEAR_TARGET, 0x0000ff00, 1.0f, 0);
5201 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
5203 color = get_surface_color(rt, 320, 240);
5204 ok(compare_color(color, 0x0000ff00, 1),
5205 "Clear with count = 1, rect = NULL has color %#08x.\n", color);
5207 IDirectDrawSurface7_Release(rt);
5208 IDirect3DDevice7_Release(device);
5209 DestroyWindow(window);
5212 static BOOL test_mode_restored(IDirectDraw7 *ddraw, HWND window)
5214 DDSURFACEDESC2 ddsd1, ddsd2;
5215 HRESULT hr;
5217 memset(&ddsd1, 0, sizeof(ddsd1));
5218 ddsd1.dwSize = sizeof(ddsd1);
5219 hr = IDirectDraw7_GetDisplayMode(ddraw, &ddsd1);
5220 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
5222 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5223 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
5224 hr = set_display_mode(ddraw, 640, 480);
5225 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
5226 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5227 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
5229 memset(&ddsd2, 0, sizeof(ddsd2));
5230 ddsd2.dwSize = sizeof(ddsd2);
5231 hr = IDirectDraw7_GetDisplayMode(ddraw, &ddsd2);
5232 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
5233 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
5234 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
5236 return ddsd1.dwWidth == ddsd2.dwWidth && ddsd1.dwHeight == ddsd2.dwHeight;
5239 static void test_coop_level_versions(void)
5241 HWND window;
5242 IDirectDraw *ddraw;
5243 HRESULT hr;
5244 BOOL restored;
5245 IDirectDrawSurface *surface;
5246 IDirectDraw7 *ddraw7;
5247 DDSURFACEDESC ddsd;
5249 window = create_window();
5250 ddraw7 = create_ddraw();
5251 ok(!!ddraw7, "Failed to create a ddraw object.\n");
5252 /* Newly created ddraw objects restore the mode on ddraw2+::SetCooperativeLevel(NORMAL) */
5253 restored = test_mode_restored(ddraw7, window);
5254 ok(restored, "Display mode not restored in new ddraw object\n");
5256 /* A failing ddraw1::SetCooperativeLevel call does not have an effect */
5257 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
5258 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
5260 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
5261 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
5262 restored = test_mode_restored(ddraw7, window);
5263 ok(restored, "Display mode not restored after bad ddraw1::SetCooperativeLevel call\n");
5265 /* A successful one does */
5266 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5267 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
5268 restored = test_mode_restored(ddraw7, window);
5269 ok(!restored, "Display mode restored after good ddraw1::SetCooperativeLevel call\n");
5271 IDirectDraw_Release(ddraw);
5272 IDirectDraw7_Release(ddraw7);
5274 ddraw7 = create_ddraw();
5275 ok(!!ddraw7, "Failed to create a ddraw object.\n");
5276 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
5277 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
5279 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_SETFOCUSWINDOW);
5280 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
5281 restored = test_mode_restored(ddraw7, window);
5282 ok(!restored, "Display mode restored after ddraw1::SetCooperativeLevel(SETFOCUSWINDOW) call\n");
5284 IDirectDraw_Release(ddraw);
5285 IDirectDraw7_Release(ddraw7);
5287 /* A failing call does not restore the ddraw2+ behavior */
5288 ddraw7 = create_ddraw();
5289 ok(!!ddraw7, "Failed to create a ddraw object.\n");
5290 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
5291 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
5293 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5294 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
5295 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
5296 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
5297 restored = test_mode_restored(ddraw7, window);
5298 ok(!restored, "Display mode restored after good-bad ddraw1::SetCooperativeLevel() call sequence\n");
5300 IDirectDraw_Release(ddraw);
5301 IDirectDraw7_Release(ddraw7);
5303 /* Neither does a sequence of successful calls with the new interface */
5304 ddraw7 = create_ddraw();
5305 ok(!!ddraw7, "Failed to create a ddraw object.\n");
5306 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
5307 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
5309 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5310 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
5311 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
5312 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
5313 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
5314 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
5316 restored = test_mode_restored(ddraw7, window);
5317 ok(!restored, "Display mode restored after ddraw1-ddraw7 SetCooperativeLevel() call sequence\n");
5318 IDirectDraw_Release(ddraw);
5319 IDirectDraw7_Release(ddraw7);
5321 /* ddraw1::CreateSurface does not triger the ddraw1 behavior */
5322 ddraw7 = create_ddraw();
5323 ok(!!ddraw7, "Failed to create a ddraw object.\n");
5324 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
5325 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
5327 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
5328 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
5330 memset(&ddsd, 0, sizeof(ddsd));
5331 ddsd.dwSize = sizeof(ddsd);
5332 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
5333 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5334 ddsd.dwWidth = ddsd.dwHeight = 8;
5335 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
5336 ok(SUCCEEDED(hr), "CreateSurface failed, hr %#x.\n", hr);
5337 IDirectDrawSurface_Release(surface);
5338 restored = test_mode_restored(ddraw7, window);
5339 ok(restored, "Display mode not restored after ddraw1::CreateSurface() call\n");
5341 IDirectDraw_Release(ddraw);
5342 IDirectDraw7_Release(ddraw7);
5343 DestroyWindow(window);
5346 static void test_fog_special(void)
5348 static struct
5350 struct vec3 position;
5351 D3DCOLOR diffuse;
5353 quad[] =
5355 {{ -1.0f, 1.0f, 0.0f}, 0xff00ff00},
5356 {{ 1.0f, 1.0f, 1.0f}, 0xff00ff00},
5357 {{ -1.0f, -1.0f, 0.0f}, 0xff00ff00},
5358 {{ 1.0f, -1.0f, 1.0f}, 0xff00ff00},
5360 static const struct
5362 DWORD vertexmode, tablemode;
5363 D3DCOLOR color_left, color_right;
5365 tests[] =
5367 {D3DFOG_LINEAR, D3DFOG_NONE, 0x00ff0000, 0x00ff0000},
5368 {D3DFOG_NONE, D3DFOG_LINEAR, 0x0000ff00, 0x00ff0000},
5370 union
5372 float f;
5373 DWORD d;
5374 } conv;
5375 D3DCOLOR color;
5376 HRESULT hr;
5377 unsigned int i;
5378 HWND window;
5379 IDirect3DDevice7 *device;
5380 IDirectDrawSurface7 *rt;
5382 window = create_window();
5383 if (!(device = create_device(window, DDSCL_NORMAL)))
5385 skip("Failed to create a 3D device, skipping test.\n");
5386 DestroyWindow(window);
5387 return;
5390 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
5391 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
5393 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
5394 ok(SUCCEEDED(hr), "Failed to enable fog, hr %#x.\n", hr);
5395 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0xffff0000);
5396 ok(SUCCEEDED(hr), "Failed to set fog color, hr %#x.\n", hr);
5397 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
5398 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
5399 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
5400 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
5402 conv.f = 0.5f;
5403 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGSTART, conv.d);
5404 ok(SUCCEEDED(hr), "Failed to set fog start, hr %#x.\n", hr);
5405 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGEND, conv.d);
5406 ok(SUCCEEDED(hr), "Failed to set fog end, hr %#x.\n", hr);
5408 for (i = 0; i < ARRAY_SIZE(tests); ++i)
5410 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x000000ff, 1.0f, 0);
5411 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
5413 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, tests[i].vertexmode);
5414 ok(SUCCEEDED(hr), "Failed to set fogvertexmode, hr %#x.\n", hr);
5415 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, tests[i].tablemode);
5416 ok(SUCCEEDED(hr), "Failed to set fogtablemode, hr %#x.\n", hr);
5418 hr = IDirect3DDevice7_BeginScene(device);
5419 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5420 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, 4, 0);
5421 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5422 hr = IDirect3DDevice7_EndScene(device);
5423 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5425 color = get_surface_color(rt, 310, 240);
5426 ok(compare_color(color, tests[i].color_left, 1),
5427 "Expected left color 0x%08x, got 0x%08x, case %u.\n", tests[i].color_left, color, i);
5428 color = get_surface_color(rt, 330, 240);
5429 ok(compare_color(color, tests[i].color_right, 1),
5430 "Expected right color 0x%08x, got 0x%08x, case %u.\n", tests[i].color_right, color, i);
5433 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
5434 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
5436 IDirectDrawSurface7_Release(rt);
5437 IDirect3DDevice7_Release(device);
5438 DestroyWindow(window);
5441 static void test_lighting_interface_versions(void)
5443 IDirect3DDevice7 *device;
5444 IDirectDrawSurface7 *rt;
5445 D3DCOLOR color;
5446 HWND window;
5447 HRESULT hr;
5448 DWORD rs;
5449 unsigned int i;
5450 ULONG ref;
5451 D3DMATERIAL7 material;
5452 static D3DVERTEX quad[] =
5454 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
5455 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
5456 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
5457 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
5460 #define FVF_COLORVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_SPECULAR)
5461 static struct
5463 struct vec3 position;
5464 struct vec3 normal;
5465 DWORD diffuse, specular;
5467 quad2[] =
5469 {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
5470 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
5471 {{-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
5472 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
5475 static D3DLVERTEX lquad[] =
5477 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
5478 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
5479 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
5480 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
5483 #define FVF_LVERTEX2 (D3DFVF_LVERTEX & ~D3DFVF_RESERVED1)
5484 static struct
5486 struct vec3 position;
5487 DWORD diffuse, specular;
5488 struct vec2 texcoord;
5490 lquad2[] =
5492 {{-1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
5493 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
5494 {{-1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
5495 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
5498 static D3DTLVERTEX tlquad[] =
5500 {{ 0.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
5501 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
5502 {{ 640.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
5503 {{ 640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
5506 static const struct
5508 DWORD vertextype;
5509 void *data;
5510 DWORD d3drs_lighting, d3drs_specular;
5511 DWORD draw_flags;
5512 D3DCOLOR color;
5514 tests[] =
5516 /* Lighting is enabled when D3DFVF_XYZ is used and D3DRENDERSTATE_LIGHTING is
5517 * enabled. D3DDP_DONOTLIGHT is ignored. Lighting is also enabled when normals
5518 * are not available
5520 * Note that the specular result is 0x00000000 when lighting is on even if the
5521 * input vertex has specular color because D3DRENDERSTATE_COLORVERTEX is not
5522 * enabled */
5524 /* 0 */
5525 { D3DFVF_VERTEX, quad, FALSE, FALSE, 0, 0x00ffffff},
5526 { D3DFVF_VERTEX, quad, TRUE, FALSE, 0, 0x0000ff00},
5527 { D3DFVF_VERTEX, quad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
5528 { D3DFVF_VERTEX, quad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
5529 { D3DFVF_VERTEX, quad, FALSE, TRUE, 0, 0x00ffffff},
5530 { D3DFVF_VERTEX, quad, TRUE, TRUE, 0, 0x0000ff00},
5531 { D3DFVF_VERTEX, quad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
5532 { D3DFVF_VERTEX, quad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
5534 /* 8 */
5535 { FVF_COLORVERTEX, quad2, FALSE, FALSE, 0, 0x00ff0000},
5536 { FVF_COLORVERTEX, quad2, TRUE, FALSE, 0, 0x0000ff00},
5537 { FVF_COLORVERTEX, quad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
5538 { FVF_COLORVERTEX, quad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
5539 { FVF_COLORVERTEX, quad2, FALSE, TRUE, 0, 0x00ff8080},
5540 { FVF_COLORVERTEX, quad2, TRUE, TRUE, 0, 0x0000ff00},
5541 { FVF_COLORVERTEX, quad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
5542 { FVF_COLORVERTEX, quad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
5544 /* 16 */
5545 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, 0, 0x00ff0000},
5546 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, 0, 0x0000ff00},
5547 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
5548 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
5549 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, 0, 0x00ff8080},
5550 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, 0, 0x0000ff00},
5551 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
5552 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
5554 /* 24 */
5555 { FVF_LVERTEX2, lquad2, FALSE, FALSE, 0, 0x00ff0000},
5556 { FVF_LVERTEX2, lquad2, TRUE, FALSE, 0, 0x0000ff00},
5557 { FVF_LVERTEX2, lquad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
5558 { FVF_LVERTEX2, lquad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
5559 { FVF_LVERTEX2, lquad2, FALSE, TRUE, 0, 0x00ff8080},
5560 { FVF_LVERTEX2, lquad2, TRUE, TRUE, 0, 0x0000ff00},
5561 { FVF_LVERTEX2, lquad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
5562 { FVF_LVERTEX2, lquad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
5564 /* 32 */
5565 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, 0, 0x000000ff},
5566 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, 0, 0x000000ff},
5567 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
5568 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
5569 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, 0, 0x008080ff},
5570 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, 0, 0x008080ff},
5571 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
5572 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
5575 window = create_window();
5576 if (!(device = create_device(window, DDSCL_NORMAL)))
5578 skip("Failed to create a 3D device, skipping test.\n");
5579 DestroyWindow(window);
5580 return;
5583 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
5584 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
5586 memset(&material, 0, sizeof(material));
5587 U2(U3(material).emissive).g = 1.0f;
5588 hr = IDirect3DDevice7_SetMaterial(device, &material);
5589 ok(SUCCEEDED(hr), "Failed set material, hr %#x.\n", hr);
5590 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
5591 ok(SUCCEEDED(hr), "Failed to disable z test, hr %#x.\n", hr);
5593 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &rs);
5594 ok(SUCCEEDED(hr), "Failed to get lighting render state, hr %#x.\n", hr);
5595 ok(rs == TRUE, "Initial D3DRENDERSTATE_LIGHTING is %#x, expected TRUE.\n", rs);
5596 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, &rs);
5597 ok(SUCCEEDED(hr), "Failed to get specularenable render state, hr %#x.\n", hr);
5598 ok(rs == FALSE, "Initial D3DRENDERSTATE_SPECULARENABLE is %#x, expected FALSE.\n", rs);
5600 for (i = 0; i < ARRAY_SIZE(tests); ++i)
5602 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff202020, 0.0f, 0);
5603 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
5605 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, tests[i].d3drs_lighting);
5606 ok(SUCCEEDED(hr), "Failed to set lighting render state, hr %#x.\n", hr);
5607 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE,
5608 tests[i].d3drs_specular);
5609 ok(SUCCEEDED(hr), "Failed to set specularenable render state, hr %#x.\n", hr);
5611 hr = IDirect3DDevice7_BeginScene(device);
5612 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5613 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
5614 tests[i].vertextype, tests[i].data, 4, tests[i].draw_flags | D3DDP_WAIT);
5615 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5616 hr = IDirect3DDevice7_EndScene(device);
5617 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5619 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &rs);
5620 ok(SUCCEEDED(hr), "Failed to get lighting render state, hr %#x.\n", hr);
5621 ok(rs == tests[i].d3drs_lighting, "D3DRENDERSTATE_LIGHTING is %#x, expected %#x.\n",
5622 rs, tests[i].d3drs_lighting);
5624 color = get_surface_color(rt, 320, 240);
5625 ok(compare_color(color, tests[i].color, 1),
5626 "Got unexpected color 0x%08x, expected 0x%08x, test %u.\n",
5627 color, tests[i].color, i);
5630 IDirectDrawSurface7_Release(rt);
5631 ref = IDirect3DDevice7_Release(device);
5632 ok(ref == 0, "Device not properly released, refcount %u.\n", ref);
5633 DestroyWindow(window);
5636 static struct
5638 BOOL received;
5639 IDirectDraw7 *ddraw;
5640 HWND window;
5641 DWORD coop_level;
5642 } activateapp_testdata;
5644 static LRESULT CALLBACK activateapp_test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
5646 if (message == WM_ACTIVATEAPP)
5648 if (activateapp_testdata.ddraw)
5650 HRESULT hr;
5651 activateapp_testdata.received = FALSE;
5652 hr = IDirectDraw7_SetCooperativeLevel(activateapp_testdata.ddraw,
5653 activateapp_testdata.window, activateapp_testdata.coop_level);
5654 ok(SUCCEEDED(hr), "Recursive SetCooperativeLevel call failed, hr %#x.\n", hr);
5655 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP during recursive SetCooperativeLevel call.\n");
5657 activateapp_testdata.received = TRUE;
5660 return DefWindowProcA(hwnd, message, wparam, lparam);
5663 static void test_coop_level_activateapp(void)
5665 IDirectDraw7 *ddraw;
5666 HRESULT hr;
5667 HWND window;
5668 WNDCLASSA wc = {0};
5669 DDSURFACEDESC2 ddsd;
5670 IDirectDrawSurface7 *surface;
5672 ddraw = create_ddraw();
5673 ok(!!ddraw, "Failed to create a ddraw object.\n");
5675 wc.lpfnWndProc = activateapp_test_proc;
5676 wc.lpszClassName = "ddraw_test_wndproc_wc";
5677 ok(RegisterClassA(&wc), "Failed to register window class.\n");
5679 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
5680 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
5682 /* Exclusive with window already active. */
5683 SetForegroundWindow(window);
5684 activateapp_testdata.received = FALSE;
5685 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5686 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5687 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP although window was already active.\n");
5688 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5689 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5691 /* Exclusive with window not active. */
5692 SetForegroundWindow(GetDesktopWindow());
5693 activateapp_testdata.received = FALSE;
5694 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5695 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5696 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
5697 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5698 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5700 /* Normal with window not active, then exclusive with the same window. */
5701 SetForegroundWindow(GetDesktopWindow());
5702 activateapp_testdata.received = FALSE;
5703 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5704 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5705 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP when setting DDSCL_NORMAL.\n");
5706 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5707 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5708 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
5709 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5710 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5712 /* Recursive set of DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. */
5713 SetForegroundWindow(GetDesktopWindow());
5714 activateapp_testdata.received = FALSE;
5715 activateapp_testdata.ddraw = ddraw;
5716 activateapp_testdata.window = window;
5717 activateapp_testdata.coop_level = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
5718 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5719 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5720 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
5721 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5722 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5724 /* The recursive call seems to have some bad effect on native ddraw, despite (apparently)
5725 * succeeding. Another switch to exclusive and back to normal is needed to release the
5726 * window properly. Without doing this, SetCooperativeLevel(EXCLUSIVE) will not send
5727 * WM_ACTIVATEAPP messages. */
5728 activateapp_testdata.ddraw = NULL;
5729 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5730 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5731 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5732 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5734 /* Setting DDSCL_NORMAL with recursive invocation. */
5735 SetForegroundWindow(GetDesktopWindow());
5736 activateapp_testdata.received = FALSE;
5737 activateapp_testdata.ddraw = ddraw;
5738 activateapp_testdata.window = window;
5739 activateapp_testdata.coop_level = DDSCL_NORMAL;
5740 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5741 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5742 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
5744 /* DDraw is in exclusive mode now. */
5745 memset(&ddsd, 0, sizeof(ddsd));
5746 ddsd.dwSize = sizeof(ddsd);
5747 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
5748 U5(ddsd).dwBackBufferCount = 1;
5749 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
5750 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5751 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5752 IDirectDrawSurface7_Release(surface);
5754 /* Recover again, just to be sure. */
5755 activateapp_testdata.ddraw = NULL;
5756 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5757 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5758 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5759 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5761 DestroyWindow(window);
5762 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
5763 IDirectDraw7_Release(ddraw);
5766 static void test_texturemanage(void)
5768 IDirectDraw7 *ddraw;
5769 HRESULT hr;
5770 DDSURFACEDESC2 ddsd;
5771 IDirectDrawSurface7 *surface;
5772 unsigned int i;
5773 DDCAPS hal_caps, hel_caps;
5774 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
5775 static const struct
5777 DWORD caps_in, caps2_in;
5778 HRESULT hr;
5779 DWORD caps_out, caps2_out;
5781 tests[] =
5783 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
5784 ~0U, ~0U},
5785 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
5786 ~0U, ~0U},
5787 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
5788 ~0U, ~0U},
5789 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
5790 ~0U, ~0U},
5791 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DD_OK,
5792 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE},
5793 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DD_OK,
5794 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE},
5795 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
5796 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_LOCALVIDMEM, 0},
5797 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
5798 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0},
5800 {0, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
5801 ~0U, ~0U},
5802 {0, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
5803 ~0U, ~0U},
5804 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
5805 ~0U, ~0U},
5806 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
5807 ~0U, ~0U},
5808 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
5809 ~0U, ~0U},
5810 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
5811 ~0U, ~0U},
5812 {DDSCAPS_VIDEOMEMORY, 0, DD_OK,
5813 DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY, 0},
5814 {DDSCAPS_SYSTEMMEMORY, 0, DD_OK,
5815 DDSCAPS_SYSTEMMEMORY, 0},
5818 ddraw = create_ddraw();
5819 ok(!!ddraw, "Failed to create a ddraw object.\n");
5820 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5821 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5823 memset(&hal_caps, 0, sizeof(hal_caps));
5824 hal_caps.dwSize = sizeof(hal_caps);
5825 memset(&hel_caps, 0, sizeof(hel_caps));
5826 hel_caps.dwSize = sizeof(hel_caps);
5827 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, &hel_caps);
5828 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
5829 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps)
5831 skip("Managed textures not supported, skipping managed texture test.\n");
5832 IDirectDraw7_Release(ddraw);
5833 return;
5836 for (i = 0; i < ARRAY_SIZE(tests); ++i)
5838 memset(&ddsd, 0, sizeof(ddsd));
5839 ddsd.dwSize = sizeof(ddsd);
5840 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
5841 ddsd.ddsCaps.dwCaps = tests[i].caps_in;
5842 ddsd.ddsCaps.dwCaps2 = tests[i].caps2_in;
5843 ddsd.dwWidth = 4;
5844 ddsd.dwHeight = 4;
5846 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5847 if (tests[i].hr == DD_OK && is_ddraw64 && (tests[i].caps_in & DDSCAPS_TEXTURE))
5848 todo_wine ok(hr == E_NOINTERFACE, "Test %u: Got unexpected hr %#x.\n", i, hr);
5849 else
5850 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, tests[i].hr);
5851 if (FAILED(hr))
5852 continue;
5854 memset(&ddsd, 0, sizeof(ddsd));
5855 ddsd.dwSize = sizeof(ddsd);
5856 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
5857 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5859 ok(ddsd.ddsCaps.dwCaps == tests[i].caps_out,
5860 "Input caps %#x, %#x, expected output caps %#x, got %#x, case %u.\n",
5861 tests[i].caps_in, tests[i].caps2_in, tests[i].caps_out, ddsd.ddsCaps.dwCaps, i);
5862 ok(ddsd.ddsCaps.dwCaps2 == tests[i].caps2_out,
5863 "Input caps %#x, %#x, expected output caps %#x, got %#x, case %u.\n",
5864 tests[i].caps_in, tests[i].caps2_in, tests[i].caps2_out, ddsd.ddsCaps.dwCaps2, i);
5866 IDirectDrawSurface7_Release(surface);
5869 IDirectDraw7_Release(ddraw);
5872 #define SUPPORT_DXT1 0x01
5873 #define SUPPORT_DXT2 0x02
5874 #define SUPPORT_DXT3 0x04
5875 #define SUPPORT_DXT4 0x08
5876 #define SUPPORT_DXT5 0x10
5877 #define SUPPORT_YUY2 0x20
5878 #define SUPPORT_UYVY 0x40
5880 static HRESULT WINAPI test_block_formats_creation_cb(DDPIXELFORMAT *fmt, void *ctx)
5882 DWORD *supported_fmts = ctx;
5884 if (!(fmt->dwFlags & DDPF_FOURCC))
5885 return DDENUMRET_OK;
5887 switch (fmt->dwFourCC)
5889 case MAKEFOURCC('D','X','T','1'):
5890 *supported_fmts |= SUPPORT_DXT1;
5891 break;
5892 case MAKEFOURCC('D','X','T','2'):
5893 *supported_fmts |= SUPPORT_DXT2;
5894 break;
5895 case MAKEFOURCC('D','X','T','3'):
5896 *supported_fmts |= SUPPORT_DXT3;
5897 break;
5898 case MAKEFOURCC('D','X','T','4'):
5899 *supported_fmts |= SUPPORT_DXT4;
5900 break;
5901 case MAKEFOURCC('D','X','T','5'):
5902 *supported_fmts |= SUPPORT_DXT5;
5903 break;
5904 case MAKEFOURCC('Y','U','Y','2'):
5905 *supported_fmts |= SUPPORT_YUY2;
5906 break;
5907 case MAKEFOURCC('U','Y','V','Y'):
5908 *supported_fmts |= SUPPORT_UYVY;
5909 break;
5910 default:
5911 break;
5914 return DDENUMRET_OK;
5917 static void test_block_formats_creation(void)
5919 HRESULT hr, expect_hr;
5920 unsigned int i, j, w, h;
5921 HWND window;
5922 IDirectDraw7 *ddraw;
5923 IDirect3D7 *d3d;
5924 IDirect3DDevice7 *device;
5925 IDirectDrawSurface7 *surface;
5926 DWORD supported_fmts = 0, supported_overlay_fmts = 0;
5927 DWORD num_fourcc_codes = 0, *fourcc_codes;
5928 DDSURFACEDESC2 ddsd;
5929 DDCAPS hal_caps;
5930 void *mem;
5932 static const struct
5934 DWORD fourcc;
5935 const char *name;
5936 DWORD support_flag;
5937 unsigned int block_width;
5938 unsigned int block_height;
5939 unsigned int block_size;
5940 BOOL create_size_checked, overlay;
5942 formats[] =
5944 {MAKEFOURCC('D','X','T','1'), "D3DFMT_DXT1", SUPPORT_DXT1, 4, 4, 8, TRUE, FALSE},
5945 {MAKEFOURCC('D','X','T','2'), "D3DFMT_DXT2", SUPPORT_DXT2, 4, 4, 16, TRUE, FALSE},
5946 {MAKEFOURCC('D','X','T','3'), "D3DFMT_DXT3", SUPPORT_DXT3, 4, 4, 16, TRUE, FALSE},
5947 {MAKEFOURCC('D','X','T','4'), "D3DFMT_DXT4", SUPPORT_DXT4, 4, 4, 16, TRUE, FALSE},
5948 {MAKEFOURCC('D','X','T','5'), "D3DFMT_DXT5", SUPPORT_DXT5, 4, 4, 16, TRUE, FALSE},
5949 {MAKEFOURCC('Y','U','Y','2'), "D3DFMT_YUY2", SUPPORT_YUY2, 2, 1, 4, FALSE, TRUE },
5950 {MAKEFOURCC('U','Y','V','Y'), "D3DFMT_UYVY", SUPPORT_UYVY, 2, 1, 4, FALSE, TRUE },
5952 static const struct
5954 DWORD caps, caps2;
5955 const char *name;
5956 BOOL overlay;
5958 types[] =
5960 /* DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY fails to create any fourcc
5961 * surface with DDERR_INVALIDPIXELFORMAT. Don't care about it for now.
5963 * Nvidia returns E_FAIL on DXTN DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY.
5964 * Other hw / drivers successfully create those surfaces. Ignore them, this
5965 * suggests that no game uses this, otherwise Nvidia would support it. */
5967 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0,
5968 "videomemory texture", FALSE
5971 DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY, 0,
5972 "videomemory overlay", TRUE
5975 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0,
5976 "systemmemory texture", FALSE
5979 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
5980 "managed texture", FALSE
5983 enum size_type
5985 SIZE_TYPE_ZERO,
5986 SIZE_TYPE_PITCH,
5987 SIZE_TYPE_SIZE,
5989 static const struct
5991 DWORD flags;
5992 enum size_type size_type;
5993 int rel_size;
5994 HRESULT hr;
5996 user_mem_tests[] =
5998 {DDSD_LINEARSIZE, SIZE_TYPE_ZERO, 0, DD_OK},
5999 {DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
6000 {DDSD_PITCH, SIZE_TYPE_ZERO, 0, DD_OK},
6001 {DDSD_PITCH, SIZE_TYPE_PITCH, 0, DD_OK},
6002 {DDSD_LPSURFACE, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
6003 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
6004 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_PITCH, 0, DDERR_INVALIDPARAMS},
6005 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
6006 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 1, DD_OK},
6007 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, -1, DDERR_INVALIDPARAMS},
6008 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
6009 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_PITCH, 0, DDERR_INVALIDPARAMS},
6010 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_SIZE, 0, DDERR_INVALIDPARAMS},
6011 {DDSD_LPSURFACE | DDSD_PITCH | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DDERR_INVALIDPARAMS},
6014 window = create_window();
6015 if (!(device = create_device(window, DDSCL_NORMAL)))
6017 skip("Failed to create a 3D device, skipping test.\n");
6018 DestroyWindow(window);
6019 return;
6022 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
6023 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
6024 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **) &ddraw);
6025 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
6026 IDirect3D7_Release(d3d);
6028 hr = IDirect3DDevice7_EnumTextureFormats(device, test_block_formats_creation_cb,
6029 &supported_fmts);
6030 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
6032 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
6033 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
6034 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6035 num_fourcc_codes * sizeof(*fourcc_codes));
6036 if (!fourcc_codes)
6037 goto cleanup;
6038 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
6039 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
6040 for (i = 0; i < num_fourcc_codes; i++)
6042 for (j = 0; j < ARRAY_SIZE(formats); ++j)
6044 if (fourcc_codes[i] == formats[j].fourcc)
6045 supported_overlay_fmts |= formats[j].support_flag;
6048 HeapFree(GetProcessHeap(), 0, fourcc_codes);
6050 memset(&hal_caps, 0, sizeof(hal_caps));
6051 hal_caps.dwSize = sizeof(hal_caps);
6052 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
6053 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6055 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 2 * 2 * 16 + 1);
6057 for (i = 0; i < ARRAY_SIZE(formats); ++i)
6059 for (j = 0; j < ARRAY_SIZE(types); ++j)
6061 BOOL support;
6063 if (formats[i].overlay != types[j].overlay
6064 || (types[j].overlay && !(hal_caps.dwCaps & DDCAPS_OVERLAY)))
6065 continue;
6067 if (formats[i].overlay)
6068 support = supported_overlay_fmts & formats[i].support_flag;
6069 else
6070 support = supported_fmts & formats[i].support_flag;
6072 for (w = 1; w <= 8; w++)
6074 for (h = 1; h <= 8; h++)
6076 BOOL block_aligned = TRUE;
6077 BOOL todo = FALSE;
6079 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
6080 block_aligned = FALSE;
6082 memset(&ddsd, 0, sizeof(ddsd));
6083 ddsd.dwSize = sizeof(ddsd);
6084 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
6085 ddsd.ddsCaps.dwCaps = types[j].caps;
6086 ddsd.ddsCaps.dwCaps2 = types[j].caps2;
6087 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6088 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
6089 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
6090 ddsd.dwWidth = w;
6091 ddsd.dwHeight = h;
6093 /* TODO: Handle power of two limitations. I cannot test the pow2
6094 * behavior on windows because I have no hardware that doesn't at
6095 * least support np2_conditional. There's probably no HW that
6096 * supports DXTN textures but no conditional np2 textures. */
6097 if (!support && !(types[j].caps & DDSCAPS_SYSTEMMEMORY))
6098 expect_hr = DDERR_INVALIDPARAMS;
6099 else if (formats[i].create_size_checked && !block_aligned)
6101 expect_hr = DDERR_INVALIDPARAMS;
6102 if (!(types[j].caps & DDSCAPS_TEXTURE))
6103 todo = TRUE;
6105 else
6106 expect_hr = D3D_OK;
6108 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6109 todo_wine_if (todo)
6110 ok(hr == expect_hr,
6111 "Got unexpected hr %#x for format %s, resource type %s, size %ux%u, expected %#x.\n",
6112 hr, formats[i].name, types[j].name, w, h, expect_hr);
6114 if (SUCCEEDED(hr))
6115 IDirectDrawSurface7_Release(surface);
6120 if (formats[i].overlay)
6121 continue;
6123 for (j = 0; j < ARRAY_SIZE(user_mem_tests); ++j)
6125 memset(&ddsd, 0, sizeof(ddsd));
6126 ddsd.dwSize = sizeof(ddsd);
6127 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | user_mem_tests[j].flags;
6128 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE;
6130 switch (user_mem_tests[j].size_type)
6132 case SIZE_TYPE_ZERO:
6133 U1(ddsd).dwLinearSize = 0;
6134 break;
6136 case SIZE_TYPE_PITCH:
6137 U1(ddsd).dwLinearSize = 2 * formats[i].block_size;
6138 break;
6140 case SIZE_TYPE_SIZE:
6141 U1(ddsd).dwLinearSize = 2 * 2 * formats[i].block_size;
6142 break;
6144 U1(ddsd).dwLinearSize += user_mem_tests[j].rel_size;
6146 ddsd.lpSurface = mem;
6147 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6148 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
6149 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
6150 ddsd.dwWidth = 8;
6151 ddsd.dwHeight = 8;
6153 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6154 ok(hr == user_mem_tests[j].hr, "Test %u: Got unexpected hr %#x, format %s.\n", j, hr, formats[i].name);
6156 if (FAILED(hr))
6157 continue;
6159 memset(&ddsd, 0, sizeof(ddsd));
6160 ddsd.dwSize = sizeof(ddsd);
6161 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6162 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", j, hr);
6163 ok(ddsd.dwFlags == (DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_LINEARSIZE),
6164 "Test %u: Got unexpected flags %#x.\n", j, ddsd.dwFlags);
6165 if (user_mem_tests[j].flags & DDSD_LPSURFACE)
6166 ok(U1(ddsd).dwLinearSize == ~0u, "Test %u: Got unexpected linear size %#x.\n",
6167 j, U1(ddsd).dwLinearSize);
6168 else
6169 ok(U1(ddsd).dwLinearSize == 2 * 2 * formats[i].block_size,
6170 "Test %u: Got unexpected linear size %#x, expected %#x.\n",
6171 j, U1(ddsd).dwLinearSize, 2 * 2 * formats[i].block_size);
6172 IDirectDrawSurface7_Release(surface);
6176 HeapFree(GetProcessHeap(), 0, mem);
6177 cleanup:
6178 IDirectDraw7_Release(ddraw);
6179 IDirect3DDevice7_Release(device);
6180 DestroyWindow(window);
6183 struct format_support_check
6185 const DDPIXELFORMAT *format;
6186 BOOL supported;
6189 static HRESULT WINAPI test_unsupported_formats_cb(DDPIXELFORMAT *fmt, void *ctx)
6191 struct format_support_check *format = ctx;
6193 if (!memcmp(format->format, fmt, sizeof(*fmt)))
6195 format->supported = TRUE;
6196 return DDENUMRET_CANCEL;
6199 return DDENUMRET_OK;
6202 static void test_unsupported_formats(void)
6204 HRESULT hr;
6205 BOOL expect_success;
6206 HWND window;
6207 IDirectDraw7 *ddraw;
6208 IDirect3D7 *d3d;
6209 IDirect3DDevice7 *device;
6210 IDirectDrawSurface7 *surface;
6211 DDSURFACEDESC2 ddsd;
6212 unsigned int i, j;
6213 DWORD expected_caps;
6214 static const struct
6216 const char *name;
6217 DDPIXELFORMAT fmt;
6219 formats[] =
6222 "D3DFMT_A8R8G8B8",
6224 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
6225 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
6229 "D3DFMT_P8",
6231 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
6232 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
6236 static const DWORD caps[] = {0, DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY};
6238 window = create_window();
6239 if (!(device = create_device(window, DDSCL_NORMAL)))
6241 skip("Failed to create a 3D device, skipping test.\n");
6242 DestroyWindow(window);
6243 return;
6246 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
6247 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
6248 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **) &ddraw);
6249 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
6250 IDirect3D7_Release(d3d);
6252 for (i = 0; i < ARRAY_SIZE(formats); ++i)
6254 struct format_support_check check = {&formats[i].fmt, FALSE};
6255 hr = IDirect3DDevice7_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
6256 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
6258 for (j = 0; j < ARRAY_SIZE(caps); ++j)
6260 memset(&ddsd, 0, sizeof(ddsd));
6261 ddsd.dwSize = sizeof(ddsd);
6262 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6263 U4(ddsd).ddpfPixelFormat = formats[i].fmt;
6264 ddsd.dwWidth = 4;
6265 ddsd.dwHeight = 4;
6266 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | caps[j];
6268 if (caps[j] & DDSCAPS_VIDEOMEMORY && !check.supported)
6269 expect_success = FALSE;
6270 else
6271 expect_success = TRUE;
6273 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6274 ok(SUCCEEDED(hr) == expect_success,
6275 "Got unexpected hr %#x for format %s, caps %#x, expected %s.\n",
6276 hr, formats[i].name, caps[j], expect_success ? "success" : "failure");
6277 if (FAILED(hr))
6278 continue;
6280 memset(&ddsd, 0, sizeof(ddsd));
6281 ddsd.dwSize = sizeof(ddsd);
6282 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6283 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6285 if (caps[j] & DDSCAPS_VIDEOMEMORY)
6286 expected_caps = DDSCAPS_VIDEOMEMORY;
6287 else if (caps[j] & DDSCAPS_SYSTEMMEMORY)
6288 expected_caps = DDSCAPS_SYSTEMMEMORY;
6289 else if (check.supported)
6290 expected_caps = DDSCAPS_VIDEOMEMORY;
6291 else
6292 expected_caps = DDSCAPS_SYSTEMMEMORY;
6294 ok(ddsd.ddsCaps.dwCaps & expected_caps,
6295 "Expected capability %#x, format %s, input cap %#x.\n",
6296 expected_caps, formats[i].name, caps[j]);
6298 IDirectDrawSurface7_Release(surface);
6302 IDirectDraw7_Release(ddraw);
6303 IDirect3DDevice7_Release(device);
6304 DestroyWindow(window);
6307 static void test_rt_caps(const GUID *device_guid)
6309 PALETTEENTRY palette_entries[256];
6310 IDirectDrawPalette *palette;
6311 BOOL software_device;
6312 IDirectDraw7 *ddraw;
6313 DDPIXELFORMAT z_fmt;
6314 IDirect3D7 *d3d;
6315 DDCAPS hal_caps;
6316 unsigned int i;
6317 ULONG refcount;
6318 HWND window;
6319 HRESULT hr;
6321 static const DDPIXELFORMAT p8_fmt =
6323 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
6324 {8}, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000},
6327 const struct
6329 const DDPIXELFORMAT *pf;
6330 DWORD caps_in;
6331 DWORD caps2_in;
6332 HRESULT create_device_hr;
6333 HRESULT set_rt_hr, alternative_set_rt_hr;
6335 test_data[] =
6338 NULL,
6339 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
6341 D3D_OK,
6342 D3D_OK,
6343 D3D_OK,
6346 NULL,
6347 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
6349 D3D_OK,
6350 D3D_OK,
6351 D3D_OK,
6354 NULL,
6355 DDSCAPS_OFFSCREENPLAIN,
6357 DDERR_INVALIDCAPS,
6358 DDERR_INVALIDCAPS,
6359 DDERR_INVALIDCAPS,
6362 NULL,
6363 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
6365 D3DERR_SURFACENOTINVIDMEM,
6366 DDERR_INVALIDPARAMS,
6367 D3D_OK,
6370 NULL,
6371 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
6373 DDERR_INVALIDCAPS,
6374 DDERR_INVALIDCAPS,
6375 DDERR_INVALIDCAPS,
6378 NULL,
6379 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
6381 D3D_OK,
6382 D3D_OK,
6383 D3D_OK,
6386 NULL,
6387 DDSCAPS_3DDEVICE,
6389 D3D_OK,
6390 D3D_OK,
6391 D3D_OK,
6394 NULL,
6397 DDERR_INVALIDCAPS,
6398 DDERR_INVALIDCAPS,
6399 DDERR_INVALIDCAPS,
6402 NULL,
6403 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
6405 D3DERR_SURFACENOTINVIDMEM,
6406 DDERR_INVALIDPARAMS,
6407 D3D_OK,
6410 NULL,
6411 DDSCAPS_SYSTEMMEMORY,
6413 DDERR_INVALIDCAPS,
6414 DDERR_INVALIDCAPS,
6415 DDERR_INVALIDCAPS,
6418 NULL,
6419 DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE,
6420 DDSCAPS2_TEXTUREMANAGE,
6421 D3DERR_SURFACENOTINVIDMEM,
6422 DDERR_INVALIDPARAMS,
6423 D3D_OK,
6426 NULL,
6427 DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE,
6428 DDSCAPS2_D3DTEXTUREMANAGE,
6429 D3DERR_SURFACENOTINVIDMEM,
6430 DDERR_INVALIDPARAMS,
6431 D3D_OK,
6434 &p8_fmt,
6437 DDERR_INVALIDCAPS,
6438 DDERR_INVALIDCAPS,
6439 DDERR_INVALIDCAPS,
6442 &p8_fmt,
6443 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
6445 DDERR_NOPALETTEATTACHED,
6446 DDERR_INVALIDCAPS,
6447 DDERR_INVALIDCAPS,
6450 &p8_fmt,
6451 DDSCAPS_OFFSCREENPLAIN,
6453 DDERR_INVALIDCAPS,
6454 DDERR_INVALIDCAPS,
6455 DDERR_INVALIDCAPS,
6458 &p8_fmt,
6459 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
6461 DDERR_NOPALETTEATTACHED,
6462 DDERR_INVALIDCAPS,
6463 DDERR_INVALIDCAPS,
6466 &p8_fmt,
6467 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
6469 DDERR_INVALIDCAPS,
6470 DDERR_INVALIDCAPS,
6471 DDERR_INVALIDCAPS,
6474 &z_fmt,
6475 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
6477 DDERR_INVALIDCAPS,
6478 DDERR_INVALIDPIXELFORMAT,
6479 DDERR_INVALIDPIXELFORMAT,
6482 &z_fmt,
6483 DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
6485 DDERR_INVALIDCAPS,
6486 DDERR_INVALIDPIXELFORMAT,
6487 DDERR_INVALIDPIXELFORMAT,
6490 &z_fmt,
6491 DDSCAPS_ZBUFFER,
6493 DDERR_INVALIDCAPS,
6494 DDERR_INVALIDCAPS,
6495 DDERR_INVALIDCAPS,
6498 &z_fmt,
6499 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
6501 DDERR_INVALIDCAPS,
6502 DDERR_INVALIDPARAMS,
6503 DDERR_INVALIDPIXELFORMAT,
6506 &z_fmt,
6507 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
6509 DDERR_INVALIDCAPS,
6510 DDERR_INVALIDCAPS,
6511 DDERR_INVALIDCAPS,
6515 software_device = is_software_device_type(device_guid);
6517 window = create_window();
6518 ddraw = create_ddraw();
6519 ok(!!ddraw, "Failed to create a ddraw object.\n");
6520 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6521 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6523 if (FAILED(IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d)))
6525 skip("D3D interface is not available, skipping test.\n");
6526 goto done;
6529 memset(&z_fmt, 0, sizeof(z_fmt));
6530 hr = IDirect3D7_EnumZBufferFormats(d3d, device_guid, enum_z_fmt, &z_fmt);
6531 if (FAILED(hr) || !z_fmt.dwSize)
6533 skip("No depth buffer formats available, software_device %u, skipping test.\n", software_device);
6534 IDirect3D7_Release(d3d);
6535 goto done;
6538 memset(palette_entries, 0, sizeof(palette_entries));
6539 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
6540 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6542 memset(&hal_caps, 0, sizeof(hal_caps));
6543 hal_caps.dwSize = sizeof(hal_caps);
6544 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
6545 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6547 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
6549 IDirectDrawSurface7 *surface, *rt, *expected_rt, *tmp;
6550 DDSURFACEDESC2 surface_desc;
6551 DWORD caps_in, expected_caps;
6552 IDirect3DDevice7 *device;
6553 HRESULT expected_hr;
6555 caps_in = test_data[i].caps_in;
6557 memset(&surface_desc, 0, sizeof(surface_desc));
6558 surface_desc.dwSize = sizeof(surface_desc);
6559 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6560 surface_desc.ddsCaps.dwCaps = caps_in;
6561 surface_desc.ddsCaps.dwCaps2 = test_data[i].caps2_in;
6562 if (test_data[i].pf)
6564 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
6565 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
6567 surface_desc.dwWidth = 640;
6568 surface_desc.dwHeight = 480;
6569 if ((caps_in & DDSCAPS_VIDEOMEMORY) && !(hal_caps.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
6570 expected_hr = DDERR_NODIRECTDRAWHW;
6571 else
6572 expected_hr = DD_OK;
6573 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6574 ok(hr == expected_hr || (software_device && (surface_desc.ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER))
6575 == (DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER) && hr == DDERR_UNSUPPORTED)
6576 || broken(software_device && test_data[i].pf == &p8_fmt && hr == DDERR_INVALIDPIXELFORMAT),
6577 "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
6578 if (FAILED(hr))
6579 continue;
6581 memset(&surface_desc, 0, sizeof(surface_desc));
6582 surface_desc.dwSize = sizeof(surface_desc);
6583 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
6584 ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
6586 if ((caps_in & DDSCAPS_SYSTEMMEMORY) || (test_data[i].caps2_in & (DDSCAPS2_D3DTEXTUREMANAGE
6587 | DDSCAPS2_TEXTUREMANAGE)) || !(hal_caps.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
6588 expected_caps = caps_in | DDSCAPS_SYSTEMMEMORY;
6589 else
6590 expected_caps = caps_in | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
6592 ok(surface_desc.ddsCaps.dwCaps == expected_caps || (test_data[i].pf == &p8_fmt
6593 && surface_desc.ddsCaps.dwCaps == (caps_in | DDSCAPS_SYSTEMMEMORY))
6594 || (software_device && test_data[i].pf == &z_fmt
6595 && surface_desc.ddsCaps.dwCaps == (caps_in | DDSCAPS_SYSTEMMEMORY)),
6596 "Got unexpected caps %#x, expected %#x, test %u, software_device %u.\n",
6597 surface_desc.ddsCaps.dwCaps, expected_caps, i, software_device);
6599 ok(surface_desc.ddsCaps.dwCaps2 == test_data[i].caps2_in,
6600 "Got unexpected caps2 %#x, expected %#x, test %u, software_device %u.\n",
6601 surface_desc.ddsCaps.dwCaps2, test_data[i].caps2_in, i, software_device);
6603 hr = IDirect3D7_CreateDevice(d3d, device_guid, surface, &device);
6604 ok((!software_device && hr == test_data[i].create_device_hr)
6605 || (software_device && (hr == (test_data[i].create_device_hr == D3DERR_SURFACENOTINVIDMEM
6606 ? DD_OK : test_data[i].create_device_hr))),
6607 "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
6608 if (FAILED(hr))
6610 if (hr == DDERR_NOPALETTEATTACHED)
6612 hr = IDirectDrawSurface7_SetPalette(surface, palette);
6613 ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
6614 hr = IDirect3D7_CreateDevice(d3d, device_guid, surface, &device);
6615 if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
6616 ok(hr == DDERR_INVALIDPIXELFORMAT, "Got unexpected hr %#x, test %u, software_device %u.\n",
6617 hr, i, software_device);
6618 else if (software_device)
6619 todo_wine
6620 ok(hr == E_FAIL, "Got unexpected hr %#x, test %u, software_device %u.\n",
6621 hr, i, software_device);
6622 else
6623 ok(hr == D3DERR_SURFACENOTINVIDMEM, "Got unexpected hr %#x, test %u, software_device %u.\n",
6624 hr, i, software_device);
6626 IDirectDrawSurface7_Release(surface);
6628 memset(&surface_desc, 0, sizeof(surface_desc));
6629 surface_desc.dwSize = sizeof(surface_desc);
6630 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6631 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
6632 surface_desc.dwWidth = 640;
6633 surface_desc.dwHeight = 480;
6634 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6635 ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
6637 hr = IDirect3D7_CreateDevice(d3d, device_guid, surface, &device);
6638 ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
6641 memset(&surface_desc, 0, sizeof(surface_desc));
6642 surface_desc.dwSize = sizeof(surface_desc);
6643 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6644 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
6645 surface_desc.ddsCaps.dwCaps2 = test_data[i].caps2_in;
6646 if (test_data[i].pf)
6648 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
6649 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
6651 surface_desc.dwWidth = 640;
6652 surface_desc.dwHeight = 480;
6653 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &rt, NULL);
6654 ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
6656 hr = IDirect3DDevice7_SetRenderTarget(device, rt, 0);
6657 ok(hr == test_data[i].set_rt_hr || (software_device && hr == DDERR_NOPALETTEATTACHED)
6658 || hr == test_data[i].alternative_set_rt_hr,
6659 "Got unexpected hr %#x, test %u, software_device %u.\n",
6660 hr, i, software_device);
6661 if (SUCCEEDED(hr) || hr == DDERR_INVALIDPIXELFORMAT)
6662 expected_rt = rt;
6663 else
6664 expected_rt = surface;
6666 hr = IDirect3DDevice7_GetRenderTarget(device, &tmp);
6667 ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
6668 ok(tmp == expected_rt, "Got unexpected rt %p, test %u, software_device %u.\n", tmp, i, software_device);
6670 IDirectDrawSurface7_Release(tmp);
6671 IDirectDrawSurface7_Release(rt);
6672 refcount = IDirect3DDevice7_Release(device);
6673 ok(refcount == 0, "Test %u: The device was not properly freed, refcount %u.\n", i, refcount);
6674 refcount = IDirectDrawSurface7_Release(surface);
6675 ok(refcount == 0, "Test %u: The surface was not properly freed, refcount %u.\n", i, refcount);
6678 refcount = IDirectDrawPalette_Release(palette);
6679 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6680 IDirect3D7_Release(d3d);
6682 done:
6683 refcount = IDirectDraw7_Release(ddraw);
6684 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
6685 DestroyWindow(window);
6688 static void test_primary_caps(void)
6690 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
6691 IDirectDrawSurface7 *surface;
6692 DDSURFACEDESC2 surface_desc;
6693 IDirectDraw7 *ddraw;
6694 unsigned int i;
6695 ULONG refcount;
6696 HWND window;
6697 HRESULT hr;
6699 static const struct
6701 DWORD coop_level;
6702 DWORD caps_in;
6703 DWORD back_buffer_count;
6704 HRESULT hr;
6705 DWORD caps_out;
6707 test_data[] =
6710 DDSCL_NORMAL,
6711 DDSCAPS_PRIMARYSURFACE,
6712 ~0u,
6713 DD_OK,
6714 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE,
6717 DDSCL_NORMAL,
6718 DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE,
6719 ~0u,
6720 DDERR_INVALIDCAPS,
6721 ~0u,
6724 DDSCL_NORMAL,
6725 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
6726 ~0u,
6727 DDERR_INVALIDCAPS,
6728 ~0u,
6731 DDSCL_NORMAL,
6732 DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER,
6733 ~0u,
6734 DDERR_INVALIDCAPS,
6735 ~0u,
6738 DDSCL_NORMAL,
6739 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP,
6740 ~0u,
6741 DDERR_INVALIDCAPS,
6742 ~0u,
6745 DDSCL_NORMAL,
6746 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX,
6747 ~0u,
6748 DDERR_INVALIDCAPS,
6749 ~0u,
6752 DDSCL_NORMAL,
6753 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
6754 ~0u,
6755 DDERR_INVALIDCAPS,
6756 ~0u,
6759 DDSCL_NORMAL,
6760 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
6762 DDERR_INVALIDCAPS,
6763 ~0u,
6766 DDSCL_NORMAL,
6767 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
6769 DDERR_NOEXCLUSIVEMODE,
6770 ~0u,
6773 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
6774 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
6776 DDERR_INVALIDCAPS,
6777 ~0u,
6780 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
6781 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
6783 DD_OK,
6784 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX,
6787 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
6788 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER,
6790 DDERR_INVALIDCAPS,
6791 ~0u,
6794 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
6795 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_BACKBUFFER,
6797 DDERR_INVALIDCAPS,
6798 ~0u,
6802 window = create_window();
6803 ddraw = create_ddraw();
6804 ok(!!ddraw, "Failed to create a ddraw object.\n");
6806 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
6808 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, test_data[i].coop_level);
6809 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6811 memset(&surface_desc, 0, sizeof(surface_desc));
6812 surface_desc.dwSize = sizeof(surface_desc);
6813 surface_desc.dwFlags = DDSD_CAPS;
6814 if (test_data[i].back_buffer_count != ~0u)
6815 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
6816 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
6817 U5(surface_desc).dwBackBufferCount = test_data[i].back_buffer_count;
6818 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6819 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
6820 if (FAILED(hr))
6821 continue;
6823 memset(&surface_desc, 0, sizeof(surface_desc));
6824 surface_desc.dwSize = sizeof(surface_desc);
6825 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
6826 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
6827 ok((surface_desc.ddsCaps.dwCaps & ~placement) == test_data[i].caps_out,
6828 "Test %u: Got unexpected caps %#x, expected %#x.\n",
6829 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
6831 IDirectDrawSurface7_Release(surface);
6834 refcount = IDirectDraw7_Release(ddraw);
6835 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
6836 DestroyWindow(window);
6839 static void test_surface_lock(void)
6841 IDirectDraw7 *ddraw;
6842 IDirect3D7 *d3d = NULL;
6843 IDirectDrawSurface7 *surface;
6844 IDirect3DDevice7 *device;
6845 HRESULT hr, expected_hr;
6846 HWND window;
6847 unsigned int i;
6848 DDSURFACEDESC2 ddsd;
6849 ULONG refcount;
6850 DDPIXELFORMAT z_fmt;
6851 BOOL hal_ok = FALSE;
6852 const GUID *devtype = &IID_IDirect3DHALDevice;
6853 D3DDEVICEDESC7 device_desc;
6854 BOOL cubemap_supported;
6855 static const struct
6857 DWORD caps;
6858 DWORD caps2;
6859 const char *name;
6861 tests[] =
6864 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
6866 "videomemory offscreenplain"
6869 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
6871 "systemmemory offscreenplain"
6874 DDSCAPS_PRIMARYSURFACE,
6876 "primary"
6879 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
6881 "videomemory texture"
6884 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
6885 DDSCAPS2_OPAQUE,
6886 "opaque videomemory texture"
6889 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
6891 "systemmemory texture"
6894 DDSCAPS_TEXTURE,
6895 DDSCAPS2_TEXTUREMANAGE,
6896 "managed texture"
6899 DDSCAPS_TEXTURE,
6900 DDSCAPS2_D3DTEXTUREMANAGE,
6901 "managed texture"
6904 DDSCAPS_TEXTURE,
6905 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_OPAQUE,
6906 "opaque managed texture"
6909 DDSCAPS_TEXTURE,
6910 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_OPAQUE,
6911 "opaque managed texture"
6914 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
6916 "render target"
6919 DDSCAPS_ZBUFFER,
6921 "Z buffer"
6924 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY,
6925 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
6926 "videomemory cube"
6929 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY,
6930 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_OPAQUE,
6931 "opaque videomemory cube"
6934 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_SYSTEMMEMORY,
6935 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
6936 "systemmemory cube"
6939 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
6940 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
6941 "managed cube"
6944 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
6945 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
6946 "managed cube"
6949 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
6950 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_OPAQUE,
6951 "opaque managed cube"
6954 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
6955 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_OPAQUE,
6956 "opaque managed cube"
6960 window = create_window();
6961 ddraw = create_ddraw();
6962 ok(!!ddraw, "Failed to create a ddraw object.\n");
6963 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6964 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6966 if (FAILED(IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d)))
6968 skip("D3D interface is not available, skipping test.\n");
6969 goto done;
6972 hr = IDirect3D7_EnumDevices(d3d, enum_devtype_cb, &hal_ok);
6973 ok(SUCCEEDED(hr), "Failed to enumerate devices, hr %#x.\n", hr);
6974 if (hal_ok)
6975 devtype = &IID_IDirect3DTnLHalDevice;
6977 memset(&z_fmt, 0, sizeof(z_fmt));
6978 hr = IDirect3D7_EnumZBufferFormats(d3d, devtype, enum_z_fmt, &z_fmt);
6979 if (FAILED(hr) || !z_fmt.dwSize)
6981 skip("No depth buffer formats available, skipping test.\n");
6982 goto done;
6985 memset(&ddsd, 0, sizeof(ddsd));
6986 ddsd.dwSize = sizeof(ddsd);
6987 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6988 ddsd.dwWidth = 64;
6989 ddsd.dwHeight = 64;
6990 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
6991 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6992 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6994 hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
6995 ok(SUCCEEDED(hr), "Failed to create device, hr %#x.\n", hr);
6996 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
6997 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6998 cubemap_supported = !!(device_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP);
6999 IDirect3DDevice7_Release(device);
7001 IDirectDrawSurface7_Release(surface);
7003 for (i = 0; i < ARRAY_SIZE(tests); ++i)
7005 if (!cubemap_supported && tests[i].caps2 & DDSCAPS2_CUBEMAP)
7006 continue;
7008 memset(&ddsd, 0, sizeof(ddsd));
7009 ddsd.dwSize = sizeof(ddsd);
7010 ddsd.dwFlags = DDSD_CAPS;
7011 if (!(tests[i].caps & DDSCAPS_PRIMARYSURFACE))
7013 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
7014 ddsd.dwWidth = 64;
7015 ddsd.dwHeight = 64;
7017 if (tests[i].caps & DDSCAPS_ZBUFFER)
7019 ddsd.dwFlags |= DDSD_PIXELFORMAT;
7020 U4(ddsd).ddpfPixelFormat = z_fmt;
7022 ddsd.ddsCaps.dwCaps = tests[i].caps;
7023 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
7025 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
7026 ok(SUCCEEDED(hr), "Failed to create surface, type %s, hr %#x.\n", tests[i].name, hr);
7028 memset(&ddsd, 0, sizeof(ddsd));
7029 ddsd.dwSize = sizeof(ddsd);
7030 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
7031 ok(SUCCEEDED(hr), "Failed to lock surface, type %s, hr %#x.\n", tests[i].name, hr);
7032 if (SUCCEEDED(hr))
7034 ok(ddsd.dwSize == sizeof(ddsd), "Got unexpected dwSize %u, type %s.\n", ddsd.dwSize, tests[i].name);
7035 hr = IDirectDrawSurface7_Unlock(surface, NULL);
7036 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
7039 memset(&ddsd, 0, sizeof(ddsd));
7040 expected_hr = tests[i].caps & DDSCAPS_TEXTURE && !(tests[i].caps & DDSCAPS_VIDEOMEMORY)
7041 ? DD_OK : DDERR_INVALIDPARAMS;
7042 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
7043 ok(hr == expected_hr, "Got hr %#x, expected %#x, type %s.\n", hr, expected_hr, tests[i].name);
7044 if (SUCCEEDED(hr))
7046 ok(!ddsd.dwSize, "Got unexpected dwSize %u, type %s.\n", ddsd.dwSize, tests[i].name);
7047 ok(!!ddsd.lpSurface, "Got NULL lpSurface, type %s.\n", tests[i].name);
7048 hr = IDirectDrawSurface7_Unlock(surface, NULL);
7049 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
7052 IDirectDrawSurface7_Release(surface);
7055 done:
7056 if (d3d)
7057 IDirect3D7_Release(d3d);
7058 refcount = IDirectDraw7_Release(ddraw);
7059 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
7060 DestroyWindow(window);
7063 static void test_surface_discard(void)
7065 IDirect3DDevice7 *device;
7066 IDirect3D7 *d3d;
7067 IDirectDraw7 *ddraw;
7068 HRESULT hr;
7069 HWND window;
7070 DDSURFACEDESC2 ddsd;
7071 IDirectDrawSurface7 *surface, *target;
7072 void *addr;
7073 static const struct
7075 DWORD caps, caps2;
7076 BOOL discard;
7078 tests[] =
7080 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, TRUE},
7081 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
7082 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, TRUE},
7083 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
7084 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE},
7085 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
7086 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE},
7087 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
7089 unsigned int i;
7091 window = create_window();
7093 for (i = 0; i < ARRAY_SIZE(tests); ++i)
7095 BOOL discarded;
7097 /* Sigh. Anything other than the first run of the loop randomly fails with
7098 * DDERR_SURFACELOST on my Radeon Pro 560 on Win10 19.09. Most of the time
7099 * the blit fails, but with sleeps added between surface creation and lock
7100 * the lock can fail too. Interestingly ddraw claims the render target has
7101 * been lost, not the test surface.
7103 * Recreating ddraw every iteration seems to fix this. */
7104 if (!(device = create_device(window, DDSCL_NORMAL)))
7106 skip("Failed to create a 3D device, skipping test.\n");
7107 DestroyWindow(window);
7108 return;
7110 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
7111 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
7112 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
7113 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
7114 hr = IDirect3DDevice7_GetRenderTarget(device, &target);
7115 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
7117 memset(&ddsd, 0, sizeof(ddsd));
7118 ddsd.dwSize = sizeof(ddsd);
7119 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7120 ddsd.ddsCaps.dwCaps = tests[i].caps;
7121 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
7122 ddsd.dwWidth = 64;
7123 ddsd.dwHeight = 64;
7124 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
7125 ok(SUCCEEDED(hr), "Failed to create offscreen surface, hr %#x, case %u.\n", hr, i);
7127 memset(&ddsd, 0, sizeof(ddsd));
7128 ddsd.dwSize = sizeof(ddsd);
7129 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, 0, NULL);
7130 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7131 addr = ddsd.lpSurface;
7132 hr = IDirectDrawSurface7_Unlock(surface, NULL);
7133 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7135 memset(&ddsd, 0, sizeof(ddsd));
7136 ddsd.dwSize = sizeof(ddsd);
7137 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
7138 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7139 discarded = ddsd.lpSurface != addr;
7140 hr = IDirectDrawSurface7_Unlock(surface, NULL);
7141 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7143 hr = IDirectDrawSurface7_Blt(target, NULL, surface, NULL, DDBLT_WAIT, NULL);
7144 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
7146 memset(&ddsd, 0, sizeof(ddsd));
7147 ddsd.dwSize = sizeof(ddsd);
7148 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
7149 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7150 discarded |= ddsd.lpSurface != addr;
7151 hr = IDirectDrawSurface7_Unlock(surface, NULL);
7152 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7154 IDirectDrawSurface7_Release(surface);
7156 /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler,
7157 * AMD r500, evergreen). Windows XP, at least on AMD r200, does not. */
7158 ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i);
7160 IDirectDrawSurface7_Release(target);
7161 IDirectDraw7_Release(ddraw);
7162 IDirect3D7_Release(d3d);
7163 IDirect3DDevice7_Release(device);
7166 DestroyWindow(window);
7169 static void test_flip(void)
7171 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
7172 IDirectDrawSurface7 *frontbuffer, *backbuffer1, *backbuffer2, *backbuffer3, *surface;
7173 DDSCAPS2 caps = {DDSCAPS_FLIP, 0, 0, {0}};
7174 DDSURFACEDESC2 surface_desc;
7175 D3DDEVICEDESC7 device_desc;
7176 IDirect3DDevice7 *device;
7177 BOOL sysmem_primary;
7178 IDirectDraw7 *ddraw;
7179 DWORD expected_caps;
7180 unsigned int i;
7181 D3DCOLOR color;
7182 ULONG refcount;
7183 HWND window;
7184 HRESULT hr;
7186 static const struct
7188 const char *name;
7189 DWORD caps;
7191 test_data[] =
7193 {"PRIMARYSURFACE", DDSCAPS_PRIMARYSURFACE},
7194 {"OFFSCREENPLAIN", DDSCAPS_OFFSCREENPLAIN},
7195 {"TEXTURE", DDSCAPS_TEXTURE},
7198 window = create_window();
7199 ddraw = create_ddraw();
7200 ok(!!ddraw, "Failed to create a ddraw object.\n");
7202 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7203 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7205 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
7207 /* Creating a flippable texture induces a BSoD on some versions of the
7208 * Intel graphics driver. At least Intel GMA 950 with driver version
7209 * 6.14.10.4926 on Windows XP SP3 is affected. */
7210 if ((test_data[i].caps & DDSCAPS_TEXTURE) && ddraw_is_intel(ddraw))
7212 win_skip("Skipping flippable texture test.\n");
7213 continue;
7216 memset(&surface_desc, 0, sizeof(surface_desc));
7217 surface_desc.dwSize = sizeof(surface_desc);
7218 surface_desc.dwFlags = DDSD_CAPS;
7219 if (!(test_data[i].caps & DDSCAPS_PRIMARYSURFACE))
7220 surface_desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
7221 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
7222 surface_desc.dwWidth = 512;
7223 surface_desc.dwHeight = 512;
7224 U5(surface_desc).dwBackBufferCount = 3;
7225 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
7226 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
7228 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_FLIP;
7229 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
7230 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
7231 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
7233 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_COMPLEX;
7234 surface_desc.ddsCaps.dwCaps |= DDSCAPS_FLIP;
7235 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
7236 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
7238 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
7239 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
7240 if (is_ddraw64 && test_data[i].caps & DDSCAPS_TEXTURE)
7241 todo_wine ok(hr == E_NOINTERFACE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
7242 else todo_wine_if(test_data[i].caps & DDSCAPS_TEXTURE)
7243 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
7244 if (FAILED(hr))
7245 continue;
7247 memset(&surface_desc, 0, sizeof(surface_desc));
7248 surface_desc.dwSize = sizeof(surface_desc);
7249 hr = IDirectDrawSurface7_GetSurfaceDesc(frontbuffer, &surface_desc);
7250 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
7251 expected_caps = DDSCAPS_FRONTBUFFER | DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
7252 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
7253 expected_caps |= DDSCAPS_VISIBLE;
7254 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
7255 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
7256 sysmem_primary = surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
7258 hr = IDirectDrawSurface7_GetAttachedSurface(frontbuffer, &caps, &backbuffer1);
7259 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
7260 memset(&surface_desc, 0, sizeof(surface_desc));
7261 surface_desc.dwSize = sizeof(surface_desc);
7262 hr = IDirectDrawSurface7_GetSurfaceDesc(backbuffer1, &surface_desc);
7263 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
7264 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
7265 test_data[i].name, U5(surface_desc).dwBackBufferCount);
7266 expected_caps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER);
7267 expected_caps |= DDSCAPS_BACKBUFFER;
7268 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
7269 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
7271 hr = IDirectDrawSurface7_GetAttachedSurface(backbuffer1, &caps, &backbuffer2);
7272 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
7273 memset(&surface_desc, 0, sizeof(surface_desc));
7274 surface_desc.dwSize = sizeof(surface_desc);
7275 hr = IDirectDrawSurface7_GetSurfaceDesc(backbuffer2, &surface_desc);
7276 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
7277 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
7278 test_data[i].name, U5(surface_desc).dwBackBufferCount);
7279 expected_caps &= ~DDSCAPS_BACKBUFFER;
7280 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
7281 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
7283 hr = IDirectDrawSurface7_GetAttachedSurface(backbuffer2, &caps, &backbuffer3);
7284 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
7285 memset(&surface_desc, 0, sizeof(surface_desc));
7286 surface_desc.dwSize = sizeof(surface_desc);
7287 hr = IDirectDrawSurface7_GetSurfaceDesc(backbuffer3, &surface_desc);
7288 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
7289 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
7290 test_data[i].name, U5(surface_desc).dwBackBufferCount);
7291 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
7292 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
7294 hr = IDirectDrawSurface7_GetAttachedSurface(backbuffer3, &caps, &surface);
7295 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
7296 ok(surface == frontbuffer, "%s: Got unexpected surface %p, expected %p.\n",
7297 test_data[i].name, surface, frontbuffer);
7298 IDirectDrawSurface7_Release(surface);
7300 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
7301 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
7302 hr = IDirectDrawSurface7_IsLost(frontbuffer);
7303 ok(hr == DD_OK, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
7304 hr = IDirectDrawSurface7_Flip(frontbuffer, NULL, DDFLIP_WAIT);
7305 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
7306 ok(hr == DDERR_NOEXCLUSIVEMODE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
7307 else
7308 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
7309 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7310 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
7311 hr = IDirectDrawSurface7_IsLost(frontbuffer);
7312 todo_wine ok(hr == DDERR_SURFACELOST, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
7313 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
7314 ok(SUCCEEDED(hr), "%s: Failed to restore surfaces, hr %#x.\n", test_data[i].name, hr);
7316 memset(&surface_desc, 0, sizeof(surface_desc));
7317 surface_desc.dwSize = sizeof(surface_desc);
7318 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7319 surface_desc.ddsCaps.dwCaps = 0;
7320 surface_desc.dwWidth = 640;
7321 surface_desc.dwHeight = 480;
7322 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7323 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
7324 hr = IDirectDrawSurface7_Flip(frontbuffer, surface, DDFLIP_WAIT);
7325 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
7326 IDirectDrawSurface7_Release(surface);
7328 hr = IDirectDrawSurface7_Flip(frontbuffer, frontbuffer, DDFLIP_WAIT);
7329 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
7330 hr = IDirectDrawSurface7_Flip(backbuffer1, NULL, DDFLIP_WAIT);
7331 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
7332 hr = IDirectDrawSurface7_Flip(backbuffer2, NULL, DDFLIP_WAIT);
7333 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
7334 hr = IDirectDrawSurface7_Flip(backbuffer3, NULL, DDFLIP_WAIT);
7335 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
7337 /* The Nvidia Geforce 7 driver cannot do a color fill on a texture backbuffer after
7338 * the backbuffer has been locked. Do it ourselves as a workaround. Unlike ddraw1
7339 * and 2 GetSurfaceDesc does not cause issues in ddraw4 and ddraw7. */
7340 fill_surface(backbuffer1, 0xffff0000);
7341 fill_surface(backbuffer2, 0xff00ff00);
7342 fill_surface(backbuffer3, 0xff0000ff);
7344 hr = IDirectDrawSurface7_Flip(frontbuffer, NULL, DDFLIP_WAIT);
7345 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
7346 color = get_surface_color(backbuffer1, 320, 240);
7347 /* The testbot seems to just copy the contents of one surface to all the
7348 * others, instead of properly flipping. */
7349 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
7350 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7351 color = get_surface_color(backbuffer2, 320, 240);
7352 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7353 fill_surface(backbuffer3, 0xffff0000);
7355 hr = IDirectDrawSurface7_Flip(frontbuffer, NULL, DDFLIP_WAIT);
7356 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
7357 color = get_surface_color(backbuffer1, 320, 240);
7358 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
7359 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7360 color = get_surface_color(backbuffer2, 320, 240);
7361 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7362 fill_surface(backbuffer3, 0xff00ff00);
7364 hr = IDirectDrawSurface7_Flip(frontbuffer, NULL, DDFLIP_WAIT);
7365 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
7366 color = get_surface_color(backbuffer1, 320, 240);
7367 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
7368 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7369 color = get_surface_color(backbuffer2, 320, 240);
7370 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7371 fill_surface(backbuffer3, 0xff0000ff);
7373 hr = IDirectDrawSurface7_Flip(frontbuffer, backbuffer1, DDFLIP_WAIT);
7374 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
7375 color = get_surface_color(backbuffer2, 320, 240);
7376 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
7377 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7378 color = get_surface_color(backbuffer3, 320, 240);
7379 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7380 fill_surface(backbuffer1, 0xffff0000);
7382 hr = IDirectDrawSurface7_Flip(frontbuffer, backbuffer2, DDFLIP_WAIT);
7383 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
7384 color = get_surface_color(backbuffer1, 320, 240);
7385 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7386 color = get_surface_color(backbuffer3, 320, 240);
7387 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
7388 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7389 fill_surface(backbuffer2, 0xff00ff00);
7391 hr = IDirectDrawSurface7_Flip(frontbuffer, backbuffer3, DDFLIP_WAIT);
7392 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
7393 color = get_surface_color(backbuffer1, 320, 240);
7394 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
7395 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7396 color = get_surface_color(backbuffer2, 320, 240);
7397 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7399 IDirectDrawSurface7_Release(backbuffer3);
7400 IDirectDrawSurface7_Release(backbuffer2);
7401 IDirectDrawSurface7_Release(backbuffer1);
7402 IDirectDrawSurface7_Release(frontbuffer);
7405 if (!(device = create_device(window, DDSCL_NORMAL)))
7407 skip("Failed to create 3D device.\n");
7408 goto done;
7410 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
7411 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
7412 IDirect3DDevice7_Release(device);
7413 if (!(device_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP))
7415 skip("Cubemaps are not supported.\n");
7416 goto done;
7419 memset(&surface_desc, 0, sizeof(surface_desc));
7420 surface_desc.dwSize = sizeof(surface_desc);
7421 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7422 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_TEXTURE;
7423 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
7424 surface_desc.dwWidth = 128;
7425 surface_desc.dwHeight = 128;
7426 U5(surface_desc).dwBackBufferCount = 3;
7427 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
7428 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x.\n", hr);
7430 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_FLIP;
7431 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
7432 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
7433 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7435 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_COMPLEX;
7436 surface_desc.ddsCaps.dwCaps |= DDSCAPS_FLIP;
7437 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
7438 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x.\n", hr);
7440 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
7441 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
7442 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7444 U5(surface_desc).dwBackBufferCount = 1;
7445 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
7446 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7448 U5(surface_desc).dwBackBufferCount = 0;
7449 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
7450 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x.\n", hr);
7452 done:
7453 refcount = IDirectDraw7_Release(ddraw);
7454 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
7455 DestroyWindow(window);
7458 static void reset_ddsd(DDSURFACEDESC2 *ddsd)
7460 memset(ddsd, 0, sizeof(*ddsd));
7461 ddsd->dwSize = sizeof(*ddsd);
7464 static void test_set_surface_desc(void)
7466 IDirectDraw7 *ddraw;
7467 HWND window;
7468 HRESULT hr;
7469 DDSURFACEDESC2 ddsd;
7470 IDirectDrawSurface7 *surface;
7471 BYTE data[16*16*4];
7472 ULONG ref;
7473 unsigned int i;
7474 static const struct
7476 DWORD caps, caps2;
7477 BOOL supported;
7478 const char *name;
7480 invalid_caps_tests[] =
7482 {DDSCAPS_VIDEOMEMORY, 0, FALSE, "videomemory plain"},
7483 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, TRUE, "systemmemory texture"},
7484 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE, "managed texture"},
7485 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE, "managed texture"},
7486 {DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY, 0, FALSE, "systemmemory primary"},
7489 window = create_window();
7490 ddraw = create_ddraw();
7491 ok(!!ddraw, "Failed to create a ddraw object.\n");
7492 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7493 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7495 reset_ddsd(&ddsd);
7496 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
7497 ddsd.dwWidth = 8;
7498 ddsd.dwHeight = 8;
7499 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
7500 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
7501 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
7502 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7503 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7504 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7505 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
7507 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
7508 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7510 reset_ddsd(&ddsd);
7511 ddsd.dwFlags = DDSD_LPSURFACE;
7512 ddsd.lpSurface = data;
7513 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7514 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7516 /* Redundantly setting the same lpSurface is not an error. */
7517 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7518 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7520 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
7521 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7522 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
7523 ok(ddsd.lpSurface == NULL, "lpSurface is %p, expected NULL.\n", ddsd.lpSurface);
7525 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, 0, NULL);
7526 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7527 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
7528 ok(ddsd.lpSurface == data, "lpSurface is %p, expected %p.\n", data, data);
7529 hr = IDirectDrawSurface7_Unlock(surface, NULL);
7530 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7532 reset_ddsd(&ddsd);
7533 ddsd.dwFlags = DDSD_LPSURFACE;
7534 ddsd.lpSurface = data;
7535 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 1);
7536 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with flags=1 returned %#x.\n", hr);
7538 ddsd.lpSurface = NULL;
7539 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7540 ok(hr == DDERR_INVALIDPARAMS, "Setting lpSurface=NULL returned %#x.\n", hr);
7542 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, NULL, 0);
7543 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with NULL desc returned %#x.\n", hr);
7545 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
7546 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7547 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
7548 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
7549 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#x.\n", 0);
7551 /* Setting the caps is an error. This also means the original description cannot be reapplied. */
7552 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7553 ok(hr == DDERR_INVALIDPARAMS, "Setting the original desc returned %#x.\n", hr);
7555 ddsd.dwFlags = DDSD_CAPS;
7556 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7557 ok(hr == DDERR_INVALIDPARAMS, "Setting DDSD_CAPS returned %#x.\n", hr);
7559 /* dwCaps = 0 is allowed, but ignored. Caps2 can be anything and is ignored too. */
7560 ddsd.dwFlags = DDSD_CAPS | DDSD_LPSURFACE;
7561 ddsd.lpSurface = data;
7562 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7563 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
7564 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
7565 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7566 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
7567 ddsd.ddsCaps.dwCaps = 0;
7568 ddsd.ddsCaps.dwCaps2 = 0xdeadbeef;
7569 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7570 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7572 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
7573 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7574 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
7575 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
7576 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#x.\n", 0);
7578 /* Setting the height is allowed, but it cannot be set to 0, and only if LPSURFACE is set too. */
7579 reset_ddsd(&ddsd);
7580 ddsd.dwFlags = DDSD_HEIGHT;
7581 ddsd.dwHeight = 16;
7582 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7583 ok(hr == DDERR_INVALIDPARAMS, "Setting height without lpSurface returned %#x.\n", hr);
7585 ddsd.lpSurface = data;
7586 ddsd.dwFlags = DDSD_HEIGHT | DDSD_LPSURFACE;
7587 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7588 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7590 ddsd.dwHeight = 0;
7591 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7592 ok(hr == DDERR_INVALIDPARAMS, "Setting height=0 returned %#x.\n", hr);
7594 reset_ddsd(&ddsd);
7595 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
7596 ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr);
7597 ok(ddsd.dwWidth == 8, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
7598 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
7600 /* Pitch and width can be set, but only together, and only with LPSURFACE. They must not be 0. */
7601 reset_ddsd(&ddsd);
7602 ddsd.dwFlags = DDSD_PITCH;
7603 U1(ddsd).lPitch = 8 * 4;
7604 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7605 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch without lpSurface or width returned %#x.\n", hr);
7607 ddsd.dwFlags = DDSD_WIDTH;
7608 ddsd.dwWidth = 16;
7609 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7610 ok(hr == DDERR_INVALIDPARAMS, "Setting width without lpSurface or pitch returned %#x.\n", hr);
7612 ddsd.dwFlags = DDSD_PITCH | DDSD_LPSURFACE;
7613 ddsd.lpSurface = data;
7614 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7615 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch and lpSurface without width returned %#x.\n", hr);
7617 ddsd.dwFlags = DDSD_WIDTH | DDSD_LPSURFACE;
7618 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7619 ok(hr == DDERR_INVALIDPARAMS, "Setting width and lpSurface without pitch returned %#x.\n", hr);
7621 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
7622 U1(ddsd).lPitch = 16 * 4;
7623 ddsd.dwWidth = 16;
7624 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7625 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7627 reset_ddsd(&ddsd);
7628 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
7629 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7630 ok(ddsd.dwWidth == 16, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
7631 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
7632 ok(U1(ddsd).lPitch == 16 * 4, "SetSurfaceDesc: Expected pitch 64, got %u.\n", U1(ddsd).lPitch);
7634 /* The pitch must be 32 bit aligned and > 0, but is not verified for sanity otherwise.
7636 * VMware rejects those calls, but all real drivers accept it. Mark the VMware behavior broken. */
7637 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
7638 U1(ddsd).lPitch = 4 * 4;
7639 ddsd.lpSurface = data;
7640 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7641 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
7643 U1(ddsd).lPitch = 4;
7644 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7645 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
7647 U1(ddsd).lPitch = 16 * 4 + 1;
7648 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7649 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
7651 U1(ddsd).lPitch = 16 * 4 + 3;
7652 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7653 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
7655 U1(ddsd).lPitch = -4;
7656 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7657 ok(hr == DDERR_INVALIDPARAMS, "Setting negative pitch returned %#x.\n", hr);
7659 U1(ddsd).lPitch = 16 * 4;
7660 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7661 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7663 reset_ddsd(&ddsd);
7664 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
7665 U1(ddsd).lPitch = 0;
7666 ddsd.dwWidth = 16;
7667 ddsd.lpSurface = data;
7668 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7669 ok(hr == DDERR_INVALIDPARAMS, "Setting zero pitch returned %#x.\n", hr);
7671 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
7672 U1(ddsd).lPitch = 16 * 4;
7673 ddsd.dwWidth = 0;
7674 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7675 ok(hr == DDERR_INVALIDPARAMS, "Setting zero width returned %#x.\n", hr);
7677 /* Setting the pixelformat without LPSURFACE is an error, but with LPSURFACE it works. */
7678 ddsd.dwFlags = DDSD_PIXELFORMAT;
7679 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
7680 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
7681 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
7682 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7683 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7684 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7685 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7686 ok(hr == DDERR_INVALIDPARAMS, "Setting the pixel format returned %#x.\n", hr);
7688 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_LPSURFACE;
7689 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7690 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7692 /* Can't set color keys. */
7693 reset_ddsd(&ddsd);
7694 ddsd.dwFlags = DDSD_CKSRCBLT;
7695 ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff0000;
7696 ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff0000;
7697 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7698 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
7700 ddsd.dwFlags = DDSD_CKSRCBLT | DDSD_LPSURFACE;
7701 ddsd.lpSurface = data;
7702 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7703 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
7705 IDirectDrawSurface7_Release(surface);
7707 /* Test mipmap texture. */
7708 reset_ddsd(&ddsd);
7709 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_MIPMAPCOUNT;
7710 ddsd.dwWidth = 8;
7711 ddsd.dwHeight = 8;
7712 U2(ddsd).dwMipMapCount = 3;
7713 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7715 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
7716 ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWHW || hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
7718 if (FAILED(hr))
7720 skip("Mipmaps are not supported.\n");
7722 else
7724 /* Changing surface desc for mipmap fails even without changing any
7725 * parameters. */
7726 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7727 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x.\n", hr);
7729 reset_ddsd(&ddsd);
7730 ddsd.dwFlags = DDSD_LPSURFACE;
7731 ddsd.lpSurface = data;
7732 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7733 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x.\n", hr);
7734 IDirectDrawSurface7_Release(surface);
7737 reset_ddsd(&ddsd);
7738 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_MIPMAPCOUNT;
7739 ddsd.dwWidth = 8;
7740 ddsd.dwHeight = 8;
7741 U2(ddsd).dwMipMapCount = 3;
7742 ddsd.lpSurface = data;
7743 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7745 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
7746 ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWHW || hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
7748 if (hr == DD_OK)
7750 static DDSCAPS2 caps = {DDSCAPS_TEXTURE, 0, 0, {0}};
7751 void *surface2_system_mem;
7752 IDirectDrawSurface7 *surface2;
7754 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &surface2);
7755 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7756 reset_ddsd(&ddsd);
7757 hr = IDirectDrawSurface7_GetSurfaceDesc(surface2, &ddsd);
7758 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7759 ok(ddsd.dwWidth == 4, "Got unexpected dwWidth %u.\n", ddsd.dwWidth);
7761 hr = IDirectDrawSurface7_Lock(surface2, NULL, &ddsd, 0, NULL);
7762 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7763 surface2_system_mem = ddsd.lpSurface;
7764 IDirectDrawSurface7_Unlock(surface2, NULL);
7766 reset_ddsd(&ddsd);
7767 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_LPSURFACE;
7768 ddsd.dwWidth = 16;
7769 ddsd.dwHeight = 16;
7770 U1(ddsd).lPitch = 16 * 4;
7771 ddsd.lpSurface = data;
7772 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7773 todo_wine ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7775 reset_ddsd(&ddsd);
7776 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_LPSURFACE;
7777 ddsd.dwWidth = 8;
7778 ddsd.dwHeight = 8;
7779 U1(ddsd).lPitch = 8 * 4;
7780 ddsd.lpSurface = data;
7781 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7782 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7784 reset_ddsd(&ddsd);
7785 hr = IDirectDrawSurface7_Lock(surface2, NULL, &ddsd, 0, NULL);
7786 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7787 ok(ddsd.lpSurface == surface2_system_mem, "Got unexpected lpSurface %p.\n", ddsd.lpSurface);
7788 IDirectDrawSurface7_Unlock(surface2, NULL);
7790 reset_ddsd(&ddsd);
7791 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_LPSURFACE;
7792 ddsd.dwWidth = 4;
7793 ddsd.dwHeight = 4;
7794 U1(ddsd).lPitch = 4 * 4;
7795 ddsd.lpSurface = data;
7796 hr = IDirectDrawSurface7_SetSurfaceDesc(surface2, &ddsd, 0);
7797 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7799 reset_ddsd(&ddsd);
7800 hr = IDirectDrawSurface7_Lock(surface2, NULL, &ddsd, 0, NULL);
7801 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7802 ok(ddsd.lpSurface == data, "Got unexpected lpSurface %p.\n", ddsd.lpSurface);
7803 IDirectDrawSurface7_Unlock(surface2, NULL);
7805 reset_ddsd(&ddsd);
7806 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_LPSURFACE;
7807 ddsd.dwWidth = 16;
7808 ddsd.dwHeight = 16;
7809 U1(ddsd).lPitch = 16 * 4;
7810 ddsd.lpSurface = data;
7811 hr = IDirectDrawSurface7_SetSurfaceDesc(surface2, &ddsd, 0);
7812 todo_wine ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7814 IDirectDrawSurface7_Release(surface2);
7815 IDirectDrawSurface7_Release(surface);
7818 /* Test surface created with DDSD_LPSURFACE. */
7819 reset_ddsd(&ddsd);
7820 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LPSURFACE | DDSD_PITCH;
7821 ddsd.dwWidth = 8;
7822 ddsd.dwHeight = 8;
7823 ddsd.lpSurface = data;
7824 U1(ddsd).lPitch = 8 * 4;
7825 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
7826 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
7827 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7829 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7830 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x.\n", hr);
7832 reset_ddsd(&ddsd);
7833 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
7834 ddsd.dwWidth = 8;
7835 ddsd.dwHeight = 8;
7836 /* Cannot reset lpSurface. */
7837 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7838 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7840 reset_ddsd(&ddsd);
7841 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_LPSURFACE | DDSD_PITCH;
7842 ddsd.dwWidth = 4;
7843 ddsd.dwHeight = 4;
7844 ddsd.lpSurface = data;
7845 U1(ddsd).lPitch = 8 * 4;
7846 /* Can change the parameters of surface created with DDSD_LPSURFACE. */
7847 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7848 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7850 IDirectDrawSurface7_Release(surface);
7852 /* SetSurfaceDesc needs systemmemory surfaces.
7854 * As a sidenote, fourcc surfaces aren't allowed in sysmem, thus testing
7855 * DDSD_LINEARSIZE is moot. */
7856 for (i = 0; i < ARRAY_SIZE(invalid_caps_tests); ++i)
7858 reset_ddsd(&ddsd);
7859 ddsd.dwFlags = DDSD_CAPS;
7860 ddsd.ddsCaps.dwCaps = invalid_caps_tests[i].caps;
7861 ddsd.ddsCaps.dwCaps2 = invalid_caps_tests[i].caps2;
7862 if (!(invalid_caps_tests[i].caps & DDSCAPS_PRIMARYSURFACE))
7864 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7865 ddsd.dwWidth = 8;
7866 ddsd.dwHeight = 8;
7867 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
7868 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
7869 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
7870 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7871 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7872 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7875 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
7876 if (is_ddraw64 && (invalid_caps_tests[i].caps & DDSCAPS_TEXTURE))
7877 todo_wine ok(hr == E_NOINTERFACE, "Test %u: Got unexpected hr %#x.\n", i, hr);
7878 else
7879 ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWHW, "Test %u: Got unexpected hr %#x.\n", i, hr);
7880 if (FAILED(hr))
7881 continue;
7883 reset_ddsd(&ddsd);
7884 ddsd.dwFlags = DDSD_LPSURFACE;
7885 ddsd.lpSurface = data;
7886 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7887 if (invalid_caps_tests[i].supported)
7889 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7891 else
7893 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
7894 invalid_caps_tests[i].name, hr);
7896 /* Check priority of error conditions. */
7897 ddsd.dwFlags = DDSD_WIDTH;
7898 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7899 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
7900 invalid_caps_tests[i].name, hr);
7903 IDirectDrawSurface7_Release(surface);
7906 ref = IDirectDraw7_Release(ddraw);
7907 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
7908 DestroyWindow(window);
7911 static void test_user_memory_getdc(void)
7913 IDirectDraw7 *ddraw;
7914 HWND window;
7915 HRESULT hr;
7916 DDSURFACEDESC2 ddsd;
7917 IDirectDrawSurface7 *surface;
7918 DWORD data[16][16];
7919 HGDIOBJ *bitmap;
7920 DIBSECTION dib;
7921 ULONG ref;
7922 int size;
7923 HDC dc;
7924 unsigned int x, y;
7926 window = create_window();
7927 ddraw = create_ddraw();
7928 ok(!!ddraw, "Failed to create a ddraw object.\n");
7929 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7930 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7932 reset_ddsd(&ddsd);
7933 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
7934 ddsd.dwWidth = 16;
7935 ddsd.dwHeight = 16;
7936 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
7937 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
7938 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
7939 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7940 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7941 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7942 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
7943 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
7944 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7946 memset(data, 0xaa, sizeof(data));
7947 reset_ddsd(&ddsd);
7948 ddsd.dwFlags = DDSD_LPSURFACE;
7949 ddsd.lpSurface = data;
7950 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7951 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7953 hr = IDirectDrawSurface7_GetDC(surface, &dc);
7954 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7955 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
7956 ok(!!bitmap, "Failed to get bitmap.\n");
7957 size = GetObjectA(bitmap, sizeof(dib), &dib);
7958 ok(size == sizeof(dib), "Got unexpected size %d.\n", size);
7959 ok(dib.dsBm.bmBits == data, "Got unexpected bits %p, expected %p.\n", dib.dsBm.bmBits, data);
7960 BitBlt(dc, 0, 0, 16, 8, NULL, 0, 0, WHITENESS);
7961 BitBlt(dc, 0, 8, 16, 8, NULL, 0, 0, BLACKNESS);
7962 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
7963 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7965 ok(data[0][0] == 0xffffffff, "Expected color 0xffffffff, got %#x.\n", data[0][0]);
7966 ok(data[15][15] == 0x00000000, "Expected color 0x00000000, got %#x.\n", data[15][15]);
7968 ddsd.dwFlags = DDSD_LPSURFACE | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH;
7969 ddsd.lpSurface = data;
7970 ddsd.dwWidth = 4;
7971 ddsd.dwHeight = 8;
7972 U1(ddsd).lPitch = sizeof(*data);
7973 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7974 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7976 memset(data, 0xaa, sizeof(data));
7977 hr = IDirectDrawSurface7_GetDC(surface, &dc);
7978 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7979 BitBlt(dc, 0, 0, 4, 8, NULL, 0, 0, BLACKNESS);
7980 BitBlt(dc, 1, 1, 2, 2, NULL, 0, 0, WHITENESS);
7981 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
7982 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7984 for (y = 0; y < 4; y++)
7986 for (x = 0; x < 4; x++)
7988 if ((x == 1 || x == 2) && (y == 1 || y == 2))
7989 ok(data[y][x] == 0xffffffff, "Expected color 0xffffffff on position %ux%u, got %#x.\n",
7990 x, y, data[y][x]);
7991 else
7992 ok(data[y][x] == 0x00000000, "Expected color 0x00000000 on position %ux%u, got %#x.\n",
7993 x, y, data[y][x]);
7996 ok(data[0][5] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 5x0, got %#x.\n",
7997 data[0][5]);
7998 ok(data[7][3] == 0x00000000, "Expected color 0x00000000 on position 3x7, got %#x.\n",
7999 data[7][3]);
8000 ok(data[7][4] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 4x7, got %#x.\n",
8001 data[7][4]);
8002 ok(data[8][0] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 0x8, got %#x.\n",
8003 data[8][0]);
8005 IDirectDrawSurface7_Release(surface);
8006 ref = IDirectDraw7_Release(ddraw);
8007 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
8008 DestroyWindow(window);
8011 static void test_sysmem_overlay(void)
8013 IDirectDraw7 *ddraw;
8014 HWND window;
8015 HRESULT hr;
8016 DDSURFACEDESC2 ddsd;
8017 IDirectDrawSurface7 *surface;
8018 ULONG ref;
8020 window = create_window();
8021 ddraw = create_ddraw();
8022 ok(!!ddraw, "Failed to create a ddraw object.\n");
8023 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8024 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8026 reset_ddsd(&ddsd);
8027 ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
8028 ddsd.dwWidth = 16;
8029 ddsd.dwHeight = 16;
8030 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OVERLAY;
8031 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
8032 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
8033 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
8034 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8035 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8036 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
8037 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
8038 ok(hr == DDERR_NOOVERLAYHW, "Got unexpected hr %#x.\n", hr);
8040 ref = IDirectDraw7_Release(ddraw);
8041 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
8042 DestroyWindow(window);
8045 static void test_primary_palette(void)
8047 DDSCAPS2 surface_caps = {DDSCAPS_FLIP, 0, 0, {0}};
8048 IDirectDrawSurface7 *primary, *backbuffer;
8049 PALETTEENTRY palette_entries[256];
8050 IDirectDrawPalette *palette, *tmp;
8051 DDSURFACEDESC2 surface_desc;
8052 IDirectDraw7 *ddraw;
8053 DWORD palette_caps;
8054 ULONG refcount;
8055 HWND window;
8056 HRESULT hr;
8058 window = create_window();
8059 ddraw = create_ddraw();
8060 ok(!!ddraw, "Failed to create a ddraw object.\n");
8061 if (FAILED(IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
8063 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
8064 IDirectDraw7_Release(ddraw);
8065 DestroyWindow(window);
8066 return;
8068 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8069 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8071 memset(&surface_desc, 0, sizeof(surface_desc));
8072 surface_desc.dwSize = sizeof(surface_desc);
8073 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
8074 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
8075 U5(surface_desc).dwBackBufferCount = 1;
8076 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
8077 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8078 hr = IDirectDrawSurface7_GetAttachedSurface(primary, &surface_caps, &backbuffer);
8079 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
8081 memset(palette_entries, 0, sizeof(palette_entries));
8082 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_entries, &palette, NULL);
8083 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
8084 refcount = get_refcount((IUnknown *)palette);
8085 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
8087 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
8088 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
8089 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
8091 hr = IDirectDrawSurface7_SetPalette(primary, palette);
8092 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8094 /* The Windows 8 testbot attaches the palette to the backbuffer as well,
8095 * and is generally somewhat broken with respect to 8 bpp / palette
8096 * handling. */
8097 if (SUCCEEDED(IDirectDrawSurface7_GetPalette(backbuffer, &tmp)))
8099 win_skip("Broken palette handling detected, skipping tests.\n");
8100 IDirectDrawPalette_Release(tmp);
8101 IDirectDrawPalette_Release(palette);
8102 /* The Windows 8 testbot keeps extra references to the primary and
8103 * backbuffer while in 8 bpp mode. */
8104 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
8105 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
8106 goto done;
8109 refcount = get_refcount((IUnknown *)palette);
8110 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
8112 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
8113 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
8114 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE | DDPCAPS_ALLOW256),
8115 "Got unexpected palette caps %#x.\n", palette_caps);
8117 hr = IDirectDrawSurface7_SetPalette(primary, NULL);
8118 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8119 refcount = get_refcount((IUnknown *)palette);
8120 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
8122 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
8123 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
8124 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
8126 hr = IDirectDrawSurface7_SetPalette(primary, palette);
8127 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
8128 refcount = get_refcount((IUnknown *)palette);
8129 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
8131 hr = IDirectDrawSurface7_GetPalette(primary, &tmp);
8132 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
8133 ok(tmp == palette, "Got unexpected palette %p, expected %p.\n", tmp, palette);
8134 IDirectDrawPalette_Release(tmp);
8135 hr = IDirectDrawSurface7_GetPalette(backbuffer, &tmp);
8136 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
8138 refcount = IDirectDrawPalette_Release(palette);
8139 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
8140 refcount = IDirectDrawPalette_Release(palette);
8141 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8143 /* Note that this only seems to work when the palette is attached to the
8144 * primary surface. When attached to a regular surface, attempting to get
8145 * the palette here will cause an access violation. */
8146 hr = IDirectDrawSurface7_GetPalette(primary, &tmp);
8147 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
8149 hr = IDirectDrawSurface7_IsLost(primary);
8150 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8152 memset(&surface_desc, 0, sizeof(surface_desc));
8153 surface_desc.dwSize = sizeof(surface_desc);
8154 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &surface_desc);
8155 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8156 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
8157 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
8158 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 8, "Got unexpected bit count %u.\n",
8159 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
8161 hr = set_display_mode(ddraw, 640, 480);
8162 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
8164 memset(&surface_desc, 0, sizeof(surface_desc));
8165 surface_desc.dwSize = sizeof(surface_desc);
8166 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &surface_desc);
8167 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8168 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
8169 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
8170 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 32
8171 || U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 24,
8172 "Got unexpected bit count %u.\n", U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
8174 hr = IDirectDrawSurface7_IsLost(primary);
8175 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8176 hr = IDirectDrawSurface7_Restore(primary);
8177 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
8178 hr = IDirectDrawSurface7_IsLost(primary);
8179 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8181 memset(&surface_desc, 0, sizeof(surface_desc));
8182 surface_desc.dwSize = sizeof(surface_desc);
8183 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &surface_desc);
8184 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8185 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
8186 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
8187 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 32
8188 || U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 24,
8189 "Got unexpected bit count %u.\n", U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
8191 done:
8192 refcount = IDirectDrawSurface7_Release(backbuffer);
8193 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
8194 refcount = IDirectDrawSurface7_Release(primary);
8195 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8196 refcount = IDirectDraw7_Release(ddraw);
8197 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8198 DestroyWindow(window);
8201 static HRESULT WINAPI surface_counter(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
8203 UINT *surface_count = context;
8205 ++(*surface_count);
8206 IDirectDrawSurface_Release(surface);
8208 return DDENUMRET_OK;
8211 static void test_surface_attachment(void)
8213 IDirectDrawSurface7 *surface1, *surface2, *surface3, *surface4;
8214 IDirectDrawSurface *surface1v1, *surface2v1;
8215 DDSCAPS2 caps = {DDSCAPS_TEXTURE, 0, 0, {0}};
8216 DDSURFACEDESC2 surface_desc;
8217 IDirectDraw7 *ddraw;
8218 UINT surface_count;
8219 ULONG refcount;
8220 HWND window;
8221 HRESULT hr;
8223 window = create_window();
8224 ddraw = create_ddraw();
8225 ok(!!ddraw, "Failed to create a ddraw object.\n");
8226 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8227 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8229 memset(&surface_desc, 0, sizeof(surface_desc));
8230 surface_desc.dwSize = sizeof(surface_desc);
8231 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
8232 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
8233 U2(surface_desc).dwMipMapCount = 3;
8234 surface_desc.dwWidth = 128;
8235 surface_desc.dwHeight = 128;
8236 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL)))
8238 skip("Failed to create a texture, skipping tests.\n");
8239 IDirectDraw7_Release(ddraw);
8240 DestroyWindow(window);
8241 return;
8244 hr = IDirectDrawSurface7_GetAttachedSurface(surface1, &caps, &surface2);
8245 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
8246 hr = IDirectDrawSurface7_GetAttachedSurface(surface2, &caps, &surface3);
8247 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
8248 hr = IDirectDrawSurface7_GetAttachedSurface(surface3, &caps, &surface4);
8249 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
8251 surface_count = 0;
8252 IDirectDrawSurface7_EnumAttachedSurfaces(surface1, &surface_count, surface_counter);
8253 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
8254 surface_count = 0;
8255 IDirectDrawSurface7_EnumAttachedSurfaces(surface2, &surface_count, surface_counter);
8256 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
8257 surface_count = 0;
8258 IDirectDrawSurface7_EnumAttachedSurfaces(surface3, &surface_count, surface_counter);
8259 ok(!surface_count, "Got unexpected surface_count %u.\n", surface_count);
8261 memset(&surface_desc, 0, sizeof(surface_desc));
8262 surface_desc.dwSize = sizeof(surface_desc);
8263 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8264 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
8265 surface_desc.dwWidth = 16;
8266 surface_desc.dwHeight = 16;
8267 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
8268 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8270 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
8271 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8272 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
8273 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8274 hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface4);
8275 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8276 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface3);
8277 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8278 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface4);
8279 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8280 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface2);
8281 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8283 IDirectDrawSurface7_Release(surface4);
8285 memset(&surface_desc, 0, sizeof(surface_desc));
8286 surface_desc.dwSize = sizeof(surface_desc);
8287 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8288 surface_desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
8289 surface_desc.dwWidth = 16;
8290 surface_desc.dwHeight = 16;
8291 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
8292 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8294 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
8295 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8296 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
8297 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8298 hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface4);
8299 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8300 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface3);
8301 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8302 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface4);
8303 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8304 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface2);
8305 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8307 IDirectDrawSurface7_Release(surface4);
8308 IDirectDrawSurface7_Release(surface3);
8309 IDirectDrawSurface7_Release(surface2);
8310 IDirectDrawSurface7_Release(surface1);
8312 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8313 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8315 /* Try a single primary and two offscreen plain surfaces. */
8316 memset(&surface_desc, 0, sizeof(surface_desc));
8317 surface_desc.dwSize = sizeof(surface_desc);
8318 surface_desc.dwFlags = DDSD_CAPS;
8319 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8320 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
8321 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8323 memset(&surface_desc, 0, sizeof(surface_desc));
8324 surface_desc.dwSize = sizeof(surface_desc);
8325 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8326 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8327 surface_desc.dwWidth = registry_mode.dmPelsWidth;
8328 surface_desc.dwHeight = registry_mode.dmPelsHeight;
8329 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
8330 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8332 memset(&surface_desc, 0, sizeof(surface_desc));
8333 surface_desc.dwSize = sizeof(surface_desc);
8334 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8335 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8336 surface_desc.dwWidth = registry_mode.dmPelsWidth;
8337 surface_desc.dwHeight = registry_mode.dmPelsHeight;
8338 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
8339 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8341 /* This one has a different size. */
8342 memset(&surface_desc, 0, sizeof(surface_desc));
8343 surface_desc.dwSize = sizeof(surface_desc);
8344 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8345 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8346 surface_desc.dwWidth = 128;
8347 surface_desc.dwHeight = 128;
8348 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
8349 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8351 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
8352 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8353 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface1);
8354 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8355 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface3);
8356 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8357 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
8358 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8359 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
8360 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8362 IDirectDrawSurface7_Release(surface4);
8363 IDirectDrawSurface7_Release(surface3);
8364 IDirectDrawSurface7_Release(surface2);
8365 IDirectDrawSurface7_Release(surface1);
8367 /* Test depth surfaces of different sizes. */
8368 memset(&surface_desc, 0, sizeof(surface_desc));
8369 surface_desc.dwSize = sizeof(surface_desc);
8370 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8371 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
8372 surface_desc.dwWidth = 64;
8373 surface_desc.dwHeight = 64;
8374 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
8375 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
8377 memset(&surface_desc, 0, sizeof(surface_desc));
8378 surface_desc.dwSize = sizeof(surface_desc);
8379 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
8380 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
8381 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8382 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
8383 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = 16;
8384 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = 0x0000ffff;
8385 surface_desc.dwWidth = 32;
8386 surface_desc.dwHeight = 32;
8387 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
8388 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
8389 surface_desc.dwWidth = 64;
8390 surface_desc.dwHeight = 64;
8391 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
8392 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
8393 surface_desc.dwWidth = 128;
8394 surface_desc.dwHeight = 128;
8395 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
8396 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
8398 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
8399 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8400 if (SUCCEEDED(hr))
8401 IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface2);
8402 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface3);
8403 ok(hr == D3D_OK, "Failed to attach depth buffer, hr %#x.\n", hr);
8404 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface3);
8405 ok(hr == D3D_OK, "Failed to detach depth buffer, hr %#x.\n", hr);
8406 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
8407 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8409 IDirectDrawSurface7_Release(surface4);
8410 IDirectDrawSurface7_Release(surface3);
8411 IDirectDrawSurface7_Release(surface2);
8412 IDirectDrawSurface7_Release(surface1);
8414 /* Test DeleteAttachedSurface() and automatic detachment of attached surfaces on release. */
8415 memset(&surface_desc, 0, sizeof(surface_desc));
8416 surface_desc.dwSize = sizeof(surface_desc);
8417 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
8418 surface_desc.dwWidth = 64;
8419 surface_desc.dwHeight = 64;
8420 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
8421 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8422 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
8423 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
8424 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
8425 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
8426 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
8427 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
8428 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8429 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
8430 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8432 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
8433 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
8434 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = 16;
8435 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = 0x0000ffff;
8436 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
8437 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8439 hr = IDirectDrawSurface7_QueryInterface(surface1, &IID_IDirectDrawSurface, (void **)&surface1v1);
8440 ok(SUCCEEDED(hr), "Failed to get interface, hr %#x.\n", hr);
8441 hr = IDirectDrawSurface7_QueryInterface(surface2, &IID_IDirectDrawSurface, (void **)&surface2v1);
8442 ok(SUCCEEDED(hr), "Failed to get interface, hr %#x.\n", hr);
8444 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
8445 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
8446 refcount = get_refcount((IUnknown *)surface2);
8447 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
8448 refcount = get_refcount((IUnknown *)surface2v1);
8449 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
8450 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
8451 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
8452 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
8453 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8454 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
8455 ok(hr == DDERR_SURFACENOTATTACHED, "Got unexpected hr %#x.\n", hr);
8457 /* Attaching while already attached to other surface. */
8458 hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface2);
8459 todo_wine ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
8460 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface3, 0, surface2);
8461 todo_wine ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
8462 IDirectDrawSurface7_Release(surface3);
8464 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface2);
8465 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
8466 refcount = get_refcount((IUnknown *)surface2);
8467 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
8468 refcount = get_refcount((IUnknown *)surface2v1);
8469 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
8471 /* DeleteAttachedSurface() when attaching via IDirectDrawSurface. */
8472 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
8473 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
8474 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface2);
8475 ok(hr == DDERR_SURFACENOTATTACHED, "Got unexpected hr %#x.\n", hr);
8476 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
8477 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
8478 refcount = IDirectDrawSurface7_Release(surface2);
8479 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8480 refcount = IDirectDrawSurface7_Release(surface1);
8481 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8483 /* Automatic detachment on release. */
8484 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
8485 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
8486 refcount = get_refcount((IUnknown *)surface2v1);
8487 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
8488 refcount = IDirectDrawSurface_Release(surface1v1);
8489 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8490 refcount = IDirectDrawSurface_Release(surface2v1);
8491 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8492 refcount = IDirectDraw7_Release(ddraw);
8493 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8494 DestroyWindow(window);
8497 static void test_private_data(void)
8499 IDirectDraw7 *ddraw;
8500 IDirectDrawSurface7 *surface, *surface2;
8501 DDSURFACEDESC2 surface_desc;
8502 ULONG refcount, refcount2, refcount3;
8503 IUnknown *ptr;
8504 DWORD size = sizeof(ptr);
8505 HRESULT hr;
8506 HWND window;
8507 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
8508 DWORD data[] = {1, 2, 3, 4};
8509 DDCAPS hal_caps;
8510 static const GUID ddraw_private_data_test_guid =
8512 0xfdb37466,
8513 0x428f,
8514 0x4edf,
8515 {0xa3,0x7f,0x9b,0x1d,0xf4,0x88,0xc5,0xfc}
8517 static const GUID ddraw_private_data_test_guid2 =
8519 0x2e5afac2,
8520 0x87b5,
8521 0x4c10,
8522 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
8525 window = create_window();
8526 ddraw = create_ddraw();
8527 ok(!!ddraw, "Failed to create a ddraw object.\n");
8528 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8529 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8531 reset_ddsd(&surface_desc);
8532 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
8533 surface_desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
8534 surface_desc.dwHeight = 4;
8535 surface_desc.dwWidth = 4;
8536 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8537 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8539 /* NULL pointers are not valid, but don't cause a crash. */
8540 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL,
8541 sizeof(IUnknown *), DDSPD_IUNKNOWNPOINTER);
8542 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8543 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL, 0, 0);
8544 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8545 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL, 1, 0);
8546 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8548 /* DDSPD_IUNKNOWNPOINTER needs sizeof(IUnknown *) bytes of data. */
8549 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
8550 0, DDSPD_IUNKNOWNPOINTER);
8551 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8552 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
8553 5, DDSPD_IUNKNOWNPOINTER);
8554 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8555 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
8556 sizeof(ddraw) * 2, DDSPD_IUNKNOWNPOINTER);
8557 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8559 /* Note that with a size != 0 and size != sizeof(IUnknown *) and
8560 * DDSPD_IUNKNOWNPOINTER set SetPrivateData in ddraw4 and ddraw7
8561 * erases the old content and returns an error. This behavior has
8562 * been fixed in d3d8 and d3d9. Unless an application is found
8563 * that depends on this we don't care about this behavior. */
8564 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
8565 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
8566 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
8567 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
8568 0, DDSPD_IUNKNOWNPOINTER);
8569 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8570 size = sizeof(ptr);
8571 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
8572 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
8573 hr = IDirectDrawSurface7_FreePrivateData(surface, &ddraw_private_data_test_guid);
8574 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
8576 refcount = get_refcount((IUnknown *)ddraw);
8577 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
8578 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
8579 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
8580 refcount2 = get_refcount((IUnknown *)ddraw);
8581 ok(refcount2 == refcount + 1, "Got unexpected refcount %u.\n", refcount2);
8583 hr = IDirectDrawSurface7_FreePrivateData(surface, &ddraw_private_data_test_guid);
8584 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
8585 refcount2 = get_refcount((IUnknown *)ddraw);
8586 ok(refcount2 == refcount, "Got unexpected refcount %u.\n", refcount2);
8588 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
8589 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
8590 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
8591 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, surface,
8592 sizeof(surface), DDSPD_IUNKNOWNPOINTER);
8593 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
8594 refcount2 = get_refcount((IUnknown *)ddraw);
8595 ok(refcount2 == refcount, "Got unexpected refcount %u.\n", refcount2);
8597 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
8598 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
8599 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
8600 size = 2 * sizeof(ptr);
8601 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
8602 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
8603 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
8604 refcount2 = get_refcount(ptr);
8605 /* Object is NOT addref'ed by the getter. */
8606 ok(ptr == (IUnknown *)ddraw, "Returned interface pointer is %p, expected %p.\n", ptr, ddraw);
8607 ok(refcount2 == refcount + 1, "Got unexpected refcount %u.\n", refcount2);
8609 ptr = (IUnknown *)0xdeadbeef;
8610 size = 1;
8611 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, &size);
8612 ok(hr == DDERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
8613 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
8614 size = 2 * sizeof(ptr);
8615 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, &size);
8616 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8617 ok(size == 2 * sizeof(ptr), "Got unexpected size %u.\n", size);
8618 size = 1;
8619 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
8620 ok(hr == DDERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
8621 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
8622 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
8623 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid2, NULL, NULL);
8624 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
8625 size = 0xdeadbabe;
8626 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid2, &ptr, &size);
8627 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
8628 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
8629 ok(size == 0xdeadbabe, "Got unexpected size %u.\n", size);
8630 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, NULL);
8631 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8633 refcount3 = IDirectDrawSurface7_Release(surface);
8634 ok(!refcount3, "Got unexpected refcount %u.\n", refcount3);
8636 /* Destroying the surface frees the reference held on the private data. It also frees
8637 * the reference the surface is holding on its creating object. */
8638 refcount2 = get_refcount((IUnknown *)ddraw);
8639 ok(refcount2 == refcount - 1, "Got unexpected refcount %u.\n", refcount2);
8641 memset(&hal_caps, 0, sizeof(hal_caps));
8642 hal_caps.dwSize = sizeof(hal_caps);
8643 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
8644 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8645 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) == (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)
8646 && !is_ddraw64)
8648 reset_ddsd(&surface_desc);
8649 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_MIPMAPCOUNT;
8650 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
8651 surface_desc.dwHeight = 4;
8652 surface_desc.dwWidth = 4;
8653 U2(surface_desc).dwMipMapCount = 2;
8654 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8655 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8656 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &surface2);
8657 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
8659 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, data, sizeof(data), 0);
8660 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
8661 hr = IDirectDrawSurface7_GetPrivateData(surface2, &ddraw_private_data_test_guid, NULL, NULL);
8662 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
8664 IDirectDrawSurface7_Release(surface2);
8665 IDirectDrawSurface7_Release(surface);
8667 else
8668 skip("Mipmapped textures not supported, skipping mipmap private data test.\n");
8670 refcount = IDirectDraw7_Release(ddraw);
8671 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8672 DestroyWindow(window);
8675 static void test_pixel_format(void)
8677 HWND window, window2 = NULL;
8678 HDC hdc, hdc2 = NULL;
8679 HMODULE gl = NULL;
8680 int format, test_format;
8681 PIXELFORMATDESCRIPTOR pfd;
8682 IDirectDraw7 *ddraw = NULL;
8683 IDirectDrawClipper *clipper = NULL;
8684 DDSURFACEDESC2 ddsd;
8685 IDirectDrawSurface7 *primary = NULL, *offscreen;
8686 DDBLTFX fx;
8687 HRESULT hr;
8689 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
8690 100, 100, 160, 160, NULL, NULL, NULL, NULL);
8691 if (!window)
8693 skip("Failed to create window\n");
8694 return;
8697 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
8698 100, 100, 160, 160, NULL, NULL, NULL, NULL);
8700 hdc = GetDC(window);
8701 if (!hdc)
8703 skip("Failed to get DC\n");
8704 goto cleanup;
8707 if (window2)
8708 hdc2 = GetDC(window2);
8710 gl = LoadLibraryA("opengl32.dll");
8711 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
8713 format = GetPixelFormat(hdc);
8714 ok(format == 0, "new window has pixel format %d\n", format);
8716 ZeroMemory(&pfd, sizeof(pfd));
8717 pfd.nSize = sizeof(pfd);
8718 pfd.nVersion = 1;
8719 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
8720 pfd.iPixelType = PFD_TYPE_RGBA;
8721 pfd.iLayerType = PFD_MAIN_PLANE;
8722 format = ChoosePixelFormat(hdc, &pfd);
8723 if (format <= 0)
8725 skip("no pixel format available\n");
8726 goto cleanup;
8729 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
8731 skip("failed to set pixel format\n");
8732 goto cleanup;
8735 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
8737 skip("failed to set pixel format on second window\n");
8738 if (hdc2)
8740 ReleaseDC(window2, hdc2);
8741 hdc2 = NULL;
8745 ddraw = create_ddraw();
8746 ok(!!ddraw, "Failed to create a ddraw object.\n");
8748 test_format = GetPixelFormat(hdc);
8749 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8751 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8752 if (FAILED(hr))
8754 skip("Failed to set cooperative level, hr %#x.\n", hr);
8755 goto cleanup;
8758 test_format = GetPixelFormat(hdc);
8759 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8761 if (hdc2)
8763 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
8764 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
8765 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window2);
8766 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
8768 test_format = GetPixelFormat(hdc);
8769 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8771 test_format = GetPixelFormat(hdc2);
8772 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
8775 memset(&ddsd, 0, sizeof(ddsd));
8776 ddsd.dwSize = sizeof(ddsd);
8777 ddsd.dwFlags = DDSD_CAPS;
8778 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8780 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
8781 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
8783 test_format = GetPixelFormat(hdc);
8784 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8786 if (hdc2)
8788 test_format = GetPixelFormat(hdc2);
8789 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
8792 if (clipper)
8794 hr = IDirectDrawSurface7_SetClipper(primary, clipper);
8795 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
8797 test_format = GetPixelFormat(hdc);
8798 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8800 test_format = GetPixelFormat(hdc2);
8801 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
8804 memset(&ddsd, 0, sizeof(ddsd));
8805 ddsd.dwSize = sizeof(ddsd);
8806 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8807 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8808 ddsd.dwWidth = ddsd.dwHeight = 64;
8809 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &offscreen, NULL);
8810 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
8812 memset(&fx, 0, sizeof(fx));
8813 fx.dwSize = sizeof(fx);
8814 hr = IDirectDrawSurface7_Blt(offscreen, NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &fx);
8815 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
8817 test_format = GetPixelFormat(hdc);
8818 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8820 hr = IDirectDrawSurface7_Blt(primary, NULL, offscreen, NULL, DDBLT_WAIT, NULL);
8821 ok(SUCCEEDED(hr), "Failed to blit to primary surface, hr %#x.\n", hr);
8823 test_format = GetPixelFormat(hdc);
8824 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8826 if (hdc2)
8828 test_format = GetPixelFormat(hdc2);
8829 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
8832 IDirectDrawSurface7_Release(offscreen);
8834 cleanup:
8835 if (primary) IDirectDrawSurface7_Release(primary);
8836 if (clipper) IDirectDrawClipper_Release(clipper);
8837 if (ddraw) IDirectDraw7_Release(ddraw);
8838 if (gl) FreeLibrary(gl);
8839 if (hdc) ReleaseDC(window, hdc);
8840 if (hdc2) ReleaseDC(window2, hdc2);
8841 DestroyWindow(window);
8842 if (window2) DestroyWindow(window2);
8845 static void test_create_surface_pitch(void)
8847 IDirectDrawSurface7 *surface;
8848 DDSURFACEDESC2 surface_desc;
8849 IDirectDraw7 *ddraw;
8850 unsigned int i;
8851 ULONG refcount;
8852 HWND window;
8853 HRESULT hr;
8854 void *mem;
8856 static const struct
8858 DWORD caps;
8859 DWORD flags_in;
8860 DWORD pitch_in;
8861 HRESULT hr;
8862 DWORD flags_out;
8863 DWORD pitch_out32;
8864 DWORD pitch_out64;
8866 test_data[] =
8868 /* 0 */
8869 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
8870 0, 0, DD_OK,
8871 DDSD_PITCH, 0x100, 0x100},
8872 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
8873 DDSD_PITCH, 0x104, DD_OK,
8874 DDSD_PITCH, 0x100, 0x100},
8875 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
8876 DDSD_PITCH, 0x0f8, DD_OK,
8877 DDSD_PITCH, 0x100, 0x100},
8878 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
8879 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
8880 0, 0, 0 },
8881 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8882 0, 0, DD_OK,
8883 DDSD_PITCH, 0x100, 0x0fc},
8884 /* 5 */
8885 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8886 DDSD_PITCH, 0x104, DD_OK,
8887 DDSD_PITCH, 0x100, 0x0fc},
8888 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8889 DDSD_PITCH, 0x0f8, DD_OK,
8890 DDSD_PITCH, 0x100, 0x0fc},
8891 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8892 DDSD_PITCH | DDSD_LINEARSIZE, 0, DD_OK,
8893 DDSD_PITCH, 0x100, 0x0fc},
8894 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8895 DDSD_LPSURFACE, 0, DDERR_INVALIDPARAMS,
8896 0, 0, 0 },
8897 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8898 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DD_OK,
8899 DDSD_PITCH, 0x100, 0x100},
8900 /* 10 */
8901 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8902 DDSD_LPSURFACE | DDSD_PITCH, 0x0fe, DDERR_INVALIDPARAMS,
8903 0, 0, 0 },
8904 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8905 DDSD_LPSURFACE | DDSD_PITCH, 0x0fc, DD_OK,
8906 DDSD_PITCH, 0x0fc, 0x0fc},
8907 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8908 DDSD_LPSURFACE | DDSD_PITCH, 0x0f8, DDERR_INVALIDPARAMS,
8909 0, 0, 0 },
8910 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8911 DDSD_LPSURFACE | DDSD_LINEARSIZE, 0x100, DDERR_INVALIDPARAMS,
8912 0, 0, 0 },
8913 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8914 DDSD_LPSURFACE | DDSD_LINEARSIZE, 0x3f00, DDERR_INVALIDPARAMS,
8915 0, 0, 0 },
8916 /* 15 */
8917 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8918 DDSD_LPSURFACE | DDSD_PITCH | DDSD_LINEARSIZE, 0x100, DD_OK,
8919 DDSD_PITCH, 0x100, 0x100},
8920 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
8921 0, 0, DDERR_INVALIDCAPS,
8922 0, 0, 0 },
8923 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
8924 0, 0, DD_OK,
8925 DDSD_PITCH, 0x100, 0 },
8926 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
8927 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
8928 0, 0, 0 },
8929 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
8930 0, 0, DDERR_INVALIDCAPS,
8931 0, 0, 0 },
8932 /* 20 */
8933 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
8934 0, 0, DD_OK,
8935 DDSD_PITCH, 0x100, 0 },
8936 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
8937 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DD_OK,
8938 DDSD_PITCH, 0x100, 0 },
8940 DWORD flags_mask = DDSD_PITCH | DDSD_LPSURFACE | DDSD_LINEARSIZE;
8942 window = create_window();
8943 ddraw = create_ddraw();
8944 ok(!!ddraw, "Failed to create a ddraw object.\n");
8945 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8946 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8948 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((63 * 4) + 8) * 63);
8950 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
8952 memset(&surface_desc, 0, sizeof(surface_desc));
8953 surface_desc.dwSize = sizeof(surface_desc);
8954 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | test_data[i].flags_in;
8955 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
8956 surface_desc.dwWidth = 63;
8957 surface_desc.dwHeight = 63;
8958 U1(surface_desc).lPitch = test_data[i].pitch_in;
8959 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8960 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
8961 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
8962 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8963 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8964 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
8965 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8966 if (test_data[i].flags_in & DDSD_LPSURFACE)
8968 HRESULT expected_hr = SUCCEEDED(test_data[i].hr) ? DDERR_INVALIDPARAMS : test_data[i].hr;
8969 ok(hr == expected_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, expected_hr);
8970 surface_desc.lpSurface = mem;
8971 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8973 if ((test_data[i].caps & DDSCAPS_VIDEOMEMORY) && hr == DDERR_NODIRECTDRAWHW)
8974 continue;
8975 if (is_ddraw64 && (test_data[i].caps & DDSCAPS_TEXTURE) && SUCCEEDED(test_data[i].hr))
8976 todo_wine ok(hr == E_NOINTERFACE, "Test %u: Got unexpected hr %#x.\n", i, hr);
8977 else
8978 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
8979 if (FAILED(hr))
8980 continue;
8982 memset(&surface_desc, 0, sizeof(surface_desc));
8983 surface_desc.dwSize = sizeof(surface_desc);
8984 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
8985 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
8986 ok((surface_desc.dwFlags & flags_mask) == test_data[i].flags_out,
8987 "Test %u: Got unexpected flags %#x, expected %#x.\n",
8988 i, surface_desc.dwFlags & flags_mask, test_data[i].flags_out);
8989 /* The pitch for textures seems to be implementation specific. */
8990 if (!(test_data[i].caps & DDSCAPS_TEXTURE))
8992 if (is_ddraw64 && test_data[i].pitch_out32 != test_data[i].pitch_out64)
8993 todo_wine ok(U1(surface_desc).lPitch == test_data[i].pitch_out64,
8994 "Test %u: Got unexpected pitch %u, expected %u.\n",
8995 i, U1(surface_desc).lPitch, test_data[i].pitch_out64);
8996 else
8997 ok(U1(surface_desc).lPitch == test_data[i].pitch_out32,
8998 "Test %u: Got unexpected pitch %u, expected %u.\n",
8999 i, U1(surface_desc).lPitch, test_data[i].pitch_out32);
9001 ok(!surface_desc.lpSurface, "Test %u: Got unexpected lpSurface %p.\n", i, surface_desc.lpSurface);
9003 IDirectDrawSurface7_Release(surface);
9006 HeapFree(GetProcessHeap(), 0, mem);
9007 refcount = IDirectDraw7_Release(ddraw);
9008 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9009 DestroyWindow(window);
9012 static void test_mipmap(void)
9014 IDirectDrawSurface7 *surface, *surface_base, *surface_mip;
9015 unsigned int i, mipmap_count;
9016 DDSURFACEDESC2 surface_desc;
9017 IDirectDraw7 *ddraw;
9018 ULONG refcount;
9019 HWND window;
9020 HRESULT hr;
9021 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
9022 DDCAPS hal_caps;
9024 static const struct
9026 DWORD flags;
9027 DWORD caps;
9028 DWORD width;
9029 DWORD height;
9030 DWORD mipmap_count_in;
9031 HRESULT hr;
9032 DWORD mipmap_count_out;
9034 tests[] =
9036 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 3, DD_OK, 3},
9037 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDPARAMS, 0},
9038 {0, DDSCAPS_TEXTURE | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 1},
9039 {0, DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDCAPS, 0},
9040 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 8},
9041 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 32, 64, 0, DD_OK, 7},
9044 window = create_window();
9045 ddraw = create_ddraw();
9046 ok(!!ddraw, "Failed to create a ddraw object.\n");
9047 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9048 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9050 memset(&hal_caps, 0, sizeof(hal_caps));
9051 hal_caps.dwSize = sizeof(hal_caps);
9052 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
9053 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9054 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)
9055 || is_ddraw64)
9057 skip("Mipmapped textures not supported, skipping tests.\n");
9058 IDirectDraw7_Release(ddraw);
9059 DestroyWindow(window);
9060 return;
9063 for (i = 0; i < ARRAY_SIZE(tests); ++i)
9065 memset(&surface_desc, 0, sizeof(surface_desc));
9066 surface_desc.dwSize = sizeof(surface_desc);
9067 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | tests[i].flags;
9068 surface_desc.ddsCaps.dwCaps = tests[i].caps;
9069 surface_desc.dwWidth = tests[i].width;
9070 surface_desc.dwHeight = tests[i].height;
9071 if (tests[i].flags & DDSD_MIPMAPCOUNT)
9072 U2(surface_desc).dwMipMapCount = tests[i].mipmap_count_in;
9073 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9074 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x.\n", i, hr);
9075 if (FAILED(hr))
9076 continue;
9078 memset(&surface_desc, 0, sizeof(surface_desc));
9079 surface_desc.dwSize = sizeof(surface_desc);
9080 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
9081 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
9082 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
9083 "Test %u: Got unexpected flags %#x.\n", i, surface_desc.dwFlags);
9084 ok(U2(surface_desc).dwMipMapCount == tests[i].mipmap_count_out,
9085 "Test %u: Got unexpected mipmap count %u.\n", i, U2(surface_desc).dwMipMapCount);
9087 surface_base = surface;
9088 IDirectDrawSurface7_AddRef(surface_base);
9089 mipmap_count = U2(surface_desc).dwMipMapCount;
9090 while (mipmap_count > 1)
9092 hr = IDirectDrawSurface7_GetAttachedSurface(surface_base, &caps, &surface_mip);
9093 ok(SUCCEEDED(hr), "Test %u, %u: Failed to get attached surface, hr %#x.\n", i, mipmap_count, hr);
9095 memset(&surface_desc, 0, sizeof(surface_desc));
9096 surface_desc.dwSize = sizeof(surface_desc);
9097 hr = IDirectDrawSurface7_GetSurfaceDesc(surface_base, &surface_desc);
9098 ok(SUCCEEDED(hr), "Test %u, %u: Failed to get surface desc, hr %#x.\n", i, mipmap_count, hr);
9099 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
9100 "Test %u, %u: Got unexpected flags %#x.\n", i, mipmap_count, surface_desc.dwFlags);
9101 ok(U2(surface_desc).dwMipMapCount == mipmap_count,
9102 "Test %u, %u: Got unexpected mipmap count %u.\n",
9103 i, mipmap_count, U2(surface_desc).dwMipMapCount);
9105 memset(&surface_desc, 0, sizeof(surface_desc));
9106 surface_desc.dwSize = sizeof(surface_desc);
9107 hr = IDirectDrawSurface7_Lock(surface_base, NULL, &surface_desc, 0, NULL);
9108 ok(SUCCEEDED(hr), "Test %u, %u: Failed to lock surface, hr %#x.\n", i, mipmap_count, hr);
9109 ok(surface_desc.dwMipMapCount == mipmap_count,
9110 "Test %u, %u: unexpected change of mipmap count %u.\n",
9111 i, mipmap_count, surface_desc.dwMipMapCount);
9112 memset(&surface_desc, 0, sizeof(surface_desc));
9113 surface_desc.dwSize = sizeof(surface_desc);
9114 hr = IDirectDrawSurface7_Lock(surface_mip, NULL, &surface_desc, 0, NULL);
9115 ok(SUCCEEDED(hr), "Test %u, %u: Failed to lock surface, hr %#x.\n", i, mipmap_count, hr);
9116 ok(surface_desc.dwMipMapCount == mipmap_count - 1,
9117 "Test %u, %u: Child mipmap count unexpected %u\n", i, mipmap_count, surface_desc.dwMipMapCount);
9118 IDirectDrawSurface7_Unlock(surface_mip, NULL);
9119 IDirectDrawSurface7_Unlock(surface_base, NULL);
9121 IDirectDrawSurface7_Release(surface_base);
9122 surface_base = surface_mip;
9123 --mipmap_count;
9125 IDirectDrawSurface7_Release(surface_base);
9127 IDirectDrawSurface7_Release(surface);
9130 refcount = IDirectDraw7_Release(ddraw);
9131 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9132 DestroyWindow(window);
9135 static void test_palette_complex(void)
9137 IDirectDrawSurface7 *surface, *mipmap, *tmp;
9138 DDSURFACEDESC2 surface_desc;
9139 IDirectDraw7 *ddraw;
9140 IDirectDrawPalette *palette, *palette2;
9141 ULONG refcount;
9142 HWND window;
9143 HRESULT hr;
9144 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
9145 DDCAPS hal_caps;
9146 PALETTEENTRY palette_entries[256];
9147 unsigned int i;
9149 window = create_window();
9150 ddraw = create_ddraw();
9151 ok(!!ddraw, "Failed to create a ddraw object.\n");
9152 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9153 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9155 memset(&hal_caps, 0, sizeof(hal_caps));
9156 hal_caps.dwSize = sizeof(hal_caps);
9157 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
9158 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9159 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)
9160 || is_ddraw64)
9162 skip("Mipmapped textures not supported, skipping mipmap palette test.\n");
9163 IDirectDraw7_Release(ddraw);
9164 DestroyWindow(window);
9165 return;
9168 memset(&surface_desc, 0, sizeof(surface_desc));
9169 surface_desc.dwSize = sizeof(surface_desc);
9170 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9171 surface_desc.dwWidth = 128;
9172 surface_desc.dwHeight = 128;
9173 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
9174 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9175 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
9176 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
9177 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9178 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9180 memset(palette_entries, 0, sizeof(palette_entries));
9181 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
9182 palette_entries, &palette, NULL);
9183 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
9185 palette2 = (void *)0xdeadbeef;
9186 hr = IDirectDrawSurface7_GetPalette(surface, &palette2);
9187 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
9188 ok(!palette2, "Got unexpected palette %p.\n", palette2);
9189 hr = IDirectDrawSurface7_SetPalette(surface, palette);
9190 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
9191 hr = IDirectDrawSurface7_GetPalette(surface, &palette2);
9192 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
9193 ok(palette == palette2, "Got unexpected palette %p.\n", palette2);
9194 IDirectDrawPalette_Release(palette2);
9196 mipmap = surface;
9197 IDirectDrawSurface7_AddRef(mipmap);
9198 for (i = 0; i < 7; ++i)
9200 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
9201 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
9202 palette2 = (void *)0xdeadbeef;
9203 hr = IDirectDrawSurface7_GetPalette(tmp, &palette2);
9204 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x, i %u.\n", hr, i);
9205 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
9207 hr = IDirectDrawSurface7_SetPalette(tmp, palette);
9208 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x, i %u.\n", hr, i);
9210 hr = IDirectDrawSurface7_GetPalette(tmp, &palette2);
9211 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x, i %u.\n", hr, i);
9212 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
9214 /* Ddraw7 uses the palette of the mipmap for GetDC, just like previous
9215 * ddraw versions. Combined with the test results above this means no
9216 * palette is available. So depending on the driver either GetDC fails
9217 * or the DIB color table contains random data. */
9219 IDirectDrawSurface7_Release(mipmap);
9220 mipmap = tmp;
9223 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
9224 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
9225 IDirectDrawSurface7_Release(mipmap);
9226 refcount = IDirectDrawSurface7_Release(surface);
9227 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9229 /* Test DDERR_INVALIDPIXELFORMAT vs DDERR_NOTONMIPMAPSUBLEVEL. */
9230 memset(&surface_desc, 0, sizeof(surface_desc));
9231 surface_desc.dwSize = sizeof(surface_desc);
9232 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9233 surface_desc.dwWidth = 128;
9234 surface_desc.dwHeight = 128;
9235 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
9236 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9237 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
9238 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
9239 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9240 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9241 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
9242 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9243 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9245 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
9246 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
9247 hr = IDirectDrawSurface7_SetPalette(mipmap, palette);
9248 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x.\n", hr);
9250 IDirectDrawSurface7_Release(mipmap);
9251 refcount = IDirectDrawSurface7_Release(surface);
9252 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9253 refcount = IDirectDrawPalette_Release(palette);
9254 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9256 refcount = IDirectDraw7_Release(ddraw);
9257 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9258 DestroyWindow(window);
9261 static void test_p8_blit(void)
9263 IDirectDrawSurface7 *src, *dst, *dst_p8;
9264 DDSURFACEDESC2 surface_desc;
9265 IDirectDraw7 *ddraw;
9266 IDirectDrawPalette *palette, *palette2;
9267 ULONG refcount;
9268 HWND window;
9269 HRESULT hr;
9270 PALETTEENTRY palette_entries[256];
9271 unsigned int x;
9272 DDBLTFX fx;
9273 BOOL is_warp;
9274 static const BYTE src_data[] = {0x10, 0x1, 0x2, 0x3, 0x4, 0x5, 0xff, 0x80};
9275 static const BYTE src_data2[] = {0x10, 0x5, 0x4, 0x3, 0x2, 0x1, 0xff, 0x80};
9276 static const BYTE expected_p8[] = {0x10, 0x1, 0x4, 0x3, 0x4, 0x5, 0xff, 0x80};
9277 static const D3DCOLOR expected[] =
9279 0x00101010, 0x00010101, 0x00020202, 0x00030303,
9280 0x00040404, 0x00050505, 0x00ffffff, 0x00808080,
9282 D3DCOLOR color;
9284 window = create_window();
9285 ddraw = create_ddraw();
9286 ok(!!ddraw, "Failed to create a ddraw object.\n");
9287 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9288 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9289 is_warp = ddraw_is_warp(ddraw);
9291 memset(palette_entries, 0, sizeof(palette_entries));
9292 palette_entries[1].peGreen = 0xff;
9293 palette_entries[2].peBlue = 0xff;
9294 palette_entries[3].peFlags = 0xff;
9295 palette_entries[4].peRed = 0xff;
9296 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
9297 palette_entries, &palette, NULL);
9298 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
9299 palette_entries[1].peBlue = 0xff;
9300 palette_entries[2].peGreen = 0xff;
9301 palette_entries[3].peRed = 0xff;
9302 palette_entries[4].peFlags = 0x0;
9303 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
9304 palette_entries, &palette2, NULL);
9305 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
9307 memset(&surface_desc, 0, sizeof(surface_desc));
9308 surface_desc.dwSize = sizeof(surface_desc);
9309 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9310 surface_desc.dwWidth = 8;
9311 surface_desc.dwHeight = 1;
9312 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9313 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9314 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
9315 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
9316 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
9317 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9318 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_p8, NULL);
9319 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9320 hr = IDirectDrawSurface7_SetPalette(dst_p8, palette2);
9321 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
9323 memset(&surface_desc, 0, sizeof(surface_desc));
9324 surface_desc.dwSize = sizeof(surface_desc);
9325 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9326 surface_desc.dwWidth = 8;
9327 surface_desc.dwHeight = 1;
9328 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9329 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9330 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
9331 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
9332 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9333 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9334 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
9335 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
9336 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
9337 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9339 memset(&surface_desc, 0, sizeof(surface_desc));
9340 surface_desc.dwSize = sizeof(surface_desc);
9341 hr = IDirectDrawSurface7_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
9342 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
9343 memcpy(surface_desc.lpSurface, src_data, sizeof(src_data));
9344 hr = IDirectDrawSurface7_Unlock(src, NULL);
9345 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
9347 hr = IDirectDrawSurface7_Lock(dst_p8, NULL, &surface_desc, DDLOCK_WAIT, NULL);
9348 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#x.\n", hr);
9349 memcpy(surface_desc.lpSurface, src_data2, sizeof(src_data2));
9350 hr = IDirectDrawSurface7_Unlock(dst_p8, NULL);
9351 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#x.\n", hr);
9353 fx.dwSize = sizeof(fx);
9354 fx.dwFillColor = 0xdeadbeef;
9355 hr = IDirectDrawSurface7_Blt(dst, NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &fx);
9356 ok(SUCCEEDED(hr), "Failed to color fill %#x.\n", hr);
9358 hr = IDirectDrawSurface7_SetPalette(src, palette);
9359 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
9360 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_WAIT, NULL);
9361 /* The r500 Windows 7 driver returns E_NOTIMPL. r200 on Windows XP works.
9362 * The Geforce 7 driver on Windows Vista returns E_FAIL. Newer Nvidia GPUs work. */
9363 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL) || broken(hr == E_FAIL),
9364 "Failed to blit, hr %#x.\n", hr);
9366 if (SUCCEEDED(hr))
9368 for (x = 0; x < ARRAY_SIZE(expected); ++x)
9370 color = get_surface_color(dst, x, 0);
9371 /* WARP on 1709 and newer write zeroes on non-colorkeyed P8 -> RGB blits. For ckey
9372 * blits see below. */
9373 todo_wine ok(compare_color(color, expected[x], 0)
9374 || broken(is_warp && compare_color(color, 0x00000000, 0)),
9375 "Pixel %u: Got color %#x, expected %#x.\n",
9376 x, color, expected[x]);
9380 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x2;
9381 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x2;
9382 hr = IDirectDrawSurface7_Blt(dst_p8, NULL, src, NULL, DDBLT_WAIT | DDBLT_KEYSRCOVERRIDE, &fx);
9383 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
9385 hr = IDirectDrawSurface7_Lock(dst_p8, NULL, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
9386 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#x.\n", hr);
9387 /* A color keyed P8 blit doesn't do anything on WARP - it just leaves the data in the destination
9388 * surface untouched. Error checking (DDBLT_KEYSRC without a key
9389 * for example) also works as expected.
9391 * Using DDBLT_KEYSRC instead of DDBLT_KEYSRCOVERRIDE doesn't change this. Doing this blit with
9392 * the display mode set to P8 doesn't help either. */
9393 ok(!memcmp(surface_desc.lpSurface, expected_p8, sizeof(expected_p8))
9394 || broken(is_warp && !memcmp(surface_desc.lpSurface, src_data2, sizeof(src_data2))),
9395 "Got unexpected P8 color key blit result.\n");
9396 hr = IDirectDrawSurface7_Unlock(dst_p8, NULL);
9397 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#x.\n", hr);
9399 IDirectDrawSurface7_Release(src);
9400 IDirectDrawSurface7_Release(dst);
9401 IDirectDrawSurface7_Release(dst_p8);
9402 IDirectDrawPalette_Release(palette);
9403 IDirectDrawPalette_Release(palette2);
9405 refcount = IDirectDraw7_Release(ddraw);
9406 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9407 DestroyWindow(window);
9410 static void test_material(void)
9412 static const D3DCOLORVALUE null_color;
9413 IDirect3DDevice7 *device;
9414 D3DMATERIAL7 material;
9415 ULONG refcount;
9416 HWND window;
9417 HRESULT hr;
9419 window = create_window();
9420 if (!(device = create_device(window, DDSCL_NORMAL)))
9422 skip("Failed to create a 3D device, skipping test.\n");
9423 DestroyWindow(window);
9424 return;
9427 hr = IDirect3DDevice7_GetMaterial(device, &material);
9428 ok(SUCCEEDED(hr), "Failed to get material, hr %#x.\n", hr);
9429 ok(!memcmp(&U(material).diffuse, &null_color, sizeof(null_color)),
9430 "Got unexpected diffuse color {%.8e, %.8e, %.8e, %.8e}.\n",
9431 U1(U(material).diffuse).r, U2(U(material).diffuse).g,
9432 U3(U(material).diffuse).b, U4(U(material).diffuse).a);
9433 ok(!memcmp(&U1(material).ambient, &null_color, sizeof(null_color)),
9434 "Got unexpected ambient color {%.8e, %.8e, %.8e, %.8e}.\n",
9435 U1(U1(material).ambient).r, U2(U1(material).ambient).g,
9436 U3(U1(material).ambient).b, U4(U1(material).ambient).a);
9437 ok(!memcmp(&U2(material).specular, &null_color, sizeof(null_color)),
9438 "Got unexpected specular color {%.8e, %.8e, %.8e, %.8e}.\n",
9439 U1(U2(material).specular).r, U2(U2(material).specular).g,
9440 U3(U2(material).specular).b, U4(U2(material).specular).a);
9441 ok(!memcmp(&U3(material).emissive, &null_color, sizeof(null_color)),
9442 "Got unexpected emissive color {%.8e, %.8e, %.8e, %.8e}.\n",
9443 U1(U3(material).emissive).r, U2(U3(material).emissive).g,
9444 U3(U3(material).emissive).b, U4(U3(material).emissive).a);
9445 ok(U4(material).power == 0.0f, "Got unexpected power %.8e.\n", U4(material).power);
9447 refcount = IDirect3DDevice7_Release(device);
9448 ok(!refcount, "Device has %u references left.\n", refcount);
9449 DestroyWindow(window);
9452 static void test_palette_gdi(void)
9454 IDirectDrawSurface7 *surface, *primary;
9455 DDSURFACEDESC2 surface_desc;
9456 IDirectDraw7 *ddraw;
9457 IDirectDrawPalette *palette, *palette2;
9458 ULONG refcount;
9459 HWND window;
9460 HRESULT hr;
9461 PALETTEENTRY palette_entries[256];
9462 UINT i;
9463 HDC dc;
9464 DDBLTFX fx;
9465 RECT r;
9466 COLORREF color;
9467 /* On the Windows 8 testbot palette index 0 of the onscreen palette is forced to
9468 * r = 0, g = 0, b = 0. Do not attempt to set it to something else as this is
9469 * not the point of this test. */
9470 static const RGBQUAD expected1[] =
9472 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
9473 {0x03, 0x00, 0x00, 0x00}, {0x15, 0x14, 0x13, 0x00},
9475 static const RGBQUAD expected2[] =
9477 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
9478 {0x03, 0x00, 0x00, 0x00}, {0x25, 0x24, 0x23, 0x00},
9480 static const RGBQUAD expected3[] =
9482 {0x00, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x40, 0x00},
9483 {0x00, 0x40, 0x00, 0x00}, {0x56, 0x34, 0x12, 0x00},
9485 HPALETTE ddraw_palette_handle;
9486 /* Similar to index 0, index 255 is r = 0xff, g = 0xff, b = 0xff on the Win8 VMs. */
9487 RGBQUAD rgbquad[255];
9488 static const RGBQUAD rgb_zero = {0, 0, 0, 0};
9490 window = create_window();
9491 ddraw = create_ddraw();
9492 ok(!!ddraw, "Failed to create a ddraw object.\n");
9493 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9494 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9496 memset(&surface_desc, 0, sizeof(surface_desc));
9497 surface_desc.dwSize = sizeof(surface_desc);
9498 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9499 surface_desc.dwWidth = 16;
9500 surface_desc.dwHeight = 16;
9501 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9502 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9503 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
9504 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
9505 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9506 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9508 /* Avoid colors from the Windows default palette. */
9509 memset(palette_entries, 0, sizeof(palette_entries));
9510 palette_entries[1].peRed = 0x01;
9511 palette_entries[2].peGreen = 0x02;
9512 palette_entries[3].peBlue = 0x03;
9513 palette_entries[4].peRed = 0x13;
9514 palette_entries[4].peGreen = 0x14;
9515 palette_entries[4].peBlue = 0x15;
9516 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
9517 palette_entries, &palette, NULL);
9518 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
9520 /* If there is no palette assigned and the display mode is not 8 bpp, some
9521 * drivers refuse to create a DC while others allow it. If a DC is created,
9522 * the DIB color table is uninitialized and contains random colors. No error
9523 * is generated when trying to read pixels and random garbage is returned.
9525 * The most likely explanation is that if the driver creates a DC, it (or
9526 * the higher-level runtime) uses GetSystemPaletteEntries to find the
9527 * palette, but GetSystemPaletteEntries fails when bpp > 8 and the palette
9528 * contains uninitialized garbage. See comments below for the P8 case. */
9530 hr = IDirectDrawSurface7_SetPalette(surface, palette);
9531 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
9532 hr = IDirectDrawSurface7_GetDC(surface, &dc);
9533 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
9534 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
9535 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
9536 "Got unexpected palette %p, expected %p.\n",
9537 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
9539 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
9540 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
9541 for (i = 0; i < ARRAY_SIZE(expected1); ++i)
9543 ok(!memcmp(&rgbquad[i], &expected1[i], sizeof(rgbquad[i])),
9544 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
9545 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
9546 expected1[i].rgbRed, expected1[i].rgbGreen, expected1[i].rgbBlue);
9548 for (; i < ARRAY_SIZE(rgbquad); ++i)
9550 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
9551 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
9552 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
9555 /* Update the palette while the DC is in use. This does not modify the DC. */
9556 palette_entries[4].peRed = 0x23;
9557 palette_entries[4].peGreen = 0x24;
9558 palette_entries[4].peBlue = 0x25;
9559 hr = IDirectDrawPalette_SetEntries(palette, 0, 4, 1, &palette_entries[4]);
9560 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
9562 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
9563 ok(i == 1, "Expected count 1, got %u.\n", i);
9564 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
9565 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
9566 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
9567 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
9569 /* Neither does re-setting the palette. */
9570 hr = IDirectDrawSurface7_SetPalette(surface, NULL);
9571 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
9572 hr = IDirectDrawSurface7_SetPalette(surface, palette);
9573 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
9575 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
9576 ok(i == 1, "Expected count 1, got %u.\n", i);
9577 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
9578 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
9579 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
9580 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
9582 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
9583 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
9585 /* Refresh the DC. This updates the palette. */
9586 hr = IDirectDrawSurface7_GetDC(surface, &dc);
9587 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
9588 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
9589 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
9590 for (i = 0; i < ARRAY_SIZE(expected2); ++i)
9592 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
9593 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
9594 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
9595 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
9597 for (; i < ARRAY_SIZE(rgbquad); ++i)
9599 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
9600 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
9601 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
9603 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
9604 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
9606 refcount = IDirectDrawSurface7_Release(surface);
9607 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9609 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
9610 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9611 if (FAILED(IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
9613 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
9614 IDirectDrawPalette_Release(palette);
9615 IDirectDraw7_Release(ddraw);
9616 DestroyWindow(window);
9617 return;
9619 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
9621 memset(&surface_desc, 0, sizeof(surface_desc));
9622 surface_desc.dwSize = sizeof(surface_desc);
9623 surface_desc.dwFlags = DDSD_CAPS;
9624 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
9625 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
9626 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9628 memset(&fx, 0, sizeof(fx));
9629 fx.dwSize = sizeof(fx);
9630 U5(fx).dwFillColor = 3;
9631 SetRect(&r, 0, 0, 319, 479);
9632 hr = IDirectDrawSurface7_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9633 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#x.\n", hr);
9634 SetRect(&r, 320, 0, 639, 479);
9635 U5(fx).dwFillColor = 4;
9636 hr = IDirectDrawSurface7_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9637 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#x.\n", hr);
9639 hr = IDirectDrawSurface7_SetPalette(primary, palette);
9640 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
9641 hr = IDirectDrawSurface7_GetDC(primary, &dc);
9642 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
9644 color = GetPixel(dc, 160, 240);
9645 ok(color == 0x00030000, "Clear index 3: Got unexpected color 0x%08x.\n", color);
9646 color = GetPixel(dc, 480, 240);
9647 ok(color == 0x00252423, "Clear index 4: Got unexpected color 0x%08x.\n", color);
9649 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
9650 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
9651 "Got unexpected palette %p, expected %p.\n",
9652 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
9653 SelectPalette(dc, ddraw_palette_handle, FALSE);
9655 /* The primary uses the system palette. In exclusive mode, the system palette matches
9656 * the ddraw palette attached to the primary, so the result is what you would expect
9657 * from a regular surface. Tests for the interaction between the ddraw palette and
9658 * the system palette are not included pending an application that depends on this.
9659 * The relation between those causes problems on Windows Vista and newer for games
9660 * like Age of Empires or StarcCaft. Don't emulate it without a real need. */
9661 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
9662 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
9663 for (i = 0; i < ARRAY_SIZE(expected2); ++i)
9665 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
9666 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
9667 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
9668 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
9670 for (; i < ARRAY_SIZE(rgbquad); ++i)
9672 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
9673 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
9674 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
9676 hr = IDirectDrawSurface7_ReleaseDC(primary, dc);
9677 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
9679 memset(&surface_desc, 0, sizeof(surface_desc));
9680 surface_desc.dwSize = sizeof(surface_desc);
9681 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
9682 surface_desc.dwWidth = 16;
9683 surface_desc.dwHeight = 16;
9684 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9685 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9686 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9688 /* Here the offscreen surface appears to use the primary's palette,
9689 * but in all likelihood it is actually the system palette. */
9690 hr = IDirectDrawSurface7_GetDC(surface, &dc);
9691 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
9692 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
9693 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
9694 for (i = 0; i < ARRAY_SIZE(expected2); ++i)
9696 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
9697 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
9698 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
9699 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
9701 for (; i < ARRAY_SIZE(rgbquad); ++i)
9703 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
9704 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
9705 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
9707 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
9708 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
9710 /* On real hardware a change to the primary surface's palette applies immediately,
9711 * even on device contexts from offscreen surfaces that do not have their own
9712 * palette. On the testbot VMs this is not the case. Don't test this until we
9713 * know of an application that depends on this. */
9715 memset(palette_entries, 0, sizeof(palette_entries));
9716 palette_entries[1].peBlue = 0x40;
9717 palette_entries[2].peRed = 0x40;
9718 palette_entries[3].peGreen = 0x40;
9719 palette_entries[4].peRed = 0x12;
9720 palette_entries[4].peGreen = 0x34;
9721 palette_entries[4].peBlue = 0x56;
9722 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
9723 palette_entries, &palette2, NULL);
9724 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
9725 hr = IDirectDrawSurface7_SetPalette(surface, palette2);
9726 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
9728 /* A palette assigned to the offscreen surface overrides the primary / system
9729 * palette. */
9730 hr = IDirectDrawSurface7_GetDC(surface, &dc);
9731 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
9732 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
9733 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
9734 for (i = 0; i < ARRAY_SIZE(expected3); ++i)
9736 ok(!memcmp(&rgbquad[i], &expected3[i], sizeof(rgbquad[i])),
9737 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
9738 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
9739 expected3[i].rgbRed, expected3[i].rgbGreen, expected3[i].rgbBlue);
9741 for (; i < ARRAY_SIZE(rgbquad); ++i)
9743 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
9744 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
9745 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
9747 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
9748 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
9750 refcount = IDirectDrawSurface7_Release(surface);
9751 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9753 /* The Windows 8 testbot keeps extra references to the primary and
9754 * backbuffer while in 8 bpp mode. */
9755 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
9756 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
9758 refcount = IDirectDrawSurface7_Release(primary);
9759 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9760 refcount = IDirectDrawPalette_Release(palette2);
9761 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9762 refcount = IDirectDrawPalette_Release(palette);
9763 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9764 refcount = IDirectDraw7_Release(ddraw);
9765 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9766 DestroyWindow(window);
9769 static void test_palette_alpha(void)
9771 IDirectDrawSurface7 *surface;
9772 DDSURFACEDESC2 surface_desc;
9773 IDirectDraw7 *ddraw;
9774 IDirectDrawPalette *palette;
9775 ULONG refcount;
9776 HWND window;
9777 HRESULT hr;
9778 PALETTEENTRY palette_entries[256];
9779 unsigned int i;
9780 static const struct
9782 DWORD caps, flags;
9783 BOOL attach_allowed;
9784 const char *name;
9786 test_data[] =
9788 {DDSCAPS_OFFSCREENPLAIN, DDSD_WIDTH | DDSD_HEIGHT, FALSE, "offscreenplain"},
9789 {DDSCAPS_TEXTURE, DDSD_WIDTH | DDSD_HEIGHT, TRUE, "texture"},
9790 {DDSCAPS_PRIMARYSURFACE, 0, FALSE, "primary"}
9793 window = create_window();
9794 ddraw = create_ddraw();
9795 ok(!!ddraw, "Failed to create a ddraw object.\n");
9796 if (FAILED(IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
9798 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
9799 IDirectDraw7_Release(ddraw);
9800 DestroyWindow(window);
9801 return;
9803 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
9804 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9806 memset(palette_entries, 0, sizeof(palette_entries));
9807 palette_entries[1].peFlags = 0x42;
9808 palette_entries[2].peFlags = 0xff;
9809 palette_entries[3].peFlags = 0x80;
9810 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
9811 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
9813 memset(palette_entries, 0x66, sizeof(palette_entries));
9814 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
9815 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
9816 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
9817 palette_entries[0].peFlags);
9818 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
9819 palette_entries[1].peFlags);
9820 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
9821 palette_entries[2].peFlags);
9822 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
9823 palette_entries[3].peFlags);
9825 IDirectDrawPalette_Release(palette);
9827 memset(palette_entries, 0, sizeof(palette_entries));
9828 palette_entries[1].peFlags = 0x42;
9829 palette_entries[1].peRed = 0xff;
9830 palette_entries[2].peFlags = 0xff;
9831 palette_entries[3].peFlags = 0x80;
9832 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT | DDPCAPS_ALPHA,
9833 palette_entries, &palette, NULL);
9834 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
9836 memset(palette_entries, 0x66, sizeof(palette_entries));
9837 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
9838 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
9839 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
9840 palette_entries[0].peFlags);
9841 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
9842 palette_entries[1].peFlags);
9843 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
9844 palette_entries[2].peFlags);
9845 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
9846 palette_entries[3].peFlags);
9848 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
9850 memset(&surface_desc, 0, sizeof(surface_desc));
9851 surface_desc.dwSize = sizeof(surface_desc);
9852 surface_desc.dwFlags = DDSD_CAPS | test_data[i].flags;
9853 surface_desc.dwWidth = 128;
9854 surface_desc.dwHeight = 128;
9855 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
9856 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9857 if (is_ddraw64 && test_data[i].caps & DDSCAPS_TEXTURE)
9858 todo_wine ok(hr == E_NOINTERFACE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
9859 else
9860 ok(hr == DD_OK, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
9861 if (FAILED(hr))
9862 continue;
9864 hr = IDirectDrawSurface7_SetPalette(surface, palette);
9865 if (test_data[i].attach_allowed)
9866 ok(SUCCEEDED(hr), "Failed to attach palette to %s surface, hr %#x.\n", test_data[i].name, hr);
9867 else
9868 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x, %s surface.\n", hr, test_data[i].name);
9870 if (SUCCEEDED(hr))
9872 HDC dc;
9873 RGBQUAD rgbquad;
9874 UINT retval;
9876 hr = IDirectDrawSurface7_GetDC(surface, &dc);
9877 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x, %s surface.\n", hr, test_data[i].name);
9878 retval = GetDIBColorTable(dc, 1, 1, &rgbquad);
9879 ok(retval == 1, "GetDIBColorTable returned unexpected result %u.\n", retval);
9880 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x, %s surface.\n",
9881 rgbquad.rgbRed, test_data[i].name);
9882 ok(rgbquad.rgbGreen == 0, "Expected rgbGreen = 0, got %#x, %s surface.\n",
9883 rgbquad.rgbGreen, test_data[i].name);
9884 ok(rgbquad.rgbBlue == 0, "Expected rgbBlue = 0, got %#x, %s surface.\n",
9885 rgbquad.rgbBlue, test_data[i].name);
9886 ok(rgbquad.rgbReserved == 0, "Expected rgbReserved = 0, got %u, %s surface.\n",
9887 rgbquad.rgbReserved, test_data[i].name);
9888 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
9889 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
9891 IDirectDrawSurface7_Release(surface);
9894 /* Test INVALIDSURFACETYPE vs INVALIDPIXELFORMAT. */
9895 memset(&surface_desc, 0, sizeof(surface_desc));
9896 surface_desc.dwSize = sizeof(surface_desc);
9897 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9898 surface_desc.dwWidth = 128;
9899 surface_desc.dwHeight = 128;
9900 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9901 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9902 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
9903 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
9904 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9905 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9906 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
9907 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9908 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9909 hr = IDirectDrawSurface7_SetPalette(surface, palette);
9910 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x.\n", hr);
9911 IDirectDrawSurface7_Release(surface);
9913 /* The Windows 8 testbot keeps extra references to the primary
9914 * while in 8 bpp mode. */
9915 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
9916 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
9918 refcount = IDirectDrawPalette_Release(palette);
9919 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9920 refcount = IDirectDraw7_Release(ddraw);
9921 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9922 DestroyWindow(window);
9925 static void test_vb_writeonly(void)
9927 IDirect3DDevice7 *device;
9928 IDirect3D7 *d3d;
9929 IDirect3DVertexBuffer7 *buffer;
9930 HWND window;
9931 HRESULT hr;
9932 D3DVERTEXBUFFERDESC desc;
9933 void *ptr;
9934 static const struct vec4 quad[] =
9936 { 0.0f, 480.0f, 0.0f, 1.0f},
9937 { 0.0f, 0.0f, 0.0f, 1.0f},
9938 {640.0f, 480.0f, 0.0f, 1.0f},
9939 {640.0f, 0.0f, 0.0f, 1.0f},
9942 window = create_window();
9943 if (!(device = create_device(window, DDSCL_NORMAL)))
9945 skip("Failed to create a 3D device, skipping test.\n");
9946 DestroyWindow(window);
9947 return;
9950 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
9951 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
9953 memset(&desc, 0, sizeof(desc));
9954 desc.dwSize = sizeof(desc);
9955 desc.dwCaps = D3DVBCAPS_WRITEONLY;
9956 desc.dwFVF = D3DFVF_XYZRHW;
9957 desc.dwNumVertices = ARRAY_SIZE(quad);
9958 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &buffer, 0);
9959 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
9961 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, &ptr, NULL);
9962 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
9963 memcpy(ptr, quad, sizeof(quad));
9964 hr = IDirect3DVertexBuffer7_Unlock(buffer);
9965 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
9967 hr = IDirect3DDevice7_BeginScene(device);
9968 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9969 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
9970 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9971 hr = IDirect3DDevice7_EndScene(device);
9972 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9974 hr = IDirect3DVertexBuffer7_Lock(buffer, 0, &ptr, NULL);
9975 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
9976 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
9977 hr = IDirect3DVertexBuffer7_Unlock(buffer);
9978 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
9980 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_READONLY, &ptr, NULL);
9981 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
9982 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
9983 hr = IDirect3DVertexBuffer7_Unlock(buffer);
9984 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
9986 IDirect3DVertexBuffer7_Release(buffer);
9987 IDirect3D7_Release(d3d);
9988 IDirect3DDevice7_Release(device);
9989 DestroyWindow(window);
9992 static void test_lost_device(void)
9994 IDirectDrawSurface7 *sysmem_surface, *vidmem_surface;
9995 IDirectDrawSurface7 *surface, *back_buffer;
9996 DDSURFACEDESC2 surface_desc;
9997 HWND window1, window2;
9998 IDirectDraw7 *ddraw;
9999 ULONG refcount;
10000 DDSCAPS2 caps;
10001 HRESULT hr;
10002 BOOL ret;
10004 window1 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
10005 0, 0, 640, 480, 0, 0, 0, 0);
10006 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
10007 0, 0, 640, 480, 0, 0, 0, 0);
10008 ddraw = create_ddraw();
10009 ok(!!ddraw, "Failed to create a ddraw object.\n");
10010 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
10011 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10013 memset(&surface_desc, 0, sizeof(surface_desc));
10014 surface_desc.dwSize = sizeof(surface_desc);
10015 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
10016 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
10017 U5(surface_desc).dwBackBufferCount = 1;
10018 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10019 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10021 memset(&surface_desc, 0, sizeof(surface_desc));
10022 surface_desc.dwSize = sizeof(surface_desc);
10023 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
10024 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
10025 surface_desc.dwWidth = 100;
10026 surface_desc.dwHeight = 100;
10027 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &sysmem_surface, NULL);
10028 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10030 memset(&surface_desc, 0, sizeof(surface_desc));
10031 surface_desc.dwSize = sizeof(surface_desc);
10032 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
10033 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
10034 surface_desc.dwWidth = 64;
10035 surface_desc.dwHeight = 64;
10036 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
10037 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
10038 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
10039 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
10040 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
10041 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
10042 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &surface_desc, &vidmem_surface, NULL)))
10044 skip("Failed to create video memory surface, skipping related tests.\n");
10045 vidmem_surface = NULL;
10048 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
10049 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10050 hr = IDirectDrawSurface7_IsLost(surface);
10051 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10052 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
10053 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10054 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
10055 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10056 if (vidmem_surface)
10058 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
10059 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10062 ret = SetForegroundWindow(GetDesktopWindow());
10063 ok(ret, "Failed to set foreground window.\n");
10064 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
10065 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
10066 hr = IDirectDrawSurface7_IsLost(surface);
10067 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
10068 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
10069 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
10070 hr = IDirectDrawSurface7_Restore(surface);
10071 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
10072 hr = IDirectDrawSurface7_IsLost(surface);
10073 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
10074 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
10075 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10076 hr = IDirectDrawSurface7_Restore(sysmem_surface);
10077 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10078 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
10079 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10080 if (vidmem_surface)
10082 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
10083 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
10084 hr = IDirectDrawSurface7_Restore(vidmem_surface);
10085 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
10086 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
10087 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
10090 ret = SetForegroundWindow(window1);
10091 ok(ret, "Failed to set foreground window.\n");
10092 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
10093 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10094 hr = IDirectDrawSurface7_IsLost(surface);
10095 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
10096 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
10097 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
10098 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
10099 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10100 if (vidmem_surface)
10102 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
10103 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
10106 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
10107 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10108 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
10109 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10110 hr = IDirectDrawSurface7_IsLost(surface);
10111 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10112 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
10113 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10114 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
10115 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10116 if (vidmem_surface)
10118 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
10119 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10122 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
10123 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10124 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
10125 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10126 hr = IDirectDrawSurface7_IsLost(surface);
10127 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
10128 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
10129 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
10130 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
10131 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10132 if (vidmem_surface)
10134 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
10135 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
10138 /* Trying to restore the primary will crash, probably because flippable
10139 * surfaces can't exist in DDSCL_NORMAL. */
10140 IDirectDrawSurface7_Release(surface);
10141 memset(&surface_desc, 0, sizeof(surface_desc));
10142 surface_desc.dwSize = sizeof(surface_desc);
10143 surface_desc.dwFlags = DDSD_CAPS;
10144 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
10145 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10146 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10147 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
10148 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10149 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
10150 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10152 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
10153 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10154 hr = IDirectDrawSurface7_IsLost(surface);
10155 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10156 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
10157 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10158 if (vidmem_surface)
10160 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
10161 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10164 ret = SetForegroundWindow(GetDesktopWindow());
10165 ok(ret, "Failed to set foreground window.\n");
10166 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
10167 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10168 hr = IDirectDrawSurface7_IsLost(surface);
10169 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10170 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
10171 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10172 if (vidmem_surface)
10174 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
10175 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10178 ret = SetForegroundWindow(window1);
10179 ok(ret, "Failed to set foreground window.\n");
10180 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
10181 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10182 hr = IDirectDrawSurface7_IsLost(surface);
10183 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10184 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
10185 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10186 if (vidmem_surface)
10188 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
10189 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10192 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
10193 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10194 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
10195 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10196 hr = IDirectDrawSurface7_IsLost(surface);
10197 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
10198 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
10199 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10200 if (vidmem_surface)
10202 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
10203 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
10206 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
10207 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10208 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
10209 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10210 hr = IDirectDrawSurface7_IsLost(surface);
10211 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10212 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
10213 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10214 if (vidmem_surface)
10216 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
10217 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10220 IDirectDrawSurface7_Release(surface);
10221 memset(&surface_desc, 0, sizeof(surface_desc));
10222 surface_desc.dwSize = sizeof(surface_desc);
10223 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
10224 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
10225 U5(surface_desc).dwBackBufferCount = 1;
10226 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10227 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10229 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
10230 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10231 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
10232 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10233 hr = IDirectDrawSurface7_IsLost(surface);
10234 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10235 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
10236 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10237 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
10238 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10239 if (vidmem_surface)
10241 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
10242 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10245 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL | DDSCL_FULLSCREEN);
10246 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10247 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
10248 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10249 hr = IDirectDrawSurface7_IsLost(surface);
10250 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10251 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
10252 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
10253 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
10254 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10255 if (vidmem_surface)
10257 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
10258 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10261 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
10262 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10263 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
10264 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10265 hr = IDirectDrawSurface7_IsLost(surface);
10266 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10267 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
10268 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
10269 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
10270 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10271 if (vidmem_surface)
10273 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
10274 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10277 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
10278 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10279 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
10280 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10281 hr = IDirectDrawSurface7_IsLost(surface);
10282 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10283 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
10284 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
10285 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
10286 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10287 if (vidmem_surface)
10289 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
10290 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10293 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL | DDSCL_FULLSCREEN);
10294 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10295 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
10296 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10297 hr = IDirectDrawSurface7_IsLost(surface);
10298 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10299 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
10300 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
10301 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
10302 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10303 if (vidmem_surface)
10305 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
10306 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10309 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
10310 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10311 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
10312 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10313 hr = IDirectDrawSurface7_IsLost(surface);
10314 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
10315 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
10316 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
10317 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
10318 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10319 if (vidmem_surface)
10321 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
10322 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
10325 memset(&caps, 0, sizeof(caps));
10326 caps.dwCaps = DDSCAPS_FLIP;
10328 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &back_buffer);
10329 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
10330 hr = IDirectDrawSurface7_Restore(surface);
10331 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10332 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &back_buffer);
10333 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10334 hr = IDirectDrawSurface7_IsLost(back_buffer);
10335 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10337 IDirectDrawSurface7_Release(back_buffer);
10339 if (vidmem_surface)
10340 IDirectDrawSurface7_Release(vidmem_surface);
10341 IDirectDrawSurface7_Release(sysmem_surface);
10342 IDirectDrawSurface7_Release(surface);
10343 refcount = IDirectDraw7_Release(ddraw);
10344 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
10345 DestroyWindow(window2);
10346 DestroyWindow(window1);
10349 static void test_resource_priority(void)
10351 IDirectDrawSurface7 *surface, *mipmap;
10352 DDSURFACEDESC2 surface_desc;
10353 IDirectDraw7 *ddraw;
10354 ULONG refcount;
10355 HWND window;
10356 HRESULT hr;
10357 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
10358 DDCAPS hal_caps;
10359 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_MIPMAP;
10360 unsigned int i;
10361 DWORD priority;
10362 static const struct
10364 DWORD caps, caps2;
10365 const char *name;
10366 HRESULT hr;
10367 /* SetPriority on offscreenplain surfaces crashes on AMD GPUs on Win7. */
10368 BOOL crash;
10370 test_data[] =
10372 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, "vidmem texture", DDERR_INVALIDPARAMS, FALSE},
10373 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, "sysmem texture", DDERR_INVALIDPARAMS, FALSE},
10374 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, "managed texture", DD_OK, FALSE},
10375 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, "managed texture", DD_OK, FALSE},
10376 {DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP,
10377 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_TEXTUREMANAGE,
10378 "cubemap", DD_OK, FALSE},
10379 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, "vidmem offscreenplain", DDERR_INVALIDOBJECT, TRUE},
10380 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, "sysmem offscreenplain", DDERR_INVALIDOBJECT, TRUE},
10383 window = create_window();
10384 ddraw = create_ddraw();
10385 ok(!!ddraw, "Failed to create a ddraw object.\n");
10386 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10387 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
10389 memset(&hal_caps, 0, sizeof(hal_caps));
10390 hal_caps.dwSize = sizeof(hal_caps);
10391 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
10392 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
10393 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps
10394 || !(hal_caps.ddsCaps.dwCaps & DDSCAPS2_TEXTUREMANAGE))
10396 skip("Required surface types not supported, skipping test.\n");
10397 goto done;
10400 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
10402 memset(&surface_desc, 0, sizeof(surface_desc));
10403 surface_desc.dwSize = sizeof(surface_desc);
10404 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
10405 surface_desc.dwWidth = 32;
10406 surface_desc.dwHeight = 32;
10407 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
10408 surface_desc.ddsCaps.dwCaps2 = test_data[i].caps2;
10409 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10410 if (is_ddraw64 && (test_data[i].caps & DDSCAPS_TEXTURE))
10412 todo_wine ok(hr == E_NOINTERFACE, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
10413 if (SUCCEEDED(hr))
10414 IDirectDrawSurface7_Release(surface);
10415 continue;
10417 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n", hr, test_data[i].name);
10419 /* Priority == NULL segfaults. */
10420 priority = 0xdeadbeef;
10421 hr = IDirectDrawSurface7_GetPriority(surface, &priority);
10422 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
10423 if (SUCCEEDED(test_data[i].hr))
10424 ok(priority == 0, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
10425 else
10426 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
10428 if (!test_data[i].crash)
10430 hr = IDirectDrawSurface7_SetPriority(surface, 1);
10431 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
10432 hr = IDirectDrawSurface7_GetPriority(surface, &priority);
10433 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
10434 if (SUCCEEDED(test_data[i].hr))
10436 ok(priority == 1, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
10437 hr = IDirectDrawSurface7_SetPriority(surface, 2);
10438 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
10440 else
10441 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
10444 if (test_data[i].caps2 & DDSCAPS2_CUBEMAP)
10446 caps.dwCaps2 = DDSCAPS2_CUBEMAP_NEGATIVEZ;
10447 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
10448 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
10449 /* IDirectDrawSurface7_SetPriority crashes when called on non-positive X surfaces on Windows */
10450 priority = 0xdeadbeef;
10451 hr = IDirectDrawSurface7_GetPriority(mipmap, &priority);
10452 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
10453 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
10455 IDirectDrawSurface7_Release(mipmap);
10458 IDirectDrawSurface7_Release(surface);
10461 if (is_ddraw64)
10462 goto done;
10464 memset(&surface_desc, 0, sizeof(surface_desc));
10465 surface_desc.dwSize = sizeof(surface_desc);
10466 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_MIPMAPCOUNT;
10467 surface_desc.dwWidth = 32;
10468 surface_desc.dwHeight = 32;
10469 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
10470 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
10471 U2(surface_desc).dwMipMapCount = 2;
10472 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10473 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10474 caps.dwCaps2 = 0;
10475 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
10476 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
10478 priority = 0xdeadbeef;
10479 hr = IDirectDrawSurface7_GetPriority(mipmap, &priority);
10480 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type managed mipmap.\n", hr);
10481 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type managed mipmap.\n", priority);
10482 /* SetPriority on the mipmap surface crashes. */
10483 hr = IDirectDrawSurface7_GetPriority(surface, &priority);
10484 ok(SUCCEEDED(hr), "Failed to get priority, hr %#x.\n", hr);
10485 ok(priority == 0, "Got unexpected priority %u, type managed mipmap.\n", priority);
10487 IDirectDrawSurface7_Release(mipmap);
10488 refcount = IDirectDrawSurface7_Release(surface);
10489 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
10491 done:
10492 refcount = IDirectDraw7_Release(ddraw);
10493 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
10494 DestroyWindow(window);
10497 static void test_surface_desc_lock(void)
10499 IDirectDrawSurface7 *surface;
10500 DDSURFACEDESC2 surface_desc;
10501 IDirectDraw7 *ddraw;
10502 ULONG refcount;
10503 HWND window;
10504 HRESULT hr;
10506 window = create_window();
10507 ddraw = create_ddraw();
10508 ok(!!ddraw, "Failed to create a ddraw object.\n");
10509 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10510 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
10512 memset(&surface_desc, 0, sizeof(surface_desc));
10513 surface_desc.dwSize = sizeof(surface_desc);
10514 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
10515 surface_desc.dwWidth = 16;
10516 surface_desc.dwHeight = 16;
10517 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10518 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10519 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10521 memset(&surface_desc, 0xaa, sizeof(surface_desc));
10522 surface_desc.dwSize = sizeof(surface_desc);
10523 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
10524 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
10525 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
10527 memset(&surface_desc, 0xaa, sizeof(surface_desc));
10528 surface_desc.dwSize = sizeof(surface_desc);
10529 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, 0, NULL);
10530 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10531 ok(surface_desc.lpSurface != NULL, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
10532 memset(&surface_desc, 0xaa, sizeof(surface_desc));
10533 surface_desc.dwSize = sizeof(surface_desc);
10534 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
10535 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
10536 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
10537 hr = IDirectDrawSurface7_Unlock(surface, NULL);
10538 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10540 memset(&surface_desc, 0xaa, sizeof(surface_desc));
10541 surface_desc.dwSize = sizeof(surface_desc);
10542 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
10543 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
10544 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
10546 IDirectDrawSurface7_Release(surface);
10547 refcount = IDirectDraw7_Release(ddraw);
10548 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
10549 DestroyWindow(window);
10552 static void test_fog_interpolation(void)
10554 HRESULT hr;
10555 IDirect3DDevice7 *device;
10556 IDirectDrawSurface7 *rt;
10557 ULONG refcount;
10558 HWND window;
10559 D3DCOLOR color;
10560 static struct
10562 struct vec3 position;
10563 D3DCOLOR diffuse;
10564 D3DCOLOR specular;
10566 quad[] =
10568 {{-1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff000000},
10569 {{-1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff000000},
10570 {{ 1.0f, -1.0f, 1.0f}, 0xffff0000, 0x00000000},
10571 {{ 1.0f, 1.0f, 1.0f}, 0xffff0000, 0x00000000},
10573 union
10575 DWORD d;
10576 float f;
10577 } conv;
10578 unsigned int i;
10579 static const struct
10581 D3DFOGMODE vfog, tfog;
10582 D3DSHADEMODE shade;
10583 D3DCOLOR middle_color;
10584 BOOL todo;
10586 tests[] =
10588 {D3DFOG_NONE, D3DFOG_NONE, D3DSHADE_FLAT, 0x00007f80, FALSE},
10589 {D3DFOG_NONE, D3DFOG_NONE, D3DSHADE_GOURAUD, 0x00007f80, FALSE},
10590 {D3DFOG_EXP, D3DFOG_NONE, D3DSHADE_FLAT, 0x00007f80, TRUE},
10591 {D3DFOG_EXP, D3DFOG_NONE, D3DSHADE_GOURAUD, 0x00007f80, TRUE},
10592 {D3DFOG_NONE, D3DFOG_EXP, D3DSHADE_FLAT, 0x0000ea15, FALSE},
10593 {D3DFOG_NONE, D3DFOG_EXP, D3DSHADE_GOURAUD, 0x0000ea15, FALSE},
10594 {D3DFOG_EXP, D3DFOG_EXP, D3DSHADE_FLAT, 0x0000ea15, FALSE},
10595 {D3DFOG_EXP, D3DFOG_EXP, D3DSHADE_GOURAUD, 0x0000ea15, FALSE},
10597 D3DDEVICEDESC7 caps;
10599 window = create_window();
10600 if (!(device = create_device(window, DDSCL_NORMAL)))
10602 skip("Failed to create a 3D device, skipping test.\n");
10603 DestroyWindow(window);
10604 return;
10607 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
10608 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10609 hr = IDirect3DDevice7_GetCaps(device, &caps);
10610 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10611 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE))
10612 skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping some fog tests\n");
10614 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
10615 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10616 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
10617 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10618 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
10619 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10620 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x0000ff00);
10621 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10622 conv.f = 5.0;
10623 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGDENSITY, conv.d);
10624 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10626 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
10627 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
10628 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
10629 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
10630 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x000000ff);
10631 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10633 for (i = 0; i < ARRAY_SIZE(tests); ++i)
10635 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE) && tests[i].tfog)
10636 continue;
10638 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00808080, 0.0f, 0);
10639 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10641 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SHADEMODE, tests[i].shade);
10642 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10643 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, tests[i].vfog);
10644 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10645 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, tests[i].tfog);
10646 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10647 hr = IDirect3DDevice7_BeginScene(device);
10648 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10649 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
10650 D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR, quad, 4, 0);
10651 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10652 hr = IDirect3DDevice7_EndScene(device);
10653 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10655 color = get_surface_color(rt, 0, 240);
10656 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x, case %u.\n", color, i);
10657 color = get_surface_color(rt, 320, 240);
10658 todo_wine_if (tests[i].todo)
10659 ok(compare_color(color, tests[i].middle_color, 2),
10660 "Got unexpected color 0x%08x, case %u.\n", color, i);
10661 color = get_surface_color(rt, 639, 240);
10662 ok(compare_color(color, 0x0000fd02, 2), "Got unexpected color 0x%08x, case %u.\n", color, i);
10665 IDirectDrawSurface7_Release(rt);
10666 refcount = IDirect3DDevice7_Release(device);
10667 ok(!refcount, "Device has %u references left.\n", refcount);
10668 DestroyWindow(window);
10671 static void test_fog_process_vertices(void)
10673 static D3DMATRIX view_matrix =
10675 1.0f, 0.0f, 0.0f, 0.0f,
10676 0.0f, 1.0f, 0.0f, 0.0f,
10677 0.0f, 0.0f, 0.5f, 0.0f,
10678 0.0f, 0.0f, 0.0f, 1.0f
10680 static D3DMATRIX model_matrix =
10682 1.0f, 0.0f, 0.0f, 0.0f,
10683 0.0f, 1.0f, 0.0f, 0.0f,
10684 0.0f, 0.0f, 0.75f, 0.0f,
10685 0.0f, 0.0f, 0.0f, 1.0f
10687 static D3DMATRIX identity_matrix =
10689 1.0f, 0.0f, 0.0f, 0.0f,
10690 0.0f, 1.0f, 0.0f, 0.0f,
10691 0.0f, 0.0f, 1.0f, 0.0f,
10692 0.0f, 0.0f, 0.0f, 1.0f
10695 static D3DLIGHT7 directional_light =
10697 D3DLIGHT_DIRECTIONAL,
10698 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
10699 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
10700 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
10701 {{0.0f}, {0.0f}, {0.0f}},
10702 {{0.0f}, {0.0f}, {1.0f}},
10705 struct vertex
10707 struct vec3 position;
10708 struct vec3 normal;
10710 static const struct
10712 struct vertex vertex;
10713 D3DFOGMODE fog_vertex_mode, fog_table_mode;
10714 BOOL range_fog;
10715 D3DCOLOR expected_color, expected_broken;
10717 tests[] =
10719 /* Some drivers ignore ranged fog state without an obvious reason, even with D3DPRASTERCAPS_FOGRANGE
10720 * set, while some others (including WARP driver on Windows 10) favour it.
10721 * Vertex fog result does not depend on table fog settings. */
10722 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_NONE, D3DFOG_NONE, FALSE, 0x8000ff00},
10723 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_NONE, D3DFOG_LINEAR, FALSE, 0x8000ff00},
10724 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_EXP, D3DFOG_NONE, FALSE, 0xaf00ff00},
10725 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_EXP2, D3DFOG_NONE, FALSE, 0xde00ff00},
10726 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_LINEAR, D3DFOG_NONE, FALSE, 0x9f00ff00},
10727 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_LINEAR, D3DFOG_LINEAR, FALSE, 0x9f00ff00},
10728 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_NONE, D3DFOG_NONE, TRUE, 0x8000ff00},
10729 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_EXP, D3DFOG_NONE, TRUE, 0x8800ff00, 0xaf00ff00},
10730 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_EXP2, D3DFOG_NONE, TRUE, 0xad00ff00, 0xde00ff00},
10731 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_LINEAR, D3DFOG_NONE, TRUE, 0x6000ff00, 0x9f00ff00},
10732 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_LINEAR, D3DFOG_EXP, TRUE, 0x6000ff00, 0x9f00ff00},
10733 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_EXP, D3DFOG_LINEAR, TRUE, 0x8800ff00, 0xaf00ff00},
10736 struct
10738 struct vec4 position;
10739 D3DCOLOR diffuse, specular;
10741 *dst_data;
10743 IDirect3DVertexBuffer7 *src_vb, *dst_vb;
10744 D3DVERTEXBUFFERDESC vb_desc;
10745 IDirect3DDevice7 *device;
10746 struct vertex *src_data;
10747 D3DMATERIAL7 material;
10748 IDirect3D7 *d3d;
10749 ULONG refcount;
10750 unsigned int i;
10751 HWND window;
10752 HRESULT hr;
10754 window = create_window();
10755 if (!(device = create_device(window, DDSCL_NORMAL)))
10757 skip("Failed to create a 3D device, skipping test.\n");
10758 DestroyWindow(window);
10759 return;
10761 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
10762 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10764 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &model_matrix);
10765 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10766 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &view_matrix);
10767 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10768 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &identity_matrix);
10769 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10771 memset(&vb_desc, 0, sizeof(vb_desc));
10772 vb_desc.dwSize = sizeof(vb_desc);
10773 vb_desc.dwFVF = D3DFVF_XYZ | D3DFVF_NORMAL;
10774 vb_desc.dwNumVertices = 1;
10775 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &src_vb, 0);
10776 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10778 memset(&vb_desc, 0, sizeof(vb_desc));
10779 vb_desc.dwSize = sizeof(vb_desc);
10780 vb_desc.dwFVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR;
10781 vb_desc.dwNumVertices = 1;
10782 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &dst_vb, 0);
10783 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10785 hr = IDirect3DDevice7_LightEnable(device, 0, TRUE);
10786 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10787 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, TRUE);
10788 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10789 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
10790 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10791 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
10792 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10793 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
10794 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10796 hr = IDirect3DDevice7_SetLight(device, 0, &directional_light);
10797 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10799 memset(&material, 0, sizeof(material));
10800 U1(U2(material).specular).r = 0.0f;
10801 U2(U2(material).specular).g = 1.0f;
10802 U3(U2(material).specular).b = 0.0f;
10803 U4(U2(material).specular).a = 0.5f;
10804 U4(material).power = 5.0f;
10805 hr = IDirect3DDevice7_SetMaterial(device, &material);
10806 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10808 for (i = 0; i < ARRAY_SIZE(tests); ++i)
10810 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE,
10811 tests[i].fog_vertex_mode);
10812 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE,
10813 tests[i].fog_table_mode);
10814 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10815 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_RANGEFOGENABLE, tests[i].range_fog);
10816 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10818 hr = IDirect3DVertexBuffer7_Lock(src_vb, 0, (void **)&src_data, NULL);
10819 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10820 *src_data = tests[i].vertex;
10821 hr = IDirect3DVertexBuffer7_Unlock(src_vb);
10822 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10824 hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL);
10825 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10826 memset(dst_data, 0, sizeof(*dst_data));
10827 hr = IDirect3DVertexBuffer7_Unlock(dst_vb);
10828 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10829 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 0,
10830 1, src_vb, 0, device, 0);
10831 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10833 hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL);
10834 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10836 ok(compare_color(dst_data->specular, tests[i].expected_color, 1)
10837 || broken(tests[i].expected_broken
10838 && compare_color(dst_data->specular, tests[i].expected_broken, 1)),
10839 "Expected color 0x%08x, got 0x%08x, test %u.\n",
10840 tests[i].expected_color, dst_data->specular, i);
10842 hr = IDirect3DVertexBuffer7_Unlock(dst_vb);
10843 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10846 IDirect3DVertexBuffer7_Release(dst_vb);
10847 IDirect3DVertexBuffer7_Release(src_vb);
10848 IDirect3D7_Release(d3d);
10849 refcount = IDirect3DDevice7_Release(device);
10850 ok(!refcount, "Device has %u references left.\n", refcount);
10851 DestroyWindow(window);
10854 static void test_negative_fixedfunction_fog(void)
10856 HRESULT hr;
10857 IDirect3DDevice7 *device;
10858 IDirectDrawSurface7 *rt;
10859 ULONG refcount;
10860 HWND window;
10861 D3DCOLOR color;
10862 static struct
10864 struct vec3 position;
10865 D3DCOLOR diffuse;
10867 quad[] =
10869 {{-1.0f, -1.0f, -0.5f}, 0xffff0000},
10870 {{-1.0f, 1.0f, -0.5f}, 0xffff0000},
10871 {{ 1.0f, -1.0f, -0.5f}, 0xffff0000},
10872 {{ 1.0f, 1.0f, -0.5f}, 0xffff0000},
10874 static struct
10876 struct vec4 position;
10877 D3DCOLOR diffuse;
10879 tquad[] =
10881 {{ 0.0f, 0.0f, -0.5f, 1.0f}, 0xffff0000},
10882 {{640.0f, 0.0f, -0.5f, 1.0f}, 0xffff0000},
10883 {{ 0.0f, 480.0f, -0.5f, 1.0f}, 0xffff0000},
10884 {{640.0f, 480.0f, -0.5f, 1.0f}, 0xffff0000},
10886 unsigned int i;
10887 static D3DMATRIX zero =
10889 1.0f, 0.0f, 0.0f, 0.0f,
10890 0.0f, 1.0f, 0.0f, 0.0f,
10891 0.0f, 0.0f, 0.0f, 0.0f,
10892 0.0f, 0.0f, 0.0f, 1.0f
10894 static D3DMATRIX identity =
10896 1.0f, 0.0f, 0.0f, 0.0f,
10897 0.0f, 1.0f, 0.0f, 0.0f,
10898 0.0f, 0.0f, 1.0f, 0.0f,
10899 0.0f, 0.0f, 0.0f, 1.0f
10901 static const struct
10903 DWORD pos_type;
10904 void *quad;
10905 D3DMATRIX *matrix;
10906 union
10908 float f;
10909 DWORD d;
10910 } start, end;
10911 D3DFOGMODE vfog, tfog;
10912 DWORD color, color_broken, color_broken2;
10914 tests[] =
10916 /* Run the XYZRHW tests first. Depth clamping is broken after RHW draws on the testbot.
10918 * Geforce8+ GPUs on Windows abs() table fog, everything else does not. */
10919 {D3DFVF_XYZRHW, tquad, &identity, { 0.0f}, {1.0f}, D3DFOG_NONE, D3DFOG_LINEAR,
10920 0x00ff0000, 0x00808000, 0x00808000},
10921 /* r200 GPUs and presumably all d3d8 and older HW clamp the fog
10922 * parameters to 0.0 and 1.0 in the table fog case. */
10923 {D3DFVF_XYZRHW, tquad, &identity, {-1.0f}, {0.0f}, D3DFOG_NONE, D3DFOG_LINEAR,
10924 0x00808000, 0x00ff0000, 0x0000ff00},
10925 /* test_fog_interpolation shows that vertex fog evaluates the fog
10926 * equation in the vertex pipeline. Start = -1.0 && end = 0.0 shows
10927 * that the abs happens before the fog equation is evaluated.
10929 * Vertex fog abs() behavior is the same on all GPUs. */
10930 {D3DFVF_XYZ, quad, &zero, { 0.0f}, {1.0f}, D3DFOG_LINEAR, D3DFOG_NONE,
10931 0x00808000, 0x00808000, 0x00808000},
10932 {D3DFVF_XYZ, quad, &zero, {-1.0f}, {0.0f}, D3DFOG_LINEAR, D3DFOG_NONE,
10933 0x0000ff00, 0x0000ff00, 0x0000ff00},
10934 {D3DFVF_XYZ, quad, &zero, { 0.0f}, {1.0f}, D3DFOG_EXP, D3DFOG_NONE,
10935 0x009b6400, 0x009b6400, 0x009b6400},
10937 D3DDEVICEDESC7 caps;
10939 window = create_window();
10940 if (!(device = create_device(window, DDSCL_NORMAL)))
10942 skip("Failed to create a 3D device, skipping test.\n");
10943 DestroyWindow(window);
10944 return;
10947 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
10948 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10949 hr = IDirect3DDevice7_GetCaps(device, &caps);
10950 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10951 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE))
10952 skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping some fog tests.\n");
10954 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
10955 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10956 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
10957 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10958 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
10959 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10960 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x0000ff00);
10961 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10962 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
10963 ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10965 for (i = 0; i < ARRAY_SIZE(tests); ++i)
10967 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE) && tests[i].tfog)
10968 continue;
10970 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0);
10971 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10973 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, tests[i].matrix);
10974 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
10975 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGSTART, tests[i].start.d);
10976 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10977 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGEND, tests[i].end.d);
10978 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10979 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, tests[i].vfog);
10980 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10981 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, tests[i].tfog);
10982 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10984 hr = IDirect3DDevice7_BeginScene(device);
10985 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10986 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
10987 tests[i].pos_type | D3DFVF_DIFFUSE, tests[i].quad, 4, 0);
10988 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10989 hr = IDirect3DDevice7_EndScene(device);
10990 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10992 color = get_surface_color(rt, 0, 240);
10993 ok(compare_color(color, tests[i].color, 2) || broken(compare_color(color, tests[i].color_broken, 2))
10994 || broken(compare_color(color, tests[i].color_broken2, 2)),
10995 "Got unexpected color 0x%08x, case %u.\n", color, i);
10998 IDirectDrawSurface7_Release(rt);
10999 refcount = IDirect3DDevice7_Release(device);
11000 ok(!refcount, "Device has %u references left.\n", refcount);
11001 DestroyWindow(window);
11004 static void test_table_fog_zw(void)
11006 HRESULT hr;
11007 IDirect3DDevice7 *device;
11008 IDirectDrawSurface7 *rt;
11009 ULONG refcount;
11010 HWND window;
11011 D3DCOLOR color;
11012 static struct
11014 struct vec4 position;
11015 D3DCOLOR diffuse;
11017 quad[] =
11019 {{ 0.0f, 0.0f, 0.0f, 0.0f}, 0xffff0000},
11020 {{640.0f, 0.0f, 0.0f, 0.0f}, 0xffff0000},
11021 {{ 0.0f, 480.0f, 0.0f, 0.0f}, 0xffff0000},
11022 {{640.0f, 480.0f, 0.0f, 0.0f}, 0xffff0000},
11024 static D3DMATRIX identity =
11026 1.0f, 0.0f, 0.0f, 0.0f,
11027 0.0f, 1.0f, 0.0f, 0.0f,
11028 0.0f, 0.0f, 1.0f, 0.0f,
11029 0.0f, 0.0f, 0.0f, 1.0f
11031 D3DDEVICEDESC7 caps;
11032 static const struct
11034 float z, w;
11035 D3DZBUFFERTYPE z_test;
11036 D3DCOLOR color;
11038 tests[] =
11040 {0.7f, 0.0f, D3DZB_TRUE, 0x004cb200},
11041 {0.7f, 0.0f, D3DZB_FALSE, 0x004cb200},
11042 {0.7f, 0.3f, D3DZB_TRUE, 0x004cb200},
11043 {0.7f, 0.3f, D3DZB_FALSE, 0x004cb200},
11044 {0.7f, 3.0f, D3DZB_TRUE, 0x004cb200},
11045 {0.7f, 3.0f, D3DZB_FALSE, 0x004cb200},
11046 {0.3f, 0.0f, D3DZB_TRUE, 0x00b24c00},
11047 {0.3f, 0.0f, D3DZB_FALSE, 0x00b24c00},
11049 unsigned int i;
11051 window = create_window();
11052 if (!(device = create_device(window, DDSCL_NORMAL)))
11054 skip("Failed to create a 3D device, skipping test.\n");
11055 DestroyWindow(window);
11056 return;
11059 hr = IDirect3DDevice7_GetCaps(device, &caps);
11060 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
11061 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE))
11063 skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping POSITIONT table fog test.\n");
11064 goto done;
11066 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
11067 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11069 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
11070 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
11071 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
11072 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
11073 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x0000ff00);
11074 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
11075 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
11076 ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11077 /* Work around an AMD Windows driver bug. Needs a proj matrix applied redundantly. */
11078 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &identity);
11079 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
11080 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_LINEAR);
11081 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
11083 for (i = 0; i < ARRAY_SIZE(tests); ++i)
11085 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x000000ff, 1.0f, 0);
11086 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
11088 quad[0].position.z = tests[i].z;
11089 quad[1].position.z = tests[i].z;
11090 quad[2].position.z = tests[i].z;
11091 quad[3].position.z = tests[i].z;
11092 quad[0].position.w = tests[i].w;
11093 quad[1].position.w = tests[i].w;
11094 quad[2].position.w = tests[i].w;
11095 quad[3].position.w = tests[i].w;
11096 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, tests[i].z_test);
11097 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
11099 hr = IDirect3DDevice7_BeginScene(device);
11100 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11101 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
11102 D3DFVF_XYZRHW | D3DFVF_DIFFUSE, 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, 0, 240);
11108 ok(compare_color(color, tests[i].color, 2),
11109 "Got unexpected color 0x%08x, expected 0x%8x, case %u.\n", color, tests[i].color, i);
11112 IDirectDrawSurface7_Release(rt);
11113 done:
11114 refcount = IDirect3DDevice7_Release(device);
11115 ok(!refcount, "Device has %u references left.\n", refcount);
11116 DestroyWindow(window);
11119 static void test_signed_formats(void)
11121 HRESULT hr;
11122 IDirect3DDevice7 *device;
11123 IDirect3D7 *d3d;
11124 IDirectDraw7 *ddraw;
11125 IDirectDrawSurface7 *surface, *rt;
11126 DDSURFACEDESC2 surface_desc;
11127 ULONG refcount;
11128 HWND window;
11129 D3DCOLOR color, expected_color;
11130 static struct
11132 struct vec3 position;
11133 struct vec2 texcoord;
11135 quad[] =
11137 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
11138 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
11139 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
11140 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
11142 /* See test_signed_formats() in dlls/d3d9/tests/visual.c for an explanation
11143 * of these values. */
11144 static const USHORT content_v8u8[4][4] =
11146 {0x0000, 0x7f7f, 0x8880, 0x0000},
11147 {0x0080, 0x8000, 0x7f00, 0x007f},
11148 {0x193b, 0xe8c8, 0x0808, 0xf8f8},
11149 {0x4444, 0xc0c0, 0xa066, 0x22e0},
11151 static const DWORD content_x8l8v8u8[4][4] =
11153 {0x00000000, 0x00ff7f7f, 0x00008880, 0x00ff0000},
11154 {0x00000080, 0x00008000, 0x00007f00, 0x0000007f},
11155 {0x0041193b, 0x0051e8c8, 0x00040808, 0x00fff8f8},
11156 {0x00824444, 0x0000c0c0, 0x00c2a066, 0x009222e0},
11158 static const USHORT content_l6v5u5[4][4] =
11160 {0x0000, 0xfdef, 0x0230, 0xfc00},
11161 {0x0010, 0x0200, 0x01e0, 0x000f},
11162 {0x4067, 0x53b9, 0x0421, 0xffff},
11163 {0x8108, 0x0318, 0xc28c, 0x909c},
11165 static const struct
11167 const char *name;
11168 const void *content;
11169 SIZE_T pixel_size;
11170 BOOL blue;
11171 unsigned int slop, slop_broken;
11172 DDPIXELFORMAT format;
11174 formats[] =
11177 "D3DFMT_V8U8", content_v8u8, sizeof(WORD), FALSE, 1, 0,
11179 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV, 0,
11180 {16}, {0x000000ff}, {0x0000ff00}, {0x00000000}, {0x00000000}
11184 "D3DFMT_X8L8V8U8", content_x8l8v8u8, sizeof(DWORD), TRUE, 1, 0,
11186 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE, 0,
11187 {32}, {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}
11191 "D3DFMT_L6V5U5", content_l6v5u5, sizeof(WORD), TRUE, 4, 7,
11193 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE, 0,
11194 {16}, {0x0000001f}, {0x000003e0}, {0x0000fc00}, {0x00000000}
11198 /* No V16U16 or Q8W8V8U8 support in ddraw. */
11200 static const D3DCOLOR expected_colors[4][4] =
11202 {0x00808080, 0x00fefeff, 0x00010780, 0x008080ff},
11203 {0x00018080, 0x00800180, 0x0080fe80, 0x00fe8080},
11204 {0x00ba98a0, 0x004767a8, 0x00888881, 0x007878ff},
11205 {0x00c3c3c0, 0x003f3f80, 0x00e51fe1, 0x005fa2c8},
11207 unsigned int i, width, x, y;
11208 D3DDEVICEDESC7 device_desc;
11210 window = create_window();
11211 if (!(device = create_device(window, DDSCL_NORMAL)))
11213 skip("Failed to create a 3D device, skipping test.\n");
11214 DestroyWindow(window);
11215 return;
11218 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
11219 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
11220 if (!(device_desc.dwTextureOpCaps & D3DTEXOPCAPS_BLENDFACTORALPHA))
11222 skip("D3DTOP_BLENDFACTORALPHA not supported, skipping bumpmap format tests.\n");
11223 goto done;
11226 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
11227 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
11228 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
11229 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
11230 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
11231 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11233 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
11234 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
11236 /* dst = tex * 0.5 + 1.0 * (1.0 - 0.5) = tex * 0.5 + 0.5 */
11237 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x80ffffff);
11238 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
11239 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_BLENDFACTORALPHA);
11240 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
11241 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
11242 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
11243 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
11244 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
11246 for (i = 0; i < ARRAY_SIZE(formats); ++i)
11248 for (width = 1; width < 5; width += 3)
11250 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
11251 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
11253 memset(&surface_desc, 0, sizeof(surface_desc));
11254 surface_desc.dwSize = sizeof(surface_desc);
11255 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
11256 surface_desc.dwWidth = width;
11257 surface_desc.dwHeight = 4;
11258 U4(surface_desc).ddpfPixelFormat = formats[i].format;
11259 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
11260 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11261 if (FAILED(hr))
11263 skip("%s textures not supported, skipping.\n", formats[i].name);
11264 continue;
11266 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, format %s.\n", hr, formats[i].name);
11267 hr = IDirect3DDevice7_SetTexture(device, 0, surface);
11268 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x, format %s.\n", hr, formats[i].name);
11270 memset(&surface_desc, 0, sizeof(surface_desc));
11271 surface_desc.dwSize = sizeof(surface_desc);
11272 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, 0, NULL);
11273 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, format %s.\n", hr, formats[i].name);
11274 for (y = 0; y < 4; y++)
11276 memcpy((char *)surface_desc.lpSurface + y * U1(surface_desc).lPitch,
11277 (char *)formats[i].content + y * 4 * formats[i].pixel_size,
11278 width * formats[i].pixel_size);
11280 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11281 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, format %s.\n", hr, formats[i].name);
11283 hr = IDirect3DDevice7_BeginScene(device);
11284 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11285 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
11286 D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
11287 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11288 hr = IDirect3DDevice7_EndScene(device);
11289 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11291 for (y = 0; y < 4; y++)
11293 for (x = 0; x < width; x++)
11295 expected_color = expected_colors[y][x];
11296 if (!formats[i].blue)
11297 expected_color |= 0x000000ff;
11299 color = get_surface_color(rt, 80 + 160 * x, 60 + 120 * y);
11300 ok(compare_color(color, expected_color, formats[i].slop)
11301 || broken(compare_color(color, expected_color, formats[i].slop_broken)),
11302 "Expected color 0x%08x, got 0x%08x, format %s, location %ux%u.\n",
11303 expected_color, color, formats[i].name, x, y);
11307 IDirectDrawSurface7_Release(surface);
11312 IDirectDrawSurface7_Release(rt);
11313 IDirectDraw7_Release(ddraw);
11314 IDirect3D7_Release(d3d);
11316 done:
11317 refcount = IDirect3DDevice7_Release(device);
11318 ok(!refcount, "Device has %u references left.\n", refcount);
11319 DestroyWindow(window);
11322 static void test_color_fill(void)
11324 HRESULT hr;
11325 IDirect3DDevice7 *device;
11326 IDirect3D7 *d3d;
11327 IDirectDraw7 *ddraw;
11328 IDirectDrawSurface7 *surface, *surface2;
11329 DDSURFACEDESC2 surface_desc;
11330 DDPIXELFORMAT z_fmt;
11331 ULONG refcount;
11332 HWND window;
11333 unsigned int i;
11334 DDBLTFX fx;
11335 RECT rect = {5, 5, 7, 7};
11336 DWORD *color;
11337 DWORD supported_fmts = 0, num_fourcc_codes, *fourcc_codes;
11338 DDCAPS hal_caps;
11339 static const struct
11341 DWORD caps, caps2;
11342 HRESULT colorfill_hr, depthfill_hr;
11343 BOOL rop_success;
11344 const char *name;
11345 DWORD result;
11346 BOOL check_result;
11347 DDPIXELFORMAT format;
11349 tests[] =
11352 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
11353 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain RGB", 0xdeadbeef, TRUE,
11355 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
11356 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
11360 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0,
11361 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain RGB", 0xdeadbeef, TRUE,
11363 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
11364 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
11368 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0,
11369 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem texture RGB", 0xdeadbeef, TRUE,
11371 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
11372 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
11376 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0,
11377 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem texture RGB", 0xdeadbeef, TRUE,
11379 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
11380 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
11384 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
11385 DD_OK, DDERR_INVALIDPARAMS, TRUE, "managed texture RGB", 0xdeadbeef, TRUE,
11387 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
11388 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
11392 DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY, 0,
11393 DDERR_INVALIDPARAMS, DD_OK, TRUE, "vidmem zbuffer", 0xdeadbeef, TRUE,
11394 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
11397 DDSCAPS_ZBUFFER | DDSCAPS_SYSTEMMEMORY, 0,
11398 DDERR_INVALIDPARAMS, DD_OK, TRUE, "sysmem zbuffer", 0xdeadbeef, TRUE,
11399 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
11402 /* Colorfill on YUV surfaces always returns DD_OK, but the content is
11403 * different afterwards. DX9+ GPUs set one of the two luminance values
11404 * in each block, but AMD and Nvidia GPUs disagree on which luminance
11405 * value they set. r200 (dx8) just sets the entire block to the clear
11406 * value. */
11407 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
11408 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain YUY2", 0, FALSE,
11410 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
11411 {0}, {0}, {0}, {0}, {0}
11415 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
11416 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain UYVY", 0, FALSE,
11418 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
11419 {0}, {0}, {0}, {0}, {0}
11423 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY, 0,
11424 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay YUY2", 0, FALSE,
11426 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
11427 {0}, {0}, {0}, {0}, {0}
11431 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY, 0,
11432 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay UYVY", 0, FALSE,
11434 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
11435 {0}, {0}, {0}, {0}, {0}
11439 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0,
11440 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "vidmem texture DXT1", 0, FALSE,
11442 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
11443 {0}, {0}, {0}, {0}, {0}
11447 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0,
11448 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "sysmem texture DXT1", 0, FALSE,
11450 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
11451 {0}, {0}, {0}, {0}, {0}
11455 /* The testbot fills this with 0x00 instead of the blue channel. The sysmem
11456 * surface works, presumably because it is handled by the runtime instead of
11457 * the driver. */
11458 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
11459 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain P8", 0xefefefef, FALSE,
11461 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
11462 {8}, {0}, {0}, {0}, {0}
11466 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0,
11467 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain P8", 0xefefefef, TRUE,
11469 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
11470 {8}, {0}, {0}, {0}, {0}
11474 static const struct
11476 DWORD rop;
11477 const char *name;
11478 HRESULT hr;
11480 rops[] =
11482 {SRCCOPY, "SRCCOPY", DD_OK},
11483 {SRCPAINT, "SRCPAINT", DDERR_NORASTEROPHW},
11484 {SRCAND, "SRCAND", DDERR_NORASTEROPHW},
11485 {SRCINVERT, "SRCINVERT", DDERR_NORASTEROPHW},
11486 {SRCERASE, "SRCERASE", DDERR_NORASTEROPHW},
11487 {NOTSRCCOPY, "NOTSRCCOPY", DDERR_NORASTEROPHW},
11488 {NOTSRCERASE, "NOTSRCERASE", DDERR_NORASTEROPHW},
11489 {MERGECOPY, "MERGECOPY", DDERR_NORASTEROPHW},
11490 {MERGEPAINT, "MERGEPAINT", DDERR_NORASTEROPHW},
11491 {PATCOPY, "PATCOPY", DDERR_NORASTEROPHW},
11492 {PATPAINT, "PATPAINT", DDERR_NORASTEROPHW},
11493 {PATINVERT, "PATINVERT", DDERR_NORASTEROPHW},
11494 {DSTINVERT, "DSTINVERT", DDERR_NORASTEROPHW},
11495 {BLACKNESS, "BLACKNESS", DD_OK},
11496 {WHITENESS, "WHITENESS", DD_OK},
11497 {0xaa0029, "0xaa0029", DDERR_NORASTEROPHW} /* noop */
11500 window = create_window();
11501 if (!(device = create_device(window, DDSCL_NORMAL)))
11503 skip("Failed to create a 3D device, skipping test.\n");
11504 DestroyWindow(window);
11505 return;
11508 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
11509 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
11510 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
11511 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
11513 memset(&z_fmt, 0, sizeof(z_fmt));
11514 IDirect3D7_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
11515 if (!z_fmt.dwSize)
11516 skip("No Z buffer formats supported, skipping Z buffer colorfill test.\n");
11518 IDirect3DDevice7_EnumTextureFormats(device, test_block_formats_creation_cb, &supported_fmts);
11519 if (!(supported_fmts & SUPPORT_DXT1))
11520 skip("DXT1 textures not supported, skipping DXT1 colorfill test.\n");
11522 IDirect3D7_Release(d3d);
11524 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
11525 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
11526 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
11527 num_fourcc_codes * sizeof(*fourcc_codes));
11528 if (!fourcc_codes)
11529 goto done;
11530 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
11531 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
11532 for (i = 0; i < num_fourcc_codes; i++)
11534 if (fourcc_codes[i] == MAKEFOURCC('Y', 'U', 'Y', '2'))
11535 supported_fmts |= SUPPORT_YUY2;
11536 else if (fourcc_codes[i] == MAKEFOURCC('U', 'Y', 'V', 'Y'))
11537 supported_fmts |= SUPPORT_UYVY;
11539 HeapFree(GetProcessHeap(), 0, fourcc_codes);
11541 memset(&hal_caps, 0, sizeof(hal_caps));
11542 hal_caps.dwSize = sizeof(hal_caps);
11543 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
11544 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
11546 if (!(supported_fmts & (SUPPORT_YUY2 | SUPPORT_UYVY)) || !(hal_caps.dwCaps & DDCAPS_OVERLAY))
11547 skip("Overlays or some YUV formats not supported, skipping YUV colorfill tests.\n");
11549 for (i = 0; i < ARRAY_SIZE(tests); ++i)
11551 DWORD expected_broken = tests[i].result;
11553 /* Some Windows drivers modify dwFillColor when it is used on P8 or FourCC formats. */
11554 memset(&fx, 0, sizeof(fx));
11555 fx.dwSize = sizeof(fx);
11556 U5(fx).dwFillColor = 0xdeadbeef;
11558 memset(&surface_desc, 0, sizeof(surface_desc));
11559 surface_desc.dwSize = sizeof(surface_desc);
11560 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
11561 surface_desc.dwWidth = 64;
11562 surface_desc.dwHeight = 64;
11563 U4(surface_desc).ddpfPixelFormat = tests[i].format;
11564 surface_desc.ddsCaps.dwCaps = tests[i].caps;
11565 surface_desc.ddsCaps.dwCaps2 = tests[i].caps2;
11567 if (tests[i].format.dwFourCC == MAKEFOURCC('D','X','T','1') && !(supported_fmts & SUPPORT_DXT1))
11568 continue;
11569 if (tests[i].format.dwFourCC == MAKEFOURCC('Y','U','Y','2') && !(supported_fmts & SUPPORT_YUY2))
11570 continue;
11571 if (tests[i].format.dwFourCC == MAKEFOURCC('U','Y','V','Y') && !(supported_fmts & SUPPORT_UYVY))
11572 continue;
11573 if (tests[i].caps & DDSCAPS_OVERLAY && !(hal_caps.dwCaps & DDCAPS_OVERLAY))
11574 continue;
11576 if (tests[i].caps & DDSCAPS_ZBUFFER)
11578 if (!z_fmt.dwSize)
11579 continue;
11581 U4(surface_desc).ddpfPixelFormat = z_fmt;
11582 /* Some drivers seem to convert depth values incorrectly or not at
11583 * all. Affects at least AMD PALM, 8.17.10.1247. */
11584 if (tests[i].caps & DDSCAPS_VIDEOMEMORY)
11586 DWORD expected;
11587 float f, g;
11589 expected = tests[i].result & U3(z_fmt).dwZBitMask;
11590 f = ceilf(logf(expected + 1.0f) / logf(2.0f));
11591 g = (f + 1.0f) / 2.0f;
11592 g -= (int)g;
11593 expected_broken = (expected / exp2f(f) - g) * 256;
11594 expected_broken *= 0x01010101;
11598 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11599 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, surface %s.\n", hr, tests[i].name);
11601 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11602 todo_wine_if (tests[i].format.dwFourCC)
11603 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
11604 hr, tests[i].colorfill_hr, tests[i].name);
11606 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11607 todo_wine_if (tests[i].format.dwFourCC)
11608 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
11609 hr, tests[i].colorfill_hr, tests[i].name);
11611 if (SUCCEEDED(hr) && tests[i].check_result)
11613 memset(&surface_desc, 0, sizeof(surface_desc));
11614 surface_desc.dwSize = sizeof(surface_desc);
11615 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
11616 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
11617 color = surface_desc.lpSurface;
11618 ok(*color == tests[i].result, "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
11619 *color, tests[i].result, tests[i].name);
11620 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11621 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
11624 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11625 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
11626 hr, tests[i].depthfill_hr, tests[i].name);
11627 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11628 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
11629 hr, tests[i].depthfill_hr, tests[i].name);
11631 if (SUCCEEDED(hr) && tests[i].check_result)
11633 memset(&surface_desc, 0, sizeof(surface_desc));
11634 surface_desc.dwSize = sizeof(surface_desc);
11635 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
11636 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
11637 color = surface_desc.lpSurface;
11638 ok((*color & U3(z_fmt).dwZBitMask) == (tests[i].result & U3(z_fmt).dwZBitMask)
11639 || broken((*color & U3(z_fmt).dwZBitMask) == (expected_broken & U3(z_fmt).dwZBitMask)),
11640 "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
11641 *color & U3(z_fmt).dwZBitMask, tests[i].result & U3(z_fmt).dwZBitMask, tests[i].name);
11642 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11643 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
11646 U5(fx).dwFillColor = 0xdeadbeef;
11647 fx.dwROP = BLACKNESS;
11648 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
11649 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
11650 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
11651 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
11652 U5(fx).dwFillColor, tests[i].name);
11654 if (SUCCEEDED(hr) && tests[i].check_result)
11656 memset(&surface_desc, 0, sizeof(surface_desc));
11657 surface_desc.dwSize = sizeof(surface_desc);
11658 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
11659 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
11660 color = surface_desc.lpSurface;
11661 ok(*color == 0, "Got clear result 0x%08x, expected 0x00000000, surface %s.\n",
11662 *color, tests[i].name);
11663 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11664 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
11667 fx.dwROP = WHITENESS;
11668 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
11669 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
11670 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
11671 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
11672 U5(fx).dwFillColor, tests[i].name);
11674 if (SUCCEEDED(hr) && tests[i].check_result)
11676 memset(&surface_desc, 0, sizeof(surface_desc));
11677 surface_desc.dwSize = sizeof(surface_desc);
11678 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
11679 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
11680 color = surface_desc.lpSurface;
11681 /* WHITENESS sets the alpha channel to 0x00. Ignore this for now. */
11682 ok((*color & 0x00ffffff) == 0x00ffffff, "Got clear result 0x%08x, expected 0xffffffff, surface %s.\n",
11683 *color, tests[i].name);
11684 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11685 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
11688 IDirectDrawSurface7_Release(surface);
11691 memset(&fx, 0, sizeof(fx));
11692 fx.dwSize = sizeof(fx);
11693 U5(fx).dwFillColor = 0xdeadbeef;
11694 fx.dwROP = WHITENESS;
11696 memset(&surface_desc, 0, sizeof(surface_desc));
11697 surface_desc.dwSize = sizeof(surface_desc);
11698 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
11699 surface_desc.dwWidth = 64;
11700 surface_desc.dwHeight = 64;
11701 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
11702 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
11703 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
11704 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
11705 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
11706 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
11707 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
11708 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11709 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11710 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
11711 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11713 /* No DDBLTFX. */
11714 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, NULL);
11715 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11716 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, NULL);
11717 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11719 /* Unused source rectangle. */
11720 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11721 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
11722 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
11723 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
11725 /* Unused source surface. */
11726 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11727 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11728 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
11729 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
11730 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11731 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11732 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
11733 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
11735 /* Inverted destination or source rectangle. */
11736 SetRect(&rect, 5, 7, 7, 5);
11737 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11738 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
11739 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11740 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
11741 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11742 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11743 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11744 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11745 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
11746 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
11748 /* Negative rectangle. */
11749 SetRect(&rect, -1, -1, 5, 5);
11750 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11751 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
11752 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11753 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
11754 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11755 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11756 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11757 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11758 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
11759 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
11761 /* Out of bounds rectangle. */
11762 SetRect(&rect, 0, 0, 65, 65);
11763 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11764 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
11765 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
11766 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
11768 /* Combine multiple flags. */
11769 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11770 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
11771 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
11772 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11773 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
11774 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11776 for (i = 0; i < ARRAY_SIZE(rops); ++i)
11778 fx.dwROP = rops[i].rop;
11779 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
11780 ok(hr == rops[i].hr, "Got unexpected hr %#x for rop %s.\n", hr, rops[i].name);
11783 IDirectDrawSurface7_Release(surface2);
11784 IDirectDrawSurface7_Release(surface);
11786 if (!z_fmt.dwSize)
11787 goto done;
11789 memset(&surface_desc, 0, sizeof(surface_desc));
11790 surface_desc.dwSize = sizeof(surface_desc);
11791 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
11792 surface_desc.dwWidth = 64;
11793 surface_desc.dwHeight = 64;
11794 U4(surface_desc).ddpfPixelFormat = z_fmt;
11795 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
11796 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11797 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11798 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
11799 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11801 /* No DDBLTFX. */
11802 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, NULL);
11803 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11805 /* Unused source rectangle. */
11806 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11807 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
11809 /* Unused source surface. */
11810 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11811 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11812 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11813 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11815 /* Inverted destination or source rectangle. */
11816 SetRect(&rect, 5, 7, 7, 5);
11817 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11818 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
11819 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11820 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
11821 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11822 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11823 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11824 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11826 /* Negative rectangle. */
11827 SetRect(&rect, -1, -1, 5, 5);
11828 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11829 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
11830 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11831 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
11832 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11833 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11834 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11835 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11837 /* Out of bounds rectangle. */
11838 SetRect(&rect, 0, 0, 65, 65);
11839 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11840 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
11842 /* Combine multiple flags. */
11843 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11844 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11846 IDirectDrawSurface7_Release(surface2);
11847 IDirectDrawSurface7_Release(surface);
11849 done:
11850 IDirectDraw7_Release(ddraw);
11851 refcount = IDirect3DDevice7_Release(device);
11852 ok(!refcount, "Device has %u references left.\n", refcount);
11853 DestroyWindow(window);
11856 static void test_texcoordindex(void)
11858 static D3DMATRIX mat =
11860 1.0f, 0.0f, 0.0f, 0.0f,
11861 0.0f, 0.0f, 0.0f, 0.0f,
11862 0.0f, 0.0f, 0.0f, 0.0f,
11863 0.0f, 0.0f, 0.0f, 0.0f,
11865 static struct
11867 struct vec3 pos;
11868 struct vec2 texcoord1;
11869 struct vec2 texcoord2;
11870 struct vec2 texcoord3;
11872 quad[] =
11874 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f}},
11875 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 0.0f}},
11876 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}},
11877 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}},
11879 static const DWORD fvf = D3DFVF_XYZ | D3DFVF_TEX3;
11880 IDirect3DDevice7 *device;
11881 IDirect3D7 *d3d;
11882 IDirectDraw7 *ddraw;
11883 IDirectDrawSurface7 *rt;
11884 HWND window;
11885 HRESULT hr;
11886 IDirectDrawSurface7 *texture1, *texture2;
11887 DDSURFACEDESC2 surface_desc;
11888 ULONG refcount;
11889 D3DCOLOR color;
11890 DWORD *ptr;
11892 window = create_window();
11893 if (!(device = create_device(window, DDSCL_NORMAL)))
11895 skip("Failed to create a 3D device, skipping test.\n");
11896 DestroyWindow(window);
11897 return;
11900 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
11901 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
11902 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
11903 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
11904 IDirect3D7_Release(d3d);
11906 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
11907 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11909 memset(&surface_desc, 0, sizeof(surface_desc));
11910 surface_desc.dwSize = sizeof(surface_desc);
11911 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
11912 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
11913 surface_desc.dwWidth = 2;
11914 surface_desc.dwHeight = 2;
11915 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
11916 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
11917 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
11918 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
11919 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
11920 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
11921 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
11922 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture1, NULL);
11923 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11924 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture2, NULL);
11925 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11927 memset(&surface_desc, 0, sizeof(surface_desc));
11928 surface_desc.dwSize = sizeof(surface_desc);
11929 hr = IDirectDrawSurface7_Lock(texture1, 0, &surface_desc, 0, NULL);
11930 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11931 ptr = surface_desc.lpSurface;
11932 ptr[0] = 0xff000000;
11933 ptr[1] = 0xff00ff00;
11934 ptr += U1(surface_desc).lPitch / sizeof(*ptr);
11935 ptr[0] = 0xff0000ff;
11936 ptr[1] = 0xff00ffff;
11937 hr = IDirectDrawSurface7_Unlock(texture1, NULL);
11938 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11940 memset(&surface_desc, 0, sizeof(surface_desc));
11941 surface_desc.dwSize = sizeof(surface_desc);
11942 hr = IDirectDrawSurface7_Lock(texture2, 0, &surface_desc, 0, NULL);
11943 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11944 ptr = surface_desc.lpSurface;
11945 ptr[0] = 0xff000000;
11946 ptr[1] = 0xff0000ff;
11947 ptr += U1(surface_desc).lPitch / sizeof(*ptr);
11948 ptr[0] = 0xffff0000;
11949 ptr[1] = 0xffff00ff;
11950 hr = IDirectDrawSurface7_Unlock(texture2, 0);
11951 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11953 hr = IDirect3DDevice7_SetTexture(device, 0, texture1);
11954 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
11955 hr = IDirect3DDevice7_SetTexture(device, 1, texture2);
11956 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
11957 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
11958 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
11959 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
11960 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
11961 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
11962 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11963 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_ADD);
11964 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
11965 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
11966 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11967 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
11968 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11969 hr = IDirect3DDevice7_SetTextureStageState(device, 2, D3DTSS_COLOROP, D3DTOP_DISABLE);
11970 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
11972 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_TEXCOORDINDEX, 1);
11973 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
11974 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXCOORDINDEX, 0);
11975 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
11977 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
11978 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
11980 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
11981 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
11983 hr = IDirect3DDevice7_BeginScene(device);
11984 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11985 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
11986 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11987 hr = IDirect3DDevice7_EndScene(device);
11988 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11990 color = get_surface_color(rt, 160, 120);
11991 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
11992 color = get_surface_color(rt, 480, 120);
11993 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
11994 color = get_surface_color(rt, 160, 360);
11995 ok(compare_color(color, 0x00ff0000, 2), "Got unexpected color 0x%08x.\n", color);
11996 color = get_surface_color(rt, 480, 360);
11997 ok(compare_color(color, 0x00ffffff, 2), "Got unexpected color 0x%08x.\n", color);
11999 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
12000 ok(SUCCEEDED(hr), "Failed to set texture transform flags, hr %#x.\n", hr);
12001 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_TEXTURE1, &mat);
12002 ok(SUCCEEDED(hr), "Failed to set transformation matrix, hr %#x.\n", hr);
12004 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
12005 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12007 hr = IDirect3DDevice7_BeginScene(device);
12008 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12009 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
12010 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12011 hr = IDirect3DDevice7_EndScene(device);
12012 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12014 color = get_surface_color(rt, 160, 120);
12015 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
12016 color = get_surface_color(rt, 480, 120);
12017 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
12018 color = get_surface_color(rt, 160, 360);
12019 ok(compare_color(color, 0x00000000, 2), "Got unexpected color 0x%08x.\n", color);
12020 color = get_surface_color(rt, 480, 360);
12021 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
12023 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
12024 ok(SUCCEEDED(hr), "Failed to set texture transform flags, hr %#x.\n", hr);
12025 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXCOORDINDEX, 2);
12026 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
12028 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
12029 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12031 hr = IDirect3DDevice7_BeginScene(device);
12032 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12033 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
12034 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12035 hr = IDirect3DDevice7_EndScene(device);
12036 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12038 color = get_surface_color(rt, 160, 120);
12039 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
12040 color = get_surface_color(rt, 480, 120);
12041 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
12042 color = get_surface_color(rt, 160, 360);
12043 ok(compare_color(color, 0x00ff00ff, 2), "Got unexpected color 0x%08x.\n", color);
12044 color = get_surface_color(rt, 480, 360);
12045 ok(compare_color(color, 0x00ffff00, 2), "Got unexpected color 0x%08x.\n", color);
12047 IDirectDrawSurface7_Release(texture1);
12048 IDirectDrawSurface7_Release(texture2);
12050 IDirectDrawSurface7_Release(rt);
12051 IDirectDraw7_Release(ddraw);
12052 refcount = IDirect3DDevice7_Release(device);
12053 ok(!refcount, "Device has %u references left.\n", refcount);
12054 DestroyWindow(window);
12057 static void test_colorkey_precision(void)
12059 static struct
12061 struct vec3 pos;
12062 struct vec2 texcoord;
12064 quad[] =
12066 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
12067 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
12068 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
12069 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
12072 static const struct
12074 unsigned int max, shift, bpp, clear;
12075 const char *name;
12076 BOOL skip_nv;
12077 DDPIXELFORMAT fmt;
12079 tests[] =
12082 255, 0, 4, 0x00345678, "D3DFMT_X8R8G8B8", FALSE,
12084 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
12085 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
12090 63, 5, 2, 0x5678, "D3DFMT_R5G6B5, G channel", FALSE,
12092 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
12093 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
12098 31, 0, 2, 0x5678, "D3DFMT_R5G6B5, B channel", FALSE,
12100 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
12101 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
12106 15, 0, 2, 0x0678, "D3DFMT_A4R4G4B4", TRUE,
12108 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
12109 {16}, {0x0f00}, {0x00f0}, {0x000f}, {0xf000}
12114 IDirectDrawSurface7 *src, *dst, *texture;
12115 DDSURFACEDESC2 surface_desc, lock_desc;
12116 DWORD data[4] = {0}, color_mask;
12117 IDirect3DDevice7 *device;
12118 IDirectDrawSurface7 *rt;
12119 IDirectDraw7 *ddraw;
12120 unsigned int t, c;
12121 DDCOLORKEY ckey;
12122 IDirect3D7 *d3d;
12123 BOOL is_nvidia;
12124 ULONG refcount;
12125 D3DCOLOR color;
12126 HWND window;
12127 HRESULT hr;
12128 DDBLTFX fx;
12130 window = create_window();
12131 if (!(device = create_device(window, DDSCL_NORMAL)))
12133 skip("Failed to create a 3D device, skipping test.\n");
12134 DestroyWindow(window);
12135 return;
12138 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
12139 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12140 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
12141 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12142 IDirect3D7_Release(d3d);
12143 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
12144 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12146 is_nvidia = ddraw_is_nvidia(ddraw);
12147 /* The Windows 8 WARP driver has plenty of false negatives in X8R8G8B8
12148 * (color key doesn't match although the values are equal), and a false
12149 * positive when the color key is 0 and the texture contains the value 1.
12150 * Also on random occasions 254 == 255 and 255 != 255.
12151 * Crashes on Windows 10 WARP. */
12152 if (ddraw_is_warp(ddraw))
12154 win_skip("Skipping test on WARP driver.\n");
12155 goto done;
12158 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
12159 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12160 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
12161 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12162 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
12163 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12164 /* Multiply the texture read result with 0, that way the result color if the key doesn't
12165 * match is constant. In theory color keying works without reading the texture result
12166 * (meaning we could just op=arg1, arg1=tfactor), but the Geforce7 Windows driver begs
12167 * to differ. */
12168 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
12169 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12170 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
12171 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12172 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
12173 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12174 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x00000000);
12175 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12177 memset(&fx, 0, sizeof(fx));
12178 fx.dwSize = sizeof(fx);
12179 memset(&lock_desc, 0, sizeof(lock_desc));
12180 lock_desc.dwSize = sizeof(lock_desc);
12182 for (t = 0; t < ARRAY_SIZE(tests); ++t)
12184 if (is_nvidia && tests[t].skip_nv)
12186 win_skip("Skipping test %s on Nvidia Windows drivers.\n", tests[t].name);
12187 continue;
12190 memset(&surface_desc, 0, sizeof(surface_desc));
12191 surface_desc.dwSize = sizeof(surface_desc);
12192 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
12193 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12194 surface_desc.dwWidth = 4;
12195 surface_desc.dwHeight = 1;
12196 U4(surface_desc).ddpfPixelFormat = tests[t].fmt;
12197 /* Windows XP (at least with the r200 driver, other drivers untested) produces
12198 * garbage when doing color keyed texture->texture blits. */
12199 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
12200 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12201 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
12202 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12204 U5(fx).dwFillColor = tests[t].clear;
12205 /* On the w8 testbot (WARP driver) the blit result has different values in the
12206 * X channel. */
12207 color_mask = U2(tests[t].fmt).dwRBitMask
12208 | U3(tests[t].fmt).dwGBitMask
12209 | U4(tests[t].fmt).dwBBitMask;
12211 for (c = 0; c <= tests[t].max; ++c)
12213 /* The idiotic Nvidia Windows driver can't change the color key on a d3d
12214 * texture after it has been set once... */
12215 surface_desc.dwFlags |= DDSD_CKSRCBLT;
12216 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
12217 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = c << tests[t].shift;
12218 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = c << tests[t].shift;
12219 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
12220 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12221 hr = IDirect3DDevice7_SetTexture(device, 0, texture);
12222 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12224 hr = IDirectDrawSurface7_Blt(dst, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
12225 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12227 hr = IDirectDrawSurface7_Lock(src, NULL, &lock_desc, DDLOCK_WAIT, NULL);
12228 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12229 switch (tests[t].bpp)
12231 case 4:
12232 ((DWORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
12233 ((DWORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
12234 ((DWORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
12235 ((DWORD *)lock_desc.lpSurface)[3] = 0xffffffff;
12236 break;
12238 case 2:
12239 ((WORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
12240 ((WORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
12241 ((WORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
12242 ((WORD *)lock_desc.lpSurface)[3] = 0xffff;
12243 break;
12245 hr = IDirectDrawSurface7_Unlock(src, 0);
12246 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12247 hr = IDirectDrawSurface7_Blt(texture, NULL, src, NULL, DDBLT_WAIT, NULL);
12248 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12250 ckey.dwColorSpaceLowValue = c << tests[t].shift;
12251 ckey.dwColorSpaceHighValue = c << tests[t].shift;
12252 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
12253 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12255 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_WAIT, NULL);
12256 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12258 /* Don't make this read only, it somehow breaks the detection of the Nvidia bug below. */
12259 hr = IDirectDrawSurface7_Lock(dst, NULL, &lock_desc, DDLOCK_WAIT, NULL);
12260 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12261 switch (tests[t].bpp)
12263 case 4:
12264 data[0] = ((DWORD *)lock_desc.lpSurface)[0] & color_mask;
12265 data[1] = ((DWORD *)lock_desc.lpSurface)[1] & color_mask;
12266 data[2] = ((DWORD *)lock_desc.lpSurface)[2] & color_mask;
12267 data[3] = ((DWORD *)lock_desc.lpSurface)[3] & color_mask;
12268 break;
12270 case 2:
12271 data[0] = ((WORD *)lock_desc.lpSurface)[0] & color_mask;
12272 data[1] = ((WORD *)lock_desc.lpSurface)[1] & color_mask;
12273 data[2] = ((WORD *)lock_desc.lpSurface)[2] & color_mask;
12274 data[3] = ((WORD *)lock_desc.lpSurface)[3] & color_mask;
12275 break;
12277 hr = IDirectDrawSurface7_Unlock(dst, 0);
12278 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12280 if (!c)
12282 ok(data[0] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
12283 tests[t].clear, data[0], tests[t].name, c);
12285 if (data[3] == tests[t].clear)
12287 /* My Geforce GTX 460 on Windows 7 misbehaves when A4R4G4B4 is blitted with color
12288 * keying: The blit takes ~0.5 seconds, and subsequent color keying draws are broken,
12289 * even when a different surface is used. The blit itself doesn't draw anything,
12290 * so we can detect the bug by looking at the otherwise unused 4th texel. It should
12291 * never be masked out by the key.
12293 * On Windows 10 the problem is worse, Blt just hangs. For this reason the ARGB4444
12294 * test is disabled on Nvidia.
12296 * Also appears to affect the testbot in some way with R5G6B5. Color keying is
12297 * terrible on WARP. */
12298 skip("Nvidia A4R4G4B4 color keying blit bug detected, skipping.\n");
12299 IDirectDrawSurface7_Release(texture);
12300 IDirectDrawSurface7_Release(src);
12301 IDirectDrawSurface7_Release(dst);
12302 goto done;
12305 else
12306 ok(data[0] == (c - 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
12307 (c - 1) << tests[t].shift, data[0], tests[t].name, c);
12309 ok(data[1] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
12310 tests[t].clear, data[1], tests[t].name, c);
12312 if (c == tests[t].max)
12313 ok(data[2] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
12314 tests[t].clear, data[2], tests[t].name, c);
12315 else
12316 ok(data[2] == (c + 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
12317 (c + 1) << tests[t].shift, data[2], tests[t].name, c);
12319 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x0000ff00, 1.0f, 0);
12320 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12322 hr = IDirect3DDevice7_BeginScene(device);
12323 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12324 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
12325 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12326 hr = IDirect3DDevice7_EndScene(device);
12327 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12329 color = get_surface_color(rt, 80, 240);
12331 if (!c)
12332 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x, format %s, c=%u.\n",
12333 color, tests[t].name, c);
12334 else
12335 ok(compare_color(color, 0x00000000, 1), "Got unexpected color 0x%08x, format %s, c=%u.\n",
12336 color, tests[t].name, c);
12338 color = get_surface_color(rt, 240, 240);
12339 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x, format %s, c=%u.\n",
12340 color, tests[t].name, c);
12342 color = get_surface_color(rt, 400, 240);
12343 if (c == tests[t].max)
12344 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x, format %s, c=%u.\n",
12345 color, tests[t].name, c);
12346 else
12347 ok(compare_color(color, 0x00000000, 1), "Got unexpected color 0x%08x, format %s, c=%u.\n",
12348 color, tests[t].name, c);
12350 IDirectDrawSurface7_Release(texture);
12352 IDirectDrawSurface7_Release(src);
12353 IDirectDrawSurface7_Release(dst);
12355 done:
12357 IDirectDrawSurface7_Release(rt);
12358 IDirectDraw7_Release(ddraw);
12359 refcount = IDirect3DDevice7_Release(device);
12360 ok(!refcount, "Device has %u references left.\n", refcount);
12361 DestroyWindow(window);
12364 static void test_range_colorkey(void)
12366 IDirectDraw7 *ddraw;
12367 HWND window;
12368 HRESULT hr;
12369 IDirectDrawSurface7 *surface;
12370 DDSURFACEDESC2 surface_desc;
12371 ULONG refcount;
12372 DDCOLORKEY ckey;
12374 window = create_window();
12375 ddraw = create_ddraw();
12376 ok(!!ddraw, "Failed to create a ddraw object.\n");
12377 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12378 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12380 memset(&surface_desc, 0, sizeof(surface_desc));
12381 surface_desc.dwSize = sizeof(surface_desc);
12382 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
12383 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
12384 surface_desc.dwWidth = 1;
12385 surface_desc.dwHeight = 1;
12386 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
12387 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
12388 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
12389 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
12390 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
12391 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0x00000000;
12393 /* Creating a surface with a range color key fails with DDERR_NOCOLORKEY. */
12394 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
12395 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
12396 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12397 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
12399 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
12400 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
12401 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12402 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
12404 /* Same for DDSCAPS_OFFSCREENPLAIN. */
12405 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12406 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
12407 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
12408 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12409 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
12411 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
12412 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
12413 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12414 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
12416 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
12417 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
12418 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12419 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12421 /* Setting a range color key without DDCKEY_COLORSPACE collapses the key. */
12422 ckey.dwColorSpaceLowValue = 0x00000000;
12423 ckey.dwColorSpaceHighValue = 0x00000001;
12424 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
12425 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12427 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
12428 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
12429 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
12430 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
12432 ckey.dwColorSpaceLowValue = 0x00000001;
12433 ckey.dwColorSpaceHighValue = 0x00000000;
12434 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
12435 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12437 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
12438 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
12439 ok(ckey.dwColorSpaceLowValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
12440 ok(ckey.dwColorSpaceHighValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
12442 /* DDCKEY_COLORSPACE is ignored if the key is a single value. */
12443 ckey.dwColorSpaceLowValue = 0x00000000;
12444 ckey.dwColorSpaceHighValue = 0x00000000;
12445 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
12446 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12448 /* Using it with a range key results in DDERR_NOCOLORKEYHW. */
12449 ckey.dwColorSpaceLowValue = 0x00000001;
12450 ckey.dwColorSpaceHighValue = 0x00000000;
12451 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
12452 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
12453 ckey.dwColorSpaceLowValue = 0x00000000;
12454 ckey.dwColorSpaceHighValue = 0x00000001;
12455 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
12456 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
12457 /* Range destination keys don't work either. */
12458 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_DESTBLT | DDCKEY_COLORSPACE, &ckey);
12459 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
12461 /* Just to show it's not because of A, R, and G having equal values. */
12462 ckey.dwColorSpaceLowValue = 0x00000000;
12463 ckey.dwColorSpaceHighValue = 0x01010101;
12464 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
12465 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
12467 /* None of these operations modified the key. */
12468 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
12469 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
12470 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
12471 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
12473 IDirectDrawSurface7_Release(surface);
12474 refcount = IDirectDraw7_Release(ddraw);
12475 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
12476 DestroyWindow(window);
12479 static void test_shademode(void)
12481 IDirect3DVertexBuffer7 *vb_strip, *vb_list, *buffer;
12482 IDirect3DDevice7 *device;
12483 D3DVERTEXBUFFERDESC desc;
12484 IDirectDrawSurface7 *rt;
12485 DWORD color0, color1;
12486 void *data = NULL;
12487 IDirect3D7 *d3d;
12488 ULONG refcount;
12489 UINT i, count;
12490 HWND window;
12491 HRESULT hr;
12492 static const struct
12494 struct vec3 position;
12495 DWORD diffuse;
12497 quad_strip[] =
12499 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
12500 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
12501 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
12502 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
12504 quad_list[] =
12506 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
12507 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
12508 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
12510 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
12511 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
12512 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
12514 static const struct
12516 DWORD primtype;
12517 DWORD shademode;
12518 DWORD color0, color1;
12520 tests[] =
12522 {D3DPT_TRIANGLESTRIP, D3DSHADE_FLAT, 0x00ff0000, 0x0000ff00},
12523 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
12524 {D3DPT_TRIANGLESTRIP, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
12525 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
12526 {D3DPT_TRIANGLELIST, D3DSHADE_FLAT, 0x00ff0000, 0x000000ff},
12527 {D3DPT_TRIANGLELIST, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
12530 window = create_window();
12531 if (!(device = create_device(window, DDSCL_NORMAL)))
12533 skip("Failed to create a 3D device, skipping test.\n");
12534 DestroyWindow(window);
12535 return;
12538 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
12539 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
12540 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
12541 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
12543 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
12544 ok(hr == D3D_OK, "Failed to disable lighting, hr %#x.\n", hr);
12545 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
12546 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
12548 memset(&desc, 0, sizeof(desc));
12549 desc.dwSize = sizeof(desc);
12550 desc.dwCaps = D3DVBCAPS_WRITEONLY;
12551 desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
12552 desc.dwNumVertices = ARRAY_SIZE(quad_strip);
12553 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &vb_strip, 0);
12554 ok(hr == D3D_OK, "Failed to create vertex buffer, hr %#x.\n", hr);
12555 hr = IDirect3DVertexBuffer7_Lock(vb_strip, 0, &data, NULL);
12556 ok(hr == D3D_OK, "Failed to lock vertex buffer, hr %#x.\n", hr);
12557 memcpy(data, quad_strip, sizeof(quad_strip));
12558 hr = IDirect3DVertexBuffer7_Unlock(vb_strip);
12559 ok(hr == D3D_OK, "Failed to unlock vertex buffer, hr %#x.\n", hr);
12561 desc.dwNumVertices = ARRAY_SIZE(quad_list);
12562 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &vb_list, 0);
12563 ok(hr == D3D_OK, "Failed to create vertex buffer, hr %#x.\n", hr);
12564 hr = IDirect3DVertexBuffer7_Lock(vb_list, 0, &data, NULL);
12565 ok(hr == D3D_OK, "Failed to lock vertex buffer, hr %#x.\n", hr);
12566 memcpy(data, quad_list, sizeof(quad_list));
12567 hr = IDirect3DVertexBuffer7_Unlock(vb_list);
12568 ok(hr == D3D_OK, "Failed to unlock vertex buffer, hr %#x.\n", hr);
12570 /* Try it first with a TRIANGLESTRIP. Do it with different geometry because
12571 * the color fixups we have to do for FLAT shading will be dependent on that. */
12573 for (i = 0; i < ARRAY_SIZE(tests); ++i)
12575 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
12576 ok(hr == D3D_OK, "Failed to clear, hr %#x.\n", hr);
12578 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SHADEMODE, tests[i].shademode);
12579 ok(hr == D3D_OK, "Failed to set shade mode, hr %#x.\n", hr);
12581 hr = IDirect3DDevice7_BeginScene(device);
12582 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12583 buffer = tests[i].primtype == D3DPT_TRIANGLESTRIP ? vb_strip : vb_list;
12584 count = tests[i].primtype == D3DPT_TRIANGLESTRIP ? 4 : 6;
12585 hr = IDirect3DDevice7_DrawPrimitiveVB(device, tests[i].primtype, buffer, 0, count, 0);
12586 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12587 hr = IDirect3DDevice7_EndScene(device);
12588 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12590 color0 = get_surface_color(rt, 100, 100); /* Inside first triangle */
12591 color1 = get_surface_color(rt, 500, 350); /* Inside second triangle */
12593 /* For D3DSHADE_FLAT it should take the color of the first vertex of
12594 * each triangle. This requires EXT_provoking_vertex or similar
12595 * functionality being available. */
12596 /* PHONG should be the same as GOURAUD, since no hardware implements
12597 * this. */
12598 ok(compare_color(color0, tests[i].color0, 1), "Test %u shading has color0 %08x, expected %08x.\n",
12599 i, color0, tests[i].color0);
12600 ok(compare_color(color1, tests[i].color1, 1), "Test %u shading has color1 %08x, expected %08x.\n",
12601 i, color1, tests[i].color1);
12604 IDirect3DVertexBuffer7_Release(vb_strip);
12605 IDirect3DVertexBuffer7_Release(vb_list);
12606 IDirectDrawSurface7_Release(rt);
12607 IDirect3D7_Release(d3d);
12608 refcount = IDirect3DDevice7_Release(device);
12609 ok(!refcount, "Device has %u references left.\n", refcount);
12610 DestroyWindow(window);
12613 static void test_lockrect_invalid(void)
12615 unsigned int i, r;
12616 IDirectDraw7 *ddraw;
12617 IDirectDrawSurface7 *surface;
12618 HWND window;
12619 HRESULT hr;
12620 DDSURFACEDESC2 surface_desc;
12621 DDSURFACEDESC2 locked_desc;
12622 DDCAPS hal_caps;
12623 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
12624 static RECT valid[] =
12626 {60, 60, 68, 68},
12627 {60, 60, 60, 68},
12628 {60, 60, 68, 60},
12629 {120, 60, 128, 68},
12630 {60, 120, 68, 128},
12632 static RECT invalid[] =
12634 {68, 60, 60, 68}, /* left > right */
12635 {60, 68, 68, 60}, /* top > bottom */
12636 {-8, 60, 0, 68}, /* left < surface */
12637 {60, -8, 68, 0}, /* top < surface */
12638 {-16, 60, -8, 68}, /* right < surface */
12639 {60, -16, 68, -8}, /* bottom < surface */
12640 {60, 60, 136, 68}, /* right > surface */
12641 {60, 60, 68, 136}, /* bottom > surface */
12642 {136, 60, 144, 68}, /* left > surface */
12643 {60, 136, 68, 144}, /* top > surface */
12645 static const struct
12647 DWORD caps, caps2;
12648 const char *name;
12649 BOOL allowed;
12650 HRESULT hr;
12652 resources[] =
12654 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, "sysmem offscreenplain", TRUE, DDERR_INVALIDPARAMS},
12655 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, "vidmem offscreenplain", TRUE, DDERR_INVALIDPARAMS},
12656 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, "sysmem texture", TRUE, DD_OK},
12657 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, "vidmem texture", TRUE, DDERR_INVALIDPARAMS},
12658 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, "managed texture", TRUE, DD_OK},
12660 /* FWIW the SDK header mentions DDSCAPS_WRITEONLY as being a "READ
12661 * ONLY" flag. */
12662 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_WRITEONLY, 0, "sysmem offscreenplain writeonly", FALSE, DDERR_INVALIDPARAMS},
12663 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_WRITEONLY, 0, "vidmem offscreenplain writeonly", FALSE, DDERR_INVALIDPARAMS},
12664 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_WRITEONLY, 0, "sysmem texture writeonly", FALSE, DD_OK},
12665 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_WRITEONLY, 0, "vidmem texture writeonly", FALSE, DDERR_INVALIDPARAMS},
12666 {DDSCAPS_TEXTURE | DDSCAPS_WRITEONLY, DDSCAPS2_TEXTUREMANAGE, "managed texture writeonly", TRUE, DD_OK},
12669 window = create_window();
12670 ddraw = create_ddraw();
12671 ok(!!ddraw, "Failed to create a ddraw object.\n");
12672 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12673 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12675 memset(&hal_caps, 0, sizeof(hal_caps));
12676 hal_caps.dwSize = sizeof(hal_caps);
12677 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
12678 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
12679 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps
12680 || !(hal_caps.ddsCaps.dwCaps & DDSCAPS2_TEXTUREMANAGE))
12682 skip("Required surface types not supported, skipping test.\n");
12683 goto done;
12686 for (r = 0; r < ARRAY_SIZE(resources); ++r)
12688 memset(&surface_desc, 0, sizeof(surface_desc));
12689 surface_desc.dwSize = sizeof(surface_desc);
12690 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
12691 surface_desc.ddsCaps.dwCaps = resources[r].caps;
12692 surface_desc.ddsCaps.dwCaps2 = resources[r].caps2;
12693 surface_desc.dwWidth = 128;
12694 surface_desc.dwHeight = 128;
12695 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
12696 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
12697 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
12698 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xff0000;
12699 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x00ff00;
12700 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x0000ff;
12702 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12703 if (!resources[r].allowed)
12705 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
12706 continue;
12708 if (is_ddraw64 && (resources[r].caps & DDSCAPS_TEXTURE))
12710 todo_wine ok(hr == E_NOINTERFACE, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
12711 if (SUCCEEDED(hr))
12712 IDirectDrawSurface7_Release(surface);
12713 continue;
12715 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n", hr, resources[r].name);
12717 /* Crashes in ddraw7
12718 hr = IDirectDrawSurface7_Lock(surface, NULL, NULL, DDLOCK_WAIT, NULL);
12719 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
12722 for (i = 0; i < ARRAY_SIZE(valid); ++i)
12724 RECT *rect = &valid[i];
12726 memset(&locked_desc, 0, sizeof(locked_desc));
12727 locked_desc.dwSize = sizeof(locked_desc);
12729 hr = IDirectDrawSurface7_Lock(surface, rect, &locked_desc, DDLOCK_WAIT, NULL);
12730 ok(SUCCEEDED(hr), "Lock failed (%#x) for rect %s, type %s.\n",
12731 hr, wine_dbgstr_rect(rect), resources[r].name);
12733 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12734 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
12737 for (i = 0; i < ARRAY_SIZE(invalid); ++i)
12739 RECT *rect = &invalid[i];
12741 memset(&locked_desc, 1, sizeof(locked_desc));
12742 locked_desc.dwSize = sizeof(locked_desc);
12744 hr = IDirectDrawSurface7_Lock(surface, rect, &locked_desc, DDLOCK_WAIT, NULL);
12745 todo_wine_if (SUCCEEDED(resources[r].hr))
12746 ok(hr == resources[r].hr, "Lock returned %#x for rect %s, type %s.\n",
12747 hr, wine_dbgstr_rect(rect), resources[r].name);
12748 if (SUCCEEDED(hr))
12750 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12751 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
12753 else
12754 ok(!locked_desc.lpSurface, "Got unexpected lpSurface %p.\n", locked_desc.lpSurface);
12757 hr = IDirectDrawSurface7_Lock(surface, NULL, &locked_desc, DDLOCK_WAIT, NULL);
12758 ok(SUCCEEDED(hr), "Lock(rect = NULL) failed, hr %#x, type %s.\n",
12759 hr, resources[r].name);
12760 hr = IDirectDrawSurface7_Lock(surface, NULL, &locked_desc, DDLOCK_WAIT, NULL);
12761 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = NULL) returned %#x, type %s.\n",
12762 hr, resources[r].name);
12763 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12764 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
12766 hr = IDirectDrawSurface7_Lock(surface, &valid[0], &locked_desc, DDLOCK_WAIT, NULL);
12767 ok(SUCCEEDED(hr), "Lock(rect = %s) failed (%#x).\n", wine_dbgstr_rect(&valid[0]), hr);
12768 hr = IDirectDrawSurface7_Lock(surface, &valid[0], &locked_desc, DDLOCK_WAIT, NULL);
12769 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = %s) failed (%#x).\n",
12770 wine_dbgstr_rect(&valid[0]), hr);
12772 /* Locking a different rectangle returns DD_OK, but it seems to break the surface.
12773 * Afterwards unlocking the surface fails(NULL rectangle or both locked rectangles) */
12775 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12776 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
12778 IDirectDrawSurface7_Release(surface);
12781 done:
12782 IDirectDraw7_Release(ddraw);
12783 DestroyWindow(window);
12786 static void test_yv12_overlay(void)
12788 IDirectDrawSurface7 *src_surface, *dst_surface;
12789 RECT rect = {13, 17, 14, 18};
12790 unsigned int offset, y;
12791 DDSURFACEDESC2 desc;
12792 unsigned char *base;
12793 IDirectDraw7 *ddraw;
12794 HWND window;
12795 HRESULT hr;
12797 window = create_window();
12798 ddraw = create_ddraw();
12799 ok(!!ddraw, "Failed to create a ddraw object.\n");
12800 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12801 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12803 if (!(src_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
12805 skip("Failed to create a YV12 overlay, skipping test.\n");
12806 goto done;
12809 memset(&desc, 0, sizeof(desc));
12810 desc.dwSize = sizeof(desc);
12811 hr = IDirectDrawSurface7_Lock(src_surface, NULL, &desc, DDLOCK_WAIT, NULL);
12812 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12814 ok(desc.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH),
12815 "Got unexpected flags %#x.\n", desc.dwFlags);
12816 ok(desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_HWCODEC)
12817 || desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
12818 "Got unexpected caps %#x.\n", desc.ddsCaps.dwCaps);
12819 ok(desc.dwWidth == 256, "Got unexpected width %u.\n", desc.dwWidth);
12820 ok(desc.dwHeight == 256, "Got unexpected height %u.\n", desc.dwHeight);
12821 /* The overlay pitch seems to have 256 byte alignment. */
12822 ok(!(U1(desc).lPitch & 0xff), "Got unexpected pitch %u.\n", U1(desc).lPitch);
12824 /* Fill the surface with some data for the blit test. */
12825 base = desc.lpSurface;
12826 /* Luminance */
12827 for (y = 0; y < desc.dwHeight; ++y)
12829 memset(base + U1(desc).lPitch * y, 0x10, desc.dwWidth);
12831 /* V */
12832 for (; y < desc.dwHeight + desc.dwHeight / 4; ++y)
12834 memset(base + U1(desc).lPitch * y, 0x20, desc.dwWidth);
12836 /* U */
12837 for (; y < desc.dwHeight + desc.dwHeight / 2; ++y)
12839 memset(base + U1(desc).lPitch * y, 0x30, desc.dwWidth);
12842 hr = IDirectDrawSurface7_Unlock(src_surface, NULL);
12843 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12845 /* YV12 uses 2x2 blocks with 6 bytes per block (4*Y, 1*U, 1*V). Unlike
12846 * other block-based formats like DXT the entire Y channel is stored in
12847 * one big chunk of memory, followed by the chroma channels. So partial
12848 * locks do not really make sense. Show that they are allowed nevertheless
12849 * and the offset points into the luminance data. */
12850 hr = IDirectDrawSurface7_Lock(src_surface, &rect, &desc, DDLOCK_WAIT, NULL);
12851 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12852 offset = ((const unsigned char *)desc.lpSurface - base);
12853 ok(offset == rect.top * U1(desc).lPitch + rect.left, "Got unexpected offset %u, expected %u.\n",
12854 offset, rect.top * U1(desc).lPitch + rect.left);
12855 hr = IDirectDrawSurface7_Unlock(src_surface, NULL);
12856 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12858 if (!(dst_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
12860 /* Windows XP with a Radeon X1600 GPU refuses to create a second
12861 * overlay surface, DDERR_NOOVERLAYHW, making the blit tests moot. */
12862 skip("Failed to create a second YV12 surface, skipping blit test.\n");
12863 IDirectDrawSurface7_Release(src_surface);
12864 goto done;
12867 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, src_surface, NULL, DDBLT_WAIT, NULL);
12868 /* VMware rejects YV12 blits. This behavior has not been seen on real
12869 * hardware yet, so mark it broken. */
12870 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL), "Failed to blit, hr %#x.\n", hr);
12872 if (SUCCEEDED(hr))
12874 memset(&desc, 0, sizeof(desc));
12875 desc.dwSize = sizeof(desc);
12876 hr = IDirectDrawSurface7_Lock(dst_surface, NULL, &desc, DDLOCK_WAIT, NULL);
12877 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12879 base = desc.lpSurface;
12880 ok(base[0] == 0x10, "Got unexpected Y data 0x%02x.\n", base[0]);
12881 base += desc.dwHeight * U1(desc).lPitch;
12882 todo_wine ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]);
12883 base += desc.dwHeight / 4 * U1(desc).lPitch;
12884 todo_wine ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]);
12886 hr = IDirectDrawSurface7_Unlock(dst_surface, NULL);
12887 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12890 IDirectDrawSurface7_Release(dst_surface);
12891 IDirectDrawSurface7_Release(src_surface);
12892 done:
12893 IDirectDraw7_Release(ddraw);
12894 DestroyWindow(window);
12897 static BOOL dwm_enabled(void)
12899 BOOL ret = FALSE;
12901 if (!strcmp(winetest_platform, "wine"))
12902 return FALSE;
12903 if (!pDwmIsCompositionEnabled)
12904 return FALSE;
12905 if (FAILED(pDwmIsCompositionEnabled(&ret)))
12906 return FALSE;
12907 return ret;
12910 static void test_offscreen_overlay(void)
12912 IDirectDrawSurface7 *overlay, *offscreen, *primary;
12913 DDSURFACEDESC2 surface_desc;
12914 IDirectDraw7 *ddraw;
12915 HWND window;
12916 HRESULT hr;
12917 HDC dc;
12919 window = create_window();
12920 ddraw = create_ddraw();
12921 ok(!!ddraw, "Failed to create a ddraw object.\n");
12922 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12923 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12925 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
12927 skip("Failed to create a UYVY overlay, skipping test.\n");
12928 goto done;
12931 memset(&surface_desc, 0, sizeof(surface_desc));
12932 surface_desc.dwSize = sizeof(surface_desc);
12933 surface_desc.dwFlags = DDSD_CAPS;
12934 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
12935 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
12936 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
12938 /* On Windows 7, and probably Vista, UpdateOverlay() will return
12939 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
12940 * surface prevents this by disabling the dwm. */
12941 hr = IDirectDrawSurface7_GetDC(primary, &dc);
12942 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
12943 hr = IDirectDrawSurface7_ReleaseDC(primary, dc);
12944 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
12946 /* Try to overlay a NULL surface. */
12947 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_SHOW, NULL);
12948 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
12949 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_HIDE, NULL);
12950 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
12952 /* Try to overlay an offscreen surface. */
12953 memset(&surface_desc, 0, sizeof(surface_desc));
12954 surface_desc.dwSize = sizeof(surface_desc);
12955 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
12956 surface_desc.dwWidth = 64;
12957 surface_desc.dwHeight = 64;
12958 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12959 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
12960 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
12961 U4(surface_desc).ddpfPixelFormat.dwFourCC = 0;
12962 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
12963 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
12964 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
12965 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
12966 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
12967 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
12969 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, offscreen, NULL, DDOVER_SHOW, NULL);
12970 ok(SUCCEEDED(hr) || broken(hr == DDERR_OUTOFCAPS && dwm_enabled())
12971 || broken(hr == E_NOTIMPL && ddraw_is_vmware(ddraw)),
12972 "Failed to update overlay, hr %#x.\n", hr);
12974 /* Try to overlay the primary with a non-overlay surface. */
12975 hr = IDirectDrawSurface7_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_SHOW, NULL);
12976 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
12977 hr = IDirectDrawSurface7_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_HIDE, NULL);
12978 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
12980 IDirectDrawSurface7_Release(offscreen);
12981 IDirectDrawSurface7_Release(primary);
12982 IDirectDrawSurface7_Release(overlay);
12983 done:
12984 IDirectDraw7_Release(ddraw);
12985 DestroyWindow(window);
12988 static void test_overlay_rect(void)
12990 IDirectDrawSurface7 *overlay, *primary = NULL;
12991 DDSURFACEDESC2 surface_desc;
12992 RECT rect = {0, 0, 64, 64};
12993 IDirectDraw7 *ddraw;
12994 LONG pos_x, pos_y;
12995 HRESULT hr, hr2;
12996 HWND window;
12997 HDC dc;
12999 window = create_window();
13000 ddraw = create_ddraw();
13001 ok(!!ddraw, "Failed to create a ddraw object.\n");
13002 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
13003 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13005 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
13007 skip("Failed to create a UYVY overlay, skipping test.\n");
13008 goto done;
13011 memset(&surface_desc, 0, sizeof(surface_desc));
13012 surface_desc.dwSize = sizeof(surface_desc);
13013 surface_desc.dwFlags = DDSD_CAPS;
13014 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
13015 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
13016 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
13018 /* On Windows 7, and probably Vista, UpdateOverlay() will return
13019 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
13020 * surface prevents this by disabling the dwm. */
13021 hr = IDirectDrawSurface7_GetDC(primary, &dc);
13022 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
13023 hr = IDirectDrawSurface7_ReleaseDC(primary, dc);
13024 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
13026 /* On Windows 8 and newer DWM can't be turned off, making overlays unusable. */
13027 if (dwm_enabled())
13029 win_skip("Cannot disable DWM, skipping overlay test.\n");
13030 goto done;
13033 /* The dx sdk sort of implies that rect must be set when DDOVER_SHOW is
13034 * used. This is not true in Windows Vista and earlier, but changed in
13035 * Windows 7. */
13036 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
13037 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
13038 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_HIDE, NULL);
13039 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
13040 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_SHOW, NULL);
13041 ok(hr == DD_OK || hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
13043 /* Show that the overlay position is the (top, left) coordinate of the
13044 * destination rectangle. */
13045 OffsetRect(&rect, 32, 16);
13046 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
13047 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
13048 pos_x = -1; pos_y = -1;
13049 hr = IDirectDrawSurface7_GetOverlayPosition(overlay, &pos_x, &pos_y);
13050 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
13051 ok(pos_x == rect.left, "Got unexpected pos_x %d, expected %d.\n", pos_x, rect.left);
13052 ok(pos_y == rect.top, "Got unexpected pos_y %d, expected %d.\n", pos_y, rect.top);
13054 /* Passing a NULL dest rect sets the position to 0/0. Visually it can be
13055 * seen that the overlay overlays the whole primary(==screen). */
13056 hr2 = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, NULL, 0, NULL);
13057 ok(hr2 == DD_OK || hr2 == DDERR_INVALIDPARAMS || hr2 == DDERR_OUTOFCAPS, "Got unexpected hr %#x.\n", hr2);
13058 hr = IDirectDrawSurface7_GetOverlayPosition(overlay, &pos_x, &pos_y);
13059 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
13060 if (SUCCEEDED(hr2))
13062 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
13063 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
13065 else
13067 ok(pos_x == 32, "Got unexpected pos_x %d.\n", pos_x);
13068 ok(pos_y == 16, "Got unexpected pos_y %d.\n", pos_y);
13071 /* The position cannot be retrieved when the overlay is not shown. */
13072 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_HIDE, NULL);
13073 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
13074 pos_x = -1; pos_y = -1;
13075 hr = IDirectDrawSurface7_GetOverlayPosition(overlay, &pos_x, &pos_y);
13076 ok(hr == DDERR_OVERLAYNOTVISIBLE, "Got unexpected hr %#x.\n", hr);
13077 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
13078 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
13080 done:
13081 if (primary)
13082 IDirectDrawSurface7_Release(primary);
13083 if (overlay)
13084 IDirectDrawSurface7_Release(overlay);
13085 IDirectDraw7_Release(ddraw);
13086 DestroyWindow(window);
13089 static void test_blt(void)
13091 IDirectDrawSurface7 *surface, *rt;
13092 DDSURFACEDESC2 surface_desc;
13093 IDirect3DDevice7 *device;
13094 IDirectDraw7 *ddraw;
13095 IDirect3D7 *d3d;
13096 unsigned int i;
13097 ULONG refcount;
13098 HWND window;
13099 HRESULT hr;
13101 static struct
13103 RECT src_rect;
13104 RECT dst_rect;
13105 HRESULT hr;
13107 test_data[] =
13109 {{160, 0, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit. */
13110 {{160, 480, 640, 0}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, flipped source. */
13111 {{640, 0, 160, 480}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, mirrored source. */
13112 {{160, 0, 480, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched x. */
13113 {{160, 160, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched y. */
13114 {{ 0, 0, 640, 480}, { 0, 0, 640, 480}, DD_OK}, /* Full surface blit. */
13115 {{ 0, 0, 640, 480}, { 0, 480, 640, 0}, DDERR_INVALIDRECT}, /* Full surface, flipped destination. */
13116 {{ 0, 0, 640, 480}, {640, 0, 0, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored destination. */
13117 {{ 0, 480, 640, 0}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, flipped source. */
13118 {{640, 0, 0, 480}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored source. */
13121 window = create_window();
13122 if (!(device = create_device(window, DDSCL_NORMAL)))
13124 skip("Failed to create a 3D device, skipping test.\n");
13125 DestroyWindow(window);
13126 return;
13129 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
13130 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
13131 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
13132 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
13133 IDirect3D7_Release(d3d);
13134 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
13135 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
13137 memset(&surface_desc, 0, sizeof(surface_desc));
13138 surface_desc.dwSize = sizeof(surface_desc);
13139 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
13140 surface_desc.dwWidth = 640;
13141 surface_desc.dwHeight = 480;
13142 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13143 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
13144 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13146 hr = IDirectDrawSurface7_Blt(surface, NULL, surface, NULL, 0, NULL);
13147 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13149 hr = IDirectDrawSurface7_Blt(surface, NULL, rt, NULL, 0, NULL);
13150 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13152 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
13154 hr = IDirectDrawSurface7_Blt(surface, &test_data[i].dst_rect,
13155 surface, &test_data[i].src_rect, DDBLT_WAIT, NULL);
13156 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
13158 hr = IDirectDrawSurface7_Blt(surface, &test_data[i].dst_rect,
13159 rt, &test_data[i].src_rect, DDBLT_WAIT, NULL);
13160 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
13162 hr = IDirectDrawSurface7_Blt(surface, &test_data[i].dst_rect,
13163 NULL, &test_data[i].src_rect, DDBLT_WAIT, NULL);
13164 ok(hr == DDERR_INVALIDPARAMS, "Test %u: Got unexpected hr %#x.\n", i, hr);
13166 hr = IDirectDrawSurface7_Blt(surface, &test_data[i].dst_rect, NULL, NULL, DDBLT_WAIT, NULL);
13167 ok(hr == DDERR_INVALIDPARAMS, "Test %u: Got unexpected hr %#x.\n", i, hr);
13170 IDirectDrawSurface7_Release(surface);
13171 IDirectDrawSurface7_Release(rt);
13172 IDirectDraw7_Release(ddraw);
13173 refcount = IDirect3DDevice7_Release(device);
13174 ok(!refcount, "Device has %u references left.\n", refcount);
13175 DestroyWindow(window);
13178 static void test_blt_z_alpha(void)
13180 DWORD blt_flags[] =
13182 /* 0 */
13183 DDBLT_ALPHADEST,
13184 DDBLT_ALPHADESTCONSTOVERRIDE,
13185 DDBLT_ALPHADESTNEG,
13186 DDBLT_ALPHADESTSURFACEOVERRIDE,
13187 DDBLT_ALPHAEDGEBLEND,
13188 /* 5 */
13189 DDBLT_ALPHASRC,
13190 DDBLT_ALPHASRCCONSTOVERRIDE,
13191 DDBLT_ALPHASRCNEG,
13192 DDBLT_ALPHASRCSURFACEOVERRIDE,
13193 DDBLT_ZBUFFER,
13194 /* 10 */
13195 DDBLT_ZBUFFERDESTCONSTOVERRIDE,
13196 DDBLT_ZBUFFERDESTOVERRIDE,
13197 DDBLT_ZBUFFERSRCCONSTOVERRIDE,
13198 DDBLT_ZBUFFERSRCOVERRIDE,
13200 IDirectDrawSurface7 *src_surface, *dst_surface;
13201 DDSURFACEDESC2 surface_desc;
13202 IDirectDraw7 *ddraw;
13203 DDPIXELFORMAT pf;
13204 ULONG refcount;
13205 unsigned int i;
13206 D3DCOLOR color;
13207 HWND window;
13208 HRESULT hr;
13209 DDBLTFX fx;
13211 window = create_window();
13212 ddraw = create_ddraw();
13213 ok(!!ddraw, "Failed to create a ddraw object.\n");
13214 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
13215 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13217 memset(&pf, 0, sizeof(pf));
13218 pf.dwSize = sizeof(pf);
13219 pf.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
13220 U1(pf).dwRGBBitCount = 32;
13221 U2(pf).dwRBitMask = 0x00ff0000;
13222 U3(pf).dwGBitMask = 0x0000ff00;
13223 U4(pf).dwBBitMask = 0x000000ff;
13224 U5(pf).dwRGBAlphaBitMask = 0xff000000;
13226 memset(&surface_desc, 0, sizeof(surface_desc));
13227 surface_desc.dwSize = sizeof(surface_desc);
13228 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
13229 surface_desc.dwWidth = 64;
13230 surface_desc.dwHeight = 64;
13231 U4(surface_desc).ddpfPixelFormat = pf;
13232 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13234 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
13235 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
13236 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
13237 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
13239 memset(&fx, 0, sizeof(fx));
13240 fx.dwSize = sizeof(fx);
13241 fx.dwZBufferOpCode = D3DCMP_NEVER;
13242 fx.dwZDestConstBitDepth = 32;
13243 U1(fx).dwZDestConst = 0x11111111;
13244 fx.dwZSrcConstBitDepth = 32;
13245 U2(fx).dwZSrcConst = 0xeeeeeeee;
13246 fx.dwAlphaEdgeBlendBitDepth = 8;
13247 fx.dwAlphaEdgeBlend = 0x7f;
13248 fx.dwAlphaDestConstBitDepth = 8;
13249 U3(fx).dwAlphaDestConst = 0xdd;
13250 fx.dwAlphaSrcConstBitDepth = 8;
13251 U4(fx).dwAlphaSrcConst = 0x22;
13253 for (i = 0; i < ARRAY_SIZE(blt_flags); ++i)
13255 U5(fx).dwFillColor = 0x3300ff00;
13256 hr = IDirectDrawSurface7_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
13257 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
13259 U5(fx).dwFillColor = 0xccff0000;
13260 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
13261 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
13263 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, src_surface, NULL, blt_flags[i] | DDBLT_WAIT, &fx);
13264 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
13266 color = get_surface_color(dst_surface, 32, 32);
13267 ok(compare_color(color, 0x0000ff00, 0), "Test %u: Got unexpected color 0x%08x.\n", i, color);
13270 IDirectDrawSurface7_Release(dst_surface);
13271 IDirectDrawSurface7_Release(src_surface);
13272 refcount = IDirectDraw7_Release(ddraw);
13273 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
13274 DestroyWindow(window);
13277 static void test_cross_device_blt(void)
13279 IDirectDrawSurface7 *surface, *surface2, *sysmem_surface;
13280 IDirect3DDevice7 *device, *device2;
13281 IDirectDraw7 *ddraw, *ddraw2;
13282 DDSURFACEDESC2 surface_desc;
13283 HWND window, window2;
13284 IDirect3D7 *d3d;
13285 ULONG refcount;
13286 D3DCOLOR color;
13287 DDBLTFX fx;
13288 HRESULT hr;
13290 window = create_window();
13291 if (!(device = create_device(window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
13293 skip("Failed to create a 3D device.\n");
13294 DestroyWindow(window);
13295 return;
13298 window2 = create_window();
13299 if (!(device2 = create_device(window2, DDSCL_NORMAL)))
13301 skip("Failed to create a 3D device.\n");
13302 IDirect3DDevice7_Release(device);
13303 DestroyWindow(window);
13304 DestroyWindow(window2);
13305 return;
13308 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
13309 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
13310 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
13311 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
13312 IDirect3D7_Release(d3d);
13314 hr = IDirect3DDevice7_GetDirect3D(device2, &d3d);
13315 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
13316 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw2);
13317 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
13318 IDirect3D7_Release(d3d);
13320 memset(&surface_desc, 0, sizeof(surface_desc));
13321 surface_desc.dwSize = sizeof(surface_desc);
13322 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
13323 surface_desc.dwWidth = 640;
13324 surface_desc.dwHeight = 480;
13325 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
13326 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &sysmem_surface, NULL);
13327 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13329 memset(&surface_desc, 0, sizeof(surface_desc));
13330 surface_desc.dwSize = sizeof(surface_desc);
13331 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
13332 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_VIDEOMEMORY;
13333 U5(surface_desc).dwBackBufferCount = 2;
13334 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
13335 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13337 memset(&surface_desc, 0, sizeof(surface_desc));
13338 surface_desc.dwSize = sizeof(surface_desc);
13339 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
13340 surface_desc.dwWidth = 640;
13341 surface_desc.dwHeight = 480;
13342 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
13343 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
13344 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
13345 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
13346 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00007c00;
13347 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x000003e0;
13348 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x0000001f;
13349 hr = IDirectDraw7_CreateSurface(ddraw2, &surface_desc, &surface2, NULL);
13350 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13352 memset(&fx, 0, sizeof(fx));
13353 fx.dwSize = sizeof(fx);
13354 U5(fx).dwFillColor = 0xff0000ff;
13355 hr = IDirectDrawSurface7_Blt(surface2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
13356 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
13358 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
13359 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
13360 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
13361 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
13362 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
13363 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
13364 color = get_surface_color(surface, 320, 240);
13365 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
13367 hr = IDirectDrawSurface7_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
13368 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
13369 color = get_surface_color(sysmem_surface, 320, 240);
13370 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
13372 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
13373 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13374 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
13375 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13377 hr = IDirectDrawSurface7_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
13378 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
13379 color = get_surface_color(sysmem_surface, 320, 240);
13380 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
13382 IDirectDrawSurface7_Release(surface2);
13383 memset(&surface_desc, 0, sizeof(surface_desc));
13384 surface_desc.dwSize = sizeof(surface_desc);
13385 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
13386 surface_desc.dwWidth = 640;
13387 surface_desc.dwHeight = 480;
13388 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
13389 hr = IDirectDraw7_CreateSurface(ddraw2, &surface_desc, &surface2, NULL);
13390 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13391 hr = IDirectDrawSurface7_Blt(surface2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
13392 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
13394 hr = IDirectDrawSurface7_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
13395 todo_wine ok(hr == D3D_OK, "Failed to blit, hr %#x.\n", hr);
13396 color = get_surface_color(sysmem_surface, 320, 240);
13397 todo_wine ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
13399 IDirectDrawSurface7_Release(surface);
13400 IDirectDrawSurface7_Release(surface2);
13401 IDirectDrawSurface7_Release(sysmem_surface);
13402 IDirectDraw7_Release(ddraw);
13403 IDirectDraw7_Release(ddraw2);
13404 refcount = IDirect3DDevice7_Release(device);
13405 ok(!refcount, "Device has %u references left.\n", refcount);
13406 refcount = IDirect3DDevice7_Release(device2);
13407 ok(!refcount, "Device has %u references left.\n", refcount);
13408 DestroyWindow(window);
13409 DestroyWindow(window2);
13412 static void test_color_clamping(void)
13414 static D3DMATRIX mat =
13416 1.0f, 0.0f, 0.0f, 0.0f,
13417 0.0f, 1.0f, 0.0f, 0.0f,
13418 0.0f, 0.0f, 1.0f, 0.0f,
13419 0.0f, 0.0f, 0.0f, 1.0f,
13421 static struct vec3 quad[] =
13423 {-1.0f, -1.0f, 0.1f},
13424 {-1.0f, 1.0f, 0.1f},
13425 { 1.0f, -1.0f, 0.1f},
13426 { 1.0f, 1.0f, 0.1f},
13428 IDirect3DDevice7 *device;
13429 IDirectDrawSurface7 *rt;
13430 ULONG refcount;
13431 D3DCOLOR color;
13432 HWND window;
13433 HRESULT hr;
13435 window = create_window();
13436 if (!(device = create_device(window, DDSCL_NORMAL)))
13438 skip("Failed to create a 3D device, skipping test.\n");
13439 DestroyWindow(window);
13440 return;
13443 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
13444 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
13446 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
13447 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
13448 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
13449 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
13450 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
13451 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
13452 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
13453 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
13454 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
13455 ok(SUCCEEDED(hr), "Failed to disable Z test, hr %#x.\n", hr);
13456 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
13457 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
13458 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
13459 ok(SUCCEEDED(hr), "Failed to disable stencil test, hr %#x.\n", hr);
13460 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
13461 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
13462 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
13463 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
13465 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0xff404040);
13466 ok(SUCCEEDED(hr), "Failed to set texture factor, hr %#x.\n", hr);
13467 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_ADD);
13468 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
13469 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
13470 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
13471 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_SPECULAR);
13472 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
13473 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_MODULATE);
13474 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
13475 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TFACTOR);
13476 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
13477 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
13478 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
13480 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
13481 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13483 hr = IDirect3DDevice7_BeginScene(device);
13484 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
13486 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
13487 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13489 hr = IDirect3DDevice7_EndScene(device);
13490 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
13492 color = get_surface_color(rt, 320, 240);
13493 ok(compare_color(color, 0x00404040, 1), "Got unexpected color 0x%08x.\n", color);
13495 IDirectDrawSurface7_Release(rt);
13496 refcount = IDirect3DDevice7_Release(device);
13497 ok(!refcount, "Device has %u references left.\n", refcount);
13498 DestroyWindow(window);
13501 static void test_getdc(void)
13503 DDSCAPS2 caps = {DDSCAPS_COMPLEX, DDSCAPS2_CUBEMAP_NEGATIVEZ, 0, {0}};
13504 IDirectDrawSurface7 *surface, *surface2, *tmp;
13505 DDSURFACEDESC2 surface_desc, map_desc;
13506 IDirectDraw7 *ddraw;
13507 unsigned int i, screen_bpp;
13508 HWND window;
13509 HDC dc, dc2;
13510 HRESULT hr;
13512 static const struct
13514 const char *name;
13515 DDPIXELFORMAT format;
13516 BOOL getdc_supported;
13517 HRESULT alt_result;
13519 test_data[] =
13521 {"D3DFMT_A8R8G8B8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
13522 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}}, TRUE},
13523 {"D3DFMT_X8R8G8B8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
13524 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}}, TRUE},
13525 {"D3DFMT_R5G6B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
13526 {0x0000f800}, {0x000007e0}, {0x0000001f}, {0x00000000}}, TRUE},
13527 {"D3DFMT_X1R5G5B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
13528 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00000000}}, TRUE},
13529 {"D3DFMT_A1R5G5B5", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
13530 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00008000}}, TRUE},
13531 {"D3DFMT_A4R4G4B4", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
13532 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x0000f000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
13533 {"D3DFMT_X4R4G4B4", {sizeof(test_data->format), DDPF_RGB, 0, {16},
13534 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
13535 {"D3DFMT_A2R10G10B10", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
13536 {0xc0000000}, {0x3ff00000}, {0x000ffc00}, {0x000003ff}}, TRUE},
13537 {"D3DFMT_A8B8G8R8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
13538 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0xff000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
13539 {"D3DFMT_X8B8G8R8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
13540 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
13541 {"D3DFMT_R3G3B2", {sizeof(test_data->format), DDPF_RGB, 0, {8},
13542 {0x000000e0}, {0x0000001c}, {0x00000003}, {0x00000000}}, FALSE},
13543 /* GetDC() on a P8 surface fails unless the display mode is 8 bpp.
13544 * This is not implemented in wine yet, so disable the test for now.
13545 * Succeeding P8 GetDC() calls are tested in the ddraw:visual test.
13546 {"D3DFMT_P8", {sizeof(test_data->format), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0, {8 },
13547 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
13549 {"D3DFMT_L8", {sizeof(test_data->format), DDPF_LUMINANCE, 0, {8},
13550 {0x000000ff}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
13551 {"D3DFMT_A8L8", {sizeof(test_data->format), DDPF_ALPHAPIXELS | DDPF_LUMINANCE, 0, {16},
13552 {0x000000ff}, {0x00000000}, {0x00000000}, {0x0000ff00}}, FALSE},
13553 {"D3DFMT_DXT1", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','1'), {0},
13554 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
13555 {"D3DFMT_DXT2", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','2'), {0},
13556 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
13557 {"D3DFMT_DXT3", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','3'), {0},
13558 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
13559 {"D3DFMT_DXT4", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','4'), {0},
13560 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
13561 {"D3DFMT_DXT5", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','5'), {0},
13562 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
13565 window = create_window();
13566 ddraw = create_ddraw();
13567 ok(!!ddraw, "Failed to create a ddraw object.\n");
13568 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
13569 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13571 surface_desc.dwSize = sizeof(surface_desc);
13572 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
13573 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr);
13574 screen_bpp = U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount;
13576 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
13578 memset(&surface_desc, 0, sizeof(surface_desc));
13579 surface_desc.dwSize = sizeof(surface_desc);
13580 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
13581 surface_desc.dwWidth = 64;
13582 surface_desc.dwHeight = 64;
13583 U4(surface_desc).ddpfPixelFormat = test_data[i].format;
13584 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13586 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
13588 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
13589 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
13590 if (FAILED(hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
13592 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", test_data[i].name, hr);
13593 continue;
13597 dc = (void *)0x1234;
13598 hr = IDirectDrawSurface7_GetDC(surface, &dc);
13599 if (test_data[i].getdc_supported)
13600 ok(SUCCEEDED(hr) || broken(hr == test_data[i].alt_result),
13601 "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
13602 else
13603 ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
13605 if (SUCCEEDED(hr))
13607 unsigned int width_bytes;
13608 DIBSECTION dib;
13609 HBITMAP bitmap;
13610 DWORD type;
13611 int size;
13613 type = GetObjectType(dc);
13614 ok(type == OBJ_MEMDC, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
13615 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
13616 type = GetObjectType(bitmap);
13617 ok(type == OBJ_BITMAP, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
13619 size = GetObjectA(bitmap, sizeof(dib), &dib);
13620 ok(size == sizeof(dib), "Got unexpected size %d for format %s.\n", size, test_data[i].name);
13621 ok(!dib.dsBm.bmType, "Got unexpected type %#x for format %s.\n",
13622 dib.dsBm.bmType, test_data[i].name);
13623 ok(dib.dsBm.bmWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
13624 dib.dsBm.bmWidth, test_data[i].name);
13625 ok(dib.dsBm.bmHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
13626 dib.dsBm.bmHeight, test_data[i].name);
13627 width_bytes = ((dib.dsBm.bmWidth * U1(test_data[i].format).dwRGBBitCount + 31) >> 3) & ~3;
13628 ok(dib.dsBm.bmWidthBytes == width_bytes, "Got unexpected width bytes %d for format %s.\n",
13629 dib.dsBm.bmWidthBytes, test_data[i].name);
13630 ok(dib.dsBm.bmPlanes == 1, "Got unexpected plane count %d for format %s.\n",
13631 dib.dsBm.bmPlanes, test_data[i].name);
13632 ok(dib.dsBm.bmBitsPixel == U1(test_data[i].format).dwRGBBitCount,
13633 "Got unexpected bit count %d for format %s.\n",
13634 dib.dsBm.bmBitsPixel, test_data[i].name);
13635 /* Windows XP sets bmBits == NULL for formats that match the screen at least on my r200 GPU. I
13636 * suspect this applies to all HW accelerated pre-WDDM drivers because they can handle gdi access
13637 * to ddraw surfaces themselves instead of going through a sysmem DIB section. */
13638 ok(!!dib.dsBm.bmBits || broken(!pDwmIsCompositionEnabled && dib.dsBm.bmBitsPixel == screen_bpp),
13639 "Got unexpected bits %p for format %s.\n", dib.dsBm.bmBits, test_data[i].name);
13641 ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "Got unexpected size %u for format %s.\n",
13642 dib.dsBmih.biSize, test_data[i].name);
13643 ok(dib.dsBmih.biWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
13644 dib.dsBmih.biHeight, test_data[i].name);
13645 ok(dib.dsBmih.biHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
13646 dib.dsBmih.biHeight, test_data[i].name);
13647 ok(dib.dsBmih.biPlanes == 1, "Got unexpected plane count %u for format %s.\n",
13648 dib.dsBmih.biPlanes, test_data[i].name);
13649 ok(dib.dsBmih.biBitCount == U1(test_data[i].format).dwRGBBitCount,
13650 "Got unexpected bit count %u for format %s.\n",
13651 dib.dsBmih.biBitCount, test_data[i].name);
13652 ok(dib.dsBmih.biCompression == (U1(test_data[i].format).dwRGBBitCount == 16 ? BI_BITFIELDS : BI_RGB)
13653 || broken(U1(test_data[i].format).dwRGBBitCount == 32 && dib.dsBmih.biCompression == BI_BITFIELDS),
13654 "Got unexpected compression %#x for format %s.\n",
13655 dib.dsBmih.biCompression, test_data[i].name);
13656 ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
13657 dib.dsBmih.biSizeImage, test_data[i].name);
13658 ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n",
13659 dib.dsBmih.biXPelsPerMeter, test_data[i].name);
13660 ok(!dib.dsBmih.biYPelsPerMeter, "Got unexpected vertical resolution %d for format %s.\n",
13661 dib.dsBmih.biYPelsPerMeter, test_data[i].name);
13662 ok(!dib.dsBmih.biClrUsed, "Got unexpected used colour count %u for format %s.\n",
13663 dib.dsBmih.biClrUsed, test_data[i].name);
13664 ok(!dib.dsBmih.biClrImportant, "Got unexpected important colour count %u for format %s.\n",
13665 dib.dsBmih.biClrImportant, test_data[i].name);
13667 if (dib.dsBmih.biCompression == BI_BITFIELDS)
13669 ok((dib.dsBitfields[0] == U2(test_data[i].format).dwRBitMask
13670 && dib.dsBitfields[1] == U3(test_data[i].format).dwGBitMask
13671 && dib.dsBitfields[2] == U4(test_data[i].format).dwBBitMask)
13672 || broken(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2]),
13673 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
13674 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
13676 else
13678 ok(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2],
13679 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
13680 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
13682 ok(!dib.dshSection, "Got unexpected section %p for format %s.\n", dib.dshSection, test_data[i].name);
13683 ok(!dib.dsOffset, "Got unexpected offset %u for format %s.\n", dib.dsOffset, test_data[i].name);
13685 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
13686 ok(hr == DD_OK, "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13688 else
13690 ok(!dc, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
13693 IDirectDrawSurface7_Release(surface);
13695 if (FAILED(hr))
13696 continue;
13698 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
13699 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_TEXTUREMANAGE;
13700 if (FAILED(hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
13702 skip("Failed to create cube texture for format %s (hr %#x), skipping tests.\n", test_data[i].name, hr);
13703 continue;
13706 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &surface2);
13707 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
13708 hr = IDirectDrawSurface7_GetAttachedSurface(surface2, &caps, &tmp);
13709 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
13710 IDirectDrawSurface7_Release(surface2);
13711 hr = IDirectDrawSurface7_GetAttachedSurface(tmp, &caps, &surface2);
13712 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
13713 IDirectDrawSurface7_Release(tmp);
13715 hr = IDirectDrawSurface7_GetDC(surface, &dc);
13716 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
13717 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
13718 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13719 hr = IDirectDrawSurface7_GetDC(surface2, &dc);
13720 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
13721 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc);
13722 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13724 hr = IDirectDrawSurface7_GetDC(surface, &dc);
13725 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
13726 dc2 = (void *)0x1234;
13727 hr = IDirectDrawSurface7_GetDC(surface, &dc2);
13728 ok(hr == DDERR_DCALREADYCREATED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
13729 ok(dc2 == (void *)0x1234, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
13730 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
13731 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13732 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
13733 ok(hr == DDERR_NODC, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
13735 map_desc.dwSize = sizeof(map_desc);
13736 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13737 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
13738 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13739 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
13740 hr = IDirectDrawSurface7_Unlock(surface, NULL);
13741 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
13742 hr = IDirectDrawSurface7_Unlock(surface, NULL);
13743 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
13745 hr = IDirectDrawSurface7_GetDC(surface, &dc);
13746 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
13747 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13748 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
13749 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
13750 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13752 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13753 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
13754 hr = IDirectDrawSurface7_GetDC(surface, &dc);
13755 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
13756 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
13757 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13758 hr = IDirectDrawSurface7_Unlock(surface, NULL);
13759 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
13761 hr = IDirectDrawSurface7_GetDC(surface, &dc);
13762 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
13763 hr = IDirectDrawSurface7_GetDC(surface2, &dc2);
13764 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
13765 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc2);
13766 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13767 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
13768 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13770 hr = IDirectDrawSurface7_GetDC(surface2, &dc);
13771 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
13772 hr = IDirectDrawSurface7_GetDC(surface, &dc2);
13773 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
13774 hr = IDirectDrawSurface7_ReleaseDC(surface, dc2);
13775 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13776 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc);
13777 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13779 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13780 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
13781 hr = IDirectDrawSurface7_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13782 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
13783 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
13784 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
13785 hr = IDirectDrawSurface7_Unlock(surface, NULL);
13786 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
13788 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13789 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
13790 hr = IDirectDrawSurface7_GetDC(surface, &dc);
13791 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
13792 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
13793 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13794 hr = IDirectDrawSurface7_Unlock(surface, NULL);
13795 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
13797 hr = IDirectDrawSurface7_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13798 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
13799 hr = IDirectDrawSurface7_GetDC(surface, &dc);
13800 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
13801 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
13802 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13803 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
13804 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
13806 hr = IDirectDrawSurface7_GetDC(surface, &dc);
13807 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
13808 hr = IDirectDrawSurface7_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13809 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
13810 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
13811 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
13812 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
13813 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13815 hr = IDirectDrawSurface7_GetDC(surface2, &dc);
13816 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
13817 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13818 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
13819 hr = IDirectDrawSurface7_Unlock(surface, NULL);
13820 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
13821 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc);
13822 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13824 hr = IDirectDrawSurface7_Unlock(surface, NULL);
13825 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
13826 hr = IDirectDrawSurface7_GetDC(surface2, &dc);
13827 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
13828 hr = IDirectDrawSurface7_Unlock(surface, NULL);
13829 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
13830 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc);
13831 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13832 hr = IDirectDrawSurface7_Unlock(surface, NULL);
13833 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
13835 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
13836 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
13837 hr = IDirectDrawSurface7_GetDC(surface, &dc);
13838 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
13839 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
13840 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
13841 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
13842 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13843 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
13844 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
13846 IDirectDrawSurface7_Release(surface2);
13847 IDirectDrawSurface7_Release(surface);
13850 IDirectDraw7_Release(ddraw);
13851 DestroyWindow(window);
13854 static void test_draw_primitive(void)
13856 static WORD indices[] = {0, 1, 2, 3};
13857 static struct vec3 quad[] =
13859 {-1.0f, -1.0f, 0.0f},
13860 {-1.0f, 1.0f, 0.0f},
13861 { 1.0f, -1.0f, 0.0f},
13862 { 1.0f, 1.0f, 0.0f},
13864 D3DDRAWPRIMITIVESTRIDEDDATA strided;
13865 D3DVERTEXBUFFERDESC vb_desc;
13866 IDirect3DVertexBuffer7 *vb;
13867 IDirect3DDevice7 *device;
13868 IDirect3D7 *d3d;
13869 IDirectDraw7 *ddraw;
13870 ULONG refcount;
13871 HWND window;
13872 HRESULT hr;
13873 void *data;
13875 window = create_window();
13876 if (!(device = create_device(window, DDSCL_NORMAL)))
13878 skip("Failed to create a 3D device, skipping test.\n");
13879 DestroyWindow(window);
13880 return;
13883 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
13884 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
13885 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
13886 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
13888 memset(&vb_desc, 0, sizeof(vb_desc));
13889 vb_desc.dwSize = sizeof(vb_desc);
13890 vb_desc.dwFVF = D3DFVF_XYZ;
13891 vb_desc.dwNumVertices = 4;
13892 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &vb, 0);
13893 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
13895 IDirect3D7_Release(d3d);
13897 memset(&strided, 0, sizeof(strided));
13899 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, NULL, 0, 0);
13900 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13901 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device,
13902 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, NULL, 0, 0);
13903 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13904 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, NULL, 0, 0);
13905 todo_wine ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
13906 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, NULL, 0, 0);
13907 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13908 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, 0);
13909 /* r200 rejects 0 vertices */
13910 ok(SUCCEEDED(hr) || broken(ddraw_is_amd(ddraw) && hr == E_FAIL), "Failed to draw, hr %#x.\n", hr);
13911 hr = IDirect3DDevice7_DrawPrimitiveStrided(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, 0);
13912 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13913 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, 0);
13914 ok(SUCCEEDED(hr) || broken(ddraw_is_amd(ddraw) && hr == E_FAIL), "Failed to draw, hr %#x.\n", hr);
13916 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, indices, 4, 0);
13917 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13918 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device,
13919 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, indices, 4, 0);
13920 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13921 /* Interestingly r200 rejects this, but not the call with a NULL index buffer and 0 indices. */
13922 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, indices, 4, 0);
13923 ok(SUCCEEDED(hr) || broken(ddraw_is_amd(ddraw) && hr == E_FAIL), "Failed to draw, hr %#x.\n", hr);
13925 strided.position.lpvData = quad;
13926 strided.position.dwStride = sizeof(*quad);
13927 hr = IDirect3DVertexBuffer7_Lock(vb, 0, &data, NULL);
13928 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
13929 memcpy(data, quad, sizeof(quad));
13930 hr = IDirect3DVertexBuffer7_Unlock(vb);
13931 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
13933 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, NULL, 0, 0);
13934 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13935 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device,
13936 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, NULL, 0, 0);
13937 /* r200 again fails this, this time with E_OUTOFMEMORY. */
13938 ok(SUCCEEDED(hr) || broken(ddraw_is_amd(ddraw) && hr == E_OUTOFMEMORY), "Failed to draw, hr %#x.\n", hr);
13939 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, NULL, 0, 0);
13940 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13941 /* Now this draw should work, but r200 rejects it too - presumably earlier tests broke
13942 * driver internal state. */
13943 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
13944 ok(SUCCEEDED(hr) || broken(ddraw_is_amd(ddraw) && hr == E_FAIL), "Failed to draw, hr %#x.\n", hr);
13945 hr = IDirect3DDevice7_DrawPrimitiveStrided(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, 0);
13946 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13947 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, 0);
13948 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13950 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, indices, 4, 0);
13951 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13952 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device,
13953 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, indices, 4, 0);
13954 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13955 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, indices, 4, 0);
13956 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13958 IDirect3DVertexBuffer7_Release(vb);
13959 IDirectDraw7_Release(ddraw);
13960 refcount = IDirect3DDevice7_Release(device);
13961 ok(!refcount, "Device has %u references left.\n", refcount);
13962 DestroyWindow(window);
13965 static void test_edge_antialiasing_blending(void)
13967 IDirectDrawSurface7 *offscreen;
13968 DDSURFACEDESC2 surface_desc;
13969 D3DDEVICEDESC7 device_desc;
13970 IDirect3DDevice7 *device;
13971 IDirectDraw7 *ddraw;
13972 IDirect3D7 *d3d;
13973 ULONG refcount;
13974 D3DCOLOR color;
13975 HWND window;
13976 HRESULT hr;
13978 static D3DMATRIX mat =
13980 1.0f, 0.0f, 0.0f, 0.0f,
13981 0.0f, 1.0f, 0.0f, 0.0f,
13982 0.0f, 0.0f, 1.0f, 0.0f,
13983 0.0f, 0.0f, 0.0f, 1.0f,
13985 static struct
13987 struct vec3 position;
13988 DWORD diffuse;
13990 green_quad[] =
13992 {{-1.0f, -1.0f, 0.1f}, 0x7f00ff00},
13993 {{-1.0f, 1.0f, 0.1f}, 0x7f00ff00},
13994 {{ 1.0f, -1.0f, 0.1f}, 0x7f00ff00},
13995 {{ 1.0f, 1.0f, 0.1f}, 0x7f00ff00},
13997 static struct
13999 struct vec3 position;
14000 DWORD diffuse;
14002 red_quad[] =
14004 {{-1.0f, -1.0f, 0.1f}, 0xccff0000},
14005 {{-1.0f, 1.0f, 0.1f}, 0xccff0000},
14006 {{ 1.0f, -1.0f, 0.1f}, 0xccff0000},
14007 {{ 1.0f, 1.0f, 0.1f}, 0xccff0000},
14010 window = create_window();
14011 if (!(device = create_device(window, DDSCL_NORMAL)))
14013 skip("Failed to create a 3D device.\n");
14014 DestroyWindow(window);
14015 return;
14018 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
14019 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
14020 trace("Line edge antialiasing support: %#x.\n",
14021 device_desc.dpcLineCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
14022 trace("Triangle edge antialiasing support: %#x.\n",
14023 device_desc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
14025 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
14026 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
14027 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
14028 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
14029 IDirect3D7_Release(d3d);
14031 memset(&surface_desc, 0, sizeof(surface_desc));
14032 surface_desc.dwSize = sizeof(surface_desc);
14033 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
14034 surface_desc.dwWidth = 640;
14035 surface_desc.dwHeight = 480;
14036 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
14037 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
14038 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
14039 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
14040 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
14041 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
14042 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
14043 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
14044 ok(hr == D3D_OK, "Creating the offscreen render target failed, hr %#x.\n", hr);
14046 hr = IDirect3DDevice7_SetRenderTarget(device, offscreen, 0);
14047 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
14049 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
14050 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
14051 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
14052 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
14053 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
14054 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
14055 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
14056 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
14057 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
14058 ok(SUCCEEDED(hr), "Failed to disable Z test, hr %#x.\n", hr);
14059 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
14060 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
14061 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
14062 ok(SUCCEEDED(hr), "Failed to disable stencil test, hr %#x.\n", hr);
14063 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
14064 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
14065 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
14066 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
14068 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
14069 ok(SUCCEEDED(hr), "Failed to enable blending, hr %#x.\n", hr);
14070 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
14071 ok(SUCCEEDED(hr), "Failed to set src blend, hr %#x.\n", hr);
14072 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_DESTALPHA);
14073 ok(SUCCEEDED(hr), "Failed to set dest blend, hr %#x.\n", hr);
14075 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
14076 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
14077 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
14078 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
14079 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
14080 ok(SUCCEEDED(hr), "Failed to set alpha op, hr %#x.\n", hr);
14081 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
14082 ok(SUCCEEDED(hr), "Failed to set alpha arg, hr %#x.\n", hr);
14084 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
14085 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14086 hr = IDirect3DDevice7_BeginScene(device);
14087 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14088 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
14089 green_quad, 4, 0);
14090 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14091 hr = IDirect3DDevice7_EndScene(device);
14092 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14093 color = get_surface_color(offscreen, 320, 240);
14094 ok(compare_color(color, 0x00cc7f00, 1), "Got unexpected color 0x%08x.\n", color);
14096 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
14097 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14098 hr = IDirect3DDevice7_BeginScene(device);
14099 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14100 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
14101 red_quad, 4, 0);
14102 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14103 hr = IDirect3DDevice7_EndScene(device);
14104 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14105 color = get_surface_color(offscreen, 320, 240);
14106 ok(compare_color(color, 0x00cc7f00, 1), "Got unexpected color 0x%08x.\n", color);
14108 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
14109 ok(SUCCEEDED(hr), "Failed to disable blending, hr %#x.\n", hr);
14111 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
14112 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14113 hr = IDirect3DDevice7_BeginScene(device);
14114 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14115 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
14116 green_quad, 4, 0);
14117 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14118 hr = IDirect3DDevice7_EndScene(device);
14119 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14120 color = get_surface_color(offscreen, 320, 240);
14121 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
14123 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
14124 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14125 hr = IDirect3DDevice7_BeginScene(device);
14126 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14127 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
14128 red_quad, 4, 0);
14129 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14130 hr = IDirect3DDevice7_EndScene(device);
14131 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14132 color = get_surface_color(offscreen, 320, 240);
14133 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
14135 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_EDGEANTIALIAS, TRUE);
14136 ok(SUCCEEDED(hr), "Failed to enable edge antialiasing, hr %#x.\n", hr);
14138 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
14139 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14140 hr = IDirect3DDevice7_BeginScene(device);
14141 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14142 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
14143 green_quad, 4, 0);
14144 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14145 hr = IDirect3DDevice7_EndScene(device);
14146 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14147 color = get_surface_color(offscreen, 320, 240);
14148 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
14150 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
14151 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14152 hr = IDirect3DDevice7_BeginScene(device);
14153 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14154 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
14155 red_quad, 4, 0);
14156 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14157 hr = IDirect3DDevice7_EndScene(device);
14158 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14159 color = get_surface_color(offscreen, 320, 240);
14160 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
14162 IDirectDrawSurface7_Release(offscreen);
14163 IDirectDraw7_Release(ddraw);
14164 refcount = IDirect3DDevice7_Release(device);
14165 ok(!refcount, "Device has %u references left.\n", refcount);
14166 DestroyWindow(window);
14169 static void test_display_mode_surface_pixel_format(void)
14171 unsigned int width, height, bpp;
14172 IDirectDrawSurface7 *surface;
14173 DDSURFACEDESC2 surface_desc;
14174 IDirectDraw7 *ddraw;
14175 ULONG refcount;
14176 HWND window;
14177 HRESULT hr;
14179 if (!(ddraw = create_ddraw()))
14181 skip("Failed to create ddraw.\n");
14182 return;
14185 surface_desc.dwSize = sizeof(surface_desc);
14186 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
14187 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14188 width = surface_desc.dwWidth;
14189 height = surface_desc.dwHeight;
14191 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
14192 0, 0, width, height, NULL, NULL, NULL, NULL);
14193 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
14194 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14196 bpp = 0;
14197 if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 16, 0, 0)))
14198 bpp = 16;
14199 if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 24, 0, 0)))
14200 bpp = 24;
14201 if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
14202 bpp = 32;
14203 ok(bpp, "Set display mode failed.\n");
14205 surface_desc.dwSize = sizeof(surface_desc);
14206 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
14207 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14208 ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width);
14209 ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height);
14210 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
14211 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
14213 memset(&surface_desc, 0, sizeof(surface_desc));
14214 surface_desc.dwSize = sizeof(surface_desc);
14215 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
14216 U5(surface_desc).dwBackBufferCount = 1;
14217 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE;
14218 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
14219 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14220 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
14221 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14222 ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width);
14223 ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height);
14224 ok(U4(surface_desc).ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n",
14225 U4(surface_desc).ddpfPixelFormat.dwFlags);
14226 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
14227 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
14228 IDirectDrawSurface7_Release(surface);
14230 memset(&surface_desc, 0, sizeof(surface_desc));
14231 surface_desc.dwSize = sizeof(surface_desc);
14232 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
14233 surface_desc.dwWidth = width;
14234 surface_desc.dwHeight = height;
14235 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
14236 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
14237 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14238 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
14239 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14240 ok(U4(surface_desc).ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n",
14241 U4(surface_desc).ddpfPixelFormat.dwFlags);
14242 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
14243 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
14244 IDirectDrawSurface7_Release(surface);
14246 /* Test compatibility mode mipmap texture creation. */
14247 hr = IDirectDraw7_SetDisplayMode(ddraw, width, height, 16, 0, 0);
14248 ok(hr == DD_OK || hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
14249 if (FAILED(hr))
14251 win_skip("SetDisplayMode failed, skipping test.");
14252 goto done;
14254 bpp = 16;
14256 memset(&surface_desc, 0, sizeof(surface_desc));
14257 surface_desc.dwSize = sizeof(surface_desc);
14258 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_MIPMAPCOUNT | DDSD_PITCH;
14259 U2(surface_desc).dwMipMapCount = 2;
14260 surface_desc.dwWidth = 4;
14261 surface_desc.dwHeight = 4;
14262 U1(surface_desc).lPitch = surface_desc.dwWidth * bpp / 8;
14263 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP | DDSCAPS_VIDEOMEMORY;
14264 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
14265 ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWHW, "Got unexpected hr %#x.\n", hr);
14266 if (surface)
14267 IDirectDrawSurface7_Release(surface);
14269 done:
14270 refcount = IDirectDraw7_Release(ddraw);
14271 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
14272 DestroyWindow(window);
14275 static void test_surface_desc_size(void)
14277 union
14279 DWORD dwSize;
14280 DDSURFACEDESC desc1;
14281 DDSURFACEDESC2 desc2;
14282 BYTE blob[1024];
14283 } desc;
14284 IDirectDrawSurface7 *surface7;
14285 IDirectDrawSurface3 *surface3;
14286 IDirectDrawSurface *surface;
14287 DDSURFACEDESC2 surface_desc;
14288 HRESULT expected_hr, hr;
14289 IDirectDraw7 *ddraw;
14290 unsigned int i, j;
14291 ULONG refcount;
14293 static const struct
14295 unsigned int caps;
14296 const char *name;
14298 surface_caps[] =
14300 {DDSCAPS_OFFSCREENPLAIN, "offscreenplain"},
14301 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, "systemmemory texture"},
14302 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, "videomemory texture"},
14304 static const unsigned int desc_sizes[] =
14306 sizeof(DDSURFACEDESC),
14307 sizeof(DDSURFACEDESC2),
14308 sizeof(DDSURFACEDESC) + 1,
14309 sizeof(DDSURFACEDESC2) + 1,
14310 2 * sizeof(DDSURFACEDESC),
14311 2 * sizeof(DDSURFACEDESC2),
14312 sizeof(DDSURFACEDESC) - 1,
14313 sizeof(DDSURFACEDESC2) - 1,
14314 sizeof(DDSURFACEDESC) / 2,
14315 sizeof(DDSURFACEDESC2) / 2,
14319 sizeof(desc) / 2,
14320 sizeof(desc) - 100,
14323 if (!(ddraw = create_ddraw()))
14325 skip("Failed to create ddraw.\n");
14326 return;
14328 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
14329 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
14331 for (i = 0; i < ARRAY_SIZE(surface_caps); ++i)
14333 memset(&surface_desc, 0, sizeof(surface_desc));
14334 surface_desc.dwSize = sizeof(surface_desc);
14335 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
14336 surface_desc.ddsCaps.dwCaps = surface_caps[i].caps;
14337 surface_desc.dwHeight = 128;
14338 surface_desc.dwWidth = 128;
14339 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface7, NULL)))
14341 skip("Failed to create surface, type %s.\n", surface_caps[i].name);
14342 continue;
14344 hr = IDirectDrawSurface_QueryInterface(surface7, &IID_IDirectDrawSurface, (void **)&surface);
14345 ok(hr == DD_OK, "Failed to query IDirectDrawSurface, hr %#x, type %s.\n", hr, surface_caps[i].name);
14346 hr = IDirectDrawSurface_QueryInterface(surface7, &IID_IDirectDrawSurface3, (void **)&surface3);
14347 ok(hr == DD_OK, "Failed to query IDirectDrawSurface3, hr %#x, type %s.\n", hr, surface_caps[i].name);
14349 /* GetSurfaceDesc() */
14350 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
14352 memset(&desc, 0, sizeof(desc));
14353 desc.dwSize = desc_sizes[j];
14354 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC) ? DD_OK : DDERR_INVALIDPARAMS;
14355 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &desc.desc1);
14356 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
14357 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
14359 memset(&desc, 0, sizeof(desc));
14360 desc.dwSize = desc_sizes[j];
14361 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC) ? DD_OK : DDERR_INVALIDPARAMS;
14362 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &desc.desc1);
14363 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
14364 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
14366 memset(&desc, 0, sizeof(desc));
14367 desc.dwSize = desc_sizes[j];
14368 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC2) ? DD_OK : DDERR_INVALIDPARAMS;
14369 hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &desc.desc2);
14370 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
14371 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
14374 /* Lock() */
14375 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
14377 const BOOL ignore_size = surface_caps[i].caps & DDSCAPS_TEXTURE
14378 && !(surface_caps[i].caps & DDSCAPS_VIDEOMEMORY);
14379 const BOOL valid_size = desc_sizes[j] == sizeof(DDSURFACEDESC)
14380 || desc_sizes[j] == sizeof(DDSURFACEDESC2);
14381 DWORD expected_texture_stage;
14383 memset(&desc, 0, sizeof(desc));
14384 desc.dwSize = desc_sizes[j];
14385 desc.desc2.dwTextureStage = 0xdeadbeef;
14386 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
14387 hr = IDirectDrawSurface_Lock(surface, NULL, &desc.desc1, 0, 0);
14388 expected_hr = ignore_size || valid_size ? DD_OK : DDERR_INVALIDPARAMS;
14389 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
14390 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
14391 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
14392 desc_sizes[j], desc.dwSize, surface_caps[i].name);
14393 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
14394 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
14395 if (SUCCEEDED(hr))
14397 ok(desc.desc1.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
14398 desc.desc1.dwWidth, desc_sizes[j], surface_caps[i].name);
14399 ok(desc.desc1.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
14400 desc.desc1.dwHeight, desc_sizes[j], surface_caps[i].name);
14401 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
14402 todo_wine_if(!expected_texture_stage)
14403 ok(desc.desc2.dwTextureStage == expected_texture_stage,
14404 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
14405 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
14406 IDirectDrawSurface_Unlock(surface, NULL);
14409 memset(&desc, 0, sizeof(desc));
14410 desc.dwSize = desc_sizes[j];
14411 desc.desc2.dwTextureStage = 0xdeadbeef;
14412 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
14413 hr = IDirectDrawSurface3_Lock(surface3, NULL, &desc.desc1, 0, 0);
14414 expected_hr = ignore_size || valid_size ? DD_OK : DDERR_INVALIDPARAMS;
14415 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
14416 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
14417 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
14418 desc_sizes[j], desc.dwSize, surface_caps[i].name);
14419 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
14420 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
14421 if (SUCCEEDED(hr))
14423 ok(desc.desc1.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
14424 desc.desc1.dwWidth, desc_sizes[j], surface_caps[i].name);
14425 ok(desc.desc1.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
14426 desc.desc1.dwHeight, desc_sizes[j], surface_caps[i].name);
14427 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
14428 todo_wine_if(!expected_texture_stage)
14429 ok(desc.desc2.dwTextureStage == expected_texture_stage,
14430 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
14431 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
14432 IDirectDrawSurface3_Unlock(surface3, NULL);
14435 memset(&desc, 0, sizeof(desc));
14436 desc.dwSize = desc_sizes[j];
14437 desc.desc2.dwTextureStage = 0xdeadbeef;
14438 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
14439 hr = IDirectDrawSurface7_Lock(surface7, NULL, &desc.desc2, 0, 0);
14440 expected_hr = ignore_size || valid_size ? DD_OK : DDERR_INVALIDPARAMS;
14441 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
14442 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
14443 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
14444 desc_sizes[j], desc.dwSize, surface_caps[i].name);
14445 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
14446 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
14447 if (SUCCEEDED(hr))
14449 ok(desc.desc2.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
14450 desc.desc2.dwWidth, desc_sizes[j], surface_caps[i].name);
14451 ok(desc.desc2.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
14452 desc.desc2.dwHeight, desc_sizes[j], surface_caps[i].name);
14453 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
14454 ok(desc.desc2.dwTextureStage == expected_texture_stage,
14455 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
14456 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
14457 IDirectDrawSurface7_Unlock(surface7, NULL);
14461 IDirectDrawSurface7_Release(surface7);
14462 IDirectDrawSurface3_Release(surface3);
14463 IDirectDrawSurface_Release(surface);
14466 /* GetDisplayMode() */
14467 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
14469 memset(&desc, 0xcc, sizeof(desc));
14470 desc.dwSize = desc_sizes[j];
14471 expected_hr = (desc.dwSize == sizeof(DDSURFACEDESC) || desc.dwSize == sizeof(DDSURFACEDESC2))
14472 ? DD_OK : DDERR_INVALIDPARAMS;
14473 hr = IDirectDraw7_GetDisplayMode(ddraw, &desc.desc2);
14474 ok(hr == expected_hr, "Got hr %#x, expected %#x, size %u.\n", hr, expected_hr, desc_sizes[j]);
14475 if (SUCCEEDED(hr))
14477 ok(desc.dwSize == sizeof(DDSURFACEDESC2), "Wrong size %u for %u.\n", desc.dwSize, desc_sizes[j]);
14478 ok(desc.blob[desc_sizes[j]] == 0xcc, "Overflow for size %u.\n", desc_sizes[j]);
14479 ok(desc.blob[desc_sizes[j] - 1] != 0xcc, "Struct not cleared for size %u.\n", desc_sizes[j]);
14483 refcount = IDirectDraw7_Release(ddraw);
14484 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
14487 static void test_get_surface_from_dc(void)
14489 IDirectDrawSurface *surface1, *tmp1;
14490 IDirectDrawSurface7 *surface, *tmp;
14491 DDSURFACEDESC2 surface_desc;
14492 IDirectDraw7 *ddraw;
14493 HDC dc, device_dc;
14494 ULONG refcount;
14495 HWND window;
14496 HRESULT hr;
14497 DWORD ret;
14499 window = create_window();
14500 ddraw = create_ddraw();
14501 ok(!!ddraw, "Failed to create a ddraw object.\n");
14502 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
14503 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
14505 memset(&surface_desc, 0, sizeof(surface_desc));
14506 surface_desc.dwSize = sizeof(surface_desc);
14507 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
14508 surface_desc.dwWidth = 64;
14509 surface_desc.dwHeight = 64;
14510 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
14512 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
14513 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
14514 hr = IDirectDrawSurface7_QueryInterface(surface, &IID_IDirectDrawSurface, (void **)&surface1);
14515 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
14517 refcount = get_refcount((IUnknown *)surface1);
14518 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
14519 refcount = get_refcount((IUnknown *)surface);
14520 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
14522 hr = IDirectDrawSurface7_GetDC(surface, &dc);
14523 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
14525 tmp1 = (void *)0xdeadbeef;
14526 device_dc = (void *)0xdeadbeef;
14527 hr = GetSurfaceFromDC(NULL, &tmp1, &device_dc);
14528 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
14529 ok(!tmp1, "Got unexpected surface %p.\n", tmp1);
14530 ok(!device_dc, "Got unexpected device_dc %p.\n", device_dc);
14532 device_dc = (void *)0xdeadbeef;
14533 hr = GetSurfaceFromDC(dc, NULL, &device_dc);
14534 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
14535 ok(device_dc == (void *)0xdeadbeef, "Got unexpected device_dc %p.\n", device_dc);
14537 tmp1 = (void *)0xdeadbeef;
14538 hr = GetSurfaceFromDC(dc, &tmp1, NULL);
14539 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
14540 ok(!tmp1, "Got unexpected surface %p.\n", tmp1);
14542 hr = GetSurfaceFromDC(dc, &tmp1, &device_dc);
14543 ok(SUCCEEDED(hr), "GetSurfaceFromDC failed, hr %#x.\n", hr);
14544 ok(tmp1 == surface1, "Got unexpected surface %p, expected %p.\n", tmp1, surface1);
14545 IDirectDrawSurface_Release(tmp1);
14547 ret = GetObjectType(device_dc);
14548 todo_wine ok(ret == OBJ_DC, "Got unexpected object type %#x.\n", ret);
14549 ret = GetDeviceCaps(device_dc, TECHNOLOGY);
14550 todo_wine ok(ret == DT_RASDISPLAY, "Got unexpected technology %#x.\n", ret);
14552 hr = IDirectDraw7_GetSurfaceFromDC(ddraw, dc, NULL);
14553 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
14555 hr = IDirectDraw7_GetSurfaceFromDC(ddraw, dc, &tmp);
14556 ok(SUCCEEDED(hr), "GetSurfaceFromDC failed, hr %#x.\n", hr);
14557 ok(tmp == surface, "Got unexpected surface %p, expected %p.\n", tmp, surface);
14559 refcount = get_refcount((IUnknown *)surface1);
14560 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
14561 refcount = get_refcount((IUnknown *)surface);
14562 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
14564 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
14565 ok(SUCCEEDED(hr), "ReleaseDC failed, hr %#x.\n", hr);
14567 IDirectDrawSurface_Release(tmp);
14569 dc = CreateCompatibleDC(NULL);
14570 ok(!!dc, "CreateCompatibleDC failed.\n");
14572 tmp1 = (void *)0xdeadbeef;
14573 device_dc = (void *)0xdeadbeef;
14574 hr = GetSurfaceFromDC(dc, &tmp1, &device_dc);
14575 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
14576 ok(!tmp1, "Got unexpected surface %p.\n", tmp1);
14577 ok(!device_dc, "Got unexpected device_dc %p.\n", device_dc);
14579 tmp = (void *)0xdeadbeef;
14580 hr = IDirectDraw7_GetSurfaceFromDC(ddraw, dc, &tmp);
14581 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
14582 ok(!tmp, "Got unexpected surface %p.\n", tmp);
14584 ok(DeleteDC(dc), "DeleteDC failed.\n");
14586 tmp = (void *)0xdeadbeef;
14587 hr = IDirectDraw7_GetSurfaceFromDC(ddraw, NULL, &tmp);
14588 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
14589 ok(!tmp, "Got unexpected surface %p.\n", tmp);
14591 IDirectDrawSurface7_Release(surface);
14592 IDirectDrawSurface_Release(surface1);
14593 IDirectDraw7_Release(ddraw);
14594 DestroyWindow(window);
14597 static void test_ck_operation(void)
14599 IDirectDrawSurface7 *src, *dst;
14600 IDirectDrawSurface *src1, *dst1;
14601 DDSURFACEDESC2 surface_desc;
14602 IDirectDraw7 *ddraw;
14603 ULONG refcount;
14604 HWND window;
14605 HRESULT hr;
14606 D3DCOLOR *color;
14607 unsigned int i;
14608 DDCOLORKEY ckey;
14609 DDBLTFX fx;
14611 window = create_window();
14612 ddraw = create_ddraw();
14613 ok(!!ddraw, "Failed to create a ddraw object.\n");
14614 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
14615 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
14617 memset(&surface_desc, 0, sizeof(surface_desc));
14618 surface_desc.dwSize = sizeof(surface_desc);
14619 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
14620 surface_desc.dwWidth = 4;
14621 surface_desc.dwHeight = 1;
14622 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
14623 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
14624 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
14625 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
14626 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
14627 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
14628 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
14629 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
14631 surface_desc.dwFlags |= DDSD_CKSRCBLT;
14632 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff00ff;
14633 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff00ff;
14634 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
14635 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
14637 hr = IDirectDrawSurface7_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14638 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14639 ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n");
14640 color = surface_desc.lpSurface;
14641 color[0] = 0x77010203;
14642 color[1] = 0x00010203;
14643 color[2] = 0x77ff00ff;
14644 color[3] = 0x00ff00ff;
14645 hr = IDirectDrawSurface7_Unlock(src, NULL);
14646 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14648 for (i = 0; i < 2; ++i)
14650 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14651 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14652 color = surface_desc.lpSurface;
14653 color[0] = 0xcccccccc;
14654 color[1] = 0xcccccccc;
14655 color[2] = 0xcccccccc;
14656 color[3] = 0xcccccccc;
14657 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14658 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14660 if (i)
14662 hr = IDirectDrawSurface7_BltFast(dst, 0, 0, src, NULL, DDBLTFAST_SRCCOLORKEY);
14663 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14665 else
14667 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, NULL);
14668 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14671 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT | DDLOCK_READONLY, NULL);
14672 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14673 ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n");
14674 color = surface_desc.lpSurface;
14675 /* Different behavior on some drivers / windows versions. Some versions ignore the X channel when
14676 * color keying, but copy it to the destination surface. Others (sysmem surfaces) apply it for
14677 * color keying, but do not copy it into the destination surface. Nvidia neither uses it for
14678 * color keying nor copies it. */
14679 ok((color[0] == 0x77010203 && color[1] == 0x00010203
14680 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* AMD, Wine */
14681 || broken(color[0] == 0x00010203 && color[1] == 0x00010203
14682 && color[2] == 0x00ff00ff && color[3] == 0xcccccccc) /* Sysmem surfaces? */
14683 || broken(color[0] == 0x00010203 && color[1] == 0x00010203
14684 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Nvidia */
14685 || broken(color[0] == 0xff010203 && color[1] == 0xff010203
14686 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Testbot */,
14687 "Destination data after blitting is %08x %08x %08x %08x, i=%u.\n",
14688 color[0], color[1], color[2], color[3], i);
14689 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14690 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14693 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
14694 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
14695 ok(ckey.dwColorSpaceLowValue == 0x00ff00ff && ckey.dwColorSpaceHighValue == 0x00ff00ff,
14696 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
14698 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
14699 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
14700 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14702 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
14703 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
14704 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
14705 ok(ckey.dwColorSpaceLowValue == 0x0000ff00 && ckey.dwColorSpaceHighValue == 0x0000ff00,
14706 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
14708 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0;
14709 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0;
14710 hr = IDirectDrawSurface7_GetSurfaceDesc(src, &surface_desc);
14711 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
14712 ok(surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue == 0x0000ff00
14713 && surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue == 0x0000ff00,
14714 "Got unexpected color key low=%08x high=%08x.\n", surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue,
14715 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue);
14717 /* Test SetColorKey with dwColorSpaceHighValue < dwColorSpaceLowValue */
14718 ckey.dwColorSpaceLowValue = 0x000000ff;
14719 ckey.dwColorSpaceHighValue = 0x00000000;
14720 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
14721 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14723 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
14724 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
14725 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
14726 ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff,
14727 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
14729 ckey.dwColorSpaceLowValue = 0x000000ff;
14730 ckey.dwColorSpaceHighValue = 0x00000001;
14731 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
14732 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14734 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
14735 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
14736 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
14737 ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff,
14738 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
14740 ckey.dwColorSpaceLowValue = 0x000000fe;
14741 ckey.dwColorSpaceHighValue = 0x000000fd;
14742 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
14743 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14745 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
14746 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
14747 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
14748 ok(ckey.dwColorSpaceLowValue == 0x000000fe && ckey.dwColorSpaceHighValue == 0x000000fe,
14749 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
14751 IDirectDrawSurface7_Release(src);
14752 IDirectDrawSurface7_Release(dst);
14754 /* Test source and destination keys and where they are read from. Use a surface with alpha
14755 * to avoid driver-dependent content in the X channel. */
14756 memset(&surface_desc, 0, sizeof(surface_desc));
14757 surface_desc.dwSize = sizeof(surface_desc);
14758 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
14759 surface_desc.dwWidth = 6;
14760 surface_desc.dwHeight = 1;
14761 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
14762 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
14763 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
14764 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
14765 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
14766 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
14767 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
14768 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
14769 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
14770 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
14771 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
14773 ckey.dwColorSpaceLowValue = 0x0000ff00;
14774 ckey.dwColorSpaceHighValue = 0x0000ff00;
14775 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
14776 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14777 ckey.dwColorSpaceLowValue = 0x00ff0000;
14778 ckey.dwColorSpaceHighValue = 0x00ff0000;
14779 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_DESTBLT, &ckey);
14780 ok(SUCCEEDED(hr) || hr == DDERR_NOCOLORKEYHW, "Failed to set color key, hr %#x.\n", hr);
14781 if (FAILED(hr))
14783 /* Nvidia reject dest keys, AMD allows them. This applies to vidmem and sysmem surfaces. */
14784 skip("Failed to set destination color key, skipping related tests.\n");
14785 goto done;
14788 ckey.dwColorSpaceLowValue = 0x000000ff;
14789 ckey.dwColorSpaceHighValue = 0x000000ff;
14790 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
14791 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14792 ckey.dwColorSpaceLowValue = 0x000000aa;
14793 ckey.dwColorSpaceHighValue = 0x000000aa;
14794 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_DESTBLT, &ckey);
14795 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14797 memset(&fx, 0, sizeof(fx));
14798 fx.dwSize = sizeof(fx);
14799 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x00110000;
14800 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x00110000;
14801 fx.ddckDestColorkey.dwColorSpaceHighValue = 0x00001100;
14802 fx.ddckDestColorkey.dwColorSpaceLowValue = 0x00001100;
14804 hr = IDirectDrawSurface7_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14805 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14806 color = surface_desc.lpSurface;
14807 color[0] = 0x000000ff; /* Applies to src blt key in src surface. */
14808 color[1] = 0x000000aa; /* Applies to dst blt key in src surface. */
14809 color[2] = 0x00ff0000; /* Dst color key in dst surface. */
14810 color[3] = 0x0000ff00; /* Src color key in dst surface. */
14811 color[4] = 0x00001100; /* Src color key in ddbltfx. */
14812 color[5] = 0x00110000; /* Dst color key in ddbltfx. */
14813 hr = IDirectDrawSurface7_Unlock(src, NULL);
14814 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14816 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14817 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14818 color = surface_desc.lpSurface;
14819 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
14820 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14821 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14823 /* Test a blit without keying. */
14824 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, 0, &fx);
14825 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14827 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14828 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14829 color = surface_desc.lpSurface;
14830 /* Should have copied src data unmodified to dst. */
14831 ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
14832 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
14833 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14834 color[0], color[1], color[2], color[3], color[4], color[5]);
14836 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
14837 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14838 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14840 /* Src key. */
14841 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx);
14842 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14844 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14845 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14846 color = surface_desc.lpSurface;
14847 /* Src key applied to color[0]. It is unmodified, the others are copied. */
14848 ok(color[0] == 0x55555555 && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
14849 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
14850 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14851 color[0], color[1], color[2], color[3], color[4], color[5]);
14853 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
14854 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14855 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14857 /* Src override. */
14858 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, &fx);
14859 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14861 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14862 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14863 color = surface_desc.lpSurface;
14864 /* Override key applied to color[5]. It is unmodified, the others are copied. */
14865 ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
14866 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x55555555,
14867 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14868 color[0], color[1], color[2], color[3], color[4], color[5]);
14870 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
14871 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14872 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14874 /* Src override AND src key. That is not supposed to work. */
14875 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE, &fx);
14876 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14878 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14879 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14880 color = surface_desc.lpSurface;
14881 /* Ensure the destination was not changed. */
14882 ok(color[0] == 0x55555555 && color[1] == 0x55555555 && color[2] == 0x55555555 &&
14883 color[3] == 0x55555555 && color[4] == 0x55555555 && color[5] == 0x55555555,
14884 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14885 color[0], color[1], color[2], color[3], color[4], color[5]);
14887 /* Use different dst colors for the dst key test. */
14888 color[0] = 0x00ff0000; /* Dest key in dst surface. */
14889 color[1] = 0x00ff0000; /* Dest key in dst surface. */
14890 color[2] = 0x00001100; /* Dest key in override. */
14891 color[3] = 0x00001100; /* Dest key in override. */
14892 color[4] = 0x000000aa; /* Dest key in src surface. */
14893 color[5] = 0x000000aa; /* Dest key in src surface. */
14894 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14895 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14897 /* Dest key blit. The key is taken from the DESTINATION surface in v7! */
14898 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
14899 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14901 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14902 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14903 color = surface_desc.lpSurface;
14904 /* Dst key applied to color[0,1], they are the only changed pixels. */
14905 todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 &&
14906 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
14907 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14908 color[0], color[1], color[2], color[3], color[4], color[5]);
14910 color[0] = 0x00ff0000; /* Dest key in dst surface. */
14911 color[1] = 0x00ff0000; /* Dest key in dst surface. */
14912 color[2] = 0x00001100; /* Dest key in override. */
14913 color[3] = 0x00001100; /* Dest key in override. */
14914 color[4] = 0x000000aa; /* Dest key in src surface. */
14915 color[5] = 0x000000aa; /* Dest key in src surface. */
14916 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14917 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14919 /* What happens with a QI'd older version of the interface? It takes the key
14920 * from the source surface. */
14921 hr = IDirectDrawSurface7_QueryInterface(src, &IID_IDirectDrawSurface, (void **)&src1);
14922 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
14923 hr = IDirectDrawSurface7_QueryInterface(dst, &IID_IDirectDrawSurface, (void **)&dst1);
14924 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
14926 hr = IDirectDrawSurface_Blt(dst1, NULL, src1, NULL, DDBLT_KEYDEST, &fx);
14927 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14929 IDirectDrawSurface_Release(dst1);
14930 IDirectDrawSurface_Release(src1);
14932 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14933 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14934 color = surface_desc.lpSurface;
14935 /* Dst key applied to color[4,5], they are the only changed pixels. */
14936 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
14937 color[3] == 0x00001100 && color[4] == 0x00001100 && color[5] == 0x00110000,
14938 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14939 color[0], color[1], color[2], color[3], color[4], color[5]);
14941 color[0] = 0x00ff0000; /* Dest key in dst surface. */
14942 color[1] = 0x00ff0000; /* Dest key in dst surface. */
14943 color[2] = 0x00001100; /* Dest key in override. */
14944 color[3] = 0x00001100; /* Dest key in override. */
14945 color[4] = 0x000000aa; /* Dest key in src surface. */
14946 color[5] = 0x000000aa; /* Dest key in src surface. */
14947 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14948 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14950 /* Dest override key blit. */
14951 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, &fx);
14952 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14954 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14955 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14956 color = surface_desc.lpSurface;
14957 /* Dst key applied to color[2,3], they are the only changed pixels. */
14958 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00ff0000 &&
14959 color[3] == 0x0000ff00 && color[4] == 0x000000aa && color[5] == 0x000000aa,
14960 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14961 color[0], color[1], color[2], color[3], color[4], color[5]);
14963 color[0] = 0x00ff0000; /* Dest key in dst surface. */
14964 color[1] = 0x00ff0000; /* Dest key in dst surface. */
14965 color[2] = 0x00001100; /* Dest key in override. */
14966 color[3] = 0x00001100; /* Dest key in override. */
14967 color[4] = 0x000000aa; /* Dest key in src surface. */
14968 color[5] = 0x000000aa; /* Dest key in src surface. */
14969 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14970 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14972 /* Dest override together with surface key. Supposed to fail. */
14973 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYDESTOVERRIDE, &fx);
14974 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14976 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14977 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14978 color = surface_desc.lpSurface;
14979 /* Destination is unchanged. */
14980 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
14981 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
14982 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14983 color[0], color[1], color[2], color[3], color[4], color[5]);
14984 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14985 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14987 /* Source and destination key. This is driver dependent. New HW treats it like
14988 * DDBLT_KEYSRC. Older HW and some software renderers apply both keys. */
14989 if (0)
14991 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYSRC, &fx);
14992 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14994 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14995 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14996 color = surface_desc.lpSurface;
14997 /* Color[0] is filtered by the src key, 2-5 are filtered by the dst key, if
14998 * the driver applies it. */
14999 ok(color[0] == 0x00ff0000 && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
15000 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
15001 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
15002 color[0], color[1], color[2], color[3], color[4], color[5]);
15004 color[0] = 0x00ff0000; /* Dest key in dst surface. */
15005 color[1] = 0x00ff0000; /* Dest key in dst surface. */
15006 color[2] = 0x00001100; /* Dest key in override. */
15007 color[3] = 0x00001100; /* Dest key in override. */
15008 color[4] = 0x000000aa; /* Dest key in src surface. */
15009 color[5] = 0x000000aa; /* Dest key in src surface. */
15010 hr = IDirectDrawSurface7_Unlock(dst, NULL);
15011 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
15014 /* Override keys without ddbltfx parameter fail */
15015 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, NULL);
15016 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
15017 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, NULL);
15018 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
15020 /* Try blitting without keys in the source surface. */
15021 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, NULL);
15022 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
15023 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_DESTBLT, NULL);
15024 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
15026 /* That fails now. Do not bother to check that the data is unmodified. */
15027 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx);
15028 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
15030 /* Dest key blit still works, the destination surface key is used in v7. */
15031 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
15032 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
15034 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
15035 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
15036 color = surface_desc.lpSurface;
15037 /* Dst key applied to color[0,1], they are the only changed pixels. */
15038 todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 &&
15039 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
15040 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
15041 color[0], color[1], color[2], color[3], color[4], color[5]);
15042 hr = IDirectDrawSurface7_Unlock(dst, NULL);
15043 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
15045 /* Try blitting without keys in the destination surface. */
15046 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_SRCBLT, NULL);
15047 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
15048 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_DESTBLT, NULL);
15049 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
15051 /* This fails, as sanity would dictate. */
15052 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
15053 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
15055 done:
15056 IDirectDrawSurface7_Release(src);
15057 IDirectDrawSurface7_Release(dst);
15058 refcount = IDirectDraw7_Release(ddraw);
15059 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
15060 DestroyWindow(window);
15063 static void test_vb_refcount(void)
15065 ULONG prev_d3d_refcount, prev_device_refcount;
15066 ULONG cur_d3d_refcount, cur_device_refcount;
15067 IDirect3DVertexBuffer7 *vb, *vb7;
15068 D3DVERTEXBUFFERDESC vb_desc;
15069 IDirect3DVertexBuffer *vb1;
15070 IDirect3DDevice7 *device;
15071 IDirect3D7 *d3d;
15072 ULONG refcount;
15073 IUnknown *unk;
15074 HWND window;
15075 HRESULT hr;
15077 window = create_window();
15078 if (!(device = create_device(window, DDSCL_NORMAL)))
15080 skip("Failed to create a 3D device, skipping test.\n");
15081 DestroyWindow(window);
15082 return;
15085 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
15086 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
15088 prev_d3d_refcount = get_refcount((IUnknown *)d3d);
15089 prev_device_refcount = get_refcount((IUnknown *)device);
15091 memset(&vb_desc, 0, sizeof(vb_desc));
15092 vb_desc.dwSize = sizeof(vb_desc);
15093 vb_desc.dwFVF = D3DFVF_XYZ;
15094 vb_desc.dwNumVertices = 4;
15095 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &vb, 0);
15096 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
15098 cur_d3d_refcount = get_refcount((IUnknown *)d3d);
15099 cur_device_refcount = get_refcount((IUnknown *)device);
15100 ok(cur_d3d_refcount > prev_d3d_refcount, "D3D object refcount didn't change from %u.\n", prev_d3d_refcount);
15101 ok(cur_device_refcount == prev_device_refcount, "Device refcount changed from %u to %u.\n",
15102 prev_device_refcount, cur_device_refcount);
15104 prev_d3d_refcount = cur_d3d_refcount;
15105 hr = IDirect3DVertexBuffer7_QueryInterface(vb, &IID_IDirect3DVertexBuffer7, (void **)&vb7);
15106 ok(hr == DD_OK, "Failed to query IDirect3DVertexBuffer7, hr %#x.\n", hr);
15107 cur_d3d_refcount = get_refcount((IUnknown *)d3d);
15108 ok(cur_d3d_refcount == prev_d3d_refcount, "D3D object refcount changed from %u to %u.\n",
15109 prev_d3d_refcount, cur_d3d_refcount);
15110 IDirect3DVertexBuffer7_Release(vb7);
15112 hr = IDirect3DVertexBuffer7_QueryInterface(vb, &IID_IDirect3DVertexBuffer, (void **)&vb1);
15113 ok(hr == E_NOINTERFACE, "Querying IDirect3DVertexBuffer returned unexpected hr %#x.\n", hr);
15115 hr = IDirect3DVertexBuffer_QueryInterface(vb, &IID_IUnknown, (void **)&unk);
15116 ok(hr == DD_OK, "Failed to query IUnknown, hr %#x.\n", hr);
15117 ok((IUnknown *)vb == unk,
15118 "IDirect3DVertexBuffer7 and IUnknown interface pointers don't match, %p != %p.\n", vb, unk);
15119 IUnknown_Release(unk);
15121 refcount = IDirect3DVertexBuffer7_Release(vb);
15122 ok(!refcount, "Vertex buffer has %u references left.\n", refcount);
15124 IDirect3D7_Release(d3d);
15125 refcount = IDirect3DDevice7_Release(device);
15126 ok(!refcount, "Device has %u references left.\n", refcount);
15127 DestroyWindow(window);
15130 static void test_compute_sphere_visibility(void)
15132 static D3DVALUE clip_plane[4] = {1.0f, 0.0f, 0.0f, 0.5f};
15133 static D3DMATRIX proj_1 =
15135 1.810660f, 0.000000f, 0.000000f, 0.000000f,
15136 0.000000f, 2.414213f, 0.000000f, 0.000000f,
15137 0.000000f, 0.000000f, 1.020408f, 1.000000f,
15138 0.000000f, 0.000000f, -0.102041f, 0.000000f,
15140 static D3DMATRIX proj_2 =
15142 10.0f, 0.0f, 0.0f, 0.0f,
15143 0.0f, 10.0f, 0.0f, 0.0f,
15144 0.0f, 0.0f, 10.0f, 0.0f,
15145 0.0f, 0.0f, 0.0f, 1.0f,
15147 static D3DMATRIX view_1 =
15149 1.000000f, 0.000000f, 0.000000f, 0.000000f,
15150 0.000000f, 0.768221f, -0.640185f, 0.000000f,
15151 -0.000000f, 0.640185f, 0.768221f, 0.000000f,
15152 -14.852037f, 9.857489f, 11.600972f, 1.000000f,
15154 static D3DMATRIX identity =
15156 1.0f, 0.0f, 0.0f, 0.0f,
15157 0.0f, 1.0f, 0.0f, 0.0f,
15158 0.0f, 0.0f, 1.0f, 0.0f,
15159 0.0f, 0.0f, 0.0f, 1.0f,
15161 static struct
15163 D3DMATRIX *view, *proj;
15164 unsigned int sphere_count;
15165 D3DVECTOR center[3];
15166 D3DVALUE radius[3];
15167 DWORD enable_planes;
15168 const DWORD expected[3];
15170 tests[] =
15172 {&view_1, &proj_1, 1, {{{11.461533f}, {-4.761727f}, {-1.171646f}}}, {38.252632f}, 0, {0x3f}},
15173 {&view_1, &proj_1, 3, {{{-3.515620f}, {-1.560661f}, {-12.464638f}},
15174 {{14.290396f}, {-2.981143f}, {-24.311312f}},
15175 {{1.461626f}, {-6.093709f}, {-13.901010f}}},
15176 {4.354097f, 12.500704f, 17.251318f}, 0, {0x103d, 0x3f, 0x3f}},
15177 {&identity, &proj_2, 1, {{{0.0f}, {0.0f}, {0.05f}}}, {0.04f}, 0, {0}},
15178 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.5f}}}, {0.5f}, 0, {0}},
15179 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.0f}}}, {0.0f}, 0, {0}},
15180 {&identity, &identity, 1, {{{-1.0f}, {-1.0f}, {0.5f}}}, {0.25f}, 0, {0x9}}, /* 5 */
15181 {&identity, &identity, 1, {{{-20.0f}, {0.0f}, {0.5f}}}, {3.0f}, 0, {0x103d}},
15182 {&identity, &identity, 1, {{{20.0f}, {0.0f}, {0.5f}}}, {3.0f}, 0, {0x203e}},
15183 {&identity, &identity, 1, {{{0.0f}, {-20.0f}, {0.5f}}}, {3.0f}, 0, {0x803b}},
15184 {&identity, &identity, 1, {{{0.0f}, {20.0f}, {0.5f}}}, {3.0f}, 0, {0x4037}},
15185 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {-20.0f}}}, {3.0f}, 0, {0x1001f}}, /* 10 */
15186 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {20.0f}}}, {3.0f}, 0, {0x2002f}},
15187 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.0f}}}, {5.0f}, 1, {0x7f}},
15188 {&identity, &identity, 1, {{{-0.5f}, {0.0f}, {0.0f}}}, {5.0f}, 1, {0x7f}},
15189 {&identity, &identity, 1, {{{-0.5f}, {0.0f}, {0.0f}}}, {1.0f}, 1, {0x51}},
15190 {&identity, &identity, 1, {{{-2.5f}, {0.0f}, {0.0f}}}, {1.0f}, 1, {0x41051}}, /* 15 */
15192 IDirect3DDevice7 *device;
15193 unsigned int i, j;
15194 DWORD result[3];
15195 ULONG refcount;
15196 HWND window;
15197 HRESULT hr;
15199 window = create_window();
15200 if (!(device = create_device(window, DDSCL_NORMAL)))
15202 skip("Failed to create a 3D device, skipping test.\n");
15203 DestroyWindow(window);
15204 return;
15207 hr = IDirect3DDevice7_SetClipPlane(device, 0, clip_plane);
15208 ok(SUCCEEDED(hr), "Failed to set user clip plane, hr %#x.\n", hr);
15210 IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &identity);
15212 for (i = 0; i < ARRAY_SIZE(tests); ++i)
15214 IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, tests[i].view);
15215 IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, tests[i].proj);
15217 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE,
15218 tests[i].enable_planes);
15219 ok(SUCCEEDED(hr), "Failed to enable / disable user clip planes, hr %#x.\n", hr);
15221 hr = IDirect3DDevice7_ComputeSphereVisibility(device, tests[i].center, tests[i].radius,
15222 tests[i].sphere_count, 0, result);
15223 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
15225 for (j = 0; j < tests[i].sphere_count; ++j)
15226 ok(result[j] == tests[i].expected[j], "Test %u sphere %u: expected %#x, got %#x.\n",
15227 i, j, tests[i].expected[j], result[j]);
15230 refcount = IDirect3DDevice7_Release(device);
15231 ok(!refcount, "Device has %u references left.\n", refcount);
15232 DestroyWindow(window);
15235 static void test_clip_planes_limits(void)
15237 IDirect3DDevice7 *device;
15238 D3DDEVICEDESC7 caps;
15239 unsigned int i;
15240 ULONG refcount;
15241 float plane[4];
15242 HWND window;
15243 DWORD state;
15244 HRESULT hr;
15246 window = create_window();
15247 if (!(device = create_device(window, DDSCL_NORMAL)))
15249 skip("Failed to create 3D device.\n");
15250 DestroyWindow(window);
15251 return;
15254 memset(&caps, 0, sizeof(caps));
15255 hr = IDirect3DDevice7_GetCaps(device, &caps);
15256 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
15258 trace("Max user clip planes: %u.\n", caps.wMaxUserClipPlanes);
15260 for (i = 0; i < caps.wMaxUserClipPlanes; ++i)
15262 memset(plane, 0xff, sizeof(plane));
15263 hr = IDirect3DDevice7_GetClipPlane(device, i, plane);
15264 ok(hr == D3D_OK, "Failed to get clip plane %u, hr %#x.\n", i, hr);
15265 ok(!plane[0] && !plane[1] && !plane[2] && !plane[3],
15266 "Got unexpected plane %u: %.8e, %.8e, %.8e, %.8e.\n",
15267 i, plane[0], plane[1], plane[2], plane[3]);
15270 plane[0] = 2.0f;
15271 plane[1] = 8.0f;
15272 plane[2] = 5.0f;
15273 for (i = 0; i < caps.wMaxUserClipPlanes; ++i)
15275 plane[3] = i;
15276 hr = IDirect3DDevice7_SetClipPlane(device, i, plane);
15277 ok(hr == D3D_OK, "Failed to set clip plane %u, hr %#x.\n", i, hr);
15279 for (i = 0; i < caps.wMaxUserClipPlanes; ++i)
15281 memset(plane, 0xff, sizeof(plane));
15282 hr = IDirect3DDevice7_GetClipPlane(device, i, plane);
15283 ok(hr == D3D_OK, "Failed to get clip plane %u, hr %#x.\n", i, hr);
15284 ok(plane[0] == 2.0f && plane[1] == 8.0f && plane[2] == 5.0f && plane[3] == i,
15285 "Got unexpected plane %u: %.8e, %.8e, %.8e, %.8e.\n",
15286 i, plane[0], plane[1], plane[2], plane[3]);
15289 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE, 0xffffffff);
15290 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
15291 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE, &state);
15292 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
15293 ok(state == 0xffffffff, "Got unexpected state %#x.\n", state);
15294 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE, 0x80000000);
15295 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
15296 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE, &state);
15297 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
15298 ok(state == 0x80000000, "Got unexpected state %#x.\n", state);
15300 refcount = IDirect3DDevice7_Release(device);
15301 ok(!refcount, "Device has %u references left.\n", refcount);
15302 DestroyWindow(window);
15305 static void test_texture_stages_limits(void)
15307 IDirectDrawSurface7 *texture;
15308 DDSURFACEDESC2 surface_desc;
15309 IDirect3DDevice7 *device;
15310 IDirectDraw7 *ddraw;
15311 IDirect3D7 *d3d;
15312 unsigned int i;
15313 ULONG refcount;
15314 HWND window;
15315 HRESULT hr;
15317 window = create_window();
15318 if (!(device = create_device(window, DDSCL_NORMAL)))
15320 skip("Failed to create 3D device.\n");
15321 DestroyWindow(window);
15322 return;
15324 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
15325 ok(SUCCEEDED(hr), "Failed to get Direct3D interface, hr %#x.\n", hr);
15326 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
15327 ok(SUCCEEDED(hr), "Failed to get DirectDraw interface, hr %#x.\n", hr);
15328 IDirect3D7_Release(d3d);
15330 memset(&surface_desc, 0, sizeof(surface_desc));
15331 surface_desc.dwSize = sizeof(surface_desc);
15332 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
15333 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
15334 surface_desc.dwWidth = 16;
15335 surface_desc.dwHeight = 16;
15336 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
15337 ok(hr == DD_OK, "Failed to create surface, hr %#x.\n", hr);
15339 for (i = 0; i < 8; ++i)
15341 hr = IDirect3DDevice7_SetTexture(device, i, texture);
15342 ok(hr == D3D_OK, "Failed to set texture %u, hr %#x.\n", i, hr);
15343 hr = IDirect3DDevice7_SetTexture(device, i, NULL);
15344 ok(hr == D3D_OK, "Failed to set texture %u, hr %#x.\n", i, hr);
15345 hr = IDirect3DDevice7_SetTextureStageState(device, i, D3DTSS_COLOROP, D3DTOP_ADD);
15346 ok(hr == D3D_OK, "Failed to set texture stage state %u, hr %#x.\n", i, hr);
15349 IDirectDrawSurface7_Release(texture);
15350 IDirectDraw7_Release(ddraw);
15351 refcount = IDirect3DDevice7_Release(device);
15352 ok(!refcount, "Device has %u references left.\n", refcount);
15353 DestroyWindow(window);
15356 static void test_set_render_state(void)
15358 IDirect3DDevice7 *device;
15359 ULONG refcount;
15360 HWND window;
15361 DWORD state;
15362 HRESULT hr;
15364 window = create_window();
15365 if (!(device = create_device(window, DDSCL_NORMAL)))
15367 skip("Failed to create 3D device.\n");
15368 DestroyWindow(window);
15369 return;
15372 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZVISIBLE, TRUE);
15373 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
15374 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZVISIBLE, FALSE);
15375 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
15377 /* States deprecated in D3D7 */
15378 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
15379 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
15380 state = 0xdeadbeef;
15381 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, &state);
15382 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
15383 ok(state == 0xdeadbeef, "Got unexpected render state %#x.\n", state);
15384 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
15385 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
15386 state = 0xdeadbeef;
15387 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, &state);
15388 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
15389 ok(state == 0xdeadbeef, "Got unexpected render state %#x.\n", state);
15391 refcount = IDirect3DDevice7_Release(device);
15392 ok(!refcount, "Device has %u references left.\n", refcount);
15393 DestroyWindow(window);
15396 static void test_map_synchronisation(void)
15398 LARGE_INTEGER frequency, diff, ts[3];
15399 IDirect3DVertexBuffer7 *buffer;
15400 unsigned int i, j, tri_count;
15401 D3DVERTEXBUFFERDESC vb_desc;
15402 IDirect3DDevice7 *device;
15403 BOOL unsynchronised, ret;
15404 IDirectDrawSurface7 *rt;
15405 IDirectDraw7 *ddraw;
15406 IDirect3D7 *d3d;
15407 D3DCOLOR colour;
15408 ULONG refcount;
15409 HWND window;
15410 HRESULT hr;
15412 static const struct
15414 unsigned int flags;
15415 BOOL unsynchronised;
15417 tests[] =
15419 {0, FALSE},
15420 {DDLOCK_NOOVERWRITE, TRUE},
15421 {DDLOCK_DISCARDCONTENTS, FALSE},
15422 {DDLOCK_NOOVERWRITE | DDLOCK_DISCARDCONTENTS, TRUE},
15425 static const struct quad
15427 struct
15429 struct vec3 position;
15430 DWORD diffuse;
15431 } strip[4];
15433 quad1 =
15436 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
15437 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
15438 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
15439 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
15442 quad2 =
15445 {{-1.0f, -1.0f, 0.0f}, 0xffffff00},
15446 {{-1.0f, 1.0f, 0.0f}, 0xffffff00},
15447 {{ 1.0f, -1.0f, 0.0f}, 0xffffff00},
15448 {{ 1.0f, 1.0f, 0.0f}, 0xffffff00},
15451 struct quad *quads;
15453 window = create_window();
15454 ok(!!window, "Failed to create a window.\n");
15456 if (!(device = create_device(window, DDSCL_NORMAL)))
15458 skip("Failed to create a D3D device, skipping tests.\n");
15459 DestroyWindow(window);
15460 return;
15463 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
15464 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
15465 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
15466 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
15467 /* Maps are always synchronised on WARP. */
15468 if (ddraw_is_warp(ddraw))
15470 skip("Running on WARP, skipping test.\n");
15471 goto done;
15474 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
15475 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
15477 tri_count = 0x1000;
15479 ret = QueryPerformanceFrequency(&frequency);
15480 ok(ret, "Failed to get performance counter frequency.\n");
15482 vb_desc.dwSize = sizeof(vb_desc);
15483 vb_desc.dwCaps = D3DVBCAPS_WRITEONLY;
15484 vb_desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
15485 vb_desc.dwNumVertices = tri_count + 2;
15486 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &buffer, 0);
15487 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
15488 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&quads, NULL);
15489 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
15490 for (j = 0; j < vb_desc.dwNumVertices / 4; ++j)
15492 quads[j] = quad1;
15494 hr = IDirect3DVertexBuffer7_Unlock(buffer);
15495 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
15497 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
15498 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
15500 /* Initial draw to initialise states, compile shaders, etc. */
15501 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
15502 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15503 hr = IDirect3DDevice7_BeginScene(device);
15504 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
15505 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, vb_desc.dwNumVertices, 0);
15506 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
15507 hr = IDirect3DDevice7_EndScene(device);
15508 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
15509 /* Read the result to ensure the GPU has finished drawing. */
15510 colour = get_surface_color(rt, 320, 240);
15512 /* Time drawing tri_count triangles. */
15513 ret = QueryPerformanceCounter(&ts[0]);
15514 ok(ret, "Failed to read performance counter.\n");
15515 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
15516 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15517 hr = IDirect3DDevice7_BeginScene(device);
15518 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
15519 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, vb_desc.dwNumVertices, 0);
15520 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
15521 hr = IDirect3DDevice7_EndScene(device);
15522 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
15523 colour = get_surface_color(rt, 320, 240);
15524 /* Time drawing a single triangle. */
15525 ret = QueryPerformanceCounter(&ts[1]);
15526 ok(ret, "Failed to read performance counter.\n");
15527 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
15528 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15529 hr = IDirect3DDevice7_BeginScene(device);
15530 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
15531 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 3, 0);
15532 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
15533 hr = IDirect3DDevice7_EndScene(device);
15534 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
15535 colour = get_surface_color(rt, 320, 240);
15536 ret = QueryPerformanceCounter(&ts[2]);
15537 ok(ret, "Failed to read performance counter.\n");
15539 IDirect3DVertexBuffer7_Release(buffer);
15541 /* Estimate the number of triangles we can draw in 100ms. */
15542 diff.QuadPart = ts[1].QuadPart - ts[0].QuadPart + ts[1].QuadPart - ts[2].QuadPart;
15543 tri_count = (tri_count * frequency.QuadPart) / (diff.QuadPart * 10);
15544 tri_count = ((tri_count + 2 + 3) & ~3) - 2;
15545 vb_desc.dwNumVertices = tri_count + 2;
15547 for (i = 0; i < ARRAY_SIZE(tests); ++i)
15549 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &buffer, 0);
15550 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
15551 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&quads, NULL);
15552 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
15553 for (j = 0; j < vb_desc.dwNumVertices / 4; ++j)
15555 quads[j] = quad1;
15557 hr = IDirect3DVertexBuffer7_Unlock(buffer);
15558 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
15560 /* Start a draw operation. */
15561 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
15562 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15563 hr = IDirect3DDevice7_BeginScene(device);
15564 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
15565 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, vb_desc.dwNumVertices, 0);
15566 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
15567 hr = IDirect3DDevice7_EndScene(device);
15568 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
15570 /* Map the last quad while the draw is in progress. */
15571 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_WAIT | tests[i].flags, (void **)&quads, NULL);
15572 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
15573 quads[(vb_desc.dwNumVertices / 4) - 1] = quad2;
15574 hr = IDirect3DVertexBuffer7_Unlock(buffer);
15575 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
15577 colour = get_surface_color(rt, 320, 240);
15578 unsynchronised = compare_color(colour, 0x00ffff00, 1);
15579 ok(tests[i].unsynchronised == unsynchronised, "Expected %s map for flags %#x.\n",
15580 tests[i].unsynchronised ? "unsynchronised" : "synchronised", tests[i].flags);
15582 IDirect3DVertexBuffer7_Release(buffer);
15585 IDirectDrawSurface7_Release(rt);
15586 done:
15587 IDirectDraw7_Release(ddraw);
15588 IDirect3D7_Release(d3d);
15589 refcount = IDirect3DDevice7_Release(device);
15590 ok(!refcount, "Device has %u references left.\n", refcount);
15591 DestroyWindow(window);
15594 static void test_depth_readback(void)
15596 DWORD depth, expected_depth, max_diff, raw_value, passed_fmts = 0;
15597 IDirectDrawSurface7 *rt, *ds;
15598 DDSURFACEDESC2 surface_desc;
15599 IDirect3DDevice7 *device;
15600 unsigned int i, x, y;
15601 IDirectDraw7 *ddraw;
15602 IDirect3D7 *d3d;
15603 ULONG refcount;
15604 HWND window;
15605 HRESULT hr;
15606 RECT r;
15607 BOOL all_zero, all_one, all_pass;
15609 static struct
15611 struct vec3 position;
15612 DWORD diffuse;
15614 quad[] =
15616 {{-1.0f, -1.0f, 0.1f}, 0xff00ff00},
15617 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
15618 {{ 1.0f, -1.0f, 1.0f}, 0xff00ff00},
15619 {{ 1.0f, 1.0f, 0.9f}, 0xff00ff00},
15622 static const struct
15624 unsigned int z_depth, s_depth, z_mask, s_mask;
15625 BOOL todo;
15627 tests[] =
15629 {16, 0, 0x0000ffff, 0x00000000},
15630 {24, 0, 0x00ffffff, 0x00000000},
15631 {32, 0, 0x00ffffff, 0x00000000},
15632 {32, 8, 0x00ffffff, 0xff000000, TRUE},
15633 {32, 0, 0xffffffff, 0x00000000},
15636 window = create_window();
15637 ok(!!window, "Failed to create a window.\n");
15639 if (!(device = create_device(window, DDSCL_NORMAL)))
15641 skip("Failed to create a D3D device, skipping tests.\n");
15642 DestroyWindow(window);
15643 return;
15646 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
15647 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
15648 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
15649 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
15651 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
15652 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
15654 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
15655 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
15657 ds = get_depth_stencil(device);
15658 hr = IDirectDrawSurface7_DeleteAttachedSurface(rt, 0, ds);
15659 ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
15660 IDirectDrawSurface7_Release(ds);
15662 for (i = 0; i < ARRAY_SIZE(tests); ++i)
15664 memset(&surface_desc, 0, sizeof(surface_desc));
15665 surface_desc.dwSize = sizeof(surface_desc);
15666 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
15667 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
15668 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
15669 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
15670 if (tests[i].s_depth)
15671 U4(surface_desc).ddpfPixelFormat.dwFlags |= DDPF_STENCILBUFFER;
15672 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = tests[i].z_depth;
15673 U2(U4(surface_desc).ddpfPixelFormat).dwStencilBitDepth = tests[i].s_depth;
15674 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = tests[i].z_mask;
15675 U4(U4(surface_desc).ddpfPixelFormat).dwStencilBitMask = tests[i].s_mask;
15676 surface_desc.dwWidth = 640;
15677 surface_desc.dwHeight = 480;
15678 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL);
15679 if (FAILED(hr))
15681 skip("Format %u not supported, skipping test.\n", i);
15682 continue;
15685 hr = IDirectDrawSurface_AddAttachedSurface(rt, ds);
15686 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
15687 hr = IDirect3DDevice7_SetRenderTarget(device, rt, 0);
15688 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
15690 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 1.0f, 0);
15691 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15692 hr = IDirect3DDevice7_BeginScene(device);
15693 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
15694 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, 4, 0);
15695 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
15696 hr = IDirect3DDevice7_EndScene(device);
15697 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
15699 all_zero = all_one = all_pass = TRUE;
15700 for (y = 60; y < 480; y += 120)
15702 for (x = 80; x < 640; x += 160)
15704 SetRect(&r, x, y, x + 1, y + 1);
15705 memset(&surface_desc, 0, sizeof(surface_desc));
15706 surface_desc.dwSize = sizeof(surface_desc);
15707 hr = IDirectDrawSurface7_Lock(ds, &r, &surface_desc, DDLOCK_READONLY, NULL);
15708 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
15710 raw_value = *((DWORD *)surface_desc.lpSurface);
15711 if (raw_value)
15712 all_zero = FALSE;
15713 if (raw_value != 0x00ffffff)
15714 all_one = FALSE;
15716 depth = raw_value & tests[i].z_mask;
15717 expected_depth = (x * (0.9 / 640.0) + y * (0.1 / 480.0)) * tests[i].z_mask;
15718 max_diff = ((0.5f * 0.9f) / 640.0f) * tests[i].z_mask;
15719 /* This test is very reliably on older AMD drivers, but fails in a number of interesting
15720 * ways on Nvidia GPUs:
15722 * Geforce 7 GPUs work only with D16. D24 and D24S8 return 0, D24X8 broken data.
15724 * Geforce 9 GPUs return broken data for D16 that resembles the expected data in
15725 * the lower 8 bits and has 0xff in the upper 8 bits. D24X8 works, D24 and D24S8 return
15726 * 0x00ffffff.
15728 * Geforce GTX 650 has working D16 and D24, but D24S8 returns 0.
15730 * Arx Fatalis is broken on the Geforce 9 in the same way it was broken in Wine (bug 43654).
15731 * The !tests[i].s_depth is supposed to rule out D16 on GF9 and D24X8 on GF7.
15733 * On new-ish AMD GPUs (Radeon Polaris at least) returns weird data for D24 and D24X8. D16
15734 * and D24S8 work.
15736 * Some of the tested places pass on some GPUs on Wine by accident. */
15737 todo_wine_if(tests[i].todo && !compare_uint(expected_depth, depth, max_diff))
15738 ok(compare_uint(expected_depth, depth, max_diff)
15739 || (ddraw_is_nvidia(ddraw) && (all_zero || all_one || !tests[i].s_depth))
15740 || (ddraw_is_amd(ddraw) && !tests[i].s_depth && tests[i].z_mask == 0x00ffffff),
15741 "Test %u: Got depth 0x%08x (diff %d), expected 0x%08x+/-%u, at %u, %u.\n",
15742 i, depth, expected_depth - depth, expected_depth, max_diff, x, y);
15743 if (!compare_uint(expected_depth, depth, max_diff))
15744 all_pass = FALSE;
15746 hr = IDirectDrawSurface7_Unlock(ds, &r);
15747 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
15750 if (all_pass)
15751 passed_fmts++;
15753 hr = IDirectDrawSurface7_DeleteAttachedSurface(rt, 0, ds);
15754 ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
15755 IDirectDrawSurface7_Release(ds);
15758 ok(passed_fmts, "Not a single format passed the tests, this is bad even by Nvidia's standards.\n");
15760 IDirectDrawSurface7_Release(rt);
15761 IDirectDraw7_Release(ddraw);
15762 IDirect3D7_Release(d3d);
15763 refcount = IDirect3DDevice7_Release(device);
15764 ok(!refcount, "Device has %u references left.\n", refcount);
15765 DestroyWindow(window);
15768 static void test_clear(void)
15770 IDirect3DDevice7 *device;
15771 IDirectDrawSurface7 *rt;
15772 D3DVIEWPORT7 vp, old_vp;
15773 IDirectDraw7 *ddraw;
15774 D3DRECT rect_negneg;
15775 IDirect3D7 *d3d;
15776 D3DRECT rect[2];
15777 D3DCOLOR color;
15778 ULONG refcount;
15779 HWND window;
15780 HRESULT hr;
15782 window = create_window();
15783 if (!(device = create_device(window, DDSCL_NORMAL)))
15785 skip("Failed to create 3D device.\n");
15786 DestroyWindow(window);
15787 return;
15790 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
15791 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
15792 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
15793 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
15795 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
15796 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
15798 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
15799 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15801 /* Positive x, negative y. */
15802 U1(rect[0]).x1 = 0;
15803 U2(rect[0]).y1 = 480;
15804 U3(rect[0]).x2 = 320;
15805 U4(rect[0]).y2 = 240;
15807 /* Positive x, positive y. */
15808 U1(rect[1]).x1 = 0;
15809 U2(rect[1]).y1 = 0;
15810 U3(rect[1]).x2 = 320;
15811 U4(rect[1]).y2 = 240;
15813 /* Clear 2 rectangles with one call. Unlike d3d8/9, the refrast does not
15814 * refuse negative rectangles, but it will not clear them either. */
15815 hr = IDirect3DDevice7_Clear(device, 2, rect, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
15816 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15818 color = get_surface_color(rt, 160, 360);
15819 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 3 (pos, neg) has color 0x%08x.\n", color);
15820 color = get_surface_color(rt, 160, 120);
15821 ok(compare_color(color, 0x00ff0000, 0), "Clear rectangle 1 (pos, pos) has color 0x%08x.\n", color);
15822 color = get_surface_color(rt, 480, 360);
15823 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 4 (NULL) has color 0x%08x.\n", color);
15824 color = get_surface_color(rt, 480, 120);
15825 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 4 (neg, neg) has color 0x%08x.\n", color);
15827 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
15828 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15829 /* negative x, negative y.
15830 * Also ignored, except on WARP, which clears the entire screen. */
15831 U1(rect_negneg).x1 = 640;
15832 U2(rect_negneg).y1 = 240;
15833 U3(rect_negneg).x2 = 320;
15834 U4(rect_negneg).y2 = 0;
15835 hr = IDirect3DDevice7_Clear(device, 1, &rect_negneg, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
15836 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15838 color = get_surface_color(rt, 160, 360);
15839 ok(compare_color(color, 0x00ffffff, 0)
15840 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
15841 "Got unexpected color 0x%08x.\n", color);
15842 color = get_surface_color(rt, 160, 120);
15843 ok(compare_color(color, 0x00ffffff, 0)
15844 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
15845 "Got unexpected color 0x%08x.\n", color);
15846 color = get_surface_color(rt, 480, 360);
15847 ok(compare_color(color, 0x00ffffff, 0)
15848 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
15849 "Got unexpected color 0x%08x.\n", color);
15850 color = get_surface_color(rt, 480, 120);
15851 ok(compare_color(color, 0x00ffffff, 0)
15852 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
15853 "Got unexpected color 0x%08x.\n", color);
15855 /* Test how the viewport affects clears. */
15856 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
15857 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15858 hr = IDirect3DDevice7_GetViewport(device, &old_vp);
15859 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
15861 vp.dwX = 160;
15862 vp.dwY = 120;
15863 vp.dwWidth = 160;
15864 vp.dwHeight = 120;
15865 vp.dvMinZ = 0.0f;
15866 vp.dvMaxZ = 1.0f;
15867 hr = IDirect3DDevice7_SetViewport(device, &vp);
15868 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
15869 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
15870 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15872 vp.dwX = 320;
15873 vp.dwY = 240;
15874 vp.dwWidth = 320;
15875 vp.dwHeight = 240;
15876 vp.dvMinZ = 0.0f;
15877 vp.dvMaxZ = 1.0f;
15878 hr = IDirect3DDevice7_SetViewport(device, &vp);
15879 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
15881 U1(rect[0]).x1 = 160;
15882 U2(rect[0]).y1 = 120;
15883 U3(rect[0]).x2 = 480;
15884 U4(rect[0]).y2 = 360;
15885 hr = IDirect3DDevice7_Clear(device, 1, &rect[0], D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
15886 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15888 hr = IDirect3DDevice7_SetViewport(device, &old_vp);
15889 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
15891 color = get_surface_color(rt, 158, 118);
15892 ok(compare_color(color, 0x00ffffff, 0), "(158, 118) has color 0x%08x.\n", color);
15893 color = get_surface_color(rt, 162, 118);
15894 ok(compare_color(color, 0x00ffffff, 0), "(162, 118) has color 0x%08x.\n", color);
15895 color = get_surface_color(rt, 158, 122);
15896 ok(compare_color(color, 0x00ffffff, 0), "(158, 122) has color 0x%08x.\n", color);
15897 color = get_surface_color(rt, 162, 122);
15898 ok(compare_color(color, 0x000000ff, 0), "(162, 122) has color 0x%08x.\n", color);
15900 color = get_surface_color(rt, 318, 238);
15901 ok(compare_color(color, 0x000000ff, 0), "(318, 238) has color 0x%08x.\n", color);
15902 color = get_surface_color(rt, 322, 238);
15903 ok(compare_color(color, 0x00ffffff, 0), "(322, 328) has color 0x%08x.\n", color);
15904 color = get_surface_color(rt, 318, 242);
15905 ok(compare_color(color, 0x00ffffff, 0), "(318, 242) has color 0x%08x.\n", color);
15906 color = get_surface_color(rt, 322, 242);
15907 ok(compare_color(color, 0x0000ff00, 0), "(322, 242) has color 0x%08x.\n", color);
15909 color = get_surface_color(rt, 478, 358);
15910 ok(compare_color(color, 0x0000ff00, 0), "(478, 358) has color 0x%08x.\n", color);
15911 color = get_surface_color(rt, 482, 358);
15912 ok(compare_color(color, 0x00ffffff, 0), "(482, 358) has color 0x%08x.\n", color);
15913 color = get_surface_color(rt, 478, 362);
15914 ok(compare_color(color, 0x00ffffff, 0), "(478, 362) has color 0x%08x.\n", color);
15915 color = get_surface_color(rt, 482, 362);
15916 ok(compare_color(color, 0x00ffffff, 0), "(482, 362) has color 0x%08x.\n", color);
15918 /* COLORWRITEENABLE, SRGBWRITEENABLE and scissor rectangles do not exist
15919 * in d3d7. */
15921 IDirectDrawSurface7_Release(rt);
15922 IDirectDraw7_Release(ddraw);
15923 IDirect3D7_Release(d3d);
15924 refcount = IDirect3DDevice7_Release(device);
15925 ok(!refcount, "Device has %u references left.\n", refcount);
15926 DestroyWindow(window);
15929 struct enum_surfaces_param
15931 IDirectDraw7 *ddraw;
15932 DDSURFACEDESC2 modes[20];
15933 unsigned int mode_count;
15935 IDirectDrawSurface7 *surfaces[8];
15936 unsigned int count;
15939 static HRESULT CALLBACK build_mode_list_cb(DDSURFACEDESC2 *desc, void *context)
15941 struct enum_surfaces_param *param = context;
15942 IDirectDrawSurface7 *surface;
15944 if (SUCCEEDED(IDirectDraw7_CreateSurface(param->ddraw, desc, &surface, NULL)))
15946 if (param->mode_count < ARRAY_SIZE(param->modes))
15947 param->modes[param->mode_count] = *desc;
15948 ++param->mode_count;
15949 IDirectDrawSurface7_Release(surface);
15952 return DDENUMRET_OK;
15955 static HRESULT WINAPI enum_surfaces_cb(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
15957 struct enum_surfaces_param *param = context;
15958 BOOL found = FALSE;
15959 unsigned int i;
15961 for (i = 0; i < ARRAY_SIZE(param->surfaces); ++i)
15963 if (param->surfaces[i] == surface)
15965 found = TRUE;
15966 break;
15970 ok(found, "Unexpected surface %p enumerated.\n", surface);
15971 IDirectDrawSurface7_Release(surface);
15972 ++param->count;
15974 return DDENUMRET_OK;
15977 static HRESULT WINAPI enum_surfaces_create_cb(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
15979 static const DWORD expect_flags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_PIXELFORMAT;
15980 struct enum_surfaces_param *param = context;
15982 ok(!surface, "Unexpected surface %p.\n", surface);
15983 ok((desc->dwFlags & expect_flags) == expect_flags, "Got unexpected flags %#x.\n", desc->dwFlags);
15984 if (param->count < ARRAY_SIZE(param->modes))
15986 const DDSURFACEDESC2 *expect = &param->modes[param->count];
15987 ok(desc->dwWidth == expect->dwWidth, "Expected width %u, got %u.\n", expect->dwWidth, desc->dwWidth);
15988 ok(desc->dwHeight == expect->dwHeight, "Expected height %u, got %u.\n", expect->dwHeight, desc->dwHeight);
15989 ok(!memcmp(&U4(*desc).ddpfPixelFormat, &U4(*expect).ddpfPixelFormat, sizeof(U4(*desc).ddpfPixelFormat)),
15990 "Pixel formats didn't match.\n");
15993 ++param->count;
15995 return DDENUMRET_OK;
15998 static void test_enum_surfaces(void)
16000 struct enum_surfaces_param param = {0};
16001 DDPIXELFORMAT current_format;
16002 DDSURFACEDESC2 desc;
16003 IDirectDraw7 *ddraw;
16004 HRESULT hr;
16006 ddraw = create_ddraw();
16007 ok(!!ddraw, "Failed to create a ddraw object.\n");
16008 param.ddraw = ddraw;
16010 memset(&desc, 0, sizeof(desc));
16011 desc.dwSize = sizeof(desc);
16012 hr = IDirectDraw7_GetDisplayMode(ddraw, &desc);
16013 ok(hr == DD_OK, "Failed to get display mode, hr %#x.\n", hr);
16014 current_format = U4(desc).ddpfPixelFormat;
16016 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
16017 ok(hr == DD_OK, "Failed to set cooperative level, hr %#x.\n", hr);
16019 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL, NULL, NULL, NULL);
16020 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
16022 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_ALL, NULL, NULL, enum_surfaces_cb);
16023 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
16025 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_ALL,
16026 NULL, NULL, enum_surfaces_cb);
16027 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
16029 memset(&desc, 0, sizeof(desc));
16030 desc.dwSize = sizeof(desc);
16031 desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
16032 desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
16033 U2(desc).dwMipMapCount = 3;
16034 desc.dwWidth = 32;
16035 desc.dwHeight = 32;
16036 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &desc, &param.surfaces[0], NULL)))
16038 win_skip("Failed to create a texture, skipping tests.\n");
16039 IDirectDraw7_Release(ddraw);
16040 return;
16043 hr = IDirectDrawSurface7_GetAttachedSurface(param.surfaces[0], &desc.ddsCaps, &param.surfaces[1]);
16044 ok(hr == DD_OK, "Failed to get attached surface, hr %#x.\n", hr);
16045 hr = IDirectDrawSurface7_GetAttachedSurface(param.surfaces[1], &desc.ddsCaps, &param.surfaces[2]);
16046 ok(hr == DD_OK, "Failed to get attached surface, hr %#x.\n", hr);
16047 hr = IDirectDrawSurface7_GetAttachedSurface(param.surfaces[2], &desc.ddsCaps, &param.surfaces[3]);
16048 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
16049 ok(!param.surfaces[3], "Got unexpected pointer %p.\n", param.surfaces[3]);
16051 param.count = 0;
16052 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
16053 &desc, &param, enum_surfaces_cb);
16054 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
16055 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
16057 param.count = 0;
16058 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
16059 NULL, &param, enum_surfaces_cb);
16060 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
16061 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
16063 desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
16064 param.count = 0;
16065 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_MATCH,
16066 &desc, &param, enum_surfaces_cb);
16067 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
16068 ok(param.count == 1, "Got unexpected number of enumerated surfaces %u.\n", param.count);
16070 param.count = 0;
16071 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_NOMATCH,
16072 &desc, &param, enum_surfaces_cb);
16073 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
16074 ok(param.count == 2, "Got unexpected number of enumerated surfaces %u.\n", param.count);
16076 desc.dwFlags = 0;
16077 param.count = 0;
16078 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_MATCH,
16079 &desc, &param, enum_surfaces_cb);
16080 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
16081 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
16083 desc.dwFlags = 0;
16084 param.count = 0;
16085 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST, &desc, &param, enum_surfaces_cb);
16086 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
16087 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
16089 IDirectDrawSurface7_Release(param.surfaces[2]);
16090 IDirectDrawSurface7_Release(param.surfaces[1]);
16091 IDirectDrawSurface7_Release(param.surfaces[0]);
16093 param.count = 0;
16094 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
16095 NULL, &param, enum_surfaces_cb);
16096 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
16097 ok(!param.count, "Got unexpected number of enumerated surfaces %u.\n", param.count);
16099 memset(&desc, 0, sizeof(desc));
16100 desc.dwSize = sizeof(desc);
16101 desc.dwFlags = DDSD_CAPS;
16102 desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
16104 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_ALL,
16105 &desc, &param, enum_surfaces_create_cb);
16106 ok(hr == DDERR_INVALIDPARAMS, "Failed to enumerate surfaces, hr %#x.\n", hr);
16108 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_NOMATCH,
16109 &desc, &param, enum_surfaces_create_cb);
16110 ok(hr == DDERR_INVALIDPARAMS, "Failed to enumerate surfaces, hr %#x.\n", hr);
16112 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED,
16113 &desc, &param, enum_surfaces_create_cb);
16114 ok(hr == DDERR_INVALIDPARAMS, "Failed to enumerate surfaces, hr %#x.\n", hr);
16116 /* When not passed width and height, the callback is called with every
16117 * available display resolution. */
16119 param.mode_count = 0;
16120 desc.dwFlags |= DDSD_PIXELFORMAT;
16121 U4(desc).ddpfPixelFormat = current_format;
16122 hr = IDirectDraw7_EnumDisplayModes(ddraw, 0, &desc, &param, build_mode_list_cb);
16123 ok(hr == DD_OK, "Failed to build mode list, hr %#x.\n", hr);
16125 param.count = 0;
16126 desc.dwFlags &= ~DDSD_PIXELFORMAT;
16127 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_MATCH,
16128 &desc, &param, enum_surfaces_create_cb);
16129 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
16130 ok(param.count == param.mode_count, "Expected %u surfaces, got %u.\n", param.mode_count, param.count);
16132 desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
16133 desc.dwWidth = desc.dwHeight = 32;
16135 param.modes[0].dwWidth = param.modes[0].dwHeight = 32;
16137 param.count = 0;
16138 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_MATCH,
16139 &desc, &param, enum_surfaces_create_cb);
16140 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
16141 ok(param.count == 1, "Got unexpected number of enumerated surfaces %u.\n", param.count);
16143 hr = IDirectDraw7_CreateSurface(ddraw, &desc, &param.surfaces[0], NULL);
16144 ok(hr == DD_OK, "Failed to create surface, hr %#x.\n", hr);
16145 param.count = 0;
16146 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_MATCH,
16147 &desc, &param, enum_surfaces_create_cb);
16148 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
16149 ok(param.count == 1, "Got unexpected number of enumerated surfaces %u.\n", param.count);
16150 IDirectDrawSurface7_Release(param.surfaces[0]);
16152 desc.dwFlags |= DDSD_PIXELFORMAT;
16153 U4(desc).ddpfPixelFormat.dwSize = sizeof(U4(desc).ddpfPixelFormat);
16154 U4(desc).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
16155 U4(desc).ddpfPixelFormat.dwFourCC = 0xdeadbeef;
16157 param.count = 0;
16158 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_MATCH,
16159 &desc, &param, enum_surfaces_create_cb);
16160 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
16161 ok(!param.count, "Got unexpected number of enumerated surfaces %u.\n", param.count);
16163 IDirectDraw7_Release(ddraw);
16166 static void test_viewport(void)
16168 static struct
16170 D3DVIEWPORT7 vp;
16171 float expected_z;
16172 RECT expected_rect;
16173 const char *message;
16175 tests[] =
16177 {{ 0, 0, 640, 480}, 0.001f, { 0, 120, 479, 359}, "Viewport (0, 0) - (640, 480)"},
16178 {{ 0, 0, 320, 240}, 0.001f, { 0, 60, 239, 179}, "Viewport (0, 0) - (320, 240)"},
16179 /* Don't run this right after the other 640x480 test, it breaks r500. */
16180 {{ 0, 0, 640, 480, 0.5f, 0.0f}, 0.501f,
16181 {0, 120, 479, 359}, "Viewport (0, 0, 0.5) - (640, 480, 0.0)"},
16182 {{ 0, 0, 1280, 960}, 0.001f, { 0, 240, 639, 479}, "Viewport (0, 0) - (1280, 960)"},
16183 {{ 0, 0, 2000, 1600}, 0.001f, {-10, -10, -10, -10}, "Viewport (0, 0) - (2000, 1600)"},
16184 {{100, 100, 640, 480}, 0.001f, {100, 220, 579, 459}, "Viewport (100, 100) - (640, 480)"},
16185 {{ 0, 0, 8192, 8192}, 0.001f, {-10, -10, -10, -10}, "Viewport (0, 0) - (8192, 8192)"},
16187 static struct vec3 quad[] =
16189 {-1.5f, -0.5f, 1.0f},
16190 {-1.5f, 0.5f, 1.0f},
16191 { 0.5f, -0.5f, 1.0f},
16192 { 0.5f, 0.5f, 1.0f},
16194 static const struct vec2 rt_sizes[] =
16196 {640, 480}, {1280, 960}, {320, 240}, {800, 600},
16198 IDirectDrawSurface7 *rt, *ds;
16199 DDSURFACEDESC2 surface_desc;
16200 const float z_eps = 0.0001;
16201 IDirect3DDevice7 *device;
16202 IDirectDraw7 *ddraw;
16203 DDPIXELFORMAT z_fmt;
16204 unsigned int i, j;
16205 IDirect3D7 *d3d;
16206 ULONG refcount;
16207 HWND window;
16208 HRESULT hr;
16210 window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
16211 0, 0, 640, 480, 0, 0, 0, 0);
16212 if (!(device = create_device(window, DDSCL_NORMAL)))
16214 skip("Failed to create a 3D device, skipping test.\n");
16215 DestroyWindow(window);
16216 return;
16219 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
16220 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16221 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
16222 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16223 IDirect3D7_Release(d3d);
16225 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
16226 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16228 /* Well, by default the vertices without color info should be white, and without any texture
16229 * ops this should just show up in the output, but the r200 driver begs to differ and draws a
16230 * random color. */
16231 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
16232 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16233 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
16234 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16235 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x00ffffff);
16236 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16238 hr = IDirect3DDevice7_SetViewport(device, NULL);
16239 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
16241 ds = get_depth_stencil(device);
16242 memset(&surface_desc, 0, sizeof(surface_desc));
16243 surface_desc.dwSize = sizeof(surface_desc);
16244 hr = IDirectDrawSurface7_GetSurfaceDesc(ds, &surface_desc);
16245 z_fmt = U4(surface_desc).ddpfPixelFormat;
16247 for (i = 0; i < ARRAY_SIZE(rt_sizes); ++i)
16249 if (i)
16251 memset(&surface_desc, 0, sizeof(surface_desc));
16252 surface_desc.dwSize = sizeof(surface_desc);
16253 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
16254 surface_desc.dwWidth = rt_sizes[i].x;
16255 surface_desc.dwHeight = rt_sizes[i].y;
16256 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
16257 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &rt, NULL);
16258 ok(hr == DD_OK, "Got unexpected hr %#x (i %u).\n", hr, i);
16260 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
16261 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
16262 U4(surface_desc).ddpfPixelFormat = z_fmt;
16263 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL);
16264 ok(hr == DD_OK, "Got unexpected hr %#x (i %u).\n", hr, i);
16265 hr = IDirectDrawSurface7_AddAttachedSurface(rt, ds);
16266 ok(hr == DD_OK, "Got unexpected hr %#x (i %u).\n", hr, i);
16268 hr = IDirect3DDevice7_SetRenderTarget(device, rt, 0);
16269 ok(hr == DD_OK, "Got unexpected hr %#x (i %u).\n", hr, i);
16271 else
16273 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
16274 ok(hr == DD_OK, "Got unexpected hr %#x (i %u).\n", hr, i);
16277 for (j = 0; j < ARRAY_SIZE(tests); ++j)
16279 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff000000,
16280 tests[j].expected_z - z_eps, 0);
16281 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
16282 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_GREATER);
16283 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
16285 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, !i);
16286 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
16288 hr = IDirect3DDevice7_SetViewport(device, &tests[j].vp);
16289 if (tests[j].vp.dwX + tests[j].vp.dwWidth > rt_sizes[i].x
16290 || tests[j].vp.dwY + tests[j].vp.dwHeight > rt_sizes[i].y)
16292 ok(hr == E_INVALIDARG, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
16293 continue;
16295 else
16297 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
16300 hr = IDirect3DDevice7_BeginScene(device);
16301 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
16302 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
16303 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
16304 hr = IDirect3DDevice7_EndScene(device);
16305 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
16307 check_rect(rt, tests[j].expected_rect, tests[j].message);
16309 if (!i)
16311 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff000000,
16312 tests[j].expected_z + z_eps, 0);
16313 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
16314 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESS);
16315 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
16317 hr = IDirect3DDevice7_BeginScene(device);
16318 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
16319 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
16320 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
16321 hr = IDirect3DDevice7_EndScene(device);
16322 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
16324 check_rect(rt, tests[j].expected_rect, tests[j].message);
16328 hr = IDirectDrawSurface7_DeleteAttachedSurface(rt, 0, ds);
16329 ok(hr == DD_OK, "Got unexpected hr %#x (i %u).\n", hr, i);
16330 IDirectDrawSurface7_Release(ds);
16331 IDirectDrawSurface7_Release(rt);
16334 refcount = IDirect3DDevice7_Release(device);
16335 ok(!refcount, "Device has %u references left.\n", refcount);
16336 IDirectDraw7_Release(ddraw);
16337 DestroyWindow(window);
16340 static unsigned int validate_loaded_surface(IDirectDrawSurface7 *surface, unsigned int face,
16341 unsigned int level, const RECT *src_rect, const POINT *dst_point)
16343 DDSURFACEDESC2 surface_desc;
16344 unsigned int diff, x, y;
16345 HRESULT hr;
16347 memset(&surface_desc, 0, sizeof(surface_desc));
16348 surface_desc.dwSize = sizeof(surface_desc);
16349 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
16350 ok(SUCCEEDED(hr), "Failed to map surface, hr %#x.\n", hr);
16352 for (y = 0, diff = 0; y < surface_desc.dwHeight; ++y)
16354 DWORD *texture_row = (DWORD *)((char *)surface_desc.lpSurface + y * U1(surface_desc).lPitch);
16356 for (x = 0; x < surface_desc.dwWidth; ++x)
16358 DWORD colour = texture_row[x];
16359 DWORD r = (colour & 0xff0000) >> 16;
16360 DWORD g = (colour & 0xff00) >> 8;
16361 DWORD b = (colour & 0xff);
16363 if (x < dst_point->x || x >= dst_point->x + src_rect->right - src_rect->left
16364 || y < dst_point->y || y >= dst_point->y + src_rect->bottom - src_rect->top)
16366 if (colour & 0xffffff)
16367 ++diff;
16369 else
16371 if (r != ((face << 4) | level)
16372 || g != x + src_rect->left - dst_point->x
16373 || b != y + src_rect->top - dst_point->y)
16374 ++diff;
16379 hr = IDirectDrawSurface7_Unlock(surface, NULL);
16380 ok(SUCCEEDED(hr), "Failed to unmap surface, hr %#x.\n", hr);
16382 return diff;
16385 static void test_device_load(void)
16387 IDirectDrawSurface7 *src_surface, *dst_surface, *surface, *tmp;
16388 DDSCAPS2 mip_caps = {0, DDSCAPS2_MIPMAPSUBLEVEL, 0, {0}};
16389 IDirectDrawPalette *src_palette, *dst_palette, *palette;
16390 unsigned int i, j, k, l, x, y;
16391 DDSURFACEDESC2 surface_desc;
16392 IDirect3DDevice7 *device;
16393 PALETTEENTRY table1[256];
16394 D3DDEVICEDESC7 d3d_caps;
16395 DDCOLORKEY colour_key;
16396 IDirectDraw7 *ddraw;
16397 BOOL cube_support;
16398 IDirect3D7 *d3d;
16399 ULONG refcount;
16400 HWND window;
16401 DDBLTFX fx;
16402 HRESULT hr;
16404 #define TEX_MIP 0x01
16405 #define TEX_CUBE 0x02
16406 #define NULL_COORDS 0x04
16408 /* Creating partial cube maps (e.g. created with just
16409 * DDSCAPS2_CUBEMAP_POSITIVEX) BSODs some Windows machines. (Radeon X1600,
16410 * Windows XP, Catalyst 10.2 driver, 6.14.10.6925)
16412 * Passing non-toplevel surfaces to IDirect3DDevice7_Load() crashes on
16413 * native. (Windows XP / NVIDIA, Windows 98 / RGB software rasteriser) */
16414 static const struct
16416 unsigned int src_w, src_h, src_mip_count;
16417 RECT src_rect;
16418 DWORD src_flags;
16419 unsigned int dst_w, dst_h, dst_mip_count;
16420 POINT dst_point;
16421 DWORD dst_flags;
16422 HRESULT hr;
16424 tests[] =
16426 {128, 128, 0, { 0, 0, 0, 0}, TEX_MIP, 128, 128, 0, { 0, 0}, TEX_MIP, DDERR_INVALIDPARAMS},
16427 {128, 128, 0, { 0, 0, 100, 100}, TEX_MIP, 128, 128, 0, {50, 50}, TEX_MIP, DDERR_INVALIDPARAMS},
16428 {128, 128, 0, {30, 20, 93, 52}, TEX_MIP, 128, 128, 0, {31, 31}, TEX_MIP, D3D_OK},
16429 {128, 128, 0, { 0, 0, 0, 0}, NULL_COORDS, 128, 128, 0, { 0, 0}, NULL_COORDS, D3D_OK},
16430 {128, 128, 0, { 0, 0, 0, 0}, NULL_COORDS, 256, 128, 0, { 0, 0}, NULL_COORDS, DDERR_INVALIDPARAMS},
16431 {256, 128, 0, { 0, 0, 0, 0}, NULL_COORDS, 128, 128, 0, { 0, 0}, NULL_COORDS, DDERR_INVALIDPARAMS},
16432 {128, 128, 0, {30, 20, 93, 52}, TEX_MIP | TEX_CUBE, 128, 128, 0, {10, 10}, TEX_MIP | TEX_CUBE, D3D_OK},
16433 {128, 128, 0, { 0, 0, 0, 0}, NULL_COORDS, 128, 128, 0, { 0, 0}, TEX_CUBE | NULL_COORDS, DDERR_INVALIDPARAMS},
16434 {128, 128, 0, {30, 20, 93, 52}, TEX_MIP, 128, 128, 4, {31, 31}, TEX_MIP, D3D_OK},
16435 {128, 128, 4, {30, 20, 93, 52}, TEX_MIP, 128, 128, 0, {31, 31}, TEX_MIP, DDERR_INVALIDPARAMS},
16436 {128, 128, 0, {32, 32, 96, 96}, TEX_MIP, 32, 32, 0, {32, 32}, 0, D3D_OK},
16437 {128, 128, 0, { 0, 0, 64, 64}, TEX_MIP, 32, 32, 4, { 0, 0}, TEX_MIP, D3D_OK},
16440 window = create_window();
16441 if (!(device = create_device(window, DDSCL_NORMAL)))
16443 skip("Failed to create a 3D device, skipping test.\n");
16444 DestroyWindow(window);
16445 return;
16448 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
16449 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
16450 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
16451 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
16452 IDirect3D7_Release(d3d);
16454 memset(&d3d_caps, 0, sizeof(d3d_caps));
16455 hr = IDirect3DDevice7_GetCaps(device, &d3d_caps);
16456 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
16457 cube_support = d3d_caps.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP;
16459 for (i = 0; i < ARRAY_SIZE(tests); ++i)
16461 unsigned int src_count, dst_count;
16462 POINT dst_point, dst_point_broken;
16463 RECT src_rect, src_rect_broken;
16465 if ((tests[i].src_flags | tests[i].dst_flags) & TEX_CUBE && !cube_support)
16467 skip("No cubemap support, skipping test %u.\n", i);
16468 continue;
16471 memset(&surface_desc, 0, sizeof(surface_desc));
16472 surface_desc.dwSize = sizeof(surface_desc);
16473 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
16474 if (tests[i].src_mip_count)
16475 surface_desc.dwFlags |= DDSD_MIPMAPCOUNT;
16476 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
16477 if (tests[i].src_flags & (TEX_MIP | TEX_CUBE))
16478 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
16479 if (tests[i].src_flags & TEX_MIP)
16480 surface_desc.ddsCaps.dwCaps |= DDSCAPS_MIPMAP;
16481 if (tests[i].src_flags & TEX_CUBE)
16482 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
16483 surface_desc.dwWidth = tests[i].src_w;
16484 surface_desc.dwHeight = tests[i].src_h;
16485 U2(surface_desc).dwMipMapCount = tests[i].src_mip_count;
16486 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
16487 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
16488 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
16489 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
16490 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
16491 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
16492 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
16493 ok(SUCCEEDED(hr), "Test %u: Failed to create source surface, hr %#x.\n", i, hr);
16495 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
16496 if (tests[i].dst_mip_count)
16497 surface_desc.dwFlags |= DDSD_MIPMAPCOUNT;
16498 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
16499 if (tests[i].dst_flags & (TEX_MIP | TEX_CUBE))
16500 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
16501 if (tests[i].dst_flags & TEX_MIP)
16502 surface_desc.ddsCaps.dwCaps |= DDSCAPS_MIPMAP;
16503 surface_desc.ddsCaps.dwCaps2 = 0;
16504 if (tests[i].dst_flags & TEX_CUBE)
16505 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
16506 surface_desc.dwWidth = tests[i].dst_w;
16507 surface_desc.dwHeight = tests[i].dst_h;
16508 U2(surface_desc).dwMipMapCount = tests[i].dst_mip_count;
16509 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
16510 ok(SUCCEEDED(hr), "Test %u: Failed to create destination surface, hr %#x.\n", i, hr);
16512 src_count = dst_count = 1;
16513 if (tests[i].src_flags & TEX_MIP)
16514 src_count = tests[i].src_mip_count ? tests[i].src_mip_count : 8;
16515 if (tests[i].dst_flags & TEX_MIP)
16516 dst_count = tests[i].dst_mip_count ? tests[i].dst_mip_count : 8;
16518 surface = src_surface;
16519 IDirectDrawSurface7_AddRef(surface);
16520 for (j = 0;;)
16522 DDSCAPS2 face_caps = {0, 0, 0, {0}};
16524 /* Check the number of created mipmaps. */
16525 if (tests[i].src_flags & TEX_MIP)
16527 memset(&surface_desc, 0, sizeof(surface_desc));
16528 surface_desc.dwSize = sizeof(surface_desc);
16529 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
16530 ok(SUCCEEDED(hr), "Test %u: Failed to get surface description, hr %#x.\n", i, hr);
16531 ok(U2(surface_desc).dwMipMapCount == src_count,
16532 "Test %u: Got unexpected mip count %u, expected %u.\n",
16533 i, U2(surface_desc).dwMipMapCount, src_count);
16536 for (k = 0; ; ++k)
16538 memset(&surface_desc, 0, sizeof(surface_desc));
16539 surface_desc.dwSize = sizeof(surface_desc);
16540 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
16541 ok(SUCCEEDED(hr), "Test %u: Failed to map surface, hr %#x.\n", i, hr);
16543 for (y = 0; y < surface_desc.dwHeight; ++y)
16545 DWORD *texture_row = (DWORD *)((BYTE *)surface_desc.lpSurface + y * U1(surface_desc).lPitch);
16547 for (x = 0; x < surface_desc.dwWidth; ++x)
16549 /* The face number is stored in the high 4 bits of the
16550 * red component, the mip-level in the low 4 bits. The
16551 * x-coordinate is stored in the green component, and
16552 * the y-coordinate in the blue component. */
16553 texture_row[x] = (j << 20) | (k << 16) | (x << 8) | y;
16557 hr = IDirectDrawSurface7_Unlock(surface, NULL);
16558 ok(SUCCEEDED(hr), "Test %u: Failed to unmap surface, hr %#x.\n", i, hr);
16560 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &mip_caps, &tmp);
16561 IDirectDrawSurface7_Release(surface);
16562 if (FAILED(hr))
16563 break;
16564 surface = tmp;
16567 if (!(tests[i].src_flags & TEX_CUBE) || ++j >= 6)
16568 break;
16570 face_caps.dwCaps2 = DDSCAPS2_CUBEMAP | (DDSCAPS2_CUBEMAP_POSITIVEX << j);
16571 hr = IDirectDrawSurface7_GetAttachedSurface(src_surface, &face_caps, &surface);
16572 ok(SUCCEEDED(hr), "Test %u: Failed to get face %u.\n", i, j);
16575 surface = dst_surface;
16576 IDirectDrawSurface7_AddRef(surface);
16577 for (j = 0;;)
16579 DDSCAPS2 face_caps = {0, 0, 0, {0}};
16581 /* Check the number of created mipmaps. */
16582 if (tests[i].dst_flags & TEX_MIP)
16584 memset(&surface_desc, 0, sizeof(surface_desc));
16585 surface_desc.dwSize = sizeof(surface_desc);
16586 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
16587 ok(SUCCEEDED(hr), "Test %u: Failed to get surface description, hr %#x.\n", i, hr);
16588 ok(U2(surface_desc).dwMipMapCount == dst_count,
16589 "Test %u: Got unexpected mip count %u, expected %u.\n",
16590 i, U2(surface_desc).dwMipMapCount, dst_count);
16593 for (;;)
16595 memset(&fx, 0, sizeof(fx));
16596 fx.dwSize = sizeof(fx);
16597 U5(fx).dwFillColor = 0x00000000;
16598 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
16599 ok(SUCCEEDED(hr), "Test %u: Failed to clear surface, hr %#x.\n", i, hr);
16601 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &mip_caps, &tmp);
16602 IDirectDrawSurface7_Release(surface);
16603 if (FAILED(hr))
16604 break;
16605 surface = tmp;
16608 if (!(tests[i].dst_flags & TEX_CUBE) || ++j >= 6)
16609 break;
16611 face_caps.dwCaps2 = DDSCAPS2_CUBEMAP | (DDSCAPS2_CUBEMAP_POSITIVEX << j);
16612 hr = IDirectDrawSurface7_GetAttachedSurface(dst_surface, &face_caps, &surface);
16613 ok(SUCCEEDED(hr), "Test %u: Failed to get face %u.\n", i, j);
16616 src_rect = tests[i].src_rect;
16617 dst_point = tests[i].dst_point;
16618 hr = IDirect3DDevice7_Load(device,
16619 dst_surface, tests[i].dst_flags & NULL_COORDS ? NULL : &dst_point,
16620 src_surface, tests[i].src_flags & NULL_COORDS ? NULL : &src_rect,
16621 tests[i].dst_flags & TEX_CUBE ? DDSCAPS2_CUBEMAP_ALLFACES : 0);
16622 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x.\n", i, hr);
16624 if (SUCCEEDED(hr))
16626 unsigned int level_offset, level_offset_broken;
16628 for (level_offset = 0, k = tests[i].src_w; k > tests[i].dst_w; ++level_offset, k /= 2);
16629 level_offset_broken = src_count - dst_count;
16631 surface = dst_surface;
16632 IDirectDrawSurface7_AddRef(surface);
16633 for (j = 0;;)
16635 DDSCAPS2 face_caps = {0, 0, 0, {0}};
16637 if (tests[i].src_flags & NULL_COORDS)
16638 SetRect(&src_rect, 0, 0, tests[i].src_w, tests[i].src_h);
16639 else
16640 src_rect = tests[i].src_rect;
16642 if (tests[i].dst_flags & NULL_COORDS)
16643 dst_point.x = dst_point.y = 0;
16644 else
16645 dst_point = tests[i].dst_point;
16647 for (k = 0; k < level_offset; ++k)
16649 dst_point.x /= 2;
16650 dst_point.y /= 2;
16651 src_rect.top /= 2;
16652 src_rect.left /= 2;
16653 src_rect.right = (src_rect.right + 1) / 2;
16654 src_rect.bottom = (src_rect.bottom + 1) / 2;
16657 for (k = 0; ; ++k)
16659 unsigned int diff, diff2, diff3;
16661 diff = validate_loaded_surface(surface, j, k + level_offset, &src_rect, &dst_point);
16663 /* On some newer (XP+) versions of Windows, it appears the
16664 * source/destination coordinates are divided too often.
16665 * This works correctly on Windows 98 with the RGB
16666 * software rasteriser. */
16667 src_rect_broken = src_rect;
16668 dst_point_broken = dst_point;
16669 for (l = 0; l < level_offset; ++l)
16671 dst_point_broken.x /= 2;
16672 dst_point_broken.y /= 2;
16673 src_rect_broken.top /= 2;
16674 src_rect_broken.left /= 2;
16675 src_rect_broken.right = (src_rect_broken.right + 1) / 2;
16676 src_rect_broken.bottom = (src_rect_broken.bottom + 1) / 2;
16678 diff2 = validate_loaded_surface(surface, j, k + level_offset,
16679 &src_rect_broken, &dst_point_broken);
16681 /* On Windows 8+ things are slightly worse still. Instead
16682 * of applying the correct level offset twice, like on
16683 * XP+, an incorrect offset is applied in addition to the
16684 * correct one. Additionally, on Windows 8+, this offset
16685 * also affects the selected source mip-level, as opposed
16686 * to Windows XP+ where it only affects the
16687 * source/destination coordinates. */
16688 src_rect_broken = src_rect;
16689 dst_point_broken = dst_point;
16690 for (l = 0; l < level_offset_broken; ++l)
16692 dst_point_broken.x /= 2;
16693 dst_point_broken.y /= 2;
16694 src_rect_broken.top /= 2;
16695 src_rect_broken.left /= 2;
16696 src_rect_broken.right = (src_rect_broken.right + 1) / 2;
16697 src_rect_broken.bottom = (src_rect_broken.bottom + 1) / 2;
16699 diff3 = validate_loaded_surface(surface, j, k + level_offset_broken,
16700 &src_rect_broken, &dst_point_broken);
16702 ok(!diff || broken(!diff2 || !diff3), "Test %u, face %u, level %u: "
16703 "Unexpected destination texture level pixels; %u/%u/%u differences.\n",
16704 i, j, k, diff, diff2, diff3);
16706 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &mip_caps, &tmp);
16707 IDirectDrawSurface7_Release(surface);
16708 if (FAILED(hr))
16709 break;
16710 surface = tmp;
16712 dst_point.x /= 2;
16713 dst_point.y /= 2;
16714 src_rect.top /= 2;
16715 src_rect.left /= 2;
16716 src_rect.right = (src_rect.right + 1) / 2;
16717 src_rect.bottom = (src_rect.bottom + 1) / 2;
16720 if (!(tests[i].dst_flags & TEX_CUBE) || ++j >= 6)
16721 break;
16723 face_caps.dwCaps2 = DDSCAPS2_CUBEMAP | (DDSCAPS2_CUBEMAP_POSITIVEX << j);
16724 hr = IDirectDrawSurface7_GetAttachedSurface(dst_surface, &face_caps, &surface);
16725 ok(SUCCEEDED(hr), "Test %u: Failed to get face %u.\n", i, j);
16729 IDirectDrawSurface7_Release(dst_surface);
16730 IDirectDrawSurface7_Release(src_surface);
16732 #undef TEX_MIP
16733 #undef TEX_CUBE
16734 #undef NULL_COORDS
16736 memset(&surface_desc, 0, sizeof(surface_desc));
16737 surface_desc.dwSize = sizeof(surface_desc);
16738 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
16739 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
16740 surface_desc.dwWidth = 128;
16741 surface_desc.dwHeight = 128;
16742 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
16743 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
16744 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
16745 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
16746 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
16747 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
16748 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
16749 hr = IDirectDrawSurface7_GetAttachedSurface(src_surface, &mip_caps, &surface);
16750 ok(SUCCEEDED(hr), "Failed to get surface, hr %#x.\n", hr);
16752 /* Test palette copying. */
16753 memset(table1, 0, sizeof(table1));
16754 table1[0].peBlue = 1;
16755 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &src_palette, NULL);
16756 ok(SUCCEEDED(hr), "Failed to create source palette, hr %#x.\n", hr);
16757 table1[0].peBlue = 3;
16758 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &dst_palette, NULL);
16759 ok(SUCCEEDED(hr), "Failed to create destination palette, hr %#x.\n", hr);
16761 hr = IDirectDrawSurface7_SetPalette(src_surface, src_palette);
16762 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
16764 hr = IDirect3DDevice7_Load(device, dst_surface, NULL, src_surface, NULL, 0);
16765 ok(SUCCEEDED(hr), "Failed to load texture, hr %#x.\n", hr);
16767 hr = IDirectDrawSurface7_GetPalette(surface, &palette);
16768 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
16769 hr = IDirectDrawSurface7_GetPalette(dst_surface, &palette);
16770 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
16772 hr = IDirectDrawSurface7_SetPalette(surface, src_palette);
16773 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x.\n", hr);
16774 hr = IDirectDrawSurface7_SetPalette(dst_surface, dst_palette);
16775 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
16777 hr = IDirect3DDevice7_Load(device, dst_surface, NULL, src_surface, NULL, 0);
16778 ok(SUCCEEDED(hr), "Failed to load texture, hr %#x.\n", hr);
16780 hr = IDirectDrawSurface7_GetPalette(dst_surface, &palette);
16781 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
16782 ok(palette == dst_palette, "Got unexpected palette %p, expected %p.\n", palette, dst_palette);
16783 memset(table1, 0, sizeof(table1));
16784 hr = IDirectDrawPalette_GetEntries(palette, 0, 0, 256, table1);
16785 ok(SUCCEEDED(hr), "Failed to retrieve palette entries, hr %#x.\n", hr);
16786 ok(table1[0].peBlue == 1, "Got unexpected palette colour %#x.\n", (unsigned int)table1[0].peBlue);
16787 IDirectDrawPalette_Release(palette);
16789 IDirectDrawPalette_Release(dst_palette);
16790 IDirectDrawPalette_Release(src_palette);
16792 /* Test colour-key copying. */
16793 colour_key.dwColorSpaceLowValue = 32;
16794 colour_key.dwColorSpaceHighValue = 64;
16795 hr = IDirectDrawSurface7_SetColorKey(src_surface, DDCKEY_SRCBLT, &colour_key);
16796 ok(SUCCEEDED(hr), "Failed to set colour-key, hr %#x.\n", hr);
16797 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &colour_key);
16798 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x.\n", hr);
16800 hr = IDirectDrawSurface7_GetColorKey(dst_surface, DDCKEY_SRCBLT, &colour_key);
16801 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
16803 hr = IDirect3DDevice7_Load(device, dst_surface, NULL, src_surface, NULL, 0);
16804 ok(SUCCEEDED(hr), "Failed to load texture, hr %#x.\n", hr);
16806 hr = IDirectDrawSurface7_GetColorKey(dst_surface, DDCKEY_SRCBLT, &colour_key);
16807 ok(SUCCEEDED(hr), "Failed to get colour-key, hr %#x.\n", hr);
16808 ok(colour_key.dwColorSpaceLowValue == 32, "Got unexpected value %u.\n", colour_key.dwColorSpaceLowValue);
16809 ok(colour_key.dwColorSpaceHighValue == 32, "Got unexpected value %u.\n", colour_key.dwColorSpaceHighValue);
16811 IDirectDrawSurface7_Release(surface);
16812 IDirectDrawSurface7_Release(dst_surface);
16813 IDirectDrawSurface7_Release(src_surface);
16815 IDirectDraw7_Release(ddraw);
16816 refcount = IDirect3DDevice7_Release(device);
16817 ok(!refcount, "Device has %u references left.\n", refcount);
16818 DestroyWindow(window);
16821 static void test_color_vertex(void)
16823 IDirect3DDevice7 *device;
16824 IDirectDrawSurface7 *rt;
16825 D3DMATERIAL7 material;
16826 D3DCOLOR colour;
16827 unsigned int i;
16828 ULONG refcount;
16829 HWND window;
16830 HRESULT hr;
16832 static struct
16834 struct vec3 position;
16835 DWORD diffuse;
16836 DWORD specular;
16838 quad_2c[] =
16840 {{-1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff00ff00},
16841 {{-1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff00ff00},
16842 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff00ff00},
16843 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff00ff00},
16845 static struct
16847 struct vec3 position;
16848 DWORD colour;
16850 quad_1c[] =
16852 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
16853 {{-1.0f, 1.0f, 0.0f}, 0xffff0000},
16854 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000},
16855 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000},
16857 static struct
16859 struct vec3 position;
16861 quad_0c[] =
16863 {{-1.0f, -1.0f, 0.0f}},
16864 {{-1.0f, 1.0f, 0.0f}},
16865 {{ 1.0f, -1.0f, 0.0f}},
16866 {{ 1.0f, 1.0f, 0.0f}},
16869 /* The idea here is to set up ambient light parameters in a way that the
16870 * ambient colour from the material is just passed through. The emissive
16871 * colour is just passed through anyway. The sum of ambient + emissive
16872 * should allow deduction of where the material colour came from. */
16873 static const struct
16875 DWORD fvf, color_vertex, ambient, emissive, result;
16876 void *vtx;
16878 tests[] =
16880 {D3DFVF_DIFFUSE | D3DFVF_SPECULAR, FALSE, D3DMCS_COLOR1, D3DMCS_COLOR2, 0x000000c0, quad_2c},
16882 {D3DFVF_DIFFUSE | D3DFVF_SPECULAR, TRUE, D3DMCS_COLOR1, D3DMCS_COLOR2, 0x00ffff00, quad_2c},
16883 {D3DFVF_DIFFUSE | D3DFVF_SPECULAR, TRUE, D3DMCS_MATERIAL, D3DMCS_COLOR2, 0x0000ff80, quad_2c},
16884 {D3DFVF_DIFFUSE | D3DFVF_SPECULAR, TRUE, D3DMCS_COLOR1, D3DMCS_MATERIAL, 0x00ff0040, quad_2c},
16885 {D3DFVF_DIFFUSE | D3DFVF_SPECULAR, TRUE, D3DMCS_COLOR1, D3DMCS_COLOR1, 0x00ff0000, quad_2c},
16886 {D3DFVF_DIFFUSE | D3DFVF_SPECULAR, TRUE, D3DMCS_COLOR2, D3DMCS_COLOR2, 0x0000ff00, quad_2c},
16888 {D3DFVF_SPECULAR, TRUE, D3DMCS_COLOR1, D3DMCS_COLOR2, 0x00ff0080, quad_1c},
16889 {D3DFVF_SPECULAR, TRUE, D3DMCS_COLOR1, D3DMCS_MATERIAL, 0x000000c0, quad_1c},
16890 {D3DFVF_SPECULAR, TRUE, D3DMCS_MATERIAL, D3DMCS_COLOR2, 0x00ff0080, quad_1c},
16891 {D3DFVF_DIFFUSE, TRUE, D3DMCS_COLOR1, D3DMCS_COLOR2, 0x00ff0040, quad_1c},
16892 {D3DFVF_DIFFUSE, TRUE, D3DMCS_COLOR1, D3DMCS_MATERIAL, 0x00ff0040, quad_1c},
16893 {D3DFVF_DIFFUSE, TRUE, D3DMCS_COLOR2, D3DMCS_MATERIAL, 0x000000c0, quad_1c},
16895 {0, TRUE, D3DMCS_COLOR1, D3DMCS_COLOR2, 0x000000c0, quad_0c},
16898 window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
16899 0, 0, 640, 480, 0, 0, 0, 0);
16900 if (!(device = create_device(window, DDSCL_NORMAL)))
16902 skip("Failed to create a 3D device, skipping test.\n");
16903 DestroyWindow(window);
16904 return;
16906 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
16907 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
16909 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
16910 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
16911 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_AMBIENT, 0xffffffff);
16912 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
16914 memset(&material, 0, sizeof(material));
16915 U3(U1(material).ambient).b = 0.5f;
16916 U3(U3(material).emissive).b = 0.25f;
16917 hr = IDirect3DDevice7_SetMaterial(device, &material);
16918 ok(SUCCEEDED(hr), "Failed to set material, hr %#x\n", hr);
16920 for (i = 0; i < ARRAY_SIZE(tests); ++i)
16922 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORVERTEX, tests[i].color_vertex);
16923 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
16924 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_AMBIENTMATERIALSOURCE, tests[i].ambient);
16925 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
16926 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_EMISSIVEMATERIALSOURCE, tests[i].emissive);
16927 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
16928 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
16929 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
16931 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x77777777, 0.0f, 0);
16932 ok(SUCCEEDED(hr), "Failed to clear depth/stencil, hr %#x.\n", hr);
16934 hr = IDirect3DDevice7_BeginScene(device);
16935 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
16936 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
16937 D3DFVF_XYZ | tests[i].fvf, tests[i].vtx, 4, 0);
16938 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
16939 hr = IDirect3DDevice7_EndScene(device);
16940 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
16942 colour = get_surface_color(rt, 320, 240);
16943 ok(compare_color(colour, tests[i].result, 1),
16944 "Expected colour 0x%08x for test %u, got 0x%08x.\n",
16945 tests[i].result, i, colour);
16948 IDirectDrawSurface7_Release(rt);
16949 refcount = IDirect3DDevice7_Release(device);
16950 ok(!refcount, "Device has %u references left.\n", refcount);
16951 DestroyWindow(window);
16954 static IDirectDraw7 *killfocus_ddraw;
16955 static IDirectDrawSurface7 *killfocus_surface;
16957 static LRESULT CALLBACK killfocus_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
16959 ULONG ref;
16961 if (message == WM_KILLFOCUS)
16963 ref = IDirectDrawSurface7_Release(killfocus_surface);
16964 ok(!ref, "Unexpected surface refcount %u.\n", ref);
16965 ref = IDirectDraw7_Release(killfocus_ddraw);
16966 ok(!ref, "Unexpected ddraw refcount %u.\n", ref);
16967 killfocus_ddraw = NULL;
16970 return DefWindowProcA(window, message, wparam, lparam);
16973 static void test_killfocus(void)
16975 DDSURFACEDESC2 surface_desc;
16976 HRESULT hr;
16977 HWND window;
16978 WNDCLASSA wc = {0};
16980 wc.lpfnWndProc = killfocus_proc;
16981 wc.lpszClassName = "ddraw_killfocus_wndproc_wc";
16982 ok(RegisterClassA(&wc), "Failed to register window class.\n");
16984 window = CreateWindowA("ddraw_killfocus_wndproc_wc", "d3d7_test", WS_OVERLAPPEDWINDOW,
16985 0, 0, 640, 480, 0, 0, 0, 0);
16987 killfocus_ddraw = create_ddraw();
16988 ok(!!killfocus_ddraw, "Failed to create a ddraw object.\n");
16990 hr = IDirectDraw7_SetCooperativeLevel(killfocus_ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
16991 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
16993 memset(&surface_desc, 0, sizeof(surface_desc));
16994 surface_desc.dwSize = sizeof(surface_desc);
16995 surface_desc.dwFlags = DDSD_CAPS;
16996 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
16997 hr = IDirectDraw7_CreateSurface(killfocus_ddraw, &surface_desc, &killfocus_surface, NULL);
16998 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
17000 SetForegroundWindow(GetDesktopWindow());
17001 ok(!killfocus_ddraw, "WM_KILLFOCUS was not received.\n");
17003 DestroyWindow(window);
17004 UnregisterClassA("ddraw_killfocus_wndproc_wc", GetModuleHandleA(NULL));
17007 static void test_sysmem_draw(void)
17009 IDirectDrawSurface7 *rt, *texture;
17010 DDSURFACEDESC2 surface_desc;
17011 D3DVERTEXBUFFERDESC vb_desc;
17012 IDirect3DVertexBuffer7 *vb;
17013 IDirect3DDevice7 *device;
17014 IDirectDraw7 *ddraw;
17015 IDirect3D7 *d3d;
17016 D3DCOLOR colour;
17017 ULONG refcount;
17018 HWND window;
17019 HRESULT hr;
17020 BYTE *data;
17022 static const struct
17024 struct vec3 position;
17025 DWORD diffuse;
17027 quad[] =
17029 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
17030 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
17031 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
17032 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
17034 static WORD indices[] = {0, 1, 2, 3};
17036 window = create_window();
17037 ok(!!window, "Failed to create a window.\n");
17039 if (!(device = create_device(window, DDSCL_NORMAL)))
17041 skip("Failed to create a 3D device, skipping test.\n");
17042 DestroyWindow(window);
17043 return;
17046 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
17047 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17048 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
17049 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17050 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
17051 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17053 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
17054 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17056 vb_desc.dwSize = sizeof(vb_desc);
17057 vb_desc.dwCaps = D3DVBCAPS_SYSTEMMEMORY;
17058 vb_desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
17059 vb_desc.dwNumVertices = 4;
17060 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &vb, 0);
17061 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17063 hr = IDirect3DVertexBuffer7_Lock(vb, 0, (void **)&data, NULL);
17064 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17065 memcpy(data, quad, sizeof(quad));
17066 hr = IDirect3DVertexBuffer7_Unlock(vb);
17067 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17069 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x77777777, 0.0f, 0);
17070 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17072 hr = IDirect3DDevice7_BeginScene(device);
17073 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17074 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, 0);
17075 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17076 hr = IDirect3DDevice7_EndScene(device);
17077 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17079 colour = get_surface_color(rt, 320, 240);
17080 ok(compare_color(colour, 0x00007f7f, 1), "Got unexpected colour 0x%08x.\n", colour);
17082 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x77777777, 0.0f, 0);
17083 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17085 hr = IDirect3DDevice7_BeginScene(device);
17086 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17087 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, indices, 4, 0);
17088 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17089 hr = IDirect3DDevice7_EndScene(device);
17090 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17092 colour = get_surface_color(rt, 320, 240);
17093 ok(compare_color(colour, 0x00007f7f, 1), "Got unexpected colour 0x%08x.\n", colour);
17095 memset(&surface_desc, 0, sizeof(surface_desc));
17096 surface_desc.dwSize = sizeof(surface_desc);
17097 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
17098 surface_desc.dwHeight = 2;
17099 surface_desc.dwWidth = 2;
17100 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
17101 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
17102 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
17103 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
17104 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
17105 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
17106 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
17107 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
17108 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
17109 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17110 hr = IDirect3DDevice7_SetTexture(device, 0, texture);
17111 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17113 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x77777777, 0.0f, 0);
17114 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17116 hr = IDirect3DDevice7_BeginScene(device);
17117 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17118 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, 0);
17119 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17120 hr = IDirect3DDevice7_EndScene(device);
17121 ok(hr == D3D_OK || hr == D3DERR_SCENE_END_FAILED, "Got unexpected hr %#x.\n", hr);
17123 IDirectDrawSurface7_Release(texture);
17124 IDirect3DVertexBuffer7_Release(vb);
17125 IDirectDrawSurface7_Release(rt);
17126 IDirectDraw7_Release(ddraw);
17127 IDirect3D7_Release(d3d);
17128 refcount = IDirect3DDevice7_Release(device);
17129 ok(!refcount, "Device has %u references left.\n", refcount);
17130 DestroyWindow(window);
17133 static void test_gdi_surface(void)
17135 IDirectDrawSurface7 *primary, *backbuffer, *gdi_surface;
17136 DDSCAPS2 caps = {DDSCAPS_BACKBUFFER, 0, 0, {0}};
17137 DDSURFACEDESC2 surface_desc;
17138 IDirectDraw7 *ddraw;
17139 ULONG refcount;
17140 HWND window;
17141 HRESULT hr;
17143 window = create_window();
17144 ddraw = create_ddraw();
17145 ok(!!ddraw, "Failed to create a ddraw object.\n");
17146 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
17147 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17149 /* Retrieving the GDI surface requires a primary surface to exist. */
17150 gdi_surface = (void *)0xc0dec0de;
17151 hr = IDirectDraw7_GetGDISurface(ddraw, &gdi_surface);
17152 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
17153 ok(!gdi_surface, "Got unexpected surface %p.\n", gdi_surface);
17155 hr = IDirectDraw7_FlipToGDISurface(ddraw);
17156 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
17158 memset(&surface_desc, 0, sizeof(surface_desc));
17159 surface_desc.dwSize = sizeof(surface_desc);
17160 surface_desc.dwFlags = DDSD_CAPS;
17161 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
17162 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
17163 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17165 hr = IDirectDraw7_GetGDISurface(ddraw, &gdi_surface);
17166 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17167 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
17168 IDirectDrawSurface7_Release(gdi_surface);
17170 /* Flipping to the GDI surface requires the primary surface to be
17171 * flippable. */
17172 hr = IDirectDraw7_FlipToGDISurface(ddraw);
17173 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
17175 IDirectDrawSurface7_Release(primary);
17177 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
17178 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17180 memset(&surface_desc, 0, sizeof(surface_desc));
17181 surface_desc.dwSize = sizeof(surface_desc);
17182 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
17183 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
17184 U5(surface_desc).dwBackBufferCount = 1;
17185 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
17186 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17187 hr = IDirectDrawSurface7_GetAttachedSurface(primary, &caps, &backbuffer);
17188 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17189 ok(backbuffer != primary, "Got unexpected backbuffer %p.\n", backbuffer);
17191 hr = IDirectDraw7_GetGDISurface(ddraw, &gdi_surface);
17192 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17193 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
17194 IDirectDrawSurface7_Release(gdi_surface);
17196 hr = IDirectDrawSurface7_Flip(primary, NULL, DDFLIP_WAIT);
17197 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17198 hr = IDirectDraw7_GetGDISurface(ddraw, &gdi_surface);
17199 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17200 ok(gdi_surface == backbuffer || broken(gdi_surface == primary),
17201 "Got unexpected surface %p, expected %p.\n", gdi_surface, backbuffer);
17202 IDirectDrawSurface7_Release(gdi_surface);
17204 hr = IDirectDraw7_FlipToGDISurface(ddraw);
17205 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17207 hr = IDirectDraw7_GetGDISurface(ddraw, &gdi_surface);
17208 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17209 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
17210 IDirectDrawSurface7_Release(gdi_surface);
17212 hr = IDirectDraw7_FlipToGDISurface(ddraw);
17213 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17215 IDirectDrawSurface7_Release(backbuffer);
17216 IDirectDrawSurface7_Release(primary);
17218 refcount = IDirectDraw7_Release(ddraw);
17219 ok(!refcount, "%u references left.\n", refcount);
17220 DestroyWindow(window);
17223 static void test_multiply_transform(void)
17225 IDirect3DDevice7 *device;
17226 D3DMATRIX ret_mat;
17227 DWORD stateblock;
17228 unsigned int i;
17229 ULONG refcount;
17230 HWND window;
17231 HRESULT hr;
17233 static const D3DTRANSFORMSTATETYPE tests[] =
17235 D3DTRANSFORMSTATE_WORLD,
17236 D3DTRANSFORMSTATE_VIEW,
17237 D3DTRANSFORMSTATE_PROJECTION,
17238 D3DTRANSFORMSTATE_WORLD1,
17239 D3DTRANSFORMSTATE_WORLD2,
17240 D3DTRANSFORMSTATE_WORLD3,
17241 D3DTRANSFORMSTATE_TEXTURE0,
17242 D3DTRANSFORMSTATE_TEXTURE1,
17243 D3DTRANSFORMSTATE_TEXTURE2,
17244 D3DTRANSFORMSTATE_TEXTURE3,
17245 D3DTRANSFORMSTATE_TEXTURE4,
17246 D3DTRANSFORMSTATE_TEXTURE5,
17247 D3DTRANSFORMSTATE_TEXTURE6,
17248 D3DTRANSFORMSTATE_TEXTURE7,
17251 D3DMATRIX mat1 =
17253 1.0f, 0.0f, 0.0f, 0.0f,
17254 0.0f, 1.0f, 0.0f, 0.0f,
17255 0.0f, 0.0f, 1.0f, 0.0f,
17256 0.0f, 0.0f, 0.0f, 1.0f,
17258 mat2 =
17260 2.0f, 0.0f, 0.0f, 0.0f,
17261 0.0f, 2.0f, 0.0f, 0.0f,
17262 0.0f, 0.0f, 2.0f, 0.0f,
17263 0.0f, 0.0f, 0.0f, 2.0f,
17266 window = create_window();
17267 if (!(device = create_device(window, DDSCL_NORMAL)))
17269 skip("Failed to create 3D device.\n");
17270 DestroyWindow(window);
17271 return;
17274 for (i = 0; i < ARRAY_SIZE(tests); ++i)
17276 hr = IDirect3DDevice7_GetTransform(device, tests[i], &ret_mat);
17277 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
17278 ok(!memcmp(&ret_mat, &mat1, sizeof(mat1)), "Test %u: Got unexpected transform matrix.\n", i);
17280 hr = IDirect3DDevice7_MultiplyTransform(device, tests[i], &mat2);
17281 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
17283 hr = IDirect3DDevice7_GetTransform(device, tests[i], &ret_mat);
17284 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
17285 ok(!memcmp(&ret_mat, &mat2, sizeof(mat2)), "Test %u: Got unexpected transform matrix.\n", i);
17287 /* MultiplyTransform() goes directly into the primary stateblock. */
17289 hr = IDirect3DDevice7_SetTransform(device, tests[i], &mat1);
17290 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
17292 hr = IDirect3DDevice7_BeginStateBlock(device);
17293 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
17295 hr = IDirect3DDevice7_MultiplyTransform(device, tests[i], &mat2);
17296 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
17298 hr = IDirect3DDevice7_EndStateBlock(device, &stateblock);
17299 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
17301 hr = IDirect3DDevice7_GetTransform(device, tests[i], &ret_mat);
17302 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
17303 ok(!memcmp(&ret_mat, &mat2, sizeof(mat2)), "Test %u: Got unexpected transform matrix.\n", i);
17305 hr = IDirect3DDevice7_CaptureStateBlock(device, stateblock);
17306 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
17308 hr = IDirect3DDevice7_SetTransform(device, tests[i], &mat1);
17309 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
17311 hr = IDirect3DDevice7_ApplyStateBlock(device, stateblock);
17312 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
17314 hr = IDirect3DDevice7_GetTransform(device, tests[i], &ret_mat);
17315 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
17316 ok(!memcmp(&ret_mat, &mat1, sizeof(mat1)), "Test %u: Got unexpected transform matrix.\n", i);
17318 IDirect3DDevice7_DeleteStateBlock(device, stateblock);
17321 refcount = IDirect3DDevice7_Release(device);
17322 ok(!refcount, "Device has %u references left.\n", refcount);
17323 DestroyWindow(window);
17326 static void test_alphatest(void)
17328 #define ALPHATEST_PASSED 0x0000ff00
17329 #define ALPHATEST_FAILED 0x00ff0000
17330 IDirect3DDevice7 *device;
17331 IDirectDrawSurface7 *rt;
17332 unsigned int i;
17333 D3DCOLOR color;
17334 ULONG refcount;
17335 HWND window;
17336 DWORD value;
17337 HRESULT hr;
17339 static const struct
17341 D3DCMPFUNC func;
17342 D3DCOLOR color_less;
17343 D3DCOLOR color_equal;
17344 D3DCOLOR color_greater;
17346 test_data[] =
17348 {D3DCMP_NEVER, ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_FAILED},
17349 {D3DCMP_LESS, ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_FAILED},
17350 {D3DCMP_EQUAL, ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_FAILED},
17351 {D3DCMP_LESSEQUAL, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_FAILED},
17352 {D3DCMP_GREATER, ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_PASSED},
17353 {D3DCMP_NOTEQUAL, ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_PASSED},
17354 {D3DCMP_GREATEREQUAL, ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_PASSED},
17355 {D3DCMP_ALWAYS, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_PASSED},
17357 static struct
17359 struct vec3 position;
17360 DWORD diffuse;
17362 quad[] =
17364 {{-1.0f, -1.0f, 0.1f}, ALPHATEST_PASSED | 0x80000000},
17365 {{-1.0f, 1.0f, 0.1f}, ALPHATEST_PASSED | 0x80000000},
17366 {{ 1.0f, -1.0f, 0.1f}, ALPHATEST_PASSED | 0x80000000},
17367 {{ 1.0f, 1.0f, 0.1f}, ALPHATEST_PASSED | 0x80000000},
17370 window = create_window();
17371 if (!(device = create_device(window, DDSCL_NORMAL)))
17373 skip("Failed to create a 3D device.\n");
17374 DestroyWindow(window);
17375 return;
17377 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
17378 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17380 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
17381 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17382 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
17383 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17384 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
17385 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17386 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHATESTENABLE, TRUE);
17387 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17389 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
17391 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHAFUNC, test_data[i].func);
17392 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17394 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, ALPHATEST_FAILED, 0.0f, 0);
17395 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17396 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHAREF, 0x70);
17397 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17398 hr = IDirect3DDevice7_BeginScene(device);
17399 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17400 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
17401 D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, ARRAY_SIZE(quad), 0);
17402 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17403 hr = IDirect3DDevice7_EndScene(device);
17404 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17405 color = get_surface_color(rt, 320, 240);
17406 ok(compare_color(color, test_data[i].color_greater, 0),
17407 "Alphatest failed, color 0x%08x, expected 0x%08x, alpha > ref, func %u.\n",
17408 color, test_data[i].color_greater, test_data[i].func);
17410 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, ALPHATEST_FAILED, 0.0f, 0);
17411 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17412 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHAREF, 0xff70);
17413 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17414 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ALPHAREF, &value);
17415 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17416 ok(value == 0xff70, "Got unexpected value %#x.\n", value);
17417 hr = IDirect3DDevice7_BeginScene(device);
17418 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17419 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
17420 D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, ARRAY_SIZE(quad), 0);
17421 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17422 hr = IDirect3DDevice7_EndScene(device);
17423 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17424 color = get_surface_color(rt, 320, 240);
17425 ok(compare_color(color, test_data[i].color_greater, 0),
17426 "Alphatest failed, color 0x%08x, expected 0x%08x, alpha > ref, func %u.\n",
17427 color, test_data[i].color_greater, test_data[i].func);
17430 IDirectDrawSurface7_Release(rt);
17431 refcount = IDirect3DDevice7_Release(device);
17432 ok(!refcount, "Device has %u references left.\n", refcount);
17433 DestroyWindow(window);
17436 static void test_clipper_refcount(void)
17438 IDirectDrawSurface7 *surface;
17439 IDirectDrawClipper *clipper, *clipper2;
17440 DDSURFACEDESC2 surface_desc;
17441 IDirectDraw7 *ddraw;
17442 IDirectDraw *ddraw1;
17443 ULONG refcount;
17444 HWND window;
17445 HRESULT hr;
17446 BOOL changed;
17447 const IDirectDrawClipperVtbl *orig_vtbl;
17449 window = create_window();
17450 ddraw = create_ddraw();
17451 ok(!!ddraw, "Failed to create a ddraw object.\n");
17452 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
17453 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17455 memset(&surface_desc, 0, sizeof(surface_desc));
17456 surface_desc.dwSize = sizeof(surface_desc);
17457 surface_desc.dwFlags = DDSD_CAPS;
17458 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
17459 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
17460 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17462 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
17463 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
17464 refcount = get_refcount((IUnknown *)clipper);
17465 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
17467 /* Show that clipper validation doesn't somehow happen through per-clipper vtable
17468 * pointers. */
17469 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper2, NULL);
17470 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
17471 ok(clipper->lpVtbl == clipper2->lpVtbl, "Got different clipper vtables %p and %p.\n",
17472 clipper->lpVtbl, clipper2->lpVtbl);
17473 orig_vtbl = clipper->lpVtbl;
17474 IDirectDrawClipper_Release(clipper2);
17476 /* Surfaces hold a reference to clippers. No surprises there. */
17477 hr = IDirectDrawSurface7_SetClipper(surface, clipper);
17478 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
17479 refcount = get_refcount((IUnknown *)clipper);
17480 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
17482 hr = IDirectDrawSurface7_GetClipper(surface, &clipper2);
17483 ok(SUCCEEDED(hr), "Failed to get clipper, hr %#x.\n", hr);
17484 ok(clipper == clipper2, "Got clipper %p, expected %p.\n", clipper2, clipper);
17485 refcount = IDirectDrawClipper_Release(clipper2);
17486 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
17488 hr = IDirectDrawSurface7_SetClipper(surface, NULL);
17489 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
17490 refcount = get_refcount((IUnknown *)clipper);
17491 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
17493 hr = IDirectDrawSurface7_SetClipper(surface, clipper);
17494 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
17495 refcount = get_refcount((IUnknown *)clipper);
17496 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
17498 refcount = IDirectDrawSurface7_Release(surface);
17499 ok(!refcount, "%u references left.\n", refcount);
17500 refcount = get_refcount((IUnknown *)clipper);
17501 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
17503 /* SetClipper with an invalid pointer crashes. */
17505 /* Clipper methods work with a broken vtable, with the exception of Release. */
17506 clipper->lpVtbl = (void *)0xdeadbeef;
17507 refcount = orig_vtbl->AddRef(clipper);
17508 todo_wine ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
17509 refcount = orig_vtbl->Release(clipper);
17510 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
17512 clipper->lpVtbl = orig_vtbl;
17513 refcount = orig_vtbl->Release(clipper);
17514 todo_wine ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
17516 /* Fix the refcount difference because Wine did not increase the ref in the
17517 * AddRef call above. */
17518 if (refcount)
17520 refcount = IDirectDrawClipper_Release(clipper);
17521 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
17524 /* Steal the reference and see what happens - releasing the surface works fine.
17525 * The clipper is destroyed and not kept alive by a hidden refcount - trying to
17526 * release it after the GetClipper call is likely to crash, and certain to crash
17527 * if we allocate and zero as much heap memory as we can get. */
17528 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
17529 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17530 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
17531 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
17532 hr = IDirectDrawSurface7_SetClipper(surface, clipper);
17533 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
17535 IDirectDrawClipper_Release(clipper);
17536 IDirectDrawClipper_Release(clipper);
17538 if (0)
17540 /* Disabled because it causes heap corruption (HeapValidate fails and random
17541 * hangs in a later HeapFree) on Windows on one of my Machines: MacbookPro 10,1
17542 * running Windows 10 18363.535 and Nvidia driver 425.31. Driver version 441.66
17543 * is affected too. Some testbot machines have crashes directly in GetClipper
17544 * or proceed with a corrupted heap too.
17546 * The same Windows and driver versions run the test without heap corruption on
17547 * a Geforce 1060 GTX card. I have not seen the problem on AMD GPUs either. */
17548 hr = IDirectDrawSurface7_GetClipper(surface, &clipper2);
17549 ok(SUCCEEDED(hr), "Failed to get clipper, hr %#x.\n", hr);
17550 ok(clipper == clipper2, "Got clipper %p, expected %p.\n", clipper2, clipper);
17553 /* Show that invoking the Release method does not crash, but don't get the
17554 * vtable through the clipper pointer because it is no longer pointing to
17555 * valid memory. */
17556 refcount = orig_vtbl->Release(clipper);
17557 ok(!refcount, "%u references left.\n", refcount);
17559 refcount = IDirectDrawSurface7_Release(surface);
17560 ok(!refcount, "%u references left.\n", refcount);
17562 /* It looks like the protection against invalid thispointers is part of
17563 * the IDirectDrawClipper method implementation, not IDirectDrawSurface. */
17564 clipper = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 0x1000);
17565 ok(!!clipper, "failed to allocate memory\n");
17567 /* Assigning the vtable to our fake clipper does NOT make a difference on
17568 * native - there is a different member of the clipper implementation struct
17569 * that is used to determine if a clipper is valid. */
17570 clipper->lpVtbl = orig_vtbl;
17572 refcount = orig_vtbl->AddRef(clipper);
17573 todo_wine ok(!refcount, "Got refcount %u.\n", refcount);
17574 refcount = orig_vtbl->AddRef((IDirectDrawClipper *)(ULONG_PTR)0xdeadbeef);
17575 ok(!refcount, "Got refcount %u.\n", refcount);
17577 changed = 0x1234;
17578 hr = orig_vtbl->IsClipListChanged(clipper, &changed);
17579 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
17580 todo_wine ok(changed == 0x1234, "'changed' changed: %x.\n", changed);
17582 changed = 0x1234;
17583 hr = orig_vtbl->IsClipListChanged((IDirectDrawClipper *)(ULONG_PTR)0xdeadbeef, &changed);
17584 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
17585 ok(changed == 0x1234, "'changed' changed: %x.\n", changed);
17587 /* Nope, we can't initialize our fake clipper. */
17588 hr = IDirectDraw7_QueryInterface(ddraw, &IID_IDirectDraw, (void **)&ddraw1);
17589 ok(SUCCEEDED(hr), "Failed to get ddraw1 interface, hr %#x.\n", hr);
17591 hr = orig_vtbl->Initialize(clipper, ddraw1, 0);
17592 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
17594 IDirectDraw_Release(ddraw1);
17596 HeapFree(GetProcessHeap(), 0, clipper);
17598 refcount = IDirectDraw7_Release(ddraw);
17599 ok(!refcount, "%u references left.\n", refcount);
17600 DestroyWindow(window);
17603 static void test_begin_end_state_block(void)
17605 DWORD stateblock, stateblock2;
17606 IDirect3DDevice7 *device;
17607 ULONG refcount;
17608 DWORD value;
17609 HWND window;
17610 HRESULT hr;
17612 window = create_window();
17613 if (!(device = create_device(window, DDSCL_NORMAL)))
17615 skip("Failed to create 3D device.\n");
17616 DestroyWindow(window);
17617 return;
17620 hr = IDirect3DDevice7_BeginStateBlock(device);
17621 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17623 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
17624 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17626 stateblock = 0xdeadbeef;
17627 hr = IDirect3DDevice7_EndStateBlock(device, &stateblock);
17628 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17629 ok(!!stateblock && stateblock != 0xdeadbeef, "Got unexpected stateblock %#x.\n", stateblock);
17631 stateblock2 = 0xdeadbeef;
17632 hr = IDirect3DDevice7_EndStateBlock(device, &stateblock2);
17633 ok(hr == D3DERR_NOTINBEGINSTATEBLOCK, "Got unexpected hr %#x.\n", hr);
17634 ok(stateblock2 == 0xdeadbeef, "Got unexpected stateblock %#x.\n", stateblock2);
17636 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &value);
17637 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17638 ok(value == TRUE, "Got unexpected value %#x.\n", value);
17640 hr = IDirect3DDevice7_BeginStateBlock(device);
17641 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17643 hr = IDirect3DDevice7_BeginStateBlock(device);
17644 ok(hr == D3DERR_INBEGINSTATEBLOCK, "Got unexpected hr %#x.\n", hr);
17646 hr = IDirect3DDevice7_ApplyStateBlock(device, stateblock);
17647 ok(hr == D3DERR_INBEGINSTATEBLOCK, "Got unexpected hr %#x.\n", hr);
17649 hr = IDirect3DDevice7_CaptureStateBlock(device, stateblock);
17650 ok(hr == D3DERR_INBEGINSTATEBLOCK, "Got unexpected hr %#x.\n", hr);
17652 hr = IDirect3DDevice7_CreateStateBlock(device, D3DSBT_ALL, &stateblock2);
17653 ok(hr == D3DERR_INBEGINSTATEBLOCK, "Got unexpected hr %#x.\n", hr);
17655 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &value);
17656 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17657 ok(value == TRUE, "Got unexpected value %#x.\n", value);
17659 hr = IDirect3DDevice7_EndStateBlock(device, &stateblock2);
17660 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17662 hr = IDirect3DDevice7_ApplyStateBlock(device, stateblock2);
17663 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17665 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &value);
17666 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17667 ok(value == TRUE, "Got unexpected value %#x.\n", value);
17669 refcount = IDirect3DDevice7_Release(device);
17670 ok(!refcount, "Device has %u references left.\n", refcount);
17671 DestroyWindow(window);
17674 static void test_caps(void)
17676 DWORD caps_never, caps_always, caps_hal;
17677 DDCAPS hal_caps, hel_caps;
17678 IDirectDraw7 *ddraw;
17679 HRESULT hr;
17680 BOOL no3d;
17682 caps_never = DDSCAPS_RESERVED1
17683 | DDSCAPS_ALPHA
17684 | DDSCAPS_PRIMARYSURFACELEFT
17685 | DDSCAPS_SYSTEMMEMORY
17686 | DDSCAPS_VISIBLE
17687 | DDSCAPS_WRITEONLY
17688 | DDSCAPS_LIVEVIDEO
17689 | DDSCAPS_HWCODEC
17690 | DDSCAPS_MODEX
17691 | DDSCAPS_RESERVED2
17692 | 0x01000000u
17693 | 0x02000000u
17694 | DDSCAPS_ALLOCONLOAD
17695 | DDSCAPS_VIDEOPORT
17696 | DDSCAPS_STANDARDVGAMODE
17697 | DDSCAPS_OPTIMIZED;
17699 caps_always = DDSCAPS_FLIP
17700 | DDSCAPS_OFFSCREENPLAIN
17701 | DDSCAPS_PRIMARYSURFACE
17702 | DDSCAPS_TEXTURE
17703 | DDSCAPS_ZBUFFER
17704 | DDSCAPS_MIPMAP;
17706 caps_hal = DDSCAPS_BACKBUFFER
17707 | DDSCAPS_COMPLEX
17708 | DDSCAPS_FRONTBUFFER
17709 | DDSCAPS_3DDEVICE
17710 | DDSCAPS_VIDEOMEMORY
17711 | DDSCAPS_LOCALVIDMEM
17712 | DDSCAPS_NONLOCALVIDMEM;
17714 ddraw = create_ddraw();
17715 ok(!!ddraw, "Failed to create a ddraw object.\n");
17717 memset(&hal_caps, 0, sizeof(hal_caps));
17718 memset(&hel_caps, 0, sizeof(hel_caps));
17719 hal_caps.dwSize = sizeof(hal_caps);
17720 hel_caps.dwSize = sizeof(hel_caps);
17721 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, &hel_caps);
17722 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17723 ok(hal_caps.ddsOldCaps.dwCaps == hal_caps.ddsCaps.dwCaps,
17724 "Got unexpected caps %#x, expected %#x.\n",
17725 hal_caps.ddsOldCaps.dwCaps, hal_caps.ddsCaps.dwCaps);
17726 ok(hel_caps.ddsOldCaps.dwCaps == hel_caps.ddsCaps.dwCaps,
17727 "Got unexpected caps %#x, expected %#x.\n",
17728 hel_caps.ddsOldCaps.dwCaps, hel_caps.ddsCaps.dwCaps);
17730 no3d = !(hal_caps.ddsCaps.dwCaps & DDSCAPS_3DDEVICE);
17731 if (hal_caps.ddsCaps.dwCaps)
17733 ok(!(hal_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
17734 ok(!(~hal_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
17735 todo_wine_if(no3d) ok(!(~hal_caps.ddsCaps.dwCaps & caps_hal),
17736 "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
17738 ok(!(hel_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
17739 ok(!(~hel_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
17740 todo_wine_if(!no3d) ok(!(hel_caps.ddsCaps.dwCaps & caps_hal),
17741 "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
17743 IDirectDraw7_Release(ddraw);
17745 if (hal_caps.ddsCaps.dwCaps)
17747 hr = pDirectDrawCreateEx((GUID *)DDCREATE_HARDWAREONLY, (void **)&ddraw, &IID_IDirectDraw7, NULL);
17748 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17750 memset(&hal_caps, 0, sizeof(hal_caps));
17751 memset(&hel_caps, 0, sizeof(hel_caps));
17752 hal_caps.dwSize = sizeof(hal_caps);
17753 hel_caps.dwSize = sizeof(hel_caps);
17754 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, &hel_caps);
17755 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17756 ok(hal_caps.ddsOldCaps.dwCaps == hal_caps.ddsCaps.dwCaps,
17757 "Got unexpected caps %#x, expected %#x.\n",
17758 hal_caps.ddsOldCaps.dwCaps, hal_caps.ddsCaps.dwCaps);
17759 ok(hel_caps.ddsOldCaps.dwCaps == hel_caps.ddsCaps.dwCaps,
17760 "Got unexpected caps %#x, expected %#x.\n",
17761 hel_caps.ddsOldCaps.dwCaps, hel_caps.ddsCaps.dwCaps);
17763 ok(!(hal_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
17764 ok(!(~hal_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
17765 todo_wine_if(no3d) ok(!(~hal_caps.ddsCaps.dwCaps & caps_hal),
17766 "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
17767 todo_wine ok(!hel_caps.ddsCaps.dwCaps, "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
17769 IDirectDraw7_Release(ddraw);
17772 hr = pDirectDrawCreateEx((GUID *)DDCREATE_EMULATIONONLY, (void **)&ddraw, &IID_IDirectDraw7, NULL);
17773 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17775 memset(&hal_caps, 0, sizeof(hal_caps));
17776 memset(&hel_caps, 0, sizeof(hel_caps));
17777 hal_caps.dwSize = sizeof(hal_caps);
17778 hel_caps.dwSize = sizeof(hel_caps);
17779 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, &hel_caps);
17780 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17781 ok(hal_caps.ddsOldCaps.dwCaps == hal_caps.ddsCaps.dwCaps,
17782 "Got unexpected caps %#x, expected %#x.\n",
17783 hal_caps.ddsOldCaps.dwCaps, hal_caps.ddsCaps.dwCaps);
17784 ok(hel_caps.ddsOldCaps.dwCaps == hel_caps.ddsCaps.dwCaps,
17785 "Got unexpected caps %#x, expected %#x.\n",
17786 hel_caps.ddsOldCaps.dwCaps, hel_caps.ddsCaps.dwCaps);
17788 todo_wine ok(!hal_caps.ddsCaps.dwCaps, "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
17789 ok(!(hel_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
17790 ok(!(~hel_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
17791 todo_wine_if(!no3d) ok(!(hel_caps.ddsCaps.dwCaps & caps_hal),
17792 "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
17794 IDirectDraw7_Release(ddraw);
17797 static void test_d32_support(void)
17799 IDirectDrawSurface7 *surface;
17800 DDSURFACEDESC2 surface_desc;
17801 IDirectDraw7 *ddraw;
17802 ULONG refcount;
17803 HWND window;
17804 HRESULT hr;
17806 window = create_window();
17807 ddraw = create_ddraw();
17808 ok(!!ddraw, "Failed to create a ddraw object.\n");
17809 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
17810 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17812 memset(&surface_desc, 0, sizeof(surface_desc));
17813 surface_desc.dwSize = sizeof(surface_desc);
17814 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
17815 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
17816 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
17817 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
17818 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = 32;
17819 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = 0xffffffff;
17820 surface_desc.dwWidth = 64;
17821 surface_desc.dwHeight = 64;
17822 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
17823 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17825 memset(&surface_desc, 0, sizeof(surface_desc));
17826 surface_desc.dwSize = sizeof(surface_desc);
17827 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
17828 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17829 ok((surface_desc.dwFlags & DDSD_PIXELFORMAT), "Got unexpected flags %#x.\n", surface_desc.dwFlags);
17830 ok(U4(surface_desc).ddpfPixelFormat.dwFlags & DDPF_ZBUFFER,
17831 "Got unexpected format flags %#x.\n", U4(surface_desc).ddpfPixelFormat.dwFlags);
17832 ok(U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth == 32,
17833 "Got unexpected dwZBufferBitDepth %u.\n", U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth);
17834 ok(U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask == 0xffffffff,
17835 "Got unexpected Z mask 0x%08x.\n", U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask);
17836 ok(!(surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY),
17837 "Got unexpected surface caps %#x.\n", surface_desc.ddsCaps.dwCaps);
17838 IDirectDrawSurface7_Release(surface);
17840 refcount = IDirectDraw7_Release(ddraw);
17841 ok(!refcount, "%u references left.\n", refcount);
17842 DestroyWindow(window);
17845 static void test_surface_format_conversion_alpha(void)
17847 static const unsigned int rgba_data[4 * 4] =
17849 0xff00ff00, 0xff0000ff, 0xff0000ff, 0xff0000ff,
17850 0xff0000ff, 0xff00ff00, 0xff0000ff, 0xff0000ff,
17851 0xff00ff00, 0xff0000ff, 0xff00ff00, 0xff0000ff,
17852 0xff00ff00, 0xff0000ff, 0xff0000ff, 0xff00ff00,
17854 static const unsigned int rgbx_data[4 * 4] =
17856 0x0000ff00, 0x000000ff, 0x000000ff, 0x000000ff,
17857 0x000000ff, 0x0000ff00, 0x000000ff, 0x000000ff,
17858 0x0000ff00, 0x000000ff, 0x0000ff00, 0x000000ff,
17859 0x0000ff00, 0x000000ff, 0x000000ff, 0x0000ff00,
17861 static const unsigned short int r5g6b5_data[4 * 4] =
17863 0x07e0, 0x001f, 0x001f, 0x001f,
17864 0x001f, 0x07e0, 0x001f, 0x001f,
17865 0x07e0, 0x001f, 0x07e0, 0x001f,
17866 0x07e0, 0x001f, 0x001f, 0x07e0,
17868 static const unsigned short int r5g5b5x1_data[4 * 4] =
17870 0x03e0, 0x001f, 0x001f, 0x001f,
17871 0x001f, 0x03e0, 0x001f, 0x001f,
17872 0x03e0, 0x001f, 0x03e0, 0x001f,
17873 0x03e0, 0x001f, 0x001f, 0x03e0,
17875 static const unsigned short int r5g5b5a1_data[4 * 4] =
17877 0x83e0, 0x801f, 0x801f, 0x801f,
17878 0x801f, 0x83e0, 0x801f, 0x801f,
17879 0x83e0, 0x801f, 0x83e0, 0x801f,
17880 0x83e0, 0x801f, 0x801f, 0x83e0,
17882 static const unsigned int dxt1_data[8] =
17884 0x001f07e0, 0x14445154,
17886 static const unsigned int dxt2_data[16] =
17888 0xffffffff, 0xffffffff, 0x001f07e0, 0x14445154,
17891 enum test_format_id
17893 FMT_RGBA,
17894 FMT_RGBX,
17895 FMT_R5G6B5,
17896 FMT_R5G5B5X1,
17897 FMT_R5G5B5A1,
17898 FMT_DXT1,
17899 FMT_DXT2,
17900 FMT_DXT3,
17903 static const struct test_format
17905 DDPIXELFORMAT fmt;
17906 const char *name;
17907 unsigned int block_size, x_blocks, y_blocks;
17908 DWORD support_flag;
17909 BOOL broken_software_blit, broken_hardware_blit;
17911 formats[] =
17915 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
17916 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
17918 "RGBA", 4, 4, 4,
17922 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
17923 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
17925 "RGBX", 4, 4, 4,
17929 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
17930 {16}, {0x0000f800}, {0x000007e0}, {0x0000001f}, {0x00000000}
17932 "R5G6B5", 2, 4, 4, 0, TRUE,
17933 /* Looks broken for sysmem texture conversions on Windows (at
17934 * least with hardware device), the result is either error from
17935 * _Blt() or a copy of the source data without any conversion. */
17939 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
17940 {16}, {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00000000}
17942 "R5G5B5X1", 2, 4, 4,
17946 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
17947 {16}, {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00008000}
17949 "R5G5B5A1", 2, 4, 4, 0, FALSE, TRUE,
17953 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
17954 {0}, {0}, {0}, {0}, {0}
17956 "DXT1", 8, 1, 1, SUPPORT_DXT1,
17960 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '2'),
17961 {0}, {0}, {0}, {0}, {0}
17963 "DXT2", 16, 1, 1, SUPPORT_DXT2,
17967 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '3'),
17968 {0}, {0}, {0}, {0}, {0}
17970 "DXT3", 16, 1, 1, SUPPORT_DXT3,
17974 static const struct
17976 DWORD src_caps, dst_caps;
17978 test_caps[] =
17980 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY},
17981 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY},
17982 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY},
17983 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY},
17986 static const struct
17988 enum test_format_id src_format;
17989 const void *src_data;
17990 enum test_format_id dst_format;
17991 const void *expected_data;
17992 BOOL todo;
17994 tests[] =
17996 #if 0
17997 /* The following 3 tests give different results on AMD and NVIDIA on Windows, disabling. */
17998 {FMT_RGBX, rgbx_data, FMT_RGBA, rgba_data},
17999 {FMT_RGBA, rgba_data, FMT_RGBX, rgbx_data},
18000 {FMT_R5G5B5X1, r5g5b5x1_data, FMT_RGBA, rgba_data},
18001 #endif
18002 {FMT_R5G6B5, r5g6b5_data, FMT_RGBA, rgba_data},
18003 {FMT_R5G6B5, r5g6b5_data, FMT_R5G5B5A1, r5g5b5a1_data},
18004 {FMT_R5G5B5X1, r5g5b5x1_data, FMT_R5G5B5A1, r5g5b5x1_data, TRUE},
18005 {FMT_R5G5B5A1, r5g5b5a1_data, FMT_R5G6B5, r5g6b5_data},
18006 {FMT_RGBA, rgba_data, FMT_DXT1, dxt1_data},
18007 {FMT_RGBX, rgbx_data, FMT_DXT1, dxt1_data},
18008 {FMT_RGBA, rgba_data, FMT_DXT2, dxt2_data},
18009 {FMT_RGBX, rgbx_data, FMT_DXT2, dxt2_data},
18010 {FMT_RGBA, rgba_data, FMT_DXT3, dxt2_data},
18011 {FMT_RGBX, rgbx_data, FMT_DXT3, dxt2_data},
18012 {FMT_DXT1, dxt1_data, FMT_DXT2, dxt2_data},
18013 {FMT_DXT1, dxt1_data, FMT_RGBA, rgba_data},
18014 {FMT_DXT1, dxt1_data, FMT_RGBX, rgba_data},
18015 {FMT_DXT3, dxt2_data, FMT_RGBA, rgba_data},
18016 {FMT_DXT3, dxt2_data, FMT_RGBX, rgba_data},
18019 const struct test_format *src_format, *dst_format;
18020 IDirectDrawSurface7 *src_surf, *dst_surf;
18021 DDSURFACEDESC2 surface_desc, lock;
18022 unsigned int i, j, x, y, pitch;
18023 IDirect3DDevice7 *device;
18024 DWORD supported_fmts;
18025 IDirectDraw7 *ddraw;
18026 ULONG refcount;
18027 BOOL is_wine;
18028 HWND window;
18029 BOOL passed;
18030 HRESULT hr;
18032 window = create_window();
18033 if (!(device = create_device(window, DDSCL_NORMAL)))
18035 skip("Failed to create a 3D device, skipping test.\n");
18036 DestroyWindow(window);
18037 return;
18040 ddraw = create_ddraw();
18041 ok(!!ddraw, "Failed to create a ddraw object.\n");
18042 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
18043 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
18045 hr = IDirect3DDevice7_EnumTextureFormats(device, test_block_formats_creation_cb,
18046 &supported_fmts);
18047 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
18049 is_wine = !strcmp(winetest_platform, "wine");
18051 memset(&surface_desc, 0, sizeof(surface_desc));
18052 surface_desc.dwSize = sizeof(surface_desc);
18053 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
18054 surface_desc.dwWidth = 4;
18055 surface_desc.dwHeight = 4;
18057 for (i = 0; i < ARRAY_SIZE(tests); ++i)
18059 src_format = &formats[tests[i].src_format];
18060 dst_format = &formats[tests[i].dst_format];
18062 if (~supported_fmts & dst_format->support_flag)
18064 skip("%s format is not supported, skipping test %u.\n", dst_format->name, i);
18065 continue;
18067 if (~supported_fmts & src_format->support_flag)
18069 skip("%s format is not supported, skipping test %u.\n", src_format->name, i);
18070 continue;
18073 for (j = 0; j < ARRAY_SIZE(test_caps); ++j)
18075 if (!is_wine && ((test_caps[j].src_caps | test_caps[j].dst_caps) & DDSCAPS_SYSTEMMEMORY)
18076 && (src_format->broken_software_blit || dst_format->broken_software_blit))
18077 continue;
18078 if (!is_wine && (test_caps[j].dst_caps & DDSCAPS_VIDEOMEMORY)
18079 && dst_format->broken_hardware_blit)
18080 continue;
18082 U4(surface_desc).ddpfPixelFormat = src_format->fmt;
18083 surface_desc.ddsCaps.dwCaps = test_caps[j].src_caps;
18084 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surf, NULL);
18085 ok(hr == DD_OK, "Test (%u, %u), got unexpected hr %#x.\n", j, i, hr);
18087 U4(surface_desc).ddpfPixelFormat = dst_format->fmt;
18088 surface_desc.ddsCaps.dwCaps = test_caps[j].dst_caps;
18089 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surf, NULL);
18090 ok(hr == DD_OK, "Test (%u, %u), got unexpected hr %#x.\n", j, i, hr);
18092 memset(&lock, 0, sizeof(lock));
18093 lock.dwSize = sizeof(lock);
18094 hr = IDirectDrawSurface7_Lock(src_surf, NULL, &lock, 0, NULL);
18095 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
18096 pitch = U1(lock).lPitch;
18097 for (y = 0; y < src_format->y_blocks; ++y)
18099 memcpy((BYTE *)lock.lpSurface + y * pitch,
18100 (BYTE *)tests[i].src_data + y * src_format->x_blocks * src_format->block_size,
18101 src_format->block_size * src_format->x_blocks);
18103 hr = IDirectDrawSurface7_Unlock(src_surf, NULL);
18104 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
18106 hr = IDirectDrawSurface7_Blt(dst_surf, NULL, src_surf, NULL, DDBLT_WAIT, NULL);
18107 if (!is_wine && FAILED(hr))
18109 /* Some software blits are rejected on Windows. */
18110 IDirectDrawSurface7_Release(dst_surf);
18111 IDirectDrawSurface7_Release(src_surf);
18112 skip("Skipping test (%u, %u), cannot blit %s -> %s, hr %#x.\n", j, i,
18113 src_format->name, dst_format->name, hr);
18114 continue;
18116 ok(hr == DD_OK, "Test (%u, %s -> %s), got unexpected hr %#x.\n", j,
18117 src_format->name, dst_format->name, hr);
18119 memset(&lock, 0, sizeof(lock));
18120 lock.dwSize = sizeof(lock);
18121 hr = IDirectDrawSurface7_Lock(dst_surf, NULL, &lock, 0, NULL);
18122 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
18123 pitch = U1(lock).lPitch;
18125 for (y = 0; y < dst_format->y_blocks; ++y)
18127 const void *expected_data = tests[i].expected_data;
18129 passed = !memcmp((BYTE*)lock.lpSurface + y * pitch,
18130 (BYTE *)expected_data + y * dst_format->x_blocks * dst_format->block_size,
18131 dst_format->block_size * dst_format->x_blocks);
18132 todo_wine_if(tests[i].todo)
18133 ok(passed, "Test (%u, %s -> %s), row %u, unexpected surface data.\n", j,
18134 src_format->name, dst_format->name, y);
18136 if (!passed && !(is_wine && tests[i].todo))
18138 for (x = 0; x < dst_format->x_blocks * dst_format->block_size / 4; ++x)
18140 trace("Test (%u, %u), x %u, y %u, got 0x%08x, expected 0x%08x.\n", j, i, x, y,
18141 *(unsigned int *)((BYTE *)lock.lpSurface + y * pitch + x * 4),
18142 *(unsigned int *)((BYTE *)expected_data + y * dst_format->x_blocks
18143 * dst_format->block_size + x * 4));
18146 if (!passed)
18147 break;
18149 hr = IDirectDrawSurface7_Unlock(dst_surf, NULL);
18150 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
18152 IDirectDrawSurface7_Release(dst_surf);
18153 IDirectDrawSurface7_Release(src_surf);
18157 IDirect3DDevice7_Release(device);
18158 refcount = IDirectDraw7_Release(ddraw);
18159 ok(!refcount, "%u references left.\n", refcount);
18160 DestroyWindow(window);
18163 static void test_compressed_surface_stretch(void)
18165 static const struct
18167 unsigned int src_width, src_height;
18168 unsigned int dst_width, dst_height;
18169 unsigned int src_x, src_y;
18170 unsigned int dst_x, dst_y;
18171 BOOL todo_src, todo_dst;
18173 test_sizes[] =
18175 {4, 4, 8, 8},
18176 {8, 8, 4, 4},
18177 {4, 4, 2, 2, 0, 0, 0, 0, FALSE, TRUE},
18178 {4, 4, 6, 6, 0, 0, 0, 0, FALSE, TRUE},
18179 {4, 4, 8, 8, 2, 2, 2, 2, TRUE, TRUE},
18182 static const struct
18184 DWORD src_caps, dst_caps;
18186 test_caps[] =
18188 #if 0
18189 /* Broken on Windows. */
18190 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY},
18191 #endif
18192 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY},
18193 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY},
18194 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY},
18197 static struct
18199 DDPIXELFORMAT fmt;
18200 const char *name;
18201 DWORD support_flag;
18203 test_formats[] =
18207 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
18208 {16}, {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00008000}
18210 "R5G5B5A1",
18214 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
18215 {0}, {0}, {0}, {0}, {0}
18217 "DXT1", SUPPORT_DXT1,
18221 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '3'),
18222 {0}, {0}, {0}, {0}, {0}
18224 "DXT3", SUPPORT_DXT3,
18228 unsigned int i, j, k, l, x, y, pitch;
18229 DDSURFACEDESC2 rb_surface_desc, src_surface_desc, dst_surface_desc, lock;
18230 IDirectDrawSurface7 *src_surf, *dst_surf, *rb_surf;
18231 IDirect3DDevice7 *device;
18232 RECT src_rect, dst_rect;
18233 DWORD supported_fmts;
18234 unsigned short *data;
18235 IDirectDraw7 *ddraw;
18236 ULONG refcount;
18237 HWND window;
18238 BOOL passed;
18239 DDBLTFX fx;
18240 HRESULT hr;
18242 window = create_window();
18243 if (!(device = create_device(window, DDSCL_NORMAL)))
18245 skip("Failed to create a 3D device, skipping test.\n");
18246 DestroyWindow(window);
18247 return;
18250 ddraw = create_ddraw();
18251 ok(!!ddraw, "Failed to create a ddraw object.\n");
18252 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
18253 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
18255 hr = IDirect3DDevice7_EnumTextureFormats(device, test_block_formats_creation_cb,
18256 &supported_fmts);
18257 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
18259 memset(&src_surface_desc, 0, sizeof(src_surface_desc));
18260 src_surface_desc.dwSize = sizeof(src_surface_desc);
18261 src_surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
18262 dst_surface_desc = src_surface_desc;
18264 memset(&rb_surface_desc, 0, sizeof(rb_surface_desc));
18265 rb_surface_desc.dwSize = sizeof(rb_surface_desc);
18266 rb_surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
18267 U4(rb_surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(rb_surface_desc).ddpfPixelFormat);
18268 U4(rb_surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
18269 U1(U4(rb_surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
18270 U2(U4(rb_surface_desc).ddpfPixelFormat).dwRBitMask = 0x00007c00;
18271 U3(U4(rb_surface_desc).ddpfPixelFormat).dwGBitMask = 0x000003e0;
18272 U4(U4(rb_surface_desc).ddpfPixelFormat).dwBBitMask = 0x0000001f;
18273 U5(U4(rb_surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0x00008000;
18274 rb_surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
18276 memset(&fx, 0, sizeof(fx));
18277 fx.dwSize = sizeof(fx);
18279 memset(&lock, 0, sizeof(lock));
18280 lock.dwSize = sizeof(lock);
18282 for (i = 0; i < ARRAY_SIZE(test_caps); ++i)
18284 src_surface_desc.ddsCaps.dwCaps = test_caps[i].src_caps;
18285 dst_surface_desc.ddsCaps.dwCaps = test_caps[i].dst_caps;
18287 for (j = 0; j < ARRAY_SIZE(test_sizes); ++j)
18289 SetRect(&src_rect, test_sizes[j].src_x, test_sizes[j].src_y,
18290 test_sizes[j].src_width, test_sizes[j].src_height);
18291 SetRect(&dst_rect, test_sizes[j].dst_x, test_sizes[j].dst_y,
18292 test_sizes[j].dst_width, test_sizes[j].dst_height);
18294 src_surface_desc.dwWidth = test_sizes[j].src_width;
18295 src_surface_desc.dwHeight = test_sizes[j].src_height;
18297 dst_surface_desc.dwWidth = (test_sizes[j].dst_width + 3) & ~3;
18298 dst_surface_desc.dwHeight = (test_sizes[j].dst_height + 3) & ~3;
18300 rb_surface_desc.dwWidth = max(src_surface_desc.dwWidth, dst_surface_desc.dwWidth);
18301 rb_surface_desc.dwHeight = max(src_surface_desc.dwHeight, dst_surface_desc.dwHeight);
18303 hr = IDirectDraw7_CreateSurface(ddraw, &rb_surface_desc, &rb_surf, NULL);
18304 ok(hr == DD_OK, "Test (%u, %u), got unexpected hr %#x.\n", i, j, hr);
18306 for (k = 0; k < ARRAY_SIZE(test_formats); ++k)
18308 U4(src_surface_desc).ddpfPixelFormat = test_formats[k].fmt;
18309 hr = IDirectDraw7_CreateSurface(ddraw, &src_surface_desc, &src_surf, NULL);
18310 ok(hr == DD_OK, "Test (%u, %u, %u), got unexpected hr %#x.\n", i, j, k, hr);
18312 U5(fx).dwFillColor = 0x801f;
18313 hr = IDirectDrawSurface7_Blt(rb_surf, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
18314 ok(hr == DD_OK, "Test (%u, %u, %u), got unexpected hr %#x.\n", i, j, k, hr);
18316 hr = IDirectDrawSurface7_Blt(src_surf, &src_rect, rb_surf, &src_rect, DDBLT_WAIT, NULL);
18318 todo_wine_if(test_formats[k].fmt.dwFlags == DDPF_FOURCC && test_sizes[j].todo_src)
18319 ok(hr == DD_OK, "Test (%u, %u, %u), got unexpected hr %#x.\n", i, j, k, hr);
18320 if (FAILED(hr))
18322 IDirectDrawSurface7_Release(src_surf);
18323 continue;
18326 for (l = 0; l < ARRAY_SIZE(test_formats); ++l)
18328 if (~supported_fmts & test_formats[l].support_flag)
18330 skip("%s format is not supported, skipping test %u.\n", test_formats[l].name, i);
18331 continue;
18334 U4(dst_surface_desc).ddpfPixelFormat = test_formats[l].fmt;
18336 hr = IDirectDraw7_CreateSurface(ddraw, &dst_surface_desc, &dst_surf, NULL);
18337 ok(hr == DD_OK, "Test (%u, %u, %u, %u), got unexpected hr %#x.\n", i, j, k, l, hr);
18339 memset(&lock, 0, sizeof(lock));
18340 lock.dwSize = sizeof(lock);
18342 /* r200 does not init vidmem DXT3 surfaces to 0 correctly. Do it manually.
18343 * We can't use DDBLT_COLORFILL on compressed surfaces, so we need memset.
18345 * Locking alone is not enough, so this isn't an accidental workaround that
18346 * forces a different codepath because the destination is currently in sysmem. */
18347 if (test_formats[l].fmt.dwFourCC == MAKEFOURCC('D', 'X', 'T', '3'))
18349 hr = IDirectDrawSurface7_Lock(dst_surf, NULL, &lock, 0, NULL);
18350 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
18351 memset(lock.lpSurface, 0, U1(lock).dwLinearSize);
18352 hr = IDirectDrawSurface7_Unlock(dst_surf, NULL);
18353 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
18356 hr = IDirectDrawSurface7_Blt(dst_surf, &dst_rect, src_surf, &src_rect, DDBLT_WAIT, NULL);
18357 todo_wine_if(test_formats[l].fmt.dwFlags == DDPF_FOURCC && test_sizes[j].todo_dst)
18358 ok(hr == DD_OK, "Test (%u, %u, %u, %u), got unexpected hr %#x.\n", i, j, k, l, hr);
18359 if (FAILED(hr))
18361 IDirectDrawSurface7_Release(dst_surf);
18362 continue;
18365 U5(fx).dwFillColor = 0xffffffff;
18366 hr = IDirectDrawSurface7_Blt(rb_surf, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
18367 ok(hr == DD_OK, "Test (%u, %u, %u, %u), got unexpected hr %#x.\n", i, j, k, l, hr);
18369 hr = IDirectDrawSurface7_Blt(rb_surf, &dst_rect, dst_surf, &dst_rect, DDBLT_WAIT, NULL);
18370 ok(hr == DD_OK, "Test (%u, %u, %u, %u), got unexpected hr %#x.\n", i, j, k, l, hr);
18371 hr = IDirectDrawSurface7_Lock(rb_surf, NULL, &lock, 0, NULL);
18372 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
18373 pitch = U1(lock).lPitch;
18375 passed = TRUE;
18376 for (y = dst_rect.top; y < dst_rect.bottom && passed; ++y)
18378 data = (unsigned short *)((BYTE *)lock.lpSurface + y * pitch);
18380 for (x = dst_rect.left; x < dst_rect.right && passed; ++x)
18382 passed = data[x] == 0x801f;
18383 ok(passed, "Test (%u, %u, %u, %u), x %u, y %u, "
18384 "got unexpected colour 0x%04x.\n", i, j, k, l, x, y, data[x]);
18387 hr = IDirectDrawSurface7_Unlock(rb_surf, NULL);
18388 IDirectDrawSurface7_Release(dst_surf);
18390 IDirectDrawSurface7_Release(src_surf);
18392 IDirectDrawSurface7_Release(rb_surf);
18396 IDirect3DDevice7_Release(device);
18397 refcount = IDirectDraw7_Release(ddraw);
18398 ok(!refcount, "%u references left.\n", refcount);
18399 DestroyWindow(window);
18402 struct find_different_mode_param
18404 unsigned int old_width;
18405 unsigned int old_height;
18406 unsigned int old_frequency;
18407 unsigned int new_width;
18408 unsigned int new_height;
18409 unsigned int new_frequency;
18410 unsigned int new_bpp;
18413 static HRESULT CALLBACK find_different_mode_callback(DDSURFACEDESC2 *surface_desc, void *context)
18415 struct find_different_mode_param *param = context;
18417 if (U1(U4(*surface_desc).ddpfPixelFormat).dwRGBBitCount != registry_mode.dmBitsPerPel)
18418 return DDENUMRET_OK;
18420 /* Windows will advertise 59hz (for 59.94) and 60hz (for proper 60hz) on monitors that support
18421 * only one of the two (usually 59.94). If an application requests 60hz windows will apply 59.94.
18422 * Thus if we think we found a different refresh rate, we get 59hz instead of the 60hz we
18423 * requested.
18425 * The same is true of other 1% slowed-down TV compatible refresh rates according to a Microsoft
18426 * support document: 23.976 vs 24, 30, 48, 72 and 120 hz. It can be reproduced by attempting to
18427 * set 60hz in the advanced display properties manually. Usually the restriction to one refresh
18428 * rate applies to laptop panels. */
18429 if (surface_desc->dwWidth != param->old_width && surface_desc->dwHeight != param->old_height &&
18430 (!compare_uint(surface_desc->dwRefreshRate, param->old_frequency, 1) || !param->old_frequency))
18432 param->new_width = surface_desc->dwWidth;
18433 param->new_height = surface_desc->dwHeight;
18434 param->new_frequency = surface_desc->dwRefreshRate;
18435 param->new_bpp = surface_desc->ddpfPixelFormat.dwRGBBitCount;
18436 return DDENUMRET_CANCEL;
18439 return DDENUMRET_OK;
18442 static void test_cursor_clipping(void)
18444 struct find_different_mode_param param;
18445 DDSURFACEDESC2 surface_desc;
18446 RECT rect, clip_rect;
18447 IDirectDraw7 *ddraw;
18448 HWND window;
18449 HRESULT hr;
18450 BOOL ret;
18452 window = create_window();
18453 ok(!!window, "Failed to create a window.\n");
18454 ddraw = create_ddraw();
18455 ok(!!ddraw, "Failed to create a ddraw object.\n");
18457 memset(&surface_desc, 0, sizeof(surface_desc));
18458 surface_desc.dwSize = sizeof(surface_desc);
18459 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
18460 ok(hr == DD_OK, "GetDisplayMode failed, hr %#x.\n", hr);
18462 memset(&param, 0, sizeof(param));
18463 param.old_width = surface_desc.dwWidth;
18464 param.old_height = surface_desc.dwHeight;
18465 hr = IDirectDraw7_EnumDisplayModes(ddraw, 0, NULL, &param, find_different_mode_callback);
18466 ok(hr == DD_OK, "EnumDisplayModes failed, hr %#x.\n", hr);
18467 if (!(param.new_width && param.new_height))
18469 skip("Failed to find a different mode than %ux%u.\n", param.old_width, param.old_height);
18470 goto done;
18473 ret = ClipCursor(NULL);
18474 ok(ret, "ClipCursor failed, error %#x.\n", GetLastError());
18475 get_virtual_rect(&rect);
18476 ret = GetClipCursor(&clip_rect);
18477 ok(ret, "GetClipCursor failed, error %#x.\n", GetLastError());
18478 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
18479 wine_dbgstr_rect(&clip_rect));
18481 /* Set cooperative level to normal */
18482 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
18483 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
18484 flush_events();
18485 get_virtual_rect(&rect);
18486 ret = GetClipCursor(&clip_rect);
18487 ok(ret, "GetClipCursor failed, error %#x.\n", GetLastError());
18488 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
18489 wine_dbgstr_rect(&clip_rect));
18491 hr = set_display_mode(ddraw, param.new_width, param.new_height);
18492 ok(hr == DD_OK || hr == DDERR_UNSUPPORTED, "SetDisplayMode failed, hr %#x.\n", hr);
18493 if (FAILED(hr))
18495 win_skip("SetDisplayMode failed, hr %#x.\n", hr);
18496 goto done;
18498 flush_events();
18499 get_virtual_rect(&rect);
18500 ret = GetClipCursor(&clip_rect);
18501 ok(ret, "GetClipCursor failed, error %#x.\n", GetLastError());
18502 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
18503 wine_dbgstr_rect(&clip_rect));
18505 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
18506 ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
18507 flush_events();
18508 get_virtual_rect(&rect);
18509 ret = GetClipCursor(&clip_rect);
18510 ok(ret, "GetClipCursor failed, error %#x.\n", GetLastError());
18511 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
18512 wine_dbgstr_rect(&clip_rect));
18514 /* Switch to full screen cooperative level */
18515 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
18516 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
18517 flush_events();
18518 SetRect(&rect, 0, 0, param.old_width, param.old_height);
18519 ret = GetClipCursor(&clip_rect);
18520 ok(ret, "GetClipCursor failed, error %#x.\n", GetLastError());
18521 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
18522 wine_dbgstr_rect(&clip_rect));
18524 hr = set_display_mode(ddraw, param.new_width, param.new_height);
18525 ok(hr == DD_OK || hr == DDERR_UNSUPPORTED, "SetDisplayMode failed, hr %#x.\n", hr);
18526 if (FAILED(hr))
18528 win_skip("SetDisplayMode failed, hr %#x.\n", hr);
18529 goto done;
18531 flush_events();
18532 SetRect(&rect, 0, 0, param.new_width, param.new_height);
18533 ret = GetClipCursor(&clip_rect);
18534 ok(ret, "GetClipCursor failed, error %#x.\n", GetLastError());
18535 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
18536 wine_dbgstr_rect(&clip_rect));
18538 /* Restore display mode */
18539 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
18540 ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
18541 flush_events();
18542 SetRect(&rect, 0, 0, param.old_width, param.old_height);
18543 ret = GetClipCursor(&clip_rect);
18544 ok(ret, "GetClipCursor failed, error %#x.\n", GetLastError());
18545 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
18546 wine_dbgstr_rect(&clip_rect));
18548 /* Switch to normal cooperative level */
18549 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
18550 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
18551 flush_events();
18552 get_virtual_rect(&rect);
18553 ret = GetClipCursor(&clip_rect);
18554 ok(ret, "GetClipCursor failed, error %#x.\n", GetLastError());
18555 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
18556 wine_dbgstr_rect(&clip_rect));
18558 done:
18559 IDirectDraw7_Release(ddraw);
18560 DestroyWindow(window);
18563 static BOOL CALLBACK test_window_position_cb(HMONITOR monitor, HDC hdc, RECT *monitor_rect,
18564 LPARAM lparam)
18566 RECT primary_rect, window_rect, new_rect;
18567 IDirectDraw7 *ddraw;
18568 HWND window;
18569 HRESULT hr;
18570 BOOL ret;
18572 ddraw = create_ddraw();
18573 ok(!!ddraw, "Failed to create a ddraw object.\n");
18574 window = CreateWindowA("static", "ddraw_test", WS_POPUP | WS_VISIBLE, monitor_rect->left,
18575 monitor_rect->top, monitor_rect->right - monitor_rect->left,
18576 monitor_rect->bottom - monitor_rect->top, NULL, NULL, NULL, NULL);
18577 ok(!!window, "Failed to create a window.\n");
18578 flush_events();
18580 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
18581 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
18582 flush_events();
18583 ret = GetWindowRect(window, &window_rect);
18584 ok(ret, "GetWindowRect failed, error %#x.\n", GetLastError());
18585 SetRect(&primary_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
18586 ok(EqualRect(&window_rect, &primary_rect), "Expect window rect %s, got %s.\n",
18587 wine_dbgstr_rect(&primary_rect), wine_dbgstr_rect(&window_rect));
18589 new_rect = window_rect;
18590 --new_rect.right;
18591 --new_rect.bottom;
18593 ret = MoveWindow(window, new_rect.left, new_rect.top, new_rect.right - new_rect.left,
18594 new_rect.bottom - new_rect.top, TRUE);
18595 ok(ret, "Got unexpected ret %#x, error %#x.\n", ret, GetLastError());
18596 ret = GetWindowRect(window, &window_rect);
18597 ok(ret, "Got unexpected ret %#x, error %#x.\n", ret, GetLastError());
18598 ok(EqualRect(&window_rect, &new_rect),
18599 "Expected window rect %s, got %s.\n",
18600 wine_dbgstr_rect(monitor_rect), wine_dbgstr_rect(&window_rect));
18601 /* After processing window events window rectangle gets restored. But only once, the size set
18602 * on the second resize remains. */
18603 flush_events();
18604 ret = GetWindowRect(window, &window_rect);
18605 ok(ret, "Got unexpected ret %#x, error %#x.\n", ret, GetLastError());
18606 /* Both Windows and Wine change the size of the window. On Windows it is exactly the new size but in Wine
18607 * it may get adjusted depending on window manager. */
18608 ok(window_rect.right != monitor_rect->right && window_rect.bottom != monitor_rect->bottom,
18609 "Expected window rect %s, got %s.\n",
18610 wine_dbgstr_rect(monitor_rect), wine_dbgstr_rect(&window_rect));
18612 ret = MoveWindow(window, new_rect.left, new_rect.top, new_rect.right - new_rect.left,
18613 new_rect.bottom - new_rect.top, TRUE);
18614 ok(ret, "Got unexpected ret %#x, error %#x.\n", ret, GetLastError());
18615 ret = GetWindowRect(window, &window_rect);
18616 ok(ret, "Got unexpected ret %#x, error %#x.\n", ret, GetLastError());
18617 ok(EqualRect(&window_rect, &new_rect),
18618 "Expected window rect %s, got %s.\n",
18619 wine_dbgstr_rect(monitor_rect), wine_dbgstr_rect(&window_rect));
18620 flush_events();
18621 ret = GetWindowRect(window, &window_rect);
18622 ok(ret, "Got unexpected ret %#x, error %#x.\n", ret, GetLastError());
18623 ok(window_rect.right != monitor_rect->right && window_rect.bottom != monitor_rect->bottom,
18624 "Expected window rect %s, got %s.\n",
18625 wine_dbgstr_rect(monitor_rect), wine_dbgstr_rect(&window_rect));
18627 /* Window activation should restore the window to fit the whole primary monitor */
18628 ret = SetWindowPos(window, 0, monitor_rect->left, monitor_rect->top, 0, 0,
18629 SWP_NOZORDER | SWP_NOSIZE);
18630 ok(ret, "SetWindowPos failed, error %#x.\n", GetLastError());
18631 ret = SetForegroundWindow(GetDesktopWindow());
18632 ok(ret, "Failed to set foreground window.\n");
18633 flush_events();
18634 ret = ShowWindow(window, SW_RESTORE);
18635 ok(ret, "Failed to restore window, error %#x.\n", GetLastError());
18636 flush_events();
18637 ret = SetForegroundWindow(window);
18638 ok(ret, "SetForegroundWindow failed, error %#x.\n", GetLastError());
18639 flush_events();
18640 ret = GetWindowRect(window, &window_rect);
18641 ok(ret, "GetWindowRect failed, error %#x.\n", GetLastError());
18642 ok(EqualRect(&window_rect, &primary_rect), "Expect window rect %s, got %s.\n",
18643 wine_dbgstr_rect(&primary_rect), wine_dbgstr_rect(&window_rect));
18645 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
18646 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
18647 ret = GetWindowRect(window, &window_rect);
18648 ok(ret, "GetWindowRect failed, error %#x.\n", GetLastError());
18649 ok(EqualRect(&window_rect, &primary_rect), "Expect window rect %s, got %s.\n",
18650 wine_dbgstr_rect(&primary_rect), wine_dbgstr_rect(&window_rect));
18652 DestroyWindow(window);
18653 IDirectDraw7_Release(ddraw);
18654 return TRUE;
18657 static void test_window_position(void)
18659 EnumDisplayMonitors(NULL, NULL, test_window_position_cb, 0);
18662 static BOOL CALLBACK test_get_display_mode_cb(HMONITOR monitor, HDC hdc, RECT *monitor_rect,
18663 LPARAM lparam)
18665 DDSURFACEDESC2 surface_desc;
18666 IDirectDraw7 *ddraw;
18667 HWND window;
18668 HRESULT hr;
18669 BOOL ret;
18671 ddraw = create_ddraw();
18672 ok(!!ddraw, "Failed to create a ddraw object.\n");
18673 window = create_window();
18674 ok(!!window, "Failed to create a window.\n");
18676 /* Test that DirectDraw doesn't use the device window to determine which monitor to use */
18677 ret = SetWindowPos(window, 0, monitor_rect->left, monitor_rect->top, 0, 0,
18678 SWP_NOZORDER | SWP_NOSIZE);
18679 ok(ret, "SetWindowPos failed, error %#x.\n", GetLastError());
18681 surface_desc.dwSize = sizeof(surface_desc);
18682 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
18683 ok(hr == DD_OK, "GetDisplayMode failed, hr %#x.\n", hr);
18684 ok(surface_desc.dwWidth == GetSystemMetrics(SM_CXSCREEN), "Expect width %d, got %d.\n",
18685 GetSystemMetrics(SM_CXSCREEN), surface_desc.dwWidth);
18686 ok(surface_desc.dwHeight == GetSystemMetrics(SM_CYSCREEN), "Expect height %d, got %d.\n",
18687 GetSystemMetrics(SM_CYSCREEN), surface_desc.dwHeight);
18689 DestroyWindow(window);
18690 IDirectDraw7_Release(ddraw);
18691 return TRUE;
18694 static void test_get_display_mode(void)
18696 static const DWORD flags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_REFRESHRATE | DDSD_PIXELFORMAT | DDSD_PITCH;
18697 struct find_different_mode_param param;
18698 DDSURFACEDESC2 surface_desc;
18699 IDirectDraw7 *ddraw;
18700 DEVMODEW devmode;
18701 HWND window;
18702 HRESULT hr;
18703 BOOL ret;
18705 EnumDisplayMonitors(NULL, NULL, test_get_display_mode_cb, 0);
18707 ddraw = create_ddraw();
18708 ok(!!ddraw, "Failed to create a ddraw object.\n");
18709 window = create_window();
18710 ok(!!window, "Failed to create a window.\n");
18712 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
18713 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
18715 memset(&devmode, 0, sizeof(devmode));
18716 devmode.dmSize = sizeof(devmode);
18717 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
18718 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
18720 surface_desc.dwSize = sizeof(surface_desc);
18721 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
18722 ok(hr == DD_OK, "GetDisplayMode failed, hr %#x.\n", hr);
18723 ok(surface_desc.dwSize == sizeof(surface_desc), "Expected dwSize %u, got %u.\n",
18724 sizeof(surface_desc), surface_desc.dwSize);
18725 ok(surface_desc.dwFlags == flags, "Expected dwFlags %#x, got %#x.\n", flags,
18726 surface_desc.dwFlags);
18727 ok(surface_desc.dwWidth == devmode.dmPelsWidth, "Expected width %u, got %u.\n",
18728 devmode.dmPelsWidth, surface_desc.dwWidth);
18729 ok(surface_desc.dwHeight == devmode.dmPelsHeight, "Expected height %u, got %u.\n",
18730 devmode.dmPelsHeight, surface_desc.dwHeight);
18731 ok(surface_desc.dwRefreshRate == devmode.dmDisplayFrequency, "Expected frequency %u, got %u.\n",
18732 devmode.dmDisplayFrequency, surface_desc.dwRefreshRate);
18733 ok(surface_desc.ddpfPixelFormat.dwSize == sizeof(surface_desc.ddpfPixelFormat),
18734 "Expected ddpfPixelFormat.dwSize %u, got %u.\n", sizeof(surface_desc.ddpfPixelFormat),
18735 surface_desc.ddpfPixelFormat.dwSize);
18736 ok(surface_desc.ddpfPixelFormat.dwRGBBitCount == devmode.dmBitsPerPel,
18737 "Expected ddpfPixelFormat.dwRGBBitCount %u, got %u.\n", devmode.dmBitsPerPel,
18738 surface_desc.ddpfPixelFormat.dwRGBBitCount);
18739 ok(surface_desc.lPitch == devmode.dmPelsWidth * devmode.dmBitsPerPel / 8,
18740 "Expected pitch %u, got %u.\n", devmode.dmPelsWidth * devmode.dmBitsPerPel / 8,
18741 surface_desc.lPitch);
18743 memset(&param, 0, sizeof(param));
18744 param.old_frequency = surface_desc.dwRefreshRate;
18745 hr = IDirectDraw7_EnumDisplayModes(ddraw, DDEDM_REFRESHRATES, NULL, &param,
18746 find_different_mode_callback);
18747 ok(hr == DD_OK, "EnumDisplayModes failed, hr %#x.\n", hr);
18748 if (!param.new_frequency)
18750 skip("Failed to find a display mode with a different frequency.\n");
18751 goto done;
18754 hr = IDirectDraw7_SetDisplayMode(ddraw, param.new_width, param.new_height, param.new_bpp,
18755 param.new_frequency, 0);
18756 ok(hr == DD_OK, "SetDisplayMode failed, hr %#x.\n", hr);
18757 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
18758 ok(hr == DD_OK, "GetDisplayMode failed, hr %#x.\n", hr);
18759 ok(surface_desc.dwWidth == param.new_width, "Expected width %u, got %u.\n", param.new_width,
18760 surface_desc.dwWidth);
18761 ok(surface_desc.dwHeight == param.new_height, "Expected height %u, got %u.\n", param.new_height,
18762 surface_desc.dwHeight);
18763 ok(surface_desc.dwRefreshRate == param.new_frequency, "Expected frequency %u, got %u.\n",
18764 param.new_frequency, surface_desc.dwRefreshRate);
18765 ok(surface_desc.ddpfPixelFormat.dwRGBBitCount == param.new_bpp,
18766 "Expected ddpfPixelFormat.dwRGBBitCount %u, got %u.\n", devmode.dmBitsPerPel,
18767 surface_desc.ddpfPixelFormat.dwRGBBitCount);
18769 done:
18770 DestroyWindow(window);
18771 IDirectDraw7_Release(ddraw);
18774 static void test_texture_wrong_caps(const GUID *device_guid)
18776 static struct
18778 struct vec3 position;
18779 struct vec2 texcoord;
18781 quad[] =
18783 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
18784 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
18785 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
18786 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
18788 static DDPIXELFORMAT fmt =
18790 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
18791 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
18793 IDirectDrawSurface7 *surface, *rt;
18794 IDirect3DDevice7 *device;
18795 IDirectDraw7 *ddraw;
18796 DDSURFACEDESC2 ddsd;
18797 IDirect3D7 *d3d;
18798 D3DCOLOR color;
18799 ULONG refcount;
18800 HWND window;
18801 HRESULT hr;
18803 window = create_window();
18804 if (!(device = create_device_ex(window, DDSCL_NORMAL, device_guid)))
18806 skip("Failed to create a 3D device, skipping test.\n");
18807 DestroyWindow(window);
18808 return;
18810 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
18811 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
18812 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
18813 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
18814 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
18815 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
18817 memset(&ddsd, 0, sizeof(ddsd));
18818 ddsd.dwSize = sizeof(ddsd);
18819 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
18820 ddsd.dwHeight = 16;
18821 ddsd.dwWidth = 16;
18822 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
18823 U4(ddsd).ddpfPixelFormat = fmt;
18824 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
18825 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
18827 fill_surface(surface, 0xff00ff00);
18829 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
18830 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
18832 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
18833 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
18834 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
18835 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
18836 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
18837 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
18838 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
18839 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
18841 hr = IDirect3DDevice7_SetTexture(device, 0, surface);
18842 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
18844 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0);
18845 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
18846 if (is_software_device_type(device_guid))
18847 fill_surface(rt, 0x000000ff);
18849 hr = IDirect3DDevice7_BeginScene(device);
18850 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
18851 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
18852 D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
18853 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
18854 hr = IDirect3DDevice7_EndScene(device);
18855 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
18857 color = get_surface_color(rt, 320, 240);
18858 ok(color == 0, "Got unexpected color 0x%08x.\n", color);
18860 IDirectDrawSurface7_Release(surface);
18861 IDirectDrawSurface7_Release(rt);
18862 IDirectDraw7_Release(ddraw);
18863 IDirect3D7_Release(d3d);
18864 refcount = IDirect3DDevice3_Release(device);
18865 ok(!refcount, "Device has %u references left.\n", refcount);
18866 DestroyWindow(window);
18869 static void test_filling_convention(void)
18871 static const DWORD colour_bottom = 0x00ffff00;
18872 static const DWORD colour_clear = 0x000000ff;
18873 static const DWORD colour_right = 0x00000000;
18874 static const DWORD colour_left = 0x00ff0000;
18875 static const DWORD colour_top = 0x0000ff00;
18876 IDirectDrawSurface7 *rt, *backbuffer, *cur;
18877 IDirect3DDevice7 *device;
18878 unsigned int i, j, x, y;
18879 DWORD colour, expected;
18880 IDirectDraw7 *ddraw;
18881 DDSURFACEDESC2 desc;
18882 IDirect3D7 *d3d;
18883 ULONG refcount;
18884 HWND window;
18885 HRESULT hr;
18886 BOOL todo;
18888 static const unsigned int vp_size = 8;
18889 D3DVIEWPORT7 vp = { 0, 0, vp_size, vp_size, 0.0, 1.0 };
18891 /* This test data follows the examples in MSDN's
18892 * "Rasterization Rules (Direct3D 9)" article.
18894 * See the d3d9 test for a comment about the eps value. */
18895 static const float eps = 1.0f / 64.0f;
18896 struct
18898 struct vec3 position;
18899 DWORD diffuse;
18901 center_tris[] =
18903 /* left */
18904 {{-2.5f / 4.0f, -1.5f / 4.0f, 0.0f}, colour_left},
18905 {{-2.5f / 4.0f, 2.5f / 4.0f, 0.0f}, colour_left},
18906 {{-1.5f / 4.0f, 0.5f / 4.0f, 0.0f}, colour_left},
18908 /* top */
18909 {{-1.5f / 4.0f, 0.5f / 4.0f, 0.0f}, colour_top},
18910 {{-2.5f / 4.0f, 2.5f / 4.0f, 0.0f}, colour_top},
18911 {{-0.5f / 4.0f, 2.5f / 4.0f, 0.0f}, colour_top},
18913 /* right */
18914 {{-0.5f / 4.0f, -1.5f / 4.0f, 0.0f}, colour_right},
18915 {{-1.5f / 4.0f, 0.5f / 4.0f, 0.0f}, colour_right},
18916 {{-0.5f / 4.0f, 2.5f / 4.0f, 0.0f}, colour_right},
18918 /* bottom */
18919 {{-2.5f / 4.0f, -1.5f / 4.0f, 0.0f}, colour_bottom},
18920 {{-1.5f / 4.0f, 0.5f / 4.0f, 0.0f}, colour_bottom},
18921 {{-0.5f / 4.0f, -1.5f / 4.0f, 0.0f}, colour_bottom},
18924 edge_tris[] =
18926 /* left */
18927 {{-2.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_left},
18928 {{-2.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_left},
18929 {{-1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_left},
18931 /* top */
18932 {{-1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_top},
18933 {{-2.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_top},
18934 {{ 0.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_top},
18936 /* right */
18937 {{ 0.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_right},
18938 {{-1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_right},
18939 {{ 0.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_right},
18941 /* bottom */
18942 {{-2.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_bottom},
18943 {{-1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_bottom},
18944 {{ 0.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_bottom},
18946 nudge_right_tris[] =
18948 /* left */
18949 {{eps - 2.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_left},
18950 {{eps - 2.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_left},
18951 {{eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_left},
18953 /* top */
18954 {{eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_top},
18955 {{eps - 2.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_top},
18956 {{eps - 0.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_top},
18958 /* right */
18959 {{eps - 0.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_right},
18960 {{eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_right},
18961 {{eps - 0.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_right},
18963 /* bottom */
18964 {{eps - 2.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_bottom},
18965 {{eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_bottom},
18966 {{eps - 0.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_bottom},
18968 nudge_left_tris[] =
18970 {{-eps - 2.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_left},
18971 {{-eps - 2.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_left},
18972 {{-eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_left},
18974 /* top */
18975 {{-eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_top},
18976 {{-eps - 2.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_top},
18977 {{-eps - 0.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_top},
18979 /* right */
18980 {{-eps - 0.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_right},
18981 {{-eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_right},
18982 {{-eps - 0.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_right},
18984 /* bottom */
18985 {{-eps - 2.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_bottom},
18986 {{-eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_bottom},
18987 {{-eps - 0.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_bottom},
18989 nudge_top_tris[] =
18991 /* left */
18992 {{-2.0f / 4.0f, eps - 1.0f / 4.0f, 0.0f}, colour_left},
18993 {{-2.0f / 4.0f, eps + 3.0f / 4.0f, 0.0f}, colour_left},
18994 {{-1.0f / 4.0f, eps + 1.0f / 4.0f, 0.0f}, colour_left},
18996 /* top */
18997 {{-1.0f / 4.0f, eps + 1.0f / 4.0f, 0.0f}, colour_top},
18998 {{-2.0f / 4.0f, eps + 3.0f / 4.0f, 0.0f}, colour_top},
18999 {{ 0.0f / 4.0f, eps + 3.0f / 4.0f, 0.0f}, colour_top},
19001 /* right */
19002 {{ 0.0f / 4.0f, eps - 1.0f / 4.0f, 0.0f}, colour_right},
19003 {{-1.0f / 4.0f, eps + 1.0f / 4.0f, 0.0f}, colour_right},
19004 {{ 0.0f / 4.0f, eps + 3.0f / 4.0f, 0.0f}, colour_right},
19006 /* bottom */
19007 {{-2.0f / 4.0f, eps - 1.0f / 4.0f, 0.0f}, colour_bottom},
19008 {{-1.0f / 4.0f, eps + 1.0f / 4.0f, 0.0f}, colour_bottom},
19009 {{ 0.0f / 4.0f, eps - 1.0f / 4.0f, 0.0f}, colour_bottom},
19011 nudge_bottom_tris[] =
19013 /* left */
19014 {{-2.0f / 4.0f, -eps - 1.0f / 4.0f, 0.0f}, colour_left},
19015 {{-2.0f / 4.0f, -eps + 3.0f / 4.0f, 0.0f}, colour_left},
19016 {{-1.0f / 4.0f, -eps + 1.0f / 4.0f, 0.0f}, colour_left},
19018 /* top */
19019 {{-1.0f / 4.0f, -eps + 1.0f / 4.0f, 0.0f}, colour_top},
19020 {{-2.0f / 4.0f, -eps + 3.0f / 4.0f, 0.0f}, colour_top},
19021 {{ 0.0f / 4.0f, -eps + 3.0f / 4.0f, 0.0f}, colour_top},
19023 /* right */
19024 {{ 0.0f / 4.0f, -eps - 1.0f / 4.0f, 0.0f}, colour_right},
19025 {{-1.0f / 4.0f, -eps + 1.0f / 4.0f, 0.0f}, colour_right},
19026 {{ 0.0f / 4.0f, -eps + 3.0f / 4.0f, 0.0f}, colour_right},
19028 /* bottom */
19029 {{-2.0f / 4.0f, -eps - 1.0f / 4.0f, 0.0f}, colour_bottom},
19030 {{-1.0f / 4.0f, -eps + 1.0f / 4.0f, 0.0f}, colour_bottom},
19031 {{ 0.0f / 4.0f, -eps - 1.0f / 4.0f, 0.0f}, colour_bottom},
19034 struct
19036 struct vec4 position;
19037 DWORD diffuse;
19039 center_tris_t[] =
19041 /* left */
19042 {{ 1.5f, 1.5f, 0.0f, 1.0f}, colour_left},
19043 {{ 2.5f, 3.5f, 0.0f, 1.0f}, colour_left},
19044 {{ 1.5f, 5.5f, 0.0f, 1.0f}, colour_left},
19046 /* top */
19047 {{ 1.5f, 1.5f, 0.0f, 1.0f}, colour_top},
19048 {{ 3.5f, 1.5f, 0.0f, 1.0f}, colour_top},
19049 {{ 2.5f, 3.5f, 0.0f, 1.0f}, colour_top},
19051 /* right */
19052 {{ 3.5f, 1.5f, 0.0f, 1.0f}, colour_right},
19053 {{ 3.5f, 5.5f, 0.0f, 1.0f}, colour_right},
19054 {{ 2.5f, 3.5f, 0.0f, 1.0f}, colour_right},
19056 /* bottom */
19057 {{ 2.5f, 3.5f, 0.0f, 1.0f}, colour_bottom},
19058 {{ 3.5f, 5.5f, 0.0f, 1.0f}, colour_bottom},
19059 {{ 1.5f, 5.5f, 0.0f, 1.0f}, colour_bottom},
19061 edge_tris_t[] =
19063 /* left */
19064 {{ 2.0f, 1.0f, 0.0f, 1.0f}, colour_left},
19065 {{ 3.0f, 3.0f, 0.0f, 1.0f}, colour_left},
19066 {{ 2.0f, 5.0f, 0.0f, 1.0f}, colour_left},
19068 /* top */
19069 {{ 2.0f, 1.0f, 0.0f, 1.0f}, colour_top},
19070 {{ 4.0f, 1.0f, 0.0f, 1.0f}, colour_top},
19071 {{ 3.0f, 3.0f, 0.0f, 1.0f}, colour_top},
19073 /* right */
19074 {{ 4.0f, 1.0f, 0.0f, 1.0f}, colour_right},
19075 {{ 4.0f, 5.0f, 0.0f, 1.0f}, colour_right},
19076 {{ 3.0f, 3.0f, 0.0f, 1.0f}, colour_right},
19078 /* bottom */
19079 {{ 3.0f, 3.0f, 0.0f, 1.0f}, colour_bottom},
19080 {{ 4.0f, 5.0f, 0.0f, 1.0f}, colour_bottom},
19081 {{ 2.0f, 5.0f, 0.0f, 1.0f}, colour_bottom},
19084 const struct
19086 void *geometry;
19087 DWORD fvf;
19088 const char *expected[8];
19090 tests[] =
19093 center_tris,
19094 D3DFVF_XYZ | D3DFVF_DIFFUSE,
19096 " ",
19097 " ",
19098 " TT ",
19099 " LR ",
19100 " LR ",
19101 " BB ",
19102 " ",
19107 edge_tris,
19108 D3DFVF_XYZ | D3DFVF_DIFFUSE,
19110 " ",
19111 " TT ",
19112 " LT ",
19113 " LR ",
19114 " LB ",
19115 " ",
19116 " ",
19121 nudge_right_tris,
19122 D3DFVF_XYZ | D3DFVF_DIFFUSE,
19124 " ",
19125 " TT ",
19126 " TR ",
19127 " LR ",
19128 " BR ",
19129 " ",
19130 " ",
19135 nudge_left_tris,
19136 D3DFVF_XYZ | D3DFVF_DIFFUSE,
19138 " ",
19139 " TT ",
19140 " LT ",
19141 " LR ",
19142 " LB ",
19143 " ",
19144 " ",
19149 nudge_top_tris,
19150 D3DFVF_XYZ | D3DFVF_DIFFUSE,
19152 " ",
19153 " LT ",
19154 " LT ",
19155 " LB ",
19156 " LB ",
19157 " ",
19158 " ",
19163 nudge_bottom_tris,
19164 D3DFVF_XYZ | D3DFVF_DIFFUSE,
19166 " ",
19167 " ",
19168 " LT ",
19169 " Lt ",
19170 " LB ",
19171 " lB ",
19172 " ",
19177 center_tris_t,
19178 D3DFVF_XYZRHW | D3DFVF_DIFFUSE,
19180 " ",
19181 " ",
19182 " TT ",
19183 " LR ",
19184 " LR ",
19185 " BB ",
19186 " ",
19191 edge_tris_t,
19192 D3DFVF_XYZRHW | D3DFVF_DIFFUSE,
19194 " ",
19195 " TT ",
19196 " LT ",
19197 " LR ",
19198 " LB ",
19199 " ",
19200 " ",
19206 window = create_window();
19207 if (!(device = create_device(window, DDSCL_NORMAL)))
19209 skip("Failed to create 3D device.\n");
19210 DestroyWindow(window);
19211 return;
19214 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
19215 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
19216 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
19217 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
19218 hr = IDirect3DDevice7_GetRenderTarget(device, &backbuffer);
19219 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
19221 memset(&desc, 0, sizeof(desc));
19222 desc.dwSize = sizeof(desc);
19223 desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
19224 desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
19225 desc.dwWidth = vp_size;
19226 desc.dwHeight = vp_size;
19227 desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat);
19228 desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
19229 desc.ddpfPixelFormat.dwRGBBitCount = 32;
19230 desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
19231 desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
19232 desc.ddpfPixelFormat.dwBBitMask = 0x000000ff;
19233 hr = IDirectDraw7_CreateSurface(ddraw, &desc, &rt, NULL);
19234 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
19236 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
19237 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
19238 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
19239 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
19241 for (i = 0; i < ARRAY_SIZE(tests); ++i)
19243 for (j = 0; j < 2; ++j)
19245 cur = j ? rt : backbuffer;
19247 hr = IDirect3DDevice7_SetRenderTarget(device, cur, 0);
19248 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
19249 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, colour_clear, 0.0f, 0);
19250 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
19251 hr = IDirect3DDevice7_SetViewport(device, &vp);
19252 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
19254 hr = IDirect3DDevice7_BeginScene(device);
19255 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
19256 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLELIST,
19257 tests[i].fvf, tests[i].geometry, 12, 0);
19258 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
19259 hr = IDirect3DDevice7_EndScene(device);
19260 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
19262 for (y = 0; y < 8; y++)
19264 for (x = 0; x < 8; x++)
19266 todo = FALSE;
19267 switch (tests[i].expected[y][x])
19269 case 'l': todo = TRUE;
19270 case 'L':
19271 expected = colour_left;
19272 break;
19273 case 't': todo = TRUE;
19274 case 'T':
19275 expected = colour_top;
19276 break;
19277 case 'r': todo = TRUE;
19278 case 'R':
19279 expected = colour_right;
19280 break;
19281 case 'b': todo = TRUE;
19282 case 'B':
19283 expected = colour_bottom;
19284 break;
19285 case ' ':
19286 expected = colour_clear;
19287 break;
19288 default:
19289 ok(0, "Unexpected entry in expected test char\n");
19290 expected = 0xdeadbeef;
19292 colour = get_surface_color(cur, x, y);
19293 /* The nudge-to-bottom test fails on cards that give us a bottom-left
19294 * filling convention. The cause isn't the bottom part of the filling
19295 * convention, but because wined3d will nudge geometry to the left to
19296 * keep diagonals (the 'R' in test case 'edge_tris') intact. */
19297 todo_wine_if(todo && !compare_color(colour, expected, 1))
19298 ok(compare_color(colour, expected, 1), "Got unexpected colour %08x, %ux%u, case %u, j %u.\n",
19299 colour, x, y, i, j);
19305 IDirectDrawSurface7_Release(backbuffer);
19306 IDirectDrawSurface7_Release(rt);
19307 IDirectDraw7_Release(ddraw);
19308 IDirect3D7_Release(d3d);
19309 refcount = IDirect3DDevice7_Release(device);
19310 ok(!refcount, "Device has %u references left.\n", refcount);
19311 DestroyWindow(window);
19314 static void run_for_each_device_type(void (*test_func)(const GUID *))
19316 test_func(hw_device_guid);
19317 test_func(&IID_IDirect3DRGBDevice);
19320 START_TEST(ddraw7)
19322 DDDEVICEIDENTIFIER2 identifier;
19323 HMODULE module, dwmapi;
19324 DEVMODEW current_mode;
19325 IDirectDraw7 *ddraw;
19326 IDirect3D7 *d3d;
19327 BOOL hal_ok;
19328 HRESULT hr;
19330 module = GetModuleHandleA("ddraw.dll");
19331 if (!(pDirectDrawCreateEx = (void *)GetProcAddress(module, "DirectDrawCreateEx")))
19333 win_skip("DirectDrawCreateEx not available, skipping tests.\n");
19334 return;
19337 if (!(ddraw = create_ddraw()))
19339 skip("Failed to create a ddraw object, skipping tests.\n");
19340 return;
19343 if (ddraw_get_identifier(ddraw, &identifier))
19345 trace("Driver string: \"%s\"\n", identifier.szDriver);
19346 trace("Description string: \"%s\"\n", identifier.szDescription);
19347 trace("Driver version %d.%d.%d.%d\n",
19348 HIWORD(U(identifier.liDriverVersion).HighPart), LOWORD(U(identifier.liDriverVersion).HighPart),
19349 HIWORD(U(identifier.liDriverVersion).LowPart), LOWORD(U(identifier.liDriverVersion).LowPart));
19352 if (IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d) == DD_OK)
19354 hr = IDirect3D7_EnumDevices(d3d, enum_devtype_cb, &hal_ok);
19355 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
19356 if (hal_ok)
19357 hw_device_guid = &IID_IDirect3DTnLHalDevice;
19358 IDirectDraw7_Release(d3d);
19360 else
19362 trace("D3D interface is not available.\n");
19365 IDirectDraw7_Release(ddraw);
19367 memset(&current_mode, 0, sizeof(current_mode));
19368 current_mode.dmSize = sizeof(current_mode);
19369 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
19370 registry_mode.dmSize = sizeof(registry_mode);
19371 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
19372 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
19373 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
19375 skip("Current mode does not match registry mode, skipping test.\n");
19376 return;
19379 if ((dwmapi = LoadLibraryA("dwmapi.dll")))
19380 pDwmIsCompositionEnabled = (void *)GetProcAddress(dwmapi, "DwmIsCompositionEnabled");
19382 test_process_vertices();
19383 test_coop_level_create_device_window();
19384 test_clipper_blt();
19385 test_coop_level_d3d_state();
19386 test_surface_interface_mismatch();
19387 test_coop_level_threaded();
19388 run_for_each_device_type(test_depth_blit);
19389 test_texture_load_ckey();
19390 run_for_each_device_type(test_zenable);
19391 run_for_each_device_type(test_ck_rgba);
19392 test_ck_default();
19393 test_ck_complex();
19394 test_surface_qi();
19395 test_device_qi();
19396 test_wndproc();
19397 test_window_style();
19398 test_redundant_mode_set();
19399 test_coop_level_mode_set();
19400 test_coop_level_mode_set_multi();
19401 test_initialize();
19402 test_coop_level_surf_create();
19403 test_vb_discard();
19404 test_coop_level_multi_window();
19405 test_draw_strided();
19406 test_lighting();
19407 test_specular_lighting();
19408 test_clear_rect_count();
19409 test_coop_level_versions();
19410 test_fog_special();
19411 test_lighting_interface_versions();
19412 test_coop_level_activateapp();
19413 test_texturemanage();
19414 test_block_formats_creation();
19415 test_unsupported_formats();
19416 run_for_each_device_type(test_rt_caps);
19417 test_primary_caps();
19418 test_surface_lock();
19419 test_surface_discard();
19420 test_flip();
19421 test_set_surface_desc();
19422 test_user_memory_getdc();
19423 test_sysmem_overlay();
19424 test_primary_palette();
19425 test_surface_attachment();
19426 test_private_data();
19427 test_pixel_format();
19428 test_create_surface_pitch();
19429 test_mipmap();
19430 test_palette_complex();
19431 test_p8_blit();
19432 test_material();
19433 test_palette_gdi();
19434 test_palette_alpha();
19435 test_vb_writeonly();
19436 test_lost_device();
19437 test_resource_priority();
19438 test_surface_desc_lock();
19439 test_fog_interpolation();
19440 test_fog_process_vertices();
19441 test_negative_fixedfunction_fog();
19442 test_table_fog_zw();
19443 test_signed_formats();
19444 test_color_fill();
19445 test_texcoordindex();
19446 test_colorkey_precision();
19447 test_range_colorkey();
19448 test_shademode();
19449 test_lockrect_invalid();
19450 test_yv12_overlay();
19451 test_offscreen_overlay();
19452 test_overlay_rect();
19453 test_blt();
19454 test_blt_z_alpha();
19455 test_cross_device_blt();
19456 test_color_clamping();
19457 test_getdc();
19458 test_draw_primitive();
19459 test_edge_antialiasing_blending();
19460 test_display_mode_surface_pixel_format();
19461 test_surface_desc_size();
19462 test_get_surface_from_dc();
19463 test_ck_operation();
19464 test_vb_refcount();
19465 test_compute_sphere_visibility();
19466 test_clip_planes_limits();
19467 test_texture_stages_limits();
19468 test_set_render_state();
19469 test_map_synchronisation();
19470 test_depth_readback();
19471 test_clear();
19472 test_enum_surfaces();
19473 test_viewport();
19474 test_device_load();
19475 test_color_vertex();
19476 test_killfocus();
19477 test_sysmem_draw();
19478 test_gdi_surface();
19479 test_multiply_transform();
19480 test_alphatest();
19481 test_clipper_refcount();
19482 test_begin_end_state_block();
19483 test_caps();
19484 test_d32_support();
19485 test_surface_format_conversion_alpha();
19486 test_compressed_surface_stretch();
19487 test_cursor_clipping();
19488 test_window_position();
19489 test_get_display_mode();
19490 run_for_each_device_type(test_texture_wrong_caps);
19491 test_filling_convention();