ddraw: Allow texture without DDSCAPS_TEXTURE for ddraw4 and earlier on software device.
[wine.git] / dlls / ddraw / tests / ddraw7.c
blob4c42d6f4b64cfe8d42d3373bad19bd484f972930
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 IDirectDraw7 *ddraw;
2568 HWND window;
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 ddraw = create_ddraw();
2576 ok(!!ddraw, "Failed to create a ddraw object.\n");
2578 style = GetWindowLongA(window, GWL_STYLE);
2579 exstyle = GetWindowLongA(window, GWL_EXSTYLE);
2580 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2582 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2583 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2585 tmp = GetWindowLongA(window, GWL_STYLE);
2586 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2587 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2588 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2590 GetWindowRect(window, &r);
2591 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
2592 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
2593 GetClientRect(window, &r);
2594 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2596 ret = SetForegroundWindow(GetDesktopWindow());
2597 ok(ret, "Failed to set foreground window.\n");
2599 tmp = GetWindowLongA(window, GWL_STYLE);
2600 todo_wine ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2601 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2602 todo_wine ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2604 ret = SetForegroundWindow(window);
2605 ok(ret, "Failed to set foreground window.\n");
2606 /* Windows 7 (but not Vista and XP) shows the window when it receives focus. Hide it again,
2607 * the next tests expect this. */
2608 ShowWindow(window, SW_HIDE);
2610 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
2611 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2613 tmp = GetWindowLongA(window, GWL_STYLE);
2614 ok(tmp == style, "Expected window style %#x, got %#x.\n", style, tmp);
2615 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2616 ok(tmp == exstyle, "Expected window extended style %#x, got %#x.\n", exstyle, tmp);
2618 ShowWindow(window, SW_SHOW);
2619 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2620 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2622 tmp = GetWindowLongA(window, GWL_STYLE);
2623 expected_style = style | WS_VISIBLE;
2624 todo_wine ok(tmp == expected_style, "Expected window style %#x, got %#x.\n", expected_style, tmp);
2625 tmp = GetWindowLongA(window, GWL_EXSTYLE);
2626 expected_style = exstyle | WS_EX_TOPMOST;
2627 todo_wine ok(tmp == expected_style, "Expected window extended style %#x, got %#x.\n", expected_style, tmp);
2629 ret = SetForegroundWindow(GetDesktopWindow());
2630 ok(ret, "Failed to set foreground window.\n");
2631 tmp = GetWindowLongA(window, GWL_STYLE);
2632 expected_style = style | WS_VISIBLE | WS_MINIMIZE;
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 ref = IDirectDraw7_Release(ddraw);
2639 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2641 DestroyWindow(window);
2644 static void test_redundant_mode_set(void)
2646 DDSURFACEDESC2 surface_desc = {0};
2647 IDirectDraw7 *ddraw;
2648 RECT q, r, s;
2649 HWND window;
2650 HRESULT hr;
2651 ULONG ref;
2653 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
2654 0, 0, 100, 100, 0, 0, 0, 0);
2655 ddraw = create_ddraw();
2656 ok(!!ddraw, "Failed to create a ddraw object.\n");
2657 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2658 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2660 surface_desc.dwSize = sizeof(surface_desc);
2661 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
2662 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
2664 hr = IDirectDraw7_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2665 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
2666 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2668 GetWindowRect(window, &q);
2669 r = q;
2670 r.right /= 2;
2671 r.bottom /= 2;
2672 SetWindowPos(window, HWND_TOP, r.left, r.top, r.right, r.bottom, 0);
2673 GetWindowRect(window, &s);
2674 ok(EqualRect(&r, &s), "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2676 hr = IDirectDraw7_SetDisplayMode(ddraw, surface_desc.dwWidth, surface_desc.dwHeight,
2677 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, 0, 0);
2678 ok(SUCCEEDED(hr), "SetDisplayMode failed, hr %#x.\n", hr);
2680 GetWindowRect(window, &s);
2681 ok(EqualRect(&r, &s) || broken(EqualRect(&q, &s) /* Windows 10 */),
2682 "Expected %s, got %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&s));
2684 ref = IDirectDraw7_Release(ddraw);
2685 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2687 DestroyWindow(window);
2690 static SIZE screen_size, screen_size2;
2692 static LRESULT CALLBACK mode_set_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2694 if (message == WM_SIZE)
2696 screen_size.cx = GetSystemMetrics(SM_CXSCREEN);
2697 screen_size.cy = GetSystemMetrics(SM_CYSCREEN);
2700 return test_proc(hwnd, message, wparam, lparam);
2703 static LRESULT CALLBACK mode_set_proc2(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2705 if (message == WM_SIZE)
2707 screen_size2.cx = GetSystemMetrics(SM_CXSCREEN);
2708 screen_size2.cy = GetSystemMetrics(SM_CYSCREEN);
2711 return test_proc(hwnd, message, wparam, lparam);
2714 struct test_coop_level_mode_set_enum_param
2716 DWORD ddraw_width, ddraw_height, user32_width, user32_height;
2719 static HRESULT CALLBACK test_coop_level_mode_set_enum_cb(DDSURFACEDESC2 *surface_desc, void *context)
2721 struct test_coop_level_mode_set_enum_param *param = context;
2723 if (U1(U4(*surface_desc).ddpfPixelFormat).dwRGBBitCount != registry_mode.dmBitsPerPel)
2724 return DDENUMRET_OK;
2725 if (surface_desc->dwWidth == registry_mode.dmPelsWidth
2726 && surface_desc->dwHeight == registry_mode.dmPelsHeight)
2727 return DDENUMRET_OK;
2729 if (!param->ddraw_width)
2731 param->ddraw_width = surface_desc->dwWidth;
2732 param->ddraw_height = surface_desc->dwHeight;
2733 return DDENUMRET_OK;
2735 if (surface_desc->dwWidth == param->ddraw_width && surface_desc->dwHeight == param->ddraw_height)
2736 return DDENUMRET_OK;
2738 param->user32_width = surface_desc->dwWidth;
2739 param->user32_height = surface_desc->dwHeight;
2740 return DDENUMRET_CANCEL;
2743 static void test_coop_level_mode_set(void)
2745 DEVMODEW *original_modes = NULL, devmode, devmode2;
2746 unsigned int display_count = 0;
2747 IDirectDrawSurface7 *primary;
2748 RECT registry_rect, ddraw_rect, user32_rect, r;
2749 IDirectDraw7 *ddraw;
2750 DDSURFACEDESC2 ddsd;
2751 WNDCLASSA wc = {0};
2752 HWND window, window2;
2753 HRESULT hr;
2754 ULONG ref;
2755 MSG msg;
2756 struct test_coop_level_mode_set_enum_param param;
2757 BOOL ret;
2758 LONG change_ret;
2760 static const struct message exclusive_messages[] =
2762 {WM_WINDOWPOSCHANGING, FALSE, 0},
2763 {WM_WINDOWPOSCHANGED, FALSE, 0},
2764 {WM_SIZE, FALSE, 0},
2765 {WM_DISPLAYCHANGE, FALSE, 0},
2766 {0, FALSE, 0},
2768 static const struct message exclusive_focus_loss_messages[] =
2770 {WM_ACTIVATE, TRUE, WA_INACTIVE, DD_OK},
2771 {WM_WINDOWPOSCHANGING, FALSE, 0, DD_OK}, /* Window resize due to mode change. */
2772 {WM_WINDOWPOSCHANGED, FALSE, 0, DD_OK},
2773 {WM_SIZE, TRUE, SIZE_RESTORED, DD_OK}, /* Generated by DefWindowProc. */
2774 {WM_DISPLAYCHANGE, FALSE, 0, DD_OK},
2775 {WM_KILLFOCUS, FALSE, 0, DDERR_NOEXCLUSIVEMODE},
2776 {WM_WINDOWPOSCHANGING, FALSE, 0, DDERR_NOEXCLUSIVEMODE}, /* Window minimized. */
2777 /* Like d3d8 and d3d9 ddraw seems to use SW_SHOWMINIMIZED instead of
2778 * SW_MINIMIZED, causing a recursive window activation that does not
2779 * produce the same result in Wine yet. Ignore the difference for now.
2780 * {WM_ACTIVATE, TRUE, 0x200000 | WA_ACTIVE}, */
2781 {WM_WINDOWPOSCHANGED, FALSE, 0, DDERR_NOEXCLUSIVEMODE},
2782 {WM_MOVE, FALSE, 0, DDERR_NOEXCLUSIVEMODE},
2783 {WM_SIZE, TRUE, SIZE_MINIMIZED, DDERR_NOEXCLUSIVEMODE},
2784 {WM_ACTIVATEAPP, TRUE, FALSE, DDERR_NOEXCLUSIVEMODE},
2785 {0, FALSE, 0, 0},
2787 static const struct message exclusive_focus_restore_messages[] =
2789 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* From the ShowWindow(SW_RESTORE). */
2790 {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Generated by ddraw, matches d3d9 behavior. */
2791 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching previous message. */
2792 {WM_SIZE, FALSE, 0}, /* DefWindowProc. */
2793 {WM_DISPLAYCHANGE, FALSE, 0}, /* Ddraw restores mode. */
2794 /* Native redundantly sets the window size here. */
2795 {WM_ACTIVATEAPP, TRUE, TRUE}, /* End of ddraw's hooks. */
2796 {WM_WINDOWPOSCHANGED, FALSE, 0}, /* Matching the one from ShowWindow. */
2797 {WM_MOVE, FALSE, 0}, /* DefWindowProc. */
2798 {WM_SIZE, TRUE, SIZE_RESTORED}, /* DefWindowProc. */
2799 {0, FALSE, 0},
2801 static const struct message sc_restore_messages[] =
2803 {WM_SYSCOMMAND, TRUE, SC_RESTORE},
2804 {WM_WINDOWPOSCHANGING, FALSE, 0},
2805 {WM_WINDOWPOSCHANGED, FALSE, 0},
2806 {WM_SIZE, TRUE, SIZE_RESTORED},
2807 {0, FALSE, 0},
2809 static const struct message sc_minimize_messages[] =
2811 {WM_SYSCOMMAND, TRUE, SC_MINIMIZE},
2812 {WM_WINDOWPOSCHANGING, FALSE, 0},
2813 {WM_WINDOWPOSCHANGED, FALSE, 0},
2814 {WM_SIZE, TRUE, SIZE_MINIMIZED},
2815 {0, FALSE, 0},
2817 static const struct message sc_maximize_messages[] =
2819 {WM_SYSCOMMAND, TRUE, SC_MAXIMIZE},
2820 {WM_WINDOWPOSCHANGING, FALSE, 0},
2821 {WM_WINDOWPOSCHANGED, FALSE, 0},
2822 {WM_SIZE, TRUE, SIZE_MAXIMIZED},
2823 {0, FALSE, 0},
2826 static const struct message normal_messages[] =
2828 {WM_DISPLAYCHANGE, FALSE, 0},
2829 {0, FALSE, 0},
2832 memset(&devmode, 0, sizeof(devmode));
2833 devmode.dmSize = sizeof(devmode);
2834 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2835 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
2836 ok(compare_mode_rect(&devmode, &registry_mode), "Got a different mode.\n");
2837 ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
2838 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
2839 ok(compare_mode_rect(&devmode, &registry_mode), "Got a different mode.\n");
2841 ret = save_display_modes(&original_modes, &display_count);
2842 ok(ret, "Failed to save original display modes.\n");
2844 ddraw = create_ddraw();
2845 ok(!!ddraw, "Failed to create a ddraw object.\n");
2847 memset(&param, 0, sizeof(param));
2848 hr = IDirectDraw7_EnumDisplayModes(ddraw, 0, NULL, &param, test_coop_level_mode_set_enum_cb);
2849 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
2850 ref = IDirectDraw7_Release(ddraw);
2851 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
2853 if (!param.user32_height)
2855 skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
2856 heap_free(original_modes);
2857 return;
2860 SetRect(&registry_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
2861 SetRect(&ddraw_rect, 0, 0, param.ddraw_width, param.ddraw_height);
2862 SetRect(&user32_rect, 0, 0, param.user32_width, param.user32_height);
2864 memset(&devmode, 0, sizeof(devmode));
2865 devmode.dmSize = sizeof(devmode);
2866 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2867 devmode.dmPelsWidth = param.user32_width;
2868 devmode.dmPelsHeight = param.user32_height;
2869 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2870 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2872 ddraw = create_ddraw();
2873 ok(!!ddraw, "Failed to create a ddraw object.\n");
2875 wc.lpfnWndProc = mode_set_proc;
2876 wc.lpszClassName = "ddraw_test_wndproc_wc";
2877 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2878 wc.lpfnWndProc = mode_set_proc2;
2879 wc.lpszClassName = "ddraw_test_wndproc_wc2";
2880 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2882 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test", WS_OVERLAPPEDWINDOW,
2883 0, 0, 100, 100, 0, 0, 0, 0);
2884 window2 = CreateWindowA("ddraw_test_wndproc_wc2", "ddraw_test", WS_OVERLAPPEDWINDOW,
2885 0, 0, 100, 100, 0, 0, 0, 0);
2887 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2888 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
2890 GetWindowRect(window, &r);
2891 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2892 wine_dbgstr_rect(&r));
2894 memset(&ddsd, 0, sizeof(ddsd));
2895 ddsd.dwSize = sizeof(ddsd);
2896 ddsd.dwFlags = DDSD_CAPS;
2897 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2899 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2900 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2901 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2902 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2903 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2904 param.user32_width, ddsd.dwWidth);
2905 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2906 param.user32_height, ddsd.dwHeight);
2908 GetWindowRect(window, &r);
2909 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2910 wine_dbgstr_rect(&r));
2912 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2913 expect_messages = exclusive_messages;
2914 screen_size.cx = 0;
2915 screen_size.cy = 0;
2917 hr = IDirectDrawSurface7_IsLost(primary);
2918 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2919 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
2920 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
2921 hr = IDirectDrawSurface7_IsLost(primary);
2922 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2924 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2925 expect_messages = NULL;
2926 ok(screen_size.cx == param.ddraw_width && screen_size.cy == param.ddraw_height,
2927 "Expected screen size %ux%u, got %ux%u.\n",
2928 param.ddraw_width, param.ddraw_height, screen_size.cx, screen_size.cy);
2930 GetWindowRect(window, &r);
2931 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2932 wine_dbgstr_rect(&r));
2934 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2935 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2936 ok(ddsd.dwWidth == param.user32_width, "Expected surface width %u, got %u.\n",
2937 param.user32_width, ddsd.dwWidth);
2938 ok(ddsd.dwHeight == param.user32_height, "Expected surface height %u, got %u.\n",
2939 param.user32_height, ddsd.dwHeight);
2940 IDirectDrawSurface7_Release(primary);
2942 memset(&ddsd, 0, sizeof(ddsd));
2943 ddsd.dwSize = sizeof(ddsd);
2944 ddsd.dwFlags = DDSD_CAPS;
2945 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2947 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
2948 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
2949 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
2950 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2951 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
2952 param.ddraw_width, ddsd.dwWidth);
2953 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
2954 param.ddraw_height, ddsd.dwHeight);
2956 GetWindowRect(window, &r);
2957 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
2958 wine_dbgstr_rect(&r));
2960 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
2961 expect_messages = exclusive_messages;
2962 screen_size.cx = 0;
2963 screen_size.cy = 0;
2965 hr = IDirectDrawSurface7_IsLost(primary);
2966 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
2967 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2968 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2969 hr = IDirectDrawSurface7_IsLost(primary);
2970 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
2972 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2973 expect_messages = NULL;
2974 ok(screen_size.cx == param.user32_width && screen_size.cy == param.user32_height,
2975 "Expected screen size %ux%u, got %ux%u.\n",
2976 param.user32_width, param.user32_height, screen_size.cx, screen_size.cy);
2978 GetWindowRect(window, &r);
2979 ok(EqualRect(&r, &user32_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&user32_rect),
2980 wine_dbgstr_rect(&r));
2982 expect_messages = exclusive_focus_loss_messages;
2983 focus_test_ddraw = ddraw;
2984 ret = SetForegroundWindow(GetDesktopWindow());
2985 ok(ret, "Failed to set foreground window.\n");
2986 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
2987 focus_test_ddraw = NULL;
2989 memset(&devmode, 0, sizeof(devmode));
2990 devmode.dmSize = sizeof(devmode);
2991 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2992 ok(ret, "Failed to get display mode.\n");
2993 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2994 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpected screen size %ux%u.\n",
2995 devmode.dmPelsWidth, devmode.dmPelsHeight);
2997 expect_messages = exclusive_focus_restore_messages;
2998 ShowWindow(window, SW_RESTORE);
2999 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3001 GetWindowRect(window, &r);
3002 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3003 wine_dbgstr_rect(&r));
3004 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3005 ok(ret, "Failed to get display mode.\n");
3006 ok(devmode.dmPelsWidth == param.ddraw_width
3007 && devmode.dmPelsHeight == param.ddraw_height, "Got unexpected screen size %ux%u.\n",
3008 devmode.dmPelsWidth, devmode.dmPelsHeight);
3010 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3011 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3012 /* Normally the primary should be restored here. Unfortunately this causes the
3013 * GetSurfaceDesc call after the next display mode change to crash on the Windows 8
3014 * testbot. Another Restore call would presumably avoid the crash, but it also moots
3015 * the point of the GetSurfaceDesc call. */
3017 expect_messages = sc_minimize_messages;
3018 SendMessageA(window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
3019 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3020 expect_messages = NULL;
3022 expect_messages = sc_restore_messages;
3023 SendMessageA(window, WM_SYSCOMMAND, SC_RESTORE, 0);
3024 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3025 expect_messages = NULL;
3027 expect_messages = sc_maximize_messages;
3028 SendMessageA(window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
3029 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3030 expect_messages = NULL;
3032 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3033 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3035 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3036 expect_messages = exclusive_messages;
3037 screen_size.cx = 0;
3038 screen_size.cy = 0;
3040 hr = IDirectDrawSurface7_IsLost(primary);
3041 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3042 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
3043 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3044 hr = IDirectDrawSurface7_IsLost(primary);
3045 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3047 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3048 expect_messages = NULL;
3049 ok(screen_size.cx == registry_mode.dmPelsWidth
3050 && screen_size.cy == registry_mode.dmPelsHeight,
3051 "Expected screen size %ux%u, got %ux%u.\n",
3052 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size.cx, screen_size.cy);
3054 GetWindowRect(window, &r);
3055 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3056 wine_dbgstr_rect(&r));
3058 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3059 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3060 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3061 param.ddraw_width, ddsd.dwWidth);
3062 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3063 param.ddraw_height, ddsd.dwHeight);
3064 IDirectDrawSurface7_Release(primary);
3066 /* For Wine. */
3067 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3068 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3070 memset(&ddsd, 0, sizeof(ddsd));
3071 ddsd.dwSize = sizeof(ddsd);
3072 ddsd.dwFlags = DDSD_CAPS;
3073 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3075 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3076 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3077 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3078 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3079 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3080 registry_mode.dmPelsWidth, ddsd.dwWidth);
3081 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3082 registry_mode.dmPelsHeight, ddsd.dwHeight);
3084 GetWindowRect(window, &r);
3085 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3086 wine_dbgstr_rect(&r));
3088 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3089 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3091 GetWindowRect(window, &r);
3092 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3093 wine_dbgstr_rect(&r));
3095 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3096 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3097 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3098 registry_mode.dmPelsWidth, ddsd.dwWidth);
3099 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3100 registry_mode.dmPelsHeight, ddsd.dwHeight);
3101 IDirectDrawSurface7_Release(primary);
3103 memset(&ddsd, 0, sizeof(ddsd));
3104 ddsd.dwSize = sizeof(ddsd);
3105 ddsd.dwFlags = DDSD_CAPS;
3106 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3108 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3109 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3110 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3111 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3112 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3113 registry_mode.dmPelsWidth, ddsd.dwWidth);
3114 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3115 registry_mode.dmPelsHeight, ddsd.dwHeight);
3117 GetWindowRect(window, &r);
3118 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3119 wine_dbgstr_rect(&r));
3121 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3122 expect_messages = normal_messages;
3123 screen_size.cx = 0;
3124 screen_size.cy = 0;
3126 hr = IDirectDrawSurface7_IsLost(primary);
3127 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3128 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3129 devmode.dmPelsWidth = param.user32_width;
3130 devmode.dmPelsHeight = param.user32_height;
3131 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3132 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3133 hr = IDirectDrawSurface7_IsLost(primary);
3134 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3136 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3137 expect_messages = NULL;
3138 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3140 GetWindowRect(window, &r);
3141 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3142 wine_dbgstr_rect(&r));
3144 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3145 expect_messages = normal_messages;
3146 screen_size.cx = 0;
3147 screen_size.cy = 0;
3149 hr = IDirectDrawSurface7_Restore(primary);
3150 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3151 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3152 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3153 hr = IDirectDrawSurface7_Restore(primary);
3154 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3155 hr = IDirectDrawSurface7_IsLost(primary);
3156 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3158 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3159 expect_messages = NULL;
3160 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3162 GetWindowRect(window, &r);
3163 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3164 wine_dbgstr_rect(&r));
3166 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3167 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3168 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3169 registry_mode.dmPelsWidth, ddsd.dwWidth);
3170 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3171 registry_mode.dmPelsHeight, ddsd.dwHeight);
3172 IDirectDrawSurface7_Release(primary);
3174 memset(&ddsd, 0, sizeof(ddsd));
3175 ddsd.dwSize = sizeof(ddsd);
3176 ddsd.dwFlags = DDSD_CAPS;
3177 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3179 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3180 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3181 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3182 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3183 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3184 param.ddraw_width, ddsd.dwWidth);
3185 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3186 param.ddraw_height, ddsd.dwHeight);
3188 GetWindowRect(window, &r);
3189 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3190 wine_dbgstr_rect(&r));
3192 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3193 expect_messages = normal_messages;
3194 screen_size.cx = 0;
3195 screen_size.cy = 0;
3197 hr = IDirectDrawSurface7_IsLost(primary);
3198 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3199 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
3200 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3201 hr = IDirectDrawSurface7_IsLost(primary);
3202 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3204 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3205 expect_messages = NULL;
3206 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3208 GetWindowRect(window, &r);
3209 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3210 wine_dbgstr_rect(&r));
3212 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3213 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3214 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3215 param.ddraw_width, ddsd.dwWidth);
3216 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3217 param.ddraw_height, ddsd.dwHeight);
3218 IDirectDrawSurface7_Release(primary);
3220 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3221 ok(ret, "Failed to get display mode.\n");
3222 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3223 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3224 "Expected resolution %ux%u, got %ux%u.\n",
3225 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3226 devmode.dmPelsWidth, devmode.dmPelsHeight);
3227 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3228 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3230 memset(&ddsd, 0, sizeof(ddsd));
3231 ddsd.dwSize = sizeof(ddsd);
3232 ddsd.dwFlags = DDSD_CAPS;
3233 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3235 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3236 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3237 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3238 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3239 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3240 registry_mode.dmPelsWidth, ddsd.dwWidth);
3241 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3242 registry_mode.dmPelsHeight, ddsd.dwHeight);
3244 GetWindowRect(window, &r);
3245 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3246 wine_dbgstr_rect(&r));
3248 /* DDSCL_NORMAL | DDSCL_FULLSCREEN behaves the same as just DDSCL_NORMAL.
3249 * Resizing the window on mode changes is a property of DDSCL_EXCLUSIVE,
3250 * not DDSCL_FULLSCREEN. */
3251 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3252 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3254 GetWindowRect(window, &r);
3255 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3256 wine_dbgstr_rect(&r));
3258 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3259 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3260 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3261 registry_mode.dmPelsWidth, ddsd.dwWidth);
3262 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3263 registry_mode.dmPelsHeight, ddsd.dwHeight);
3264 IDirectDrawSurface7_Release(primary);
3266 memset(&ddsd, 0, sizeof(ddsd));
3267 ddsd.dwSize = sizeof(ddsd);
3268 ddsd.dwFlags = DDSD_CAPS;
3269 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3271 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3272 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3273 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3274 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3275 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3276 registry_mode.dmPelsWidth, ddsd.dwWidth);
3277 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3278 registry_mode.dmPelsHeight, ddsd.dwHeight);
3280 GetWindowRect(window, &r);
3281 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3282 wine_dbgstr_rect(&r));
3284 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3285 expect_messages = normal_messages;
3286 screen_size.cx = 0;
3287 screen_size.cy = 0;
3289 hr = IDirectDrawSurface7_IsLost(primary);
3290 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3291 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3292 devmode.dmPelsWidth = param.user32_width;
3293 devmode.dmPelsHeight = param.user32_height;
3294 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3295 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3296 hr = IDirectDrawSurface7_IsLost(primary);
3297 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3299 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3300 expect_messages = NULL;
3301 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3303 GetWindowRect(window, &r);
3304 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3305 wine_dbgstr_rect(&r));
3307 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3308 expect_messages = normal_messages;
3309 screen_size.cx = 0;
3310 screen_size.cy = 0;
3312 hr = IDirectDrawSurface7_Restore(primary);
3313 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3314 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3315 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3316 hr = IDirectDrawSurface7_Restore(primary);
3317 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
3318 hr = IDirectDrawSurface7_IsLost(primary);
3319 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3321 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3322 expect_messages = NULL;
3323 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3325 GetWindowRect(window, &r);
3326 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3327 wine_dbgstr_rect(&r));
3329 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3330 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3331 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3332 registry_mode.dmPelsWidth, ddsd.dwWidth);
3333 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3334 registry_mode.dmPelsHeight, ddsd.dwHeight);
3335 IDirectDrawSurface7_Release(primary);
3337 memset(&ddsd, 0, sizeof(ddsd));
3338 ddsd.dwSize = sizeof(ddsd);
3339 ddsd.dwFlags = DDSD_CAPS;
3340 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3342 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3343 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3344 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3345 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3346 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3347 param.ddraw_width, ddsd.dwWidth);
3348 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3349 param.ddraw_height, ddsd.dwHeight);
3351 GetWindowRect(window, &r);
3352 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3353 wine_dbgstr_rect(&r));
3355 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3356 expect_messages = normal_messages;
3357 screen_size.cx = 0;
3358 screen_size.cy = 0;
3360 hr = IDirectDrawSurface7_IsLost(primary);
3361 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
3362 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
3363 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3364 hr = IDirectDrawSurface7_IsLost(primary);
3365 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
3367 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3368 expect_messages = NULL;
3369 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n", screen_size.cx, screen_size.cy);
3371 GetWindowRect(window, &r);
3372 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3373 wine_dbgstr_rect(&r));
3375 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3376 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3377 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3378 param.ddraw_width, ddsd.dwWidth);
3379 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3380 param.ddraw_height, ddsd.dwHeight);
3381 IDirectDrawSurface7_Release(primary);
3383 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3384 ok(ret, "Failed to get display mode.\n");
3385 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3386 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3387 "Expected resolution %ux%u, got %ux%u.\n",
3388 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3389 devmode.dmPelsWidth, devmode.dmPelsHeight);
3390 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3391 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3393 memset(&ddsd, 0, sizeof(ddsd));
3394 ddsd.dwSize = sizeof(ddsd);
3395 ddsd.dwFlags = DDSD_CAPS;
3396 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3398 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3399 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3400 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3401 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3402 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3403 registry_mode.dmPelsWidth, ddsd.dwWidth);
3404 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3405 registry_mode.dmPelsHeight, ddsd.dwHeight);
3406 IDirectDrawSurface7_Release(primary);
3408 GetWindowRect(window, &r);
3409 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3410 wine_dbgstr_rect(&r));
3412 /* Changing the coop level from EXCLUSIVE to NORMAL restores the screen resolution */
3413 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3414 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3415 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3416 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3418 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3419 expect_messages = exclusive_messages;
3420 screen_size.cx = 0;
3421 screen_size.cy = 0;
3423 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3424 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3426 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3427 expect_messages = NULL;
3428 ok(screen_size.cx == registry_mode.dmPelsWidth
3429 && screen_size.cy == registry_mode.dmPelsHeight,
3430 "Expected screen size %ux%u, got %ux%u.\n",
3431 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight,
3432 screen_size.cx, screen_size.cy);
3434 GetWindowRect(window, &r);
3435 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3436 wine_dbgstr_rect(&r));
3438 memset(&ddsd, 0, sizeof(ddsd));
3439 ddsd.dwSize = sizeof(ddsd);
3440 ddsd.dwFlags = DDSD_CAPS;
3441 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3443 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3444 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3445 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3446 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3447 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3448 registry_mode.dmPelsWidth, ddsd.dwWidth);
3449 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3450 registry_mode.dmPelsHeight, ddsd.dwHeight);
3451 IDirectDrawSurface7_Release(primary);
3453 /* The screen restore is a property of DDSCL_EXCLUSIVE */
3454 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
3455 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3456 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3457 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3459 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3460 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3462 memset(&ddsd, 0, sizeof(ddsd));
3463 ddsd.dwSize = sizeof(ddsd);
3464 ddsd.dwFlags = DDSD_CAPS;
3465 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3467 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3468 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3469 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3470 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3471 ok(ddsd.dwWidth == param.ddraw_width, "Expected surface width %u, got %u.\n",
3472 param.ddraw_width, ddsd.dwWidth);
3473 ok(ddsd.dwHeight == param.ddraw_height, "Expected surface height %u, got %u.\n",
3474 param.ddraw_height, ddsd.dwHeight);
3475 IDirectDrawSurface7_Release(primary);
3477 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
3478 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
3480 /* If the window is changed at the same time, messages are sent to the new window. */
3481 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3482 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3483 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3484 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3486 PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
3487 expect_messages = exclusive_messages;
3488 screen_size.cx = 0;
3489 screen_size.cy = 0;
3490 screen_size2.cx = 0;
3491 screen_size2.cy = 0;
3493 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
3494 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3496 ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message);
3497 expect_messages = NULL;
3498 ok(!screen_size.cx && !screen_size.cy, "Got unexpected screen size %ux%u.\n",
3499 screen_size.cx, screen_size.cy);
3500 ok(screen_size2.cx == registry_mode.dmPelsWidth && screen_size2.cy == registry_mode.dmPelsHeight,
3501 "Expected screen size 2 %ux%u, got %ux%u.\n",
3502 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, screen_size2.cx, screen_size2.cy);
3504 GetWindowRect(window, &r);
3505 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3506 wine_dbgstr_rect(&r));
3507 GetWindowRect(window2, &r);
3508 ok(EqualRect(&r, &registry_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&registry_rect),
3509 wine_dbgstr_rect(&r));
3511 memset(&ddsd, 0, sizeof(ddsd));
3512 ddsd.dwSize = sizeof(ddsd);
3513 ddsd.dwFlags = DDSD_CAPS;
3514 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3516 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
3517 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
3518 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &ddsd);
3519 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3520 ok(ddsd.dwWidth == registry_mode.dmPelsWidth, "Expected surface width %u, got %u.\n",
3521 registry_mode.dmPelsWidth, ddsd.dwWidth);
3522 ok(ddsd.dwHeight == registry_mode.dmPelsHeight, "Expected surface height %u, got %u.\n",
3523 registry_mode.dmPelsHeight, ddsd.dwHeight);
3524 IDirectDrawSurface7_Release(primary);
3526 ref = IDirectDraw7_Release(ddraw);
3527 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3529 GetWindowRect(window, &r);
3530 ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
3531 wine_dbgstr_rect(&r));
3533 ret = restore_display_modes(original_modes, display_count);
3534 ok(ret, "Failed to restore display modes.\n");
3536 /* Test that no mode restorations if no mode changes happened */
3537 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3538 devmode.dmPelsWidth = param.user32_width;
3539 devmode.dmPelsHeight = param.user32_height;
3540 change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
3541 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
3543 ddraw = create_ddraw();
3544 ok(!!ddraw, "Failed to create a ddraw object.\n");
3545 ref = IDirectDraw7_Release(ddraw);
3546 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3548 memset(&devmode2, 0, sizeof(devmode2));
3549 devmode2.dmSize = sizeof(devmode2);
3550 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
3551 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3552 ok(compare_mode_rect(&devmode2, &registry_mode), "Got a different mode.\n");
3553 ret = restore_display_modes(original_modes, display_count);
3554 ok(ret, "Failed to restore display modes.\n");
3556 /* Test that no mode restorations if no mode changes happened with fullscreen ddraw objects */
3557 change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
3558 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
3560 ddraw = create_ddraw();
3561 ok(!!ddraw, "Failed to create a ddraw object.\n");
3562 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3563 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
3564 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
3565 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
3566 ref = IDirectDraw7_Release(ddraw);
3567 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3569 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
3570 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3571 ok(compare_mode_rect(&devmode2, &registry_mode), "Got a different mode.\n");
3572 ret = restore_display_modes(original_modes, display_count);
3573 ok(ret, "Failed to restore display modes.\n");
3575 /* Test that mode restorations use display settings in the registry after ddraw object releases
3576 * if SetDisplayMode() was called */
3577 ddraw = create_ddraw();
3578 ok(!!ddraw, "Failed to create a ddraw object.\n");
3579 hr = set_display_mode(ddraw, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
3580 ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
3582 change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
3583 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
3585 ref = IDirectDraw7_Release(ddraw);
3586 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3588 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
3589 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3590 ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
3591 ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
3592 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3593 ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
3594 ret = restore_display_modes(original_modes, display_count);
3595 ok(ret, "Failed to restore display modes.\n");
3597 /* Test that mode restorations use display settings in the registry after RestoreDisplayMode() */
3598 ddraw = create_ddraw();
3599 ok(!!ddraw, "Failed to create a ddraw object.\n");
3600 hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
3601 ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
3603 change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
3604 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
3606 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
3607 ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
3609 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
3610 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3611 ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
3612 ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
3613 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3614 ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
3616 ref = IDirectDraw7_Release(ddraw);
3617 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3619 expect_messages = NULL;
3620 DestroyWindow(window);
3621 DestroyWindow(window2);
3622 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
3623 UnregisterClassA("ddraw_test_wndproc_wc2", GetModuleHandleA(NULL));
3624 ret = restore_display_modes(original_modes, display_count);
3625 ok(ret, "Failed to restore display modes.\n");
3626 heap_free(original_modes);
3629 static void test_coop_level_mode_set_multi(void)
3631 DEVMODEW old_devmode, devmode, devmode2, devmode3, *original_modes = NULL;
3632 unsigned int mode_idx = 0, display_idx, display_count = 0;
3633 WCHAR second_monitor_name[CCHDEVICENAME];
3634 IDirectDraw7 *ddraw1, *ddraw2;
3635 LONG change_ret;
3636 UINT w, h;
3637 HWND window;
3638 HRESULT hr;
3639 ULONG ref;
3640 BOOL ret;
3642 memset(&devmode, 0, sizeof(devmode));
3643 devmode.dmSize = sizeof(devmode);
3644 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3645 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3646 ok(compare_mode_rect(&devmode, &registry_mode), "Got a different mode.\n");
3647 ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
3648 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3649 ok(compare_mode_rect(&devmode, &registry_mode), "Got a different mode.\n");
3651 ret = save_display_modes(&original_modes, &display_count);
3652 ok(ret, "Failed to save original display modes.\n");
3654 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
3655 0, 0, 100, 100, 0, 0, 0, 0);
3656 ddraw1 = create_ddraw();
3657 ok(!!ddraw1, "Failed to create a ddraw object.\n");
3659 /* With just a single ddraw object, the display mode is restored on
3660 * release. */
3661 hr = set_display_mode(ddraw1, 800, 600);
3662 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3663 w = GetSystemMetrics(SM_CXSCREEN);
3664 ok(w == 800, "Got unexpected screen width %u.\n", w);
3665 h = GetSystemMetrics(SM_CYSCREEN);
3666 ok(h == 600, "Got unexpected screen height %u.\n", h);
3668 ref = IDirectDraw7_Release(ddraw1);
3669 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3670 w = GetSystemMetrics(SM_CXSCREEN);
3671 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3672 h = GetSystemMetrics(SM_CYSCREEN);
3673 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3675 /* When there are multiple ddraw objects, the display mode is restored to
3676 * the initial mode, before the first SetDisplayMode() call. */
3677 ddraw1 = create_ddraw();
3678 hr = set_display_mode(ddraw1, 800, 600);
3679 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3680 w = GetSystemMetrics(SM_CXSCREEN);
3681 ok(w == 800, "Got unexpected screen width %u.\n", w);
3682 h = GetSystemMetrics(SM_CYSCREEN);
3683 ok(h == 600, "Got unexpected screen height %u.\n", h);
3685 ddraw2 = create_ddraw();
3686 hr = set_display_mode(ddraw2, 640, 480);
3687 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3688 w = GetSystemMetrics(SM_CXSCREEN);
3689 ok(w == 640, "Got unexpected screen width %u.\n", w);
3690 h = GetSystemMetrics(SM_CYSCREEN);
3691 ok(h == 480, "Got unexpected screen height %u.\n", h);
3693 ref = IDirectDraw7_Release(ddraw2);
3694 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3695 w = GetSystemMetrics(SM_CXSCREEN);
3696 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3697 h = GetSystemMetrics(SM_CYSCREEN);
3698 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3700 ref = IDirectDraw7_Release(ddraw1);
3701 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3702 w = GetSystemMetrics(SM_CXSCREEN);
3703 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3704 h = GetSystemMetrics(SM_CYSCREEN);
3705 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3707 /* Regardless of release ordering. */
3708 ddraw1 = create_ddraw();
3709 hr = set_display_mode(ddraw1, 800, 600);
3710 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3711 w = GetSystemMetrics(SM_CXSCREEN);
3712 ok(w == 800, "Got unexpected screen width %u.\n", w);
3713 h = GetSystemMetrics(SM_CYSCREEN);
3714 ok(h == 600, "Got unexpected screen height %u.\n", h);
3716 ddraw2 = create_ddraw();
3717 hr = set_display_mode(ddraw2, 640, 480);
3718 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3719 w = GetSystemMetrics(SM_CXSCREEN);
3720 ok(w == 640, "Got unexpected screen width %u.\n", w);
3721 h = GetSystemMetrics(SM_CYSCREEN);
3722 ok(h == 480, "Got unexpected screen height %u.\n", h);
3724 ref = IDirectDraw7_Release(ddraw1);
3725 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3726 w = GetSystemMetrics(SM_CXSCREEN);
3727 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3728 h = GetSystemMetrics(SM_CYSCREEN);
3729 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3731 ref = IDirectDraw7_Release(ddraw2);
3732 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3733 w = GetSystemMetrics(SM_CXSCREEN);
3734 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3735 h = GetSystemMetrics(SM_CYSCREEN);
3736 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3738 /* But only for ddraw objects that called SetDisplayMode(). */
3739 ddraw1 = create_ddraw();
3740 ddraw2 = create_ddraw();
3741 hr = set_display_mode(ddraw2, 640, 480);
3742 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3743 w = GetSystemMetrics(SM_CXSCREEN);
3744 ok(w == 640, "Got unexpected screen width %u.\n", w);
3745 h = GetSystemMetrics(SM_CYSCREEN);
3746 ok(h == 480, "Got unexpected screen height %u.\n", h);
3748 ref = IDirectDraw7_Release(ddraw1);
3749 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3750 w = GetSystemMetrics(SM_CXSCREEN);
3751 ok(w == 640, "Got unexpected screen width %u.\n", w);
3752 h = GetSystemMetrics(SM_CYSCREEN);
3753 ok(h == 480, "Got unexpected screen height %u.\n", h);
3755 ref = IDirectDraw7_Release(ddraw2);
3756 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3757 w = GetSystemMetrics(SM_CXSCREEN);
3758 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3759 h = GetSystemMetrics(SM_CYSCREEN);
3760 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3762 /* If there's a ddraw object that's currently in exclusive mode, it blocks
3763 * restoring the display mode. */
3764 ddraw1 = create_ddraw();
3765 hr = set_display_mode(ddraw1, 800, 600);
3766 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3767 w = GetSystemMetrics(SM_CXSCREEN);
3768 ok(w == 800, "Got unexpected screen width %u.\n", w);
3769 h = GetSystemMetrics(SM_CYSCREEN);
3770 ok(h == 600, "Got unexpected screen height %u.\n", h);
3772 ddraw2 = create_ddraw();
3773 hr = set_display_mode(ddraw2, 640, 480);
3774 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3775 w = GetSystemMetrics(SM_CXSCREEN);
3776 ok(w == 640, "Got unexpected screen width %u.\n", w);
3777 h = GetSystemMetrics(SM_CYSCREEN);
3778 ok(h == 480, "Got unexpected screen height %u.\n", h);
3780 hr = IDirectDraw7_SetCooperativeLevel(ddraw2, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3781 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3783 ref = IDirectDraw7_Release(ddraw1);
3784 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3785 w = GetSystemMetrics(SM_CXSCREEN);
3786 ok(w == 640, "Got unexpected screen width %u.\n", w);
3787 h = GetSystemMetrics(SM_CYSCREEN);
3788 ok(h == 480, "Got unexpected screen height %u.\n", h);
3790 ref = IDirectDraw7_Release(ddraw2);
3791 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3792 w = GetSystemMetrics(SM_CXSCREEN);
3793 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3794 h = GetSystemMetrics(SM_CYSCREEN);
3795 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3797 /* Exclusive mode blocks mode setting on other ddraw objects in general. */
3798 ddraw1 = create_ddraw();
3799 hr = set_display_mode(ddraw1, 800, 600);
3800 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
3801 w = GetSystemMetrics(SM_CXSCREEN);
3802 ok(w == 800, "Got unexpected screen width %u.\n", w);
3803 h = GetSystemMetrics(SM_CYSCREEN);
3804 ok(h == 600, "Got unexpected screen height %u.\n", h);
3806 hr = IDirectDraw7_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3807 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
3809 ddraw2 = create_ddraw();
3810 hr = set_display_mode(ddraw2, 640, 480);
3811 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
3813 ref = IDirectDraw7_Release(ddraw1);
3814 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3815 w = GetSystemMetrics(SM_CXSCREEN);
3816 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3817 h = GetSystemMetrics(SM_CYSCREEN);
3818 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3820 ref = IDirectDraw7_Release(ddraw2);
3821 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3822 w = GetSystemMetrics(SM_CXSCREEN);
3823 ok(w == registry_mode.dmPelsWidth, "Got unexpected screen width %u.\n", w);
3824 h = GetSystemMetrics(SM_CYSCREEN);
3825 ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
3827 if (display_count < 2)
3829 skip("Following tests require two monitors.\n");
3830 goto done;
3833 ret = restore_display_modes(original_modes, display_count);
3834 ok(ret, "Failed to restore display modes.\n");
3836 second_monitor_name[0] = '\0';
3837 for (display_idx = 0; display_idx < display_count; ++display_idx)
3839 if (original_modes[display_idx].dmPosition.x || original_modes[display_idx].dmPosition.y)
3841 lstrcpyW(second_monitor_name, original_modes[display_idx].dmDeviceName);
3842 break;
3845 ok(lstrlenW(second_monitor_name), "Got an empty second monitor name.\n");
3846 memset(&old_devmode, 0, sizeof(old_devmode));
3847 old_devmode.dmSize = sizeof(old_devmode);
3848 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &old_devmode);
3849 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3851 devmode = old_devmode;
3852 while (EnumDisplaySettingsW(second_monitor_name, mode_idx++, &devmode))
3854 if (devmode.dmPelsWidth != old_devmode.dmPelsWidth
3855 || devmode.dmPelsHeight != old_devmode.dmPelsHeight)
3856 break;
3858 ok(devmode.dmPelsWidth != old_devmode.dmPelsWidth
3859 || devmode.dmPelsHeight != old_devmode.dmPelsHeight,
3860 "Failed to find a different mode for the second monitor.\n");
3862 /* Test that no mode restorations for non-primary monitors if SetDisplayMode() was not called */
3863 ddraw1 = create_ddraw();
3864 ok(!!ddraw1, "Failed to create a ddraw object.\n");
3865 hr = IDirectDraw7_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3866 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
3868 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
3869 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
3871 memset(&devmode2, 0, sizeof(devmode2));
3872 devmode2.dmSize = sizeof(devmode2);
3873 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
3874 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3875 if (compare_mode_rect(&devmode2, &old_devmode))
3877 skip("Failed to change display settings of the second monitor.\n");
3878 ref = IDirectDraw7_Release(ddraw1);
3879 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3880 goto done;
3883 hr = IDirectDraw7_SetCooperativeLevel(ddraw1, window, DDSCL_NORMAL);
3884 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
3885 ref = IDirectDraw7_Release(ddraw1);
3886 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3888 memset(&devmode3, 0, sizeof(devmode3));
3889 devmode3.dmSize = sizeof(devmode3);
3890 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode3);
3891 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3892 ok(compare_mode_rect(&devmode3, &devmode2), "Got a different mode.\n");
3893 ret = restore_display_modes(original_modes, display_count);
3894 ok(ret, "Failed to restore display modes.\n");
3896 /* Test that mode restorations happen for non-primary monitors on ddraw releases if
3897 * SetDisplayMode() was called */
3898 ddraw1 = create_ddraw();
3899 ok(!!ddraw1, "Failed to create a ddraw object.\n");
3900 hr = set_display_mode(ddraw1, 800, 600);
3901 ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
3903 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
3904 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
3906 ref = IDirectDraw7_Release(ddraw1);
3907 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3909 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
3910 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3911 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
3912 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
3913 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3914 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
3915 ret = restore_display_modes(original_modes, display_count);
3916 ok(ret, "Failed to restore display modes.\n");
3918 /* Test that mode restorations happen for non-primary monitors as well */
3919 ddraw1 = create_ddraw();
3920 ok(!!ddraw1, "Failed to create a ddraw object.\n");
3921 hr = set_display_mode(ddraw1, 800, 600);
3922 ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
3924 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
3925 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
3927 hr = IDirectDraw7_RestoreDisplayMode(ddraw1);
3928 ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
3930 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
3931 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3932 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
3933 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
3934 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3935 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
3937 ref = IDirectDraw7_Release(ddraw1);
3938 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3939 ret = restore_display_modes(original_modes, display_count);
3940 ok(ret, "Failed to restore display modes.\n");
3942 /* Test that mode restorations for non-primary monitors use display settings in the registry */
3943 ddraw1 = create_ddraw();
3944 ok(!!ddraw1, "Failed to create a ddraw object.\n");
3945 hr = set_display_mode(ddraw1, 800, 600);
3946 ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
3948 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL,
3949 CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
3950 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
3952 ref = IDirectDraw7_Release(ddraw1);
3953 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3955 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
3956 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3957 ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
3958 "Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
3959 devmode2.dmPelsWidth, devmode2.dmPelsHeight);
3960 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
3961 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3962 ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
3963 "Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
3964 devmode2.dmPelsWidth, devmode2.dmPelsHeight);
3965 ret = restore_display_modes(original_modes, display_count);
3966 ok(ret, "Failed to restore display modes.\n");
3968 /* Test mode restorations for non-primary monitors when there are multiple fullscreen ddraw
3969 * objects and one of them restores display mode */
3970 ddraw1 = create_ddraw();
3971 ok(!!ddraw1, "Failed to create a ddraw object.\n");
3972 ddraw2 = create_ddraw();
3973 ok(!!ddraw2, "Failed to create a ddraw object.\n");
3974 hr = set_display_mode(ddraw1, 800, 600);
3975 ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
3976 hr = set_display_mode(ddraw2, 640, 480);
3977 ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
3979 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
3980 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
3982 hr = IDirectDraw7_RestoreDisplayMode(ddraw2);
3983 ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
3985 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
3986 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3987 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
3988 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
3989 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
3990 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
3992 ref = IDirectDraw7_Release(ddraw2);
3993 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3994 ref = IDirectDraw7_Release(ddraw1);
3995 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
3996 ret = restore_display_modes(original_modes, display_count);
3997 ok(ret, "Failed to restore display modes.\n");
3999 /* Test mode restorations for non-primary monitors when there are multiple fullscreen ddraw
4000 * objects and one of them got released */
4001 ddraw1 = create_ddraw();
4002 ok(!!ddraw1, "Failed to create a ddraw object.\n");
4003 ddraw2 = create_ddraw();
4004 ok(!!ddraw2, "Failed to create a ddraw object.\n");
4005 hr = set_display_mode(ddraw1, 800, 600);
4006 ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
4007 hr = set_display_mode(ddraw2, 640, 480);
4008 ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
4010 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
4011 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
4013 ref = IDirectDraw7_Release(ddraw2);
4014 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
4016 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4017 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
4018 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4019 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4020 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
4021 ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4023 ref = IDirectDraw7_Release(ddraw1);
4024 ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
4026 done:
4027 DestroyWindow(window);
4028 ret = restore_display_modes(original_modes, display_count);
4029 ok(ret, "Failed to restore display modes.\n");
4030 heap_free(original_modes);
4033 static void test_initialize(void)
4035 IDirectDraw7 *ddraw;
4036 HRESULT hr;
4038 ddraw = create_ddraw();
4039 ok(!!ddraw, "Failed to create a ddraw object.\n");
4041 hr = IDirectDraw7_Initialize(ddraw, NULL);
4042 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x.\n", hr);
4043 IDirectDraw7_Release(ddraw);
4045 CoInitialize(NULL);
4046 hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectDraw7, (void **)&ddraw);
4047 ok(SUCCEEDED(hr), "Failed to create IDirectDraw7 instance, hr %#x.\n", hr);
4048 hr = IDirectDraw7_Initialize(ddraw, NULL);
4049 ok(hr == DD_OK, "Initialize returned hr %#x, expected DD_OK.\n", hr);
4050 hr = IDirectDraw7_Initialize(ddraw, NULL);
4051 ok(hr == DDERR_ALREADYINITIALIZED, "Initialize returned hr %#x, expected DDERR_ALREADYINITIALIZED.\n", hr);
4052 IDirectDraw7_Release(ddraw);
4053 CoUninitialize();
4056 static void test_coop_level_surf_create(void)
4058 IDirectDrawSurface7 *surface;
4059 IDirectDraw7 *ddraw;
4060 DDSURFACEDESC2 ddsd;
4061 HRESULT hr;
4063 ddraw = create_ddraw();
4064 ok(!!ddraw, "Failed to create a ddraw object.\n");
4066 memset(&ddsd, 0, sizeof(ddsd));
4067 ddsd.dwSize = sizeof(ddsd);
4068 ddsd.dwFlags = DDSD_CAPS;
4069 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4070 surface = (void *)0xdeadbeef;
4071 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
4072 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
4073 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
4075 surface = (void *)0xdeadbeef;
4076 hr = IDirectDraw7_CreateSurface(ddraw, NULL, &surface, NULL);
4077 ok(hr == DDERR_NOCOOPERATIVELEVELSET, "Surface creation returned hr %#x.\n", hr);
4078 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
4080 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
4081 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4083 surface = (void *)0xdeadbeef;
4084 hr = IDirectDraw7_CreateSurface(ddraw, NULL, &surface, NULL);
4085 ok(hr == DDERR_INVALIDPARAMS, "Unexpected hr %#x.\n", hr);
4086 ok(surface == (void *)0xdeadbeef, "Got unexpected surface %p.\n", surface);
4088 IDirectDraw7_Release(ddraw);
4091 static void test_vb_discard(void)
4093 static const struct vec4 quad[] =
4095 { 0.0f, 480.0f, 0.0f, 1.0f},
4096 { 0.0f, 0.0f, 0.0f, 1.0f},
4097 {640.0f, 480.0f, 0.0f, 1.0f},
4098 {640.0f, 0.0f, 0.0f, 1.0f},
4101 IDirect3DDevice7 *device;
4102 IDirect3D7 *d3d;
4103 IDirect3DVertexBuffer7 *buffer;
4104 HWND window;
4105 HRESULT hr;
4106 D3DVERTEXBUFFERDESC desc;
4107 BYTE *data;
4108 static const unsigned int vbsize = 16;
4109 unsigned int i;
4111 window = create_window();
4112 if (!(device = create_device(window, DDSCL_NORMAL)))
4114 skip("Failed to create a 3D device, skipping test.\n");
4115 DestroyWindow(window);
4116 return;
4119 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
4120 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
4122 memset(&desc, 0, sizeof(desc));
4123 desc.dwSize = sizeof(desc);
4124 desc.dwCaps = D3DVBCAPS_WRITEONLY;
4125 desc.dwFVF = D3DFVF_XYZRHW;
4126 desc.dwNumVertices = vbsize;
4127 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &buffer, 0);
4128 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
4130 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
4131 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
4132 memcpy(data, quad, sizeof(quad));
4133 hr = IDirect3DVertexBuffer7_Unlock(buffer);
4134 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
4136 hr = IDirect3DDevice7_BeginScene(device);
4137 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4138 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
4139 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4140 hr = IDirect3DDevice7_EndScene(device);
4141 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4143 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
4144 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
4145 memset(data, 0xaa, sizeof(struct vec4) * vbsize);
4146 hr = IDirect3DVertexBuffer7_Unlock(buffer);
4147 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
4149 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&data, NULL);
4150 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
4151 for (i = 0; i < sizeof(struct vec4) * vbsize; i++)
4153 if (data[i] != 0xaa)
4155 ok(FALSE, "Vertex buffer data byte %u is 0x%02x, expected 0xaa\n", i, data[i]);
4156 break;
4159 hr = IDirect3DVertexBuffer7_Unlock(buffer);
4160 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
4162 IDirect3DVertexBuffer7_Release(buffer);
4163 IDirect3D7_Release(d3d);
4164 IDirect3DDevice7_Release(device);
4165 DestroyWindow(window);
4168 static void test_coop_level_multi_window(void)
4170 HWND window1, window2;
4171 IDirectDraw7 *ddraw;
4172 HRESULT hr;
4174 window1 = create_window();
4175 window2 = create_window();
4176 ddraw = create_ddraw();
4177 ok(!!ddraw, "Failed to create a ddraw object.\n");
4179 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
4180 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4181 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
4182 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
4183 ok(IsWindow(window1), "Window 1 was destroyed.\n");
4184 ok(IsWindow(window2), "Window 2 was destroyed.\n");
4186 IDirectDraw7_Release(ddraw);
4187 DestroyWindow(window2);
4188 DestroyWindow(window1);
4191 static void test_draw_strided(void)
4193 static struct vec3 position[] =
4195 {-1.0, -1.0, 0.0},
4196 {-1.0, 1.0, 0.0},
4197 { 1.0, 1.0, 0.0},
4198 { 1.0, -1.0, 0.0},
4200 static DWORD diffuse[] =
4202 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
4204 static WORD indices[] =
4206 0, 1, 2, 2, 3, 0
4209 IDirectDrawSurface7 *rt;
4210 IDirect3DDevice7 *device;
4211 D3DCOLOR color;
4212 HWND window;
4213 HRESULT hr;
4214 D3DDRAWPRIMITIVESTRIDEDDATA strided;
4216 window = create_window();
4217 if (!(device = create_device(window, DDSCL_NORMAL)))
4219 skip("Failed to create a 3D device, skipping test.\n");
4220 DestroyWindow(window);
4221 return;
4224 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
4225 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
4227 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
4228 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
4229 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 1.0f, 0);
4230 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
4231 hr = IDirect3DDevice7_BeginScene(device);
4232 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4234 memset(&strided, 0x55, sizeof(strided));
4235 strided.position.lpvData = position;
4236 strided.position.dwStride = sizeof(*position);
4237 strided.diffuse.lpvData = diffuse;
4238 strided.diffuse.dwStride = sizeof(*diffuse);
4239 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device, D3DPT_TRIANGLELIST, D3DFVF_XYZ | D3DFVF_DIFFUSE,
4240 &strided, 4, indices, 6, 0);
4241 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4243 hr = IDirect3DDevice7_EndScene(device);
4244 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4246 color = get_surface_color(rt, 320, 240);
4247 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
4249 IDirectDrawSurface7_Release(rt);
4250 IDirect3DDevice7_Release(device);
4251 DestroyWindow(window);
4254 static void test_lighting(void)
4256 static D3DMATRIX mat =
4258 1.0f, 0.0f, 0.0f, 0.0f,
4259 0.0f, 1.0f, 0.0f, 0.0f,
4260 0.0f, 0.0f, 1.0f, 0.0f,
4261 0.0f, 0.0f, 0.0f, 1.0f,
4263 mat_singular =
4265 1.0f, 0.0f, 1.0f, 0.0f,
4266 0.0f, 1.0f, 0.0f, 0.0f,
4267 1.0f, 0.0f, 1.0f, 0.0f,
4268 0.0f, 0.0f, 0.5f, 1.0f,
4270 mat_transf =
4272 0.0f, 0.0f, 1.0f, 0.0f,
4273 0.0f, 1.0f, 0.0f, 0.0f,
4274 -1.0f, 0.0f, 0.0f, 0.0f,
4275 10.f, 10.0f, 10.0f, 1.0f,
4277 mat_nonaffine =
4279 1.0f, 0.0f, 0.0f, 0.0f,
4280 0.0f, 1.0f, 0.0f, 0.0f,
4281 0.0f, 0.0f, 1.0f, -1.0f,
4282 10.f, 10.0f, 10.0f, 0.0f,
4284 static struct vertex
4286 struct vec3 position;
4287 DWORD diffuse;
4289 unlitquad[] =
4291 {{-1.0f, -1.0f, 0.1f}, 0xffff0000},
4292 {{-1.0f, 0.0f, 0.1f}, 0xffff0000},
4293 {{ 0.0f, 0.0f, 0.1f}, 0xffff0000},
4294 {{ 0.0f, -1.0f, 0.1f}, 0xffff0000},
4296 litquad[] =
4298 {{-1.0f, 0.0f, 0.1f}, 0xff00ff00},
4299 {{-1.0f, 1.0f, 0.1f}, 0xff00ff00},
4300 {{ 0.0f, 1.0f, 0.1f}, 0xff00ff00},
4301 {{ 0.0f, 0.0f, 0.1f}, 0xff00ff00},
4303 static struct vertex_normal
4305 struct vec3 position;
4306 struct vec3 normal;
4307 DWORD diffuse;
4309 unlitnquad[] =
4311 {{0.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
4312 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
4313 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
4314 {{1.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
4316 litnquad[] =
4318 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
4319 {{0.0f, 1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
4320 {{1.0f, 1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
4321 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
4323 nquad[] =
4325 {{-1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4326 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4327 {{ 1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4328 {{ 1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4330 rotatedquad[] =
4332 {{-10.0f, -11.0f, 11.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
4333 {{-10.0f, -9.0f, 11.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
4334 {{-10.0f, -9.0f, 9.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
4335 {{-10.0f, -11.0f, 9.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
4337 translatedquad[] =
4339 {{-11.0f, -11.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4340 {{-11.0f, -9.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4341 {{ -9.0f, -9.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4342 {{ -9.0f, -11.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
4344 static WORD indices[] = {0, 1, 2, 2, 3, 0};
4345 static const struct
4347 D3DMATRIX *world_matrix;
4348 void *quad;
4349 DWORD expected, expected_process_vertices;
4350 const char *message;
4351 BOOL process_vertices_todo;
4353 tests[] =
4355 {&mat, nquad, 0x000000ff, 0xff0000ff, "Lit quad with light"},
4356 {&mat_singular, nquad, 0x000000ff, 0xff000000, "Lit quad with singular world matrix", TRUE},
4357 {&mat_transf, rotatedquad, 0x000000ff, 0xff0000ff, "Lit quad with transformation matrix"},
4358 {&mat_nonaffine, translatedquad, 0x00000000, 0xff000000, "Lit quad with non-affine matrix"},
4361 DWORD nfvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL;
4362 IDirect3DVertexBuffer7 *src_vb1, *src_vb2, *dst_vb;
4363 DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
4364 struct vertex_normal *src_data2;
4365 D3DVERTEXBUFFERDESC vb_desc;
4366 struct vertex *src_data1;
4367 IDirect3DDevice7 *device;
4368 IDirectDrawSurface7 *rt;
4369 IDirectDraw7 *ddraw;
4370 IDirect3D7 *d3d;
4371 D3DCOLOR color;
4372 ULONG refcount;
4373 unsigned int i;
4374 BOOL is_warp;
4375 HWND window;
4376 HRESULT hr;
4377 struct
4379 struct vec4 position;
4380 DWORD diffuse;
4381 DWORD specular;
4383 *dst_data;
4385 window = create_window();
4386 if (!(device = create_device(window, DDSCL_NORMAL)))
4388 skip("Failed to create a 3D device, skipping test.\n");
4389 DestroyWindow(window);
4390 return;
4392 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
4393 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4394 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
4395 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4397 is_warp = ddraw_is_warp(ddraw);
4399 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
4400 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4402 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
4403 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4405 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
4406 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4407 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
4408 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4409 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
4410 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4411 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
4412 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4413 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
4414 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4415 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
4416 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4417 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
4418 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4419 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
4420 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4422 hr = IDirect3DDevice7_BeginScene(device);
4423 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4425 memset(&vb_desc, 0, sizeof(vb_desc));
4426 vb_desc.dwSize = sizeof(vb_desc);
4427 vb_desc.dwFVF = fvf;
4428 vb_desc.dwNumVertices = 2;
4429 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &src_vb1, 0);
4430 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4431 vb_desc.dwSize = sizeof(vb_desc);
4432 vb_desc.dwFVF = nfvf;
4433 vb_desc.dwNumVertices = 2;
4434 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &src_vb2, 0);
4435 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4437 memset(&vb_desc, 0, sizeof(vb_desc));
4438 vb_desc.dwSize = sizeof(vb_desc);
4439 vb_desc.dwFVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR;
4440 vb_desc.dwNumVertices = 4;
4441 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &dst_vb, 0);
4442 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4444 hr = IDirect3DVertexBuffer7_Lock(src_vb1, 0, (void **)&src_data1, NULL);
4445 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4446 memcpy(src_data1, unlitquad, sizeof(*src_data1));
4447 memcpy(&src_data1[1], litquad, sizeof(*src_data1));
4448 hr = IDirect3DVertexBuffer7_Unlock(src_vb1);
4449 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4451 hr = IDirect3DVertexBuffer7_Lock(src_vb2, 0, (void **)&src_data2, NULL);
4452 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4453 memcpy(src_data2, unlitnquad, sizeof(*src_data2));
4454 memcpy(&src_data2[1], litnquad, sizeof(*src_data2));
4455 hr = IDirect3DVertexBuffer7_Unlock(src_vb2);
4456 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4458 /* No lights are defined... That means, lit vertices should be entirely black. */
4459 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
4460 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4461 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 0,
4462 1, src_vb1, 0, device, 0);
4463 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4464 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, unlitquad, 4,
4465 indices, 6, 0);
4466 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4468 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
4469 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4470 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 1,
4471 1, src_vb1, 1, device, 0);
4472 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4473 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, litquad, 4,
4474 indices, 6, 0);
4475 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4477 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
4478 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4479 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM, 2,
4480 1, src_vb2, 0, device, 0);
4481 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4482 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, unlitnquad, 4,
4483 indices, 6, 0);
4484 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4486 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
4487 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4488 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 3,
4489 1, src_vb2, 1, device, 0);
4490 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4491 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, litnquad, 4,
4492 indices, 6, 0);
4493 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4495 hr = IDirect3DDevice7_EndScene(device);
4496 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4498 hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL);
4499 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4501 color = get_surface_color(rt, 160, 360);
4502 ok(color == 0x00ff0000, "Unlit quad without normals has color 0x%08x, expected 0x00ff0000.\n", color);
4503 ok(dst_data[0].diffuse == 0xffff0000,
4504 "Unlit quad without normals has color 0x%08x, expected 0xffff0000.\n", dst_data[0].diffuse);
4505 ok(!dst_data[0].specular,
4506 "Unexpected specular color 0x%08x.\n", dst_data[0].specular);
4507 color = get_surface_color(rt, 160, 120);
4508 /* Broken on some of WARP drivers. */
4509 ok(color == 0x00000000 || broken(is_warp && (color == 0x000000ff || color == 0x00ff00ff)),
4510 "Lit quad without normals has color 0x%08x, expected 0x00000000.\n", color);
4511 ok(dst_data[1].diffuse == 0xff000000,
4512 "Lit quad without normals has color 0x%08x, expected 0xff000000.\n", dst_data[1].diffuse);
4513 ok(!dst_data[1].specular,
4514 "Unexpected specular color 0x%08x.\n", dst_data[1].specular);
4515 color = get_surface_color(rt, 480, 360);
4516 ok(color == 0x000000ff, "Unlit quad with normals has color 0x%08x, expected 0x000000ff.\n", color);
4517 ok(dst_data[2].diffuse == 0xff0000ff,
4518 "Unlit quad with normals has color 0x%08x, expected 0xff0000ff.\n", dst_data[2].diffuse);
4519 ok(!dst_data[2].specular,
4520 "Unexpected specular color 0x%08x.\n", dst_data[2].specular);
4521 color = get_surface_color(rt, 480, 120);
4522 ok(color == 0x00000000 || broken(is_warp && (color == 0x000000ff || color == 0x00ff00ff)),
4523 "Lit quad with normals has color 0x%08x, expected 0x00000000.\n", color);
4524 ok(dst_data[3].diffuse == 0xff000000,
4525 "Lit quad with normals has color 0x%08x, expected 0xff000000.\n", dst_data[3].diffuse);
4526 ok(!dst_data[3].specular,
4527 "Unexpected specular color 0x%08x.\n", dst_data[3].specular);
4529 hr = IDirect3DVertexBuffer7_Unlock(dst_vb);
4530 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4532 hr = IDirect3DDevice7_LightEnable(device, 0, TRUE);
4533 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4535 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4537 hr = IDirect3DVertexBuffer7_Lock(src_vb2, 0, (void **)&src_data2, NULL);
4538 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4539 memcpy(src_data2, tests[i].quad, sizeof(*src_data2));
4540 hr = IDirect3DVertexBuffer7_Unlock(src_vb2);
4541 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4543 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, tests[i].world_matrix);
4544 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4546 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
4547 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4549 hr = IDirect3DDevice7_BeginScene(device);
4550 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4552 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 0,
4553 1, src_vb2, 0, device, 0);
4554 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4556 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, tests[i].quad,
4557 4, indices, 6, 0);
4558 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4560 hr = IDirect3DDevice7_EndScene(device);
4561 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4563 hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL);
4564 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4566 color = get_surface_color(rt, 320, 240);
4567 ok(color == tests[i].expected || broken(is_warp && (color == 0x000000ff || color == 0x00ff00ff)),
4568 "%s has color 0x%08x.\n", tests[i].message, color);
4569 todo_wine_if(tests[i].process_vertices_todo)
4570 ok(dst_data[0].diffuse == tests[i].expected_process_vertices,
4571 "%s has color 0x%08x.\n", tests[i].message, dst_data[0].diffuse);
4572 ok(!dst_data[0].specular,
4573 "%s has specular color 0x%08x.\n", tests[i].message, dst_data[0].specular);
4575 hr = IDirect3DVertexBuffer7_Unlock(dst_vb);
4576 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4579 IDirect3DVertexBuffer7_Release(src_vb1);
4580 IDirect3DVertexBuffer7_Release(src_vb2);
4581 IDirect3DVertexBuffer7_Release(dst_vb);
4583 IDirectDrawSurface7_Release(rt);
4585 IDirectDraw7_Release(ddraw);
4586 IDirect3D7_Release(d3d);
4587 refcount = IDirect3DDevice7_Release(device);
4588 ok(!refcount, "Device has %u references left.\n", refcount);
4589 DestroyWindow(window);
4592 static void test_specular_lighting(void)
4594 static const unsigned int vertices_side = 5;
4595 const unsigned int indices_count = (vertices_side - 1) * (vertices_side - 1) * 2 * 3;
4596 static const DWORD fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
4597 static D3DMATRIX mat =
4599 1.0f, 0.0f, 0.0f, 0.0f,
4600 0.0f, 1.0f, 0.0f, 0.0f,
4601 0.0f, 0.0f, 1.0f, 0.0f,
4602 0.0f, 0.0f, 0.0f, 1.0f,
4604 static const struct vertex
4606 struct vec3 position;
4607 struct vec3 normal;
4609 vertices[] =
4611 {{-0.5f, -0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4612 {{ 0.0f, -0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4613 {{ 0.5f, -0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4614 {{-0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4615 {{ 0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4616 {{ 0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4617 {{-0.5f, 0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4618 {{ 0.0f, 0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4619 {{ 0.5f, 0.5f, 1.0f}, {0.0f, 0.0f, -1.0f}},
4622 static D3DLIGHT7 directional =
4624 D3DLIGHT_DIRECTIONAL,
4625 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4626 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4627 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4628 {{0.0f}, {0.0f}, {0.0f}},
4629 {{0.0f}, {0.0f}, {1.0f}},
4631 point =
4633 D3DLIGHT_POINT,
4634 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4635 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4636 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4637 {{0.0f}, {0.0f}, {0.0f}},
4638 {{0.0f}, {0.0f}, {0.0f}},
4639 100.0f,
4640 0.0f,
4641 0.0f, 0.0f, 1.0f,
4643 spot =
4645 D3DLIGHT_SPOT,
4646 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4647 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4648 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4649 {{0.0f}, {0.0f}, {0.0f}},
4650 {{0.0f}, {0.0f}, {1.0f}},
4651 100.0f,
4652 1.0f,
4653 0.0f, 0.0f, 1.0f,
4654 M_PI / 12.0f, M_PI / 3.0f
4656 /* The chosen range value makes the test fail when using a manhattan
4657 * distance metric vs the correct euclidean distance. */
4658 point_range =
4660 D3DLIGHT_POINT,
4661 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4662 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4663 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4664 {{0.0f}, {0.0f}, {0.0f}},
4665 {{0.0f}, {0.0f}, {0.0f}},
4666 1.2f,
4667 0.0f,
4668 0.0f, 0.0f, 1.0f,
4670 point_side =
4672 D3DLIGHT_POINT,
4673 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4674 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
4675 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
4676 {{-1.1f}, {0.0f}, {1.1f}},
4677 {{0.0f}, {0.0f}, {0.0f}},
4678 100.0f,
4679 0.0f,
4680 1.0f, 0.0f, 0.0f,
4682 static const struct expected_color
4684 unsigned int x, y;
4685 D3DCOLOR color;
4687 expected_directional[] =
4689 {160, 120, 0x00ffffff},
4690 {320, 120, 0x00ffffff},
4691 {480, 120, 0x00ffffff},
4692 {160, 240, 0x00ffffff},
4693 {320, 240, 0x00ffffff},
4694 {480, 240, 0x00ffffff},
4695 {160, 360, 0x00ffffff},
4696 {320, 360, 0x00ffffff},
4697 {480, 360, 0x00ffffff},
4699 expected_directional_local[] =
4701 {160, 120, 0x003c3c3c},
4702 {320, 120, 0x00717171},
4703 {480, 120, 0x003c3c3c},
4704 {160, 240, 0x00717171},
4705 {320, 240, 0x00ffffff},
4706 {480, 240, 0x00717171},
4707 {160, 360, 0x003c3c3c},
4708 {320, 360, 0x00717171},
4709 {480, 360, 0x003c3c3c},
4711 expected_point[] =
4713 {160, 120, 0x00282828},
4714 {320, 120, 0x005a5a5a},
4715 {480, 120, 0x00282828},
4716 {160, 240, 0x005a5a5a},
4717 {320, 240, 0x00ffffff},
4718 {480, 240, 0x005a5a5a},
4719 {160, 360, 0x00282828},
4720 {320, 360, 0x005a5a5a},
4721 {480, 360, 0x00282828},
4723 expected_point_local[] =
4725 {160, 120, 0x00000000},
4726 {320, 120, 0x00070707},
4727 {480, 120, 0x00000000},
4728 {160, 240, 0x00070707},
4729 {320, 240, 0x00ffffff},
4730 {480, 240, 0x00070707},
4731 {160, 360, 0x00000000},
4732 {320, 360, 0x00070707},
4733 {480, 360, 0x00000000},
4735 expected_spot[] =
4737 {160, 120, 0x00000000},
4738 {320, 120, 0x00141414},
4739 {480, 120, 0x00000000},
4740 {160, 240, 0x00141414},
4741 {320, 240, 0x00ffffff},
4742 {480, 240, 0x00141414},
4743 {160, 360, 0x00000000},
4744 {320, 360, 0x00141414},
4745 {480, 360, 0x00000000},
4747 expected_spot_local[] =
4749 {160, 120, 0x00000000},
4750 {320, 120, 0x00020202},
4751 {480, 120, 0x00000000},
4752 {160, 240, 0x00020202},
4753 {320, 240, 0x00ffffff},
4754 {480, 240, 0x00020202},
4755 {160, 360, 0x00000000},
4756 {320, 360, 0x00020202},
4757 {480, 360, 0x00000000},
4759 expected_point_range[] =
4761 {160, 120, 0x00000000},
4762 {320, 120, 0x005a5a5a},
4763 {480, 120, 0x00000000},
4764 {160, 240, 0x005a5a5a},
4765 {320, 240, 0x00ffffff},
4766 {480, 240, 0x005a5a5a},
4767 {160, 360, 0x00000000},
4768 {320, 360, 0x005a5a5a},
4769 {480, 360, 0x00000000},
4771 expected_point_side[] =
4773 {160, 120, 0x00000000},
4774 {320, 120, 0x00000000},
4775 {480, 120, 0x00000000},
4776 {160, 240, 0x00000000},
4777 {320, 240, 0x00000000},
4778 {480, 240, 0x00000000},
4779 {160, 360, 0x00000000},
4780 {320, 360, 0x00000000},
4781 {480, 360, 0x00000000},
4783 expected_directional_local_0[] =
4785 {160, 120, 0x00ffffff},
4786 {320, 120, 0x00ffffff},
4787 {480, 120, 0x00ffffff},
4788 {160, 240, 0x00ffffff},
4789 {320, 240, 0x00ffffff},
4790 {480, 240, 0x00ffffff},
4791 {160, 360, 0x00ffffff},
4792 {320, 360, 0x00ffffff},
4793 {480, 360, 0x00ffffff},
4795 expected_point_0[] =
4797 {160, 120, 0x00aaaaaa},
4798 {320, 120, 0x00cccccc},
4799 {480, 120, 0x00aaaaaa},
4800 {160, 240, 0x00cccccc},
4801 {320, 240, 0x00ffffff},
4802 {480, 240, 0x00cccccc},
4803 {160, 360, 0x00aaaaaa},
4804 {320, 360, 0x00cccccc},
4805 {480, 360, 0x00aaaaaa},
4807 expected_spot_0[] =
4809 {160, 120, 0x00000000},
4810 {320, 120, 0x002e2e2e},
4811 {480, 120, 0x00000000},
4812 {160, 240, 0x002e2e2e},
4813 {320, 240, 0x00ffffff},
4814 {480, 240, 0x002e2e2e},
4815 {160, 360, 0x00000000},
4816 {320, 360, 0x002e2e2e},
4817 {480, 360, 0x00000000},
4819 expected_point_range_0[] =
4821 {160, 120, 0x00000000},
4822 {320, 120, 0x00cccccc},
4823 {480, 120, 0x00000000},
4824 {160, 240, 0x00cccccc},
4825 {320, 240, 0x00ffffff},
4826 {480, 240, 0x00cccccc},
4827 {160, 360, 0x00000000},
4828 {320, 360, 0x00cccccc},
4829 {480, 360, 0x00000000},
4831 static const struct
4833 D3DLIGHT7 *light;
4834 BOOL local_viewer;
4835 float specular_power;
4836 const struct expected_color *expected, *expected_process_vertices;
4837 unsigned int expected_count;
4838 BOOL todo_process_vertices;
4840 tests[] =
4842 {&directional, FALSE, 30.0f, expected_directional, expected_directional,
4843 ARRAY_SIZE(expected_directional)},
4844 {&directional, TRUE, 30.0f, expected_directional_local, expected_directional_local,
4845 ARRAY_SIZE(expected_directional_local)},
4846 {&point, FALSE, 30.0f, expected_point, expected_point, ARRAY_SIZE(expected_point)},
4847 {&point, TRUE, 30.0f, expected_point_local, expected_point_local, ARRAY_SIZE(expected_point_local)},
4848 {&spot, FALSE, 30.0f, expected_spot, expected_spot, ARRAY_SIZE(expected_spot)},
4849 {&spot, TRUE, 30.0f, expected_spot_local, expected_spot_local, ARRAY_SIZE(expected_spot_local)},
4850 {&point_range, FALSE, 30.0f, expected_point_range, expected_point_range,
4851 ARRAY_SIZE(expected_point_range)},
4853 /* For zero material shininess _ProcessVertices() seem to keep non-zero material shininess set previously. */
4854 {&point_side, TRUE, 0.0f, expected_point_side, expected_point_side, ARRAY_SIZE(expected_point_side), TRUE},
4855 {&directional, FALSE, 0.0f, expected_directional, expected_directional,
4856 ARRAY_SIZE(expected_directional), TRUE},
4857 {&directional, TRUE, 0.0f, expected_directional_local_0, expected_directional_local,
4858 ARRAY_SIZE(expected_directional_local_0), TRUE},
4859 {&point, FALSE, 0.0f, expected_point_0, expected_point, ARRAY_SIZE(expected_point_0), TRUE},
4860 {&point, TRUE, 0.0f, expected_point_0, expected_point_local, ARRAY_SIZE(expected_point_0), TRUE},
4861 {&spot, FALSE, 0.0f, expected_spot_0, expected_spot, ARRAY_SIZE(expected_spot_0), TRUE},
4862 {&spot, TRUE, 0.0f, expected_spot_0, expected_spot_local, ARRAY_SIZE(expected_spot_0), TRUE},
4863 {&point_range, FALSE, 0.0f, expected_point_range_0, expected_point_range, ARRAY_SIZE(expected_point_range_0), TRUE},
4866 IDirect3DVertexBuffer7 *src_vb, *dst_vb;
4867 D3DCOLOR color, expected_color;
4868 D3DVERTEXBUFFERDESC vb_desc;
4869 IDirect3DDevice7 *device;
4870 unsigned int i, j, x, y;
4871 IDirectDrawSurface7 *rt;
4872 D3DMATERIAL7 material;
4873 struct vec3 *src_data;
4874 struct vertex *quad;
4875 IDirect3D7 *d3d;
4876 ULONG refcount;
4877 WORD *indices;
4878 HWND window;
4879 HRESULT hr;
4880 struct
4882 struct vec4 position;
4883 DWORD diffuse;
4884 DWORD specular;
4885 } *dst_data;
4887 window = create_window();
4888 if (!(device = create_device(window, DDSCL_NORMAL)))
4890 skip("Failed to create a 3D device, skipping test.\n");
4891 DestroyWindow(window);
4892 return;
4894 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
4895 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4897 quad = heap_alloc(vertices_side * vertices_side * sizeof(*quad));
4898 indices = heap_alloc(indices_count * sizeof(*indices));
4899 for (i = 0, y = 0; y < vertices_side; ++y)
4901 for (x = 0; x < vertices_side; ++x)
4903 quad[i].position.x = x * 2.0f / (vertices_side - 1) - 1.0f;
4904 quad[i].position.y = y * 2.0f / (vertices_side - 1) - 1.0f;
4905 quad[i].position.z = 1.0f;
4906 quad[i].normal.x = 0.0f;
4907 quad[i].normal.y = 0.0f;
4908 quad[i++].normal.z = -1.0f;
4911 for (i = 0, y = 0; y < (vertices_side - 1); ++y)
4913 for (x = 0; x < (vertices_side - 1); ++x)
4915 indices[i++] = y * vertices_side + x + 1;
4916 indices[i++] = y * vertices_side + x;
4917 indices[i++] = (y + 1) * vertices_side + x;
4918 indices[i++] = y * vertices_side + x + 1;
4919 indices[i++] = (y + 1) * vertices_side + x;
4920 indices[i++] = (y + 1) * vertices_side + x + 1;
4924 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
4925 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4927 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
4928 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4929 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
4930 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4931 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
4932 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4933 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
4934 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4935 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
4936 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4937 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
4938 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4940 hr = IDirect3DDevice7_LightEnable(device, 0, TRUE);
4941 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4942 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, TRUE);
4943 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4945 memset(&vb_desc, 0, sizeof(vb_desc));
4946 vb_desc.dwSize = sizeof(vb_desc);
4947 vb_desc.dwFVF = fvf;
4948 vb_desc.dwNumVertices = ARRAY_SIZE(vertices);
4949 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &src_vb, 0);
4950 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4951 hr = IDirect3DVertexBuffer7_Lock(src_vb, 0, (void **)&src_data, NULL);
4952 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4953 memcpy(src_data, vertices, sizeof(vertices));
4954 hr = IDirect3DVertexBuffer7_Unlock(src_vb);
4955 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4957 memset(&vb_desc, 0, sizeof(vb_desc));
4958 vb_desc.dwSize = sizeof(vb_desc);
4959 vb_desc.dwFVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR;
4960 vb_desc.dwNumVertices = ARRAY_SIZE(vertices);
4961 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &dst_vb, 0);
4962 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4964 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4966 hr = IDirect3DDevice7_SetLight(device, 0, tests[i].light);
4967 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4969 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LOCALVIEWER, tests[i].local_viewer);
4970 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4972 memset(&material, 0, sizeof(material));
4973 U1(U2(material).specular).r = 1.0f;
4974 U2(U2(material).specular).g = 1.0f;
4975 U3(U2(material).specular).b = 1.0f;
4976 U4(U2(material).specular).a = 0.5f;
4977 U4(material).power = tests[i].specular_power;
4978 hr = IDirect3DDevice7_SetMaterial(device, &material);
4979 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4981 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
4982 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4984 hr = IDirect3DDevice7_BeginScene(device);
4985 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4987 hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL);
4988 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4989 memset(dst_data, 0, sizeof(*dst_data) * ARRAY_SIZE(vertices));
4990 hr = IDirect3DVertexBuffer7_Unlock(dst_vb);
4991 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4993 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 0,
4994 ARRAY_SIZE(vertices), src_vb, 0, device, 0);
4995 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4997 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, quad,
4998 vertices_side * vertices_side, indices, indices_count, 0);
4999 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5001 hr = IDirect3DDevice7_EndScene(device);
5002 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5004 hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL);
5005 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5007 ok(tests[i].expected_count == ARRAY_SIZE(vertices), "Array size mismatch.\n");
5008 for (j = 0; j < tests[i].expected_count; ++j)
5010 color = get_surface_color(rt, tests[i].expected[j].x, tests[i].expected[j].y);
5011 ok(compare_color(color, tests[i].expected[j].color, 1),
5012 "Expected color 0x%08x at location (%u, %u), got 0x%08x, case %u.\n",
5013 tests[i].expected[j].color, tests[i].expected[j].x,
5014 tests[i].expected[j].y, color, i);
5015 ok(!dst_data[j].diffuse, "Expected color 0x00000000 for vertex %u, got 0x%08x, case %u.\n",
5016 j, dst_data[j].diffuse, i);
5017 expected_color = tests[i].expected_process_vertices[j].color | 0x80000000;
5018 todo_wine_if(tests[i].todo_process_vertices && dst_data[j].specular != expected_color)
5019 ok(compare_color(dst_data[j].specular, expected_color, 1),
5020 "Expected color 0x%08x for vertex %u, got 0x%08x, case %u.\n",
5021 expected_color, j, dst_data[j].specular, i);
5023 hr = IDirect3DVertexBuffer7_Unlock(dst_vb);
5024 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5027 IDirect3DVertexBuffer7_Release(dst_vb);
5028 IDirect3DVertexBuffer7_Release(src_vb);
5029 IDirectDrawSurface7_Release(rt);
5031 IDirect3D7_Release(d3d);
5032 refcount = IDirect3DDevice7_Release(device);
5033 ok(!refcount, "Device has %u references left.\n", refcount);
5034 DestroyWindow(window);
5035 heap_free(indices);
5036 heap_free(quad);
5039 static void test_clear_rect_count(void)
5041 IDirectDrawSurface7 *rt;
5042 IDirect3DDevice7 *device;
5043 D3DCOLOR color;
5044 HWND window;
5045 HRESULT hr;
5046 D3DRECT rect = {{0}, {0}, {640}, {480}};
5048 window = create_window();
5049 if (!(device = create_device(window, DDSCL_NORMAL)))
5051 skip("Failed to create a 3D device, skipping test.\n");
5052 DestroyWindow(window);
5053 return;
5056 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
5057 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
5059 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ffffff, 1.0f, 0);
5060 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
5061 hr = IDirect3DDevice7_Clear(device, 0, &rect, D3DCLEAR_TARGET, 0x00ff0000, 1.0f, 0);
5062 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
5064 color = get_surface_color(rt, 320, 240);
5065 ok(compare_color(color, 0x00ffffff, 1) || broken(compare_color(color, 0x00ff0000, 1)),
5066 "Clear with count = 0, rect != NULL has color %#08x.\n", color);
5068 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ffffff, 1.0f, 0);
5069 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
5070 hr = IDirect3DDevice7_Clear(device, 1, NULL, D3DCLEAR_TARGET, 0x0000ff00, 1.0f, 0);
5071 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
5073 color = get_surface_color(rt, 320, 240);
5074 ok(compare_color(color, 0x0000ff00, 1),
5075 "Clear with count = 1, rect = NULL has color %#08x.\n", color);
5077 IDirectDrawSurface7_Release(rt);
5078 IDirect3DDevice7_Release(device);
5079 DestroyWindow(window);
5082 static BOOL test_mode_restored(IDirectDraw7 *ddraw, HWND window)
5084 DDSURFACEDESC2 ddsd1, ddsd2;
5085 HRESULT hr;
5087 memset(&ddsd1, 0, sizeof(ddsd1));
5088 ddsd1.dwSize = sizeof(ddsd1);
5089 hr = IDirectDraw7_GetDisplayMode(ddraw, &ddsd1);
5090 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
5092 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5093 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
5094 hr = set_display_mode(ddraw, 640, 480);
5095 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
5096 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5097 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
5099 memset(&ddsd2, 0, sizeof(ddsd2));
5100 ddsd2.dwSize = sizeof(ddsd2);
5101 hr = IDirectDraw7_GetDisplayMode(ddraw, &ddsd2);
5102 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
5103 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
5104 ok(SUCCEEDED(hr), "RestoreDisplayMode failed, hr %#x.\n", hr);
5106 return ddsd1.dwWidth == ddsd2.dwWidth && ddsd1.dwHeight == ddsd2.dwHeight;
5109 static void test_coop_level_versions(void)
5111 HWND window;
5112 IDirectDraw *ddraw;
5113 HRESULT hr;
5114 BOOL restored;
5115 IDirectDrawSurface *surface;
5116 IDirectDraw7 *ddraw7;
5117 DDSURFACEDESC ddsd;
5119 window = create_window();
5120 ddraw7 = create_ddraw();
5121 ok(!!ddraw7, "Failed to create a ddraw object.\n");
5122 /* Newly created ddraw objects restore the mode on ddraw2+::SetCooperativeLevel(NORMAL) */
5123 restored = test_mode_restored(ddraw7, window);
5124 ok(restored, "Display mode not restored in new ddraw object\n");
5126 /* A failing ddraw1::SetCooperativeLevel call does not have an effect */
5127 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
5128 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
5130 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
5131 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
5132 restored = test_mode_restored(ddraw7, window);
5133 ok(restored, "Display mode not restored after bad ddraw1::SetCooperativeLevel call\n");
5135 /* A successful one does */
5136 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5137 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
5138 restored = test_mode_restored(ddraw7, window);
5139 ok(!restored, "Display mode restored after good ddraw1::SetCooperativeLevel call\n");
5141 IDirectDraw_Release(ddraw);
5142 IDirectDraw7_Release(ddraw7);
5144 ddraw7 = create_ddraw();
5145 ok(!!ddraw7, "Failed to create a ddraw object.\n");
5146 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
5147 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
5149 hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_SETFOCUSWINDOW);
5150 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
5151 restored = test_mode_restored(ddraw7, window);
5152 ok(!restored, "Display mode restored after ddraw1::SetCooperativeLevel(SETFOCUSWINDOW) call\n");
5154 IDirectDraw_Release(ddraw);
5155 IDirectDraw7_Release(ddraw7);
5157 /* A failing call does not restore the ddraw2+ behavior */
5158 ddraw7 = create_ddraw();
5159 ok(!!ddraw7, "Failed to create a ddraw object.\n");
5160 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
5161 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
5163 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5164 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
5165 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
5166 ok(FAILED(hr), "SetCooperativeLevel returned %#x, expected failure.\n", hr);
5167 restored = test_mode_restored(ddraw7, window);
5168 ok(!restored, "Display mode restored after good-bad ddraw1::SetCooperativeLevel() call sequence\n");
5170 IDirectDraw_Release(ddraw);
5171 IDirectDraw7_Release(ddraw7);
5173 /* Neither does a sequence of successful calls with the new interface */
5174 ddraw7 = create_ddraw();
5175 ok(!!ddraw7, "Failed to create a ddraw object.\n");
5176 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
5177 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
5179 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5180 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
5181 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
5182 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
5183 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
5184 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
5186 restored = test_mode_restored(ddraw7, window);
5187 ok(!restored, "Display mode restored after ddraw1-ddraw7 SetCooperativeLevel() call sequence\n");
5188 IDirectDraw_Release(ddraw);
5189 IDirectDraw7_Release(ddraw7);
5191 /* ddraw1::CreateSurface does not triger the ddraw1 behavior */
5192 ddraw7 = create_ddraw();
5193 ok(!!ddraw7, "Failed to create a ddraw object.\n");
5194 hr = IDirectDraw7_QueryInterface(ddraw7, &IID_IDirectDraw, (void **)&ddraw);
5195 ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
5197 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, window, DDSCL_NORMAL);
5198 ok(SUCCEEDED(hr), "SetCooperativeLevel failed, hr %#x.\n", hr);
5200 memset(&ddsd, 0, sizeof(ddsd));
5201 ddsd.dwSize = sizeof(ddsd);
5202 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
5203 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5204 ddsd.dwWidth = ddsd.dwHeight = 8;
5205 hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL);
5206 ok(SUCCEEDED(hr), "CreateSurface failed, hr %#x.\n", hr);
5207 IDirectDrawSurface_Release(surface);
5208 restored = test_mode_restored(ddraw7, window);
5209 ok(restored, "Display mode not restored after ddraw1::CreateSurface() call\n");
5211 IDirectDraw_Release(ddraw);
5212 IDirectDraw7_Release(ddraw7);
5213 DestroyWindow(window);
5216 static void test_fog_special(void)
5218 static struct
5220 struct vec3 position;
5221 D3DCOLOR diffuse;
5223 quad[] =
5225 {{ -1.0f, 1.0f, 0.0f}, 0xff00ff00},
5226 {{ 1.0f, 1.0f, 1.0f}, 0xff00ff00},
5227 {{ -1.0f, -1.0f, 0.0f}, 0xff00ff00},
5228 {{ 1.0f, -1.0f, 1.0f}, 0xff00ff00},
5230 static const struct
5232 DWORD vertexmode, tablemode;
5233 D3DCOLOR color_left, color_right;
5235 tests[] =
5237 {D3DFOG_LINEAR, D3DFOG_NONE, 0x00ff0000, 0x00ff0000},
5238 {D3DFOG_NONE, D3DFOG_LINEAR, 0x0000ff00, 0x00ff0000},
5240 union
5242 float f;
5243 DWORD d;
5244 } conv;
5245 D3DCOLOR color;
5246 HRESULT hr;
5247 unsigned int i;
5248 HWND window;
5249 IDirect3DDevice7 *device;
5250 IDirectDrawSurface7 *rt;
5252 window = create_window();
5253 if (!(device = create_device(window, DDSCL_NORMAL)))
5255 skip("Failed to create a 3D device, skipping test.\n");
5256 DestroyWindow(window);
5257 return;
5260 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
5261 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
5263 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
5264 ok(SUCCEEDED(hr), "Failed to enable fog, hr %#x.\n", hr);
5265 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0xffff0000);
5266 ok(SUCCEEDED(hr), "Failed to set fog color, hr %#x.\n", hr);
5267 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
5268 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
5269 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
5270 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
5272 conv.f = 0.5f;
5273 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGSTART, conv.d);
5274 ok(SUCCEEDED(hr), "Failed to set fog start, hr %#x.\n", hr);
5275 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGEND, conv.d);
5276 ok(SUCCEEDED(hr), "Failed to set fog end, hr %#x.\n", hr);
5278 for (i = 0; i < ARRAY_SIZE(tests); ++i)
5280 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x000000ff, 1.0f, 0);
5281 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
5283 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, tests[i].vertexmode);
5284 ok(SUCCEEDED(hr), "Failed to set fogvertexmode, hr %#x.\n", hr);
5285 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, tests[i].tablemode);
5286 ok(SUCCEEDED(hr), "Failed to set fogtablemode, hr %#x.\n", hr);
5288 hr = IDirect3DDevice7_BeginScene(device);
5289 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5290 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, 4, 0);
5291 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5292 hr = IDirect3DDevice7_EndScene(device);
5293 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5295 color = get_surface_color(rt, 310, 240);
5296 ok(compare_color(color, tests[i].color_left, 1),
5297 "Expected left color 0x%08x, got 0x%08x, case %u.\n", tests[i].color_left, color, i);
5298 color = get_surface_color(rt, 330, 240);
5299 ok(compare_color(color, tests[i].color_right, 1),
5300 "Expected right color 0x%08x, got 0x%08x, case %u.\n", tests[i].color_right, color, i);
5303 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
5304 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
5306 IDirectDrawSurface7_Release(rt);
5307 IDirect3DDevice7_Release(device);
5308 DestroyWindow(window);
5311 static void test_lighting_interface_versions(void)
5313 IDirect3DDevice7 *device;
5314 IDirectDrawSurface7 *rt;
5315 D3DCOLOR color;
5316 HWND window;
5317 HRESULT hr;
5318 DWORD rs;
5319 unsigned int i;
5320 ULONG ref;
5321 D3DMATERIAL7 material;
5322 static D3DVERTEX quad[] =
5324 {{-1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
5325 {{ 1.0f}, { 1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
5326 {{-1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
5327 {{ 1.0f}, {-1.0f}, {0.0f}, {1.0f}, {0.0f}, {0.0f}},
5330 #define FVF_COLORVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_SPECULAR)
5331 static struct
5333 struct vec3 position;
5334 struct vec3 normal;
5335 DWORD diffuse, specular;
5337 quad2[] =
5339 {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
5340 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
5341 {{-1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
5342 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0xffff0000, 0xff808080},
5345 static D3DLVERTEX lquad[] =
5347 {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
5348 {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
5349 {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
5350 {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xffff0000}, {0xff808080}},
5353 #define FVF_LVERTEX2 (D3DFVF_LVERTEX & ~D3DFVF_RESERVED1)
5354 static struct
5356 struct vec3 position;
5357 DWORD diffuse, specular;
5358 struct vec2 texcoord;
5360 lquad2[] =
5362 {{-1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
5363 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff808080},
5364 {{-1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
5365 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff808080},
5368 static D3DTLVERTEX tlquad[] =
5370 {{ 0.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
5371 {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
5372 {{ 640.0f}, { 480.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
5373 {{ 640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0xff0000ff}, {0xff808080}},
5376 static const struct
5378 DWORD vertextype;
5379 void *data;
5380 DWORD d3drs_lighting, d3drs_specular;
5381 DWORD draw_flags;
5382 D3DCOLOR color;
5384 tests[] =
5386 /* Lighting is enabled when D3DFVF_XYZ is used and D3DRENDERSTATE_LIGHTING is
5387 * enabled. D3DDP_DONOTLIGHT is ignored. Lighting is also enabled when normals
5388 * are not available
5390 * Note that the specular result is 0x00000000 when lighting is on even if the
5391 * input vertex has specular color because D3DRENDERSTATE_COLORVERTEX is not
5392 * enabled */
5394 /* 0 */
5395 { D3DFVF_VERTEX, quad, FALSE, FALSE, 0, 0x00ffffff},
5396 { D3DFVF_VERTEX, quad, TRUE, FALSE, 0, 0x0000ff00},
5397 { D3DFVF_VERTEX, quad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ffffff},
5398 { D3DFVF_VERTEX, quad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
5399 { D3DFVF_VERTEX, quad, FALSE, TRUE, 0, 0x00ffffff},
5400 { D3DFVF_VERTEX, quad, TRUE, TRUE, 0, 0x0000ff00},
5401 { D3DFVF_VERTEX, quad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ffffff},
5402 { D3DFVF_VERTEX, quad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
5404 /* 8 */
5405 { FVF_COLORVERTEX, quad2, FALSE, FALSE, 0, 0x00ff0000},
5406 { FVF_COLORVERTEX, quad2, TRUE, FALSE, 0, 0x0000ff00},
5407 { FVF_COLORVERTEX, quad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
5408 { FVF_COLORVERTEX, quad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
5409 { FVF_COLORVERTEX, quad2, FALSE, TRUE, 0, 0x00ff8080},
5410 { FVF_COLORVERTEX, quad2, TRUE, TRUE, 0, 0x0000ff00},
5411 { FVF_COLORVERTEX, quad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
5412 { FVF_COLORVERTEX, quad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
5414 /* 16 */
5415 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, 0, 0x00ff0000},
5416 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, 0, 0x0000ff00},
5417 { D3DFVF_LVERTEX, lquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
5418 { D3DFVF_LVERTEX, lquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
5419 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, 0, 0x00ff8080},
5420 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, 0, 0x0000ff00},
5421 { D3DFVF_LVERTEX, lquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
5422 { D3DFVF_LVERTEX, lquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
5424 /* 24 */
5425 { FVF_LVERTEX2, lquad2, FALSE, FALSE, 0, 0x00ff0000},
5426 { FVF_LVERTEX2, lquad2, TRUE, FALSE, 0, 0x0000ff00},
5427 { FVF_LVERTEX2, lquad2, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x00ff0000},
5428 { FVF_LVERTEX2, lquad2, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x0000ff00},
5429 { FVF_LVERTEX2, lquad2, FALSE, TRUE, 0, 0x00ff8080},
5430 { FVF_LVERTEX2, lquad2, TRUE, TRUE, 0, 0x0000ff00},
5431 { FVF_LVERTEX2, lquad2, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x00ff8080},
5432 { FVF_LVERTEX2, lquad2, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x0000ff00},
5434 /* 32 */
5435 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, 0, 0x000000ff},
5436 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, 0, 0x000000ff},
5437 { D3DFVF_TLVERTEX, tlquad, FALSE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
5438 { D3DFVF_TLVERTEX, tlquad, TRUE, FALSE, D3DDP_DONOTLIGHT, 0x000000ff},
5439 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, 0, 0x008080ff},
5440 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, 0, 0x008080ff},
5441 { D3DFVF_TLVERTEX, tlquad, FALSE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
5442 { D3DFVF_TLVERTEX, tlquad, TRUE, TRUE, D3DDP_DONOTLIGHT, 0x008080ff},
5445 window = create_window();
5446 if (!(device = create_device(window, DDSCL_NORMAL)))
5448 skip("Failed to create a 3D device, skipping test.\n");
5449 DestroyWindow(window);
5450 return;
5453 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
5454 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
5456 memset(&material, 0, sizeof(material));
5457 U2(U3(material).emissive).g = 1.0f;
5458 hr = IDirect3DDevice7_SetMaterial(device, &material);
5459 ok(SUCCEEDED(hr), "Failed set material, hr %#x.\n", hr);
5460 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
5461 ok(SUCCEEDED(hr), "Failed to disable z test, hr %#x.\n", hr);
5463 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &rs);
5464 ok(SUCCEEDED(hr), "Failed to get lighting render state, hr %#x.\n", hr);
5465 ok(rs == TRUE, "Initial D3DRENDERSTATE_LIGHTING is %#x, expected TRUE.\n", rs);
5466 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, &rs);
5467 ok(SUCCEEDED(hr), "Failed to get specularenable render state, hr %#x.\n", hr);
5468 ok(rs == FALSE, "Initial D3DRENDERSTATE_SPECULARENABLE is %#x, expected FALSE.\n", rs);
5470 for (i = 0; i < ARRAY_SIZE(tests); ++i)
5472 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff202020, 0.0f, 0);
5473 ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
5475 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, tests[i].d3drs_lighting);
5476 ok(SUCCEEDED(hr), "Failed to set lighting render state, hr %#x.\n", hr);
5477 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE,
5478 tests[i].d3drs_specular);
5479 ok(SUCCEEDED(hr), "Failed to set specularenable render state, hr %#x.\n", hr);
5481 hr = IDirect3DDevice7_BeginScene(device);
5482 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5483 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
5484 tests[i].vertextype, tests[i].data, 4, tests[i].draw_flags | D3DDP_WAIT);
5485 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5486 hr = IDirect3DDevice7_EndScene(device);
5487 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5489 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &rs);
5490 ok(SUCCEEDED(hr), "Failed to get lighting render state, hr %#x.\n", hr);
5491 ok(rs == tests[i].d3drs_lighting, "D3DRENDERSTATE_LIGHTING is %#x, expected %#x.\n",
5492 rs, tests[i].d3drs_lighting);
5494 color = get_surface_color(rt, 320, 240);
5495 ok(compare_color(color, tests[i].color, 1),
5496 "Got unexpected color 0x%08x, expected 0x%08x, test %u.\n",
5497 color, tests[i].color, i);
5500 IDirectDrawSurface7_Release(rt);
5501 ref = IDirect3DDevice7_Release(device);
5502 ok(ref == 0, "Device not properly released, refcount %u.\n", ref);
5503 DestroyWindow(window);
5506 static struct
5508 BOOL received;
5509 IDirectDraw7 *ddraw;
5510 HWND window;
5511 DWORD coop_level;
5512 } activateapp_testdata;
5514 static LRESULT CALLBACK activateapp_test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
5516 if (message == WM_ACTIVATEAPP)
5518 if (activateapp_testdata.ddraw)
5520 HRESULT hr;
5521 activateapp_testdata.received = FALSE;
5522 hr = IDirectDraw7_SetCooperativeLevel(activateapp_testdata.ddraw,
5523 activateapp_testdata.window, activateapp_testdata.coop_level);
5524 ok(SUCCEEDED(hr), "Recursive SetCooperativeLevel call failed, hr %#x.\n", hr);
5525 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP during recursive SetCooperativeLevel call.\n");
5527 activateapp_testdata.received = TRUE;
5530 return DefWindowProcA(hwnd, message, wparam, lparam);
5533 static void test_coop_level_activateapp(void)
5535 IDirectDraw7 *ddraw;
5536 HRESULT hr;
5537 HWND window;
5538 WNDCLASSA wc = {0};
5539 DDSURFACEDESC2 ddsd;
5540 IDirectDrawSurface7 *surface;
5542 ddraw = create_ddraw();
5543 ok(!!ddraw, "Failed to create a ddraw object.\n");
5545 wc.lpfnWndProc = activateapp_test_proc;
5546 wc.lpszClassName = "ddraw_test_wndproc_wc";
5547 ok(RegisterClassA(&wc), "Failed to register window class.\n");
5549 window = CreateWindowA("ddraw_test_wndproc_wc", "ddraw_test",
5550 WS_MAXIMIZE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
5552 /* Exclusive with window already active. */
5553 SetForegroundWindow(window);
5554 activateapp_testdata.received = FALSE;
5555 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5556 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5557 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP although window was already active.\n");
5558 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5559 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5561 /* Exclusive with window not active. */
5562 SetForegroundWindow(GetDesktopWindow());
5563 activateapp_testdata.received = FALSE;
5564 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5565 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5566 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
5567 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5568 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5570 /* Normal with window not active, then exclusive with the same window. */
5571 SetForegroundWindow(GetDesktopWindow());
5572 activateapp_testdata.received = FALSE;
5573 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
5574 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5575 ok(!activateapp_testdata.received, "Received WM_ACTIVATEAPP when setting DDSCL_NORMAL.\n");
5576 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5577 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5578 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
5579 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5580 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5582 /* Recursive set of DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. */
5583 SetForegroundWindow(GetDesktopWindow());
5584 activateapp_testdata.received = FALSE;
5585 activateapp_testdata.ddraw = ddraw;
5586 activateapp_testdata.window = window;
5587 activateapp_testdata.coop_level = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
5588 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5589 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5590 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
5591 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5592 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5594 /* The recursive call seems to have some bad effect on native ddraw, despite (apparently)
5595 * succeeding. Another switch to exclusive and back to normal is needed to release the
5596 * window properly. Without doing this, SetCooperativeLevel(EXCLUSIVE) will not send
5597 * WM_ACTIVATEAPP messages. */
5598 activateapp_testdata.ddraw = NULL;
5599 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5600 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5601 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5602 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5604 /* Setting DDSCL_NORMAL with recursive invocation. */
5605 SetForegroundWindow(GetDesktopWindow());
5606 activateapp_testdata.received = FALSE;
5607 activateapp_testdata.ddraw = ddraw;
5608 activateapp_testdata.window = window;
5609 activateapp_testdata.coop_level = DDSCL_NORMAL;
5610 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5611 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5612 ok(activateapp_testdata.received, "Expected WM_ACTIVATEAPP, but did not receive it.\n");
5614 /* DDraw is in exclusive mode now. */
5615 memset(&ddsd, 0, sizeof(ddsd));
5616 ddsd.dwSize = sizeof(ddsd);
5617 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
5618 U5(ddsd).dwBackBufferCount = 1;
5619 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
5620 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5621 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5622 IDirectDrawSurface7_Release(surface);
5624 /* Recover again, just to be sure. */
5625 activateapp_testdata.ddraw = NULL;
5626 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
5627 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5628 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5629 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5631 DestroyWindow(window);
5632 UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
5633 IDirectDraw7_Release(ddraw);
5636 static void test_texturemanage(void)
5638 IDirectDraw7 *ddraw;
5639 HRESULT hr;
5640 DDSURFACEDESC2 ddsd;
5641 IDirectDrawSurface7 *surface;
5642 unsigned int i;
5643 DDCAPS hal_caps, hel_caps;
5644 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
5645 static const struct
5647 DWORD caps_in, caps2_in;
5648 HRESULT hr;
5649 DWORD caps_out, caps2_out;
5651 tests[] =
5653 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
5654 ~0U, ~0U},
5655 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
5656 ~0U, ~0U},
5657 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
5658 ~0U, ~0U},
5659 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
5660 ~0U, ~0U},
5661 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, DD_OK,
5662 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE},
5663 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, DD_OK,
5664 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE},
5665 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
5666 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_LOCALVIDMEM, 0},
5667 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0, DD_OK,
5668 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0},
5670 {0, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
5671 ~0U, ~0U},
5672 {0, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
5673 ~0U, ~0U},
5674 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
5675 ~0U, ~0U},
5676 {DDSCAPS_SYSTEMMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
5677 ~0U, ~0U},
5678 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_TEXTUREMANAGE, DDERR_INVALIDCAPS,
5679 ~0U, ~0U},
5680 {DDSCAPS_VIDEOMEMORY, DDSCAPS2_D3DTEXTUREMANAGE, DDERR_INVALIDCAPS,
5681 ~0U, ~0U},
5682 {DDSCAPS_VIDEOMEMORY, 0, DD_OK,
5683 DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY, 0},
5684 {DDSCAPS_SYSTEMMEMORY, 0, DD_OK,
5685 DDSCAPS_SYSTEMMEMORY, 0},
5688 ddraw = create_ddraw();
5689 ok(!!ddraw, "Failed to create a ddraw object.\n");
5690 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
5691 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
5693 memset(&hal_caps, 0, sizeof(hal_caps));
5694 hal_caps.dwSize = sizeof(hal_caps);
5695 memset(&hel_caps, 0, sizeof(hel_caps));
5696 hel_caps.dwSize = sizeof(hel_caps);
5697 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, &hel_caps);
5698 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
5699 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps)
5701 skip("Managed textures not supported, skipping managed texture test.\n");
5702 IDirectDraw7_Release(ddraw);
5703 return;
5706 for (i = 0; i < ARRAY_SIZE(tests); ++i)
5708 memset(&ddsd, 0, sizeof(ddsd));
5709 ddsd.dwSize = sizeof(ddsd);
5710 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
5711 ddsd.ddsCaps.dwCaps = tests[i].caps_in;
5712 ddsd.ddsCaps.dwCaps2 = tests[i].caps2_in;
5713 ddsd.dwWidth = 4;
5714 ddsd.dwHeight = 4;
5716 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5717 if (tests[i].hr == DD_OK && is_ddraw64 && (tests[i].caps_in & DDSCAPS_TEXTURE))
5718 todo_wine ok(hr == E_NOINTERFACE, "Test %u: Got unexpected hr %#x.\n", i, hr);
5719 else
5720 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, tests[i].hr);
5721 if (FAILED(hr))
5722 continue;
5724 memset(&ddsd, 0, sizeof(ddsd));
5725 ddsd.dwSize = sizeof(ddsd);
5726 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
5727 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5729 ok(ddsd.ddsCaps.dwCaps == tests[i].caps_out,
5730 "Input caps %#x, %#x, expected output caps %#x, got %#x, case %u.\n",
5731 tests[i].caps_in, tests[i].caps2_in, tests[i].caps_out, ddsd.ddsCaps.dwCaps, i);
5732 ok(ddsd.ddsCaps.dwCaps2 == tests[i].caps2_out,
5733 "Input caps %#x, %#x, expected output caps %#x, got %#x, case %u.\n",
5734 tests[i].caps_in, tests[i].caps2_in, tests[i].caps2_out, ddsd.ddsCaps.dwCaps2, i);
5736 IDirectDrawSurface7_Release(surface);
5739 IDirectDraw7_Release(ddraw);
5742 #define SUPPORT_DXT1 0x01
5743 #define SUPPORT_DXT2 0x02
5744 #define SUPPORT_DXT3 0x04
5745 #define SUPPORT_DXT4 0x08
5746 #define SUPPORT_DXT5 0x10
5747 #define SUPPORT_YUY2 0x20
5748 #define SUPPORT_UYVY 0x40
5750 static HRESULT WINAPI test_block_formats_creation_cb(DDPIXELFORMAT *fmt, void *ctx)
5752 DWORD *supported_fmts = ctx;
5754 if (!(fmt->dwFlags & DDPF_FOURCC))
5755 return DDENUMRET_OK;
5757 switch (fmt->dwFourCC)
5759 case MAKEFOURCC('D','X','T','1'):
5760 *supported_fmts |= SUPPORT_DXT1;
5761 break;
5762 case MAKEFOURCC('D','X','T','2'):
5763 *supported_fmts |= SUPPORT_DXT2;
5764 break;
5765 case MAKEFOURCC('D','X','T','3'):
5766 *supported_fmts |= SUPPORT_DXT3;
5767 break;
5768 case MAKEFOURCC('D','X','T','4'):
5769 *supported_fmts |= SUPPORT_DXT4;
5770 break;
5771 case MAKEFOURCC('D','X','T','5'):
5772 *supported_fmts |= SUPPORT_DXT5;
5773 break;
5774 case MAKEFOURCC('Y','U','Y','2'):
5775 *supported_fmts |= SUPPORT_YUY2;
5776 break;
5777 case MAKEFOURCC('U','Y','V','Y'):
5778 *supported_fmts |= SUPPORT_UYVY;
5779 break;
5780 default:
5781 break;
5784 return DDENUMRET_OK;
5787 static void test_block_formats_creation(void)
5789 HRESULT hr, expect_hr;
5790 unsigned int i, j, w, h;
5791 HWND window;
5792 IDirectDraw7 *ddraw;
5793 IDirect3D7 *d3d;
5794 IDirect3DDevice7 *device;
5795 IDirectDrawSurface7 *surface;
5796 DWORD supported_fmts = 0, supported_overlay_fmts = 0;
5797 DWORD num_fourcc_codes = 0, *fourcc_codes;
5798 DDSURFACEDESC2 ddsd;
5799 DDCAPS hal_caps;
5800 void *mem;
5802 static const struct
5804 DWORD fourcc;
5805 const char *name;
5806 DWORD support_flag;
5807 unsigned int block_width;
5808 unsigned int block_height;
5809 unsigned int block_size;
5810 BOOL create_size_checked, overlay;
5812 formats[] =
5814 {MAKEFOURCC('D','X','T','1'), "D3DFMT_DXT1", SUPPORT_DXT1, 4, 4, 8, TRUE, FALSE},
5815 {MAKEFOURCC('D','X','T','2'), "D3DFMT_DXT2", SUPPORT_DXT2, 4, 4, 16, TRUE, FALSE},
5816 {MAKEFOURCC('D','X','T','3'), "D3DFMT_DXT3", SUPPORT_DXT3, 4, 4, 16, TRUE, FALSE},
5817 {MAKEFOURCC('D','X','T','4'), "D3DFMT_DXT4", SUPPORT_DXT4, 4, 4, 16, TRUE, FALSE},
5818 {MAKEFOURCC('D','X','T','5'), "D3DFMT_DXT5", SUPPORT_DXT5, 4, 4, 16, TRUE, FALSE},
5819 {MAKEFOURCC('Y','U','Y','2'), "D3DFMT_YUY2", SUPPORT_YUY2, 2, 1, 4, FALSE, TRUE },
5820 {MAKEFOURCC('U','Y','V','Y'), "D3DFMT_UYVY", SUPPORT_UYVY, 2, 1, 4, FALSE, TRUE },
5822 static const struct
5824 DWORD caps, caps2;
5825 const char *name;
5826 BOOL overlay;
5828 types[] =
5830 /* DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY fails to create any fourcc
5831 * surface with DDERR_INVALIDPIXELFORMAT. Don't care about it for now.
5833 * Nvidia returns E_FAIL on DXTN DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY.
5834 * Other hw / drivers successfully create those surfaces. Ignore them, this
5835 * suggests that no game uses this, otherwise Nvidia would support it. */
5837 DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE, 0,
5838 "videomemory texture", FALSE
5841 DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY, 0,
5842 "videomemory overlay", TRUE
5845 DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE, 0,
5846 "systemmemory texture", FALSE
5849 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
5850 "managed texture", FALSE
5853 enum size_type
5855 SIZE_TYPE_ZERO,
5856 SIZE_TYPE_PITCH,
5857 SIZE_TYPE_SIZE,
5859 static const struct
5861 DWORD flags;
5862 enum size_type size_type;
5863 int rel_size;
5864 HRESULT hr;
5866 user_mem_tests[] =
5868 {DDSD_LINEARSIZE, SIZE_TYPE_ZERO, 0, DD_OK},
5869 {DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
5870 {DDSD_PITCH, SIZE_TYPE_ZERO, 0, DD_OK},
5871 {DDSD_PITCH, SIZE_TYPE_PITCH, 0, DD_OK},
5872 {DDSD_LPSURFACE, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
5873 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
5874 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_PITCH, 0, DDERR_INVALIDPARAMS},
5875 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DD_OK},
5876 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 1, DD_OK},
5877 {DDSD_LPSURFACE | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, -1, DDERR_INVALIDPARAMS},
5878 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_ZERO, 0, DDERR_INVALIDPARAMS},
5879 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_PITCH, 0, DDERR_INVALIDPARAMS},
5880 {DDSD_LPSURFACE | DDSD_PITCH, SIZE_TYPE_SIZE, 0, DDERR_INVALIDPARAMS},
5881 {DDSD_LPSURFACE | DDSD_PITCH | DDSD_LINEARSIZE, SIZE_TYPE_SIZE, 0, DDERR_INVALIDPARAMS},
5884 window = create_window();
5885 if (!(device = create_device(window, DDSCL_NORMAL)))
5887 skip("Failed to create a 3D device, skipping test.\n");
5888 DestroyWindow(window);
5889 return;
5892 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
5893 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
5894 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **) &ddraw);
5895 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
5896 IDirect3D7_Release(d3d);
5898 hr = IDirect3DDevice7_EnumTextureFormats(device, test_block_formats_creation_cb,
5899 &supported_fmts);
5900 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
5902 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
5903 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
5904 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5905 num_fourcc_codes * sizeof(*fourcc_codes));
5906 if (!fourcc_codes)
5907 goto cleanup;
5908 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
5909 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
5910 for (i = 0; i < num_fourcc_codes; i++)
5912 for (j = 0; j < ARRAY_SIZE(formats); ++j)
5914 if (fourcc_codes[i] == formats[j].fourcc)
5915 supported_overlay_fmts |= formats[j].support_flag;
5918 HeapFree(GetProcessHeap(), 0, fourcc_codes);
5920 memset(&hal_caps, 0, sizeof(hal_caps));
5921 hal_caps.dwSize = sizeof(hal_caps);
5922 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
5923 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
5925 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 2 * 2 * 16 + 1);
5927 for (i = 0; i < ARRAY_SIZE(formats); ++i)
5929 for (j = 0; j < ARRAY_SIZE(types); ++j)
5931 BOOL support;
5933 if (formats[i].overlay != types[j].overlay
5934 || (types[j].overlay && !(hal_caps.dwCaps & DDCAPS_OVERLAY)))
5935 continue;
5937 if (formats[i].overlay)
5938 support = supported_overlay_fmts & formats[i].support_flag;
5939 else
5940 support = supported_fmts & formats[i].support_flag;
5942 for (w = 1; w <= 8; w++)
5944 for (h = 1; h <= 8; h++)
5946 BOOL block_aligned = TRUE;
5947 BOOL todo = FALSE;
5949 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
5950 block_aligned = FALSE;
5952 memset(&ddsd, 0, sizeof(ddsd));
5953 ddsd.dwSize = sizeof(ddsd);
5954 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
5955 ddsd.ddsCaps.dwCaps = types[j].caps;
5956 ddsd.ddsCaps.dwCaps2 = types[j].caps2;
5957 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
5958 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
5959 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
5960 ddsd.dwWidth = w;
5961 ddsd.dwHeight = h;
5963 /* TODO: Handle power of two limitations. I cannot test the pow2
5964 * behavior on windows because I have no hardware that doesn't at
5965 * least support np2_conditional. There's probably no HW that
5966 * supports DXTN textures but no conditional np2 textures. */
5967 if (!support && !(types[j].caps & DDSCAPS_SYSTEMMEMORY))
5968 expect_hr = DDERR_INVALIDPARAMS;
5969 else if (formats[i].create_size_checked && !block_aligned)
5971 expect_hr = DDERR_INVALIDPARAMS;
5972 if (!(types[j].caps & DDSCAPS_TEXTURE))
5973 todo = TRUE;
5975 else
5976 expect_hr = D3D_OK;
5978 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
5979 todo_wine_if (todo)
5980 ok(hr == expect_hr,
5981 "Got unexpected hr %#x for format %s, resource type %s, size %ux%u, expected %#x.\n",
5982 hr, formats[i].name, types[j].name, w, h, expect_hr);
5984 if (SUCCEEDED(hr))
5985 IDirectDrawSurface7_Release(surface);
5990 if (formats[i].overlay)
5991 continue;
5993 for (j = 0; j < ARRAY_SIZE(user_mem_tests); ++j)
5995 memset(&ddsd, 0, sizeof(ddsd));
5996 ddsd.dwSize = sizeof(ddsd);
5997 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | user_mem_tests[j].flags;
5998 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE;
6000 switch (user_mem_tests[j].size_type)
6002 case SIZE_TYPE_ZERO:
6003 U1(ddsd).dwLinearSize = 0;
6004 break;
6006 case SIZE_TYPE_PITCH:
6007 U1(ddsd).dwLinearSize = 2 * formats[i].block_size;
6008 break;
6010 case SIZE_TYPE_SIZE:
6011 U1(ddsd).dwLinearSize = 2 * 2 * formats[i].block_size;
6012 break;
6014 U1(ddsd).dwLinearSize += user_mem_tests[j].rel_size;
6016 ddsd.lpSurface = mem;
6017 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
6018 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
6019 U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
6020 ddsd.dwWidth = 8;
6021 ddsd.dwHeight = 8;
6023 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6024 ok(hr == user_mem_tests[j].hr, "Test %u: Got unexpected hr %#x, format %s.\n", j, hr, formats[i].name);
6026 if (FAILED(hr))
6027 continue;
6029 memset(&ddsd, 0, sizeof(ddsd));
6030 ddsd.dwSize = sizeof(ddsd);
6031 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6032 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", j, hr);
6033 ok(ddsd.dwFlags == (DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_LINEARSIZE),
6034 "Test %u: Got unexpected flags %#x.\n", j, ddsd.dwFlags);
6035 if (user_mem_tests[j].flags & DDSD_LPSURFACE)
6036 ok(U1(ddsd).dwLinearSize == ~0u, "Test %u: Got unexpected linear size %#x.\n",
6037 j, U1(ddsd).dwLinearSize);
6038 else
6039 ok(U1(ddsd).dwLinearSize == 2 * 2 * formats[i].block_size,
6040 "Test %u: Got unexpected linear size %#x, expected %#x.\n",
6041 j, U1(ddsd).dwLinearSize, 2 * 2 * formats[i].block_size);
6042 IDirectDrawSurface7_Release(surface);
6046 HeapFree(GetProcessHeap(), 0, mem);
6047 cleanup:
6048 IDirectDraw7_Release(ddraw);
6049 IDirect3DDevice7_Release(device);
6050 DestroyWindow(window);
6053 struct format_support_check
6055 const DDPIXELFORMAT *format;
6056 BOOL supported;
6059 static HRESULT WINAPI test_unsupported_formats_cb(DDPIXELFORMAT *fmt, void *ctx)
6061 struct format_support_check *format = ctx;
6063 if (!memcmp(format->format, fmt, sizeof(*fmt)))
6065 format->supported = TRUE;
6066 return DDENUMRET_CANCEL;
6069 return DDENUMRET_OK;
6072 static void test_unsupported_formats(void)
6074 HRESULT hr;
6075 BOOL expect_success;
6076 HWND window;
6077 IDirectDraw7 *ddraw;
6078 IDirect3D7 *d3d;
6079 IDirect3DDevice7 *device;
6080 IDirectDrawSurface7 *surface;
6081 DDSURFACEDESC2 ddsd;
6082 unsigned int i, j;
6083 DWORD expected_caps;
6084 static const struct
6086 const char *name;
6087 DDPIXELFORMAT fmt;
6089 formats[] =
6092 "D3DFMT_A8R8G8B8",
6094 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
6095 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
6099 "D3DFMT_P8",
6101 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
6102 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
6106 static const DWORD caps[] = {0, DDSCAPS_SYSTEMMEMORY, DDSCAPS_VIDEOMEMORY};
6108 window = create_window();
6109 if (!(device = create_device(window, DDSCL_NORMAL)))
6111 skip("Failed to create a 3D device, skipping test.\n");
6112 DestroyWindow(window);
6113 return;
6116 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
6117 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
6118 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **) &ddraw);
6119 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
6120 IDirect3D7_Release(d3d);
6122 for (i = 0; i < ARRAY_SIZE(formats); ++i)
6124 struct format_support_check check = {&formats[i].fmt, FALSE};
6125 hr = IDirect3DDevice7_EnumTextureFormats(device, test_unsupported_formats_cb, &check);
6126 ok(SUCCEEDED(hr), "Failed to enumerate texture formats %#x.\n", hr);
6128 for (j = 0; j < ARRAY_SIZE(caps); ++j)
6130 memset(&ddsd, 0, sizeof(ddsd));
6131 ddsd.dwSize = sizeof(ddsd);
6132 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
6133 U4(ddsd).ddpfPixelFormat = formats[i].fmt;
6134 ddsd.dwWidth = 4;
6135 ddsd.dwHeight = 4;
6136 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | caps[j];
6138 if (caps[j] & DDSCAPS_VIDEOMEMORY && !check.supported)
6139 expect_success = FALSE;
6140 else
6141 expect_success = TRUE;
6143 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6144 ok(SUCCEEDED(hr) == expect_success,
6145 "Got unexpected hr %#x for format %s, caps %#x, expected %s.\n",
6146 hr, formats[i].name, caps[j], expect_success ? "success" : "failure");
6147 if (FAILED(hr))
6148 continue;
6150 memset(&ddsd, 0, sizeof(ddsd));
6151 ddsd.dwSize = sizeof(ddsd);
6152 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
6153 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
6155 if (caps[j] & DDSCAPS_VIDEOMEMORY)
6156 expected_caps = DDSCAPS_VIDEOMEMORY;
6157 else if (caps[j] & DDSCAPS_SYSTEMMEMORY)
6158 expected_caps = DDSCAPS_SYSTEMMEMORY;
6159 else if (check.supported)
6160 expected_caps = DDSCAPS_VIDEOMEMORY;
6161 else
6162 expected_caps = DDSCAPS_SYSTEMMEMORY;
6164 ok(ddsd.ddsCaps.dwCaps & expected_caps,
6165 "Expected capability %#x, format %s, input cap %#x.\n",
6166 expected_caps, formats[i].name, caps[j]);
6168 IDirectDrawSurface7_Release(surface);
6172 IDirectDraw7_Release(ddraw);
6173 IDirect3DDevice7_Release(device);
6174 DestroyWindow(window);
6177 static void test_rt_caps(const GUID *device_guid)
6179 PALETTEENTRY palette_entries[256];
6180 IDirectDrawPalette *palette;
6181 BOOL software_device;
6182 IDirectDraw7 *ddraw;
6183 DDPIXELFORMAT z_fmt;
6184 IDirect3D7 *d3d;
6185 DDCAPS hal_caps;
6186 unsigned int i;
6187 ULONG refcount;
6188 HWND window;
6189 HRESULT hr;
6191 static const DDPIXELFORMAT p8_fmt =
6193 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
6194 {8}, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000},
6197 const struct
6199 const DDPIXELFORMAT *pf;
6200 DWORD caps_in;
6201 DWORD caps2_in;
6202 HRESULT create_device_hr;
6203 HRESULT set_rt_hr, alternative_set_rt_hr;
6205 test_data[] =
6208 NULL,
6209 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
6211 D3D_OK,
6212 D3D_OK,
6213 D3D_OK,
6216 NULL,
6217 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
6219 D3D_OK,
6220 D3D_OK,
6221 D3D_OK,
6224 NULL,
6225 DDSCAPS_OFFSCREENPLAIN,
6227 DDERR_INVALIDCAPS,
6228 DDERR_INVALIDCAPS,
6229 DDERR_INVALIDCAPS,
6232 NULL,
6233 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
6235 D3DERR_SURFACENOTINVIDMEM,
6236 DDERR_INVALIDPARAMS,
6237 D3D_OK,
6240 NULL,
6241 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
6243 DDERR_INVALIDCAPS,
6244 DDERR_INVALIDCAPS,
6245 DDERR_INVALIDCAPS,
6248 NULL,
6249 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY,
6251 D3D_OK,
6252 D3D_OK,
6253 D3D_OK,
6256 NULL,
6257 DDSCAPS_3DDEVICE,
6259 D3D_OK,
6260 D3D_OK,
6261 D3D_OK,
6264 NULL,
6267 DDERR_INVALIDCAPS,
6268 DDERR_INVALIDCAPS,
6269 DDERR_INVALIDCAPS,
6272 NULL,
6273 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
6275 D3DERR_SURFACENOTINVIDMEM,
6276 DDERR_INVALIDPARAMS,
6277 D3D_OK,
6280 NULL,
6281 DDSCAPS_SYSTEMMEMORY,
6283 DDERR_INVALIDCAPS,
6284 DDERR_INVALIDCAPS,
6285 DDERR_INVALIDCAPS,
6288 NULL,
6289 DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE,
6290 DDSCAPS2_TEXTUREMANAGE,
6291 D3DERR_SURFACENOTINVIDMEM,
6292 DDERR_INVALIDPARAMS,
6293 D3D_OK,
6296 NULL,
6297 DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE,
6298 DDSCAPS2_D3DTEXTUREMANAGE,
6299 D3DERR_SURFACENOTINVIDMEM,
6300 DDERR_INVALIDPARAMS,
6301 D3D_OK,
6304 &p8_fmt,
6307 DDERR_INVALIDCAPS,
6308 DDERR_INVALIDCAPS,
6309 DDERR_INVALIDCAPS,
6312 &p8_fmt,
6313 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
6315 DDERR_NOPALETTEATTACHED,
6316 DDERR_INVALIDCAPS,
6317 DDERR_INVALIDCAPS,
6320 &p8_fmt,
6321 DDSCAPS_OFFSCREENPLAIN,
6323 DDERR_INVALIDCAPS,
6324 DDERR_INVALIDCAPS,
6325 DDERR_INVALIDCAPS,
6328 &p8_fmt,
6329 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE,
6331 DDERR_NOPALETTEATTACHED,
6332 DDERR_INVALIDCAPS,
6333 DDERR_INVALIDCAPS,
6336 &p8_fmt,
6337 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
6339 DDERR_INVALIDCAPS,
6340 DDERR_INVALIDCAPS,
6341 DDERR_INVALIDCAPS,
6344 &z_fmt,
6345 DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER,
6347 DDERR_INVALIDCAPS,
6348 DDERR_INVALIDPIXELFORMAT,
6349 DDERR_INVALIDPIXELFORMAT,
6352 &z_fmt,
6353 DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
6355 DDERR_INVALIDCAPS,
6356 DDERR_INVALIDPIXELFORMAT,
6357 DDERR_INVALIDPIXELFORMAT,
6360 &z_fmt,
6361 DDSCAPS_ZBUFFER,
6363 DDERR_INVALIDCAPS,
6364 DDERR_INVALIDCAPS,
6365 DDERR_INVALIDCAPS,
6368 &z_fmt,
6369 DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_ZBUFFER,
6371 DDERR_INVALIDCAPS,
6372 DDERR_INVALIDPARAMS,
6373 DDERR_INVALIDPIXELFORMAT,
6376 &z_fmt,
6377 DDSCAPS_SYSTEMMEMORY | DDSCAPS_ZBUFFER,
6379 DDERR_INVALIDCAPS,
6380 DDERR_INVALIDCAPS,
6381 DDERR_INVALIDCAPS,
6385 software_device = is_software_device_type(device_guid);
6387 window = create_window();
6388 ddraw = create_ddraw();
6389 ok(!!ddraw, "Failed to create a ddraw object.\n");
6390 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6391 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6393 if (FAILED(IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d)))
6395 skip("D3D interface is not available, skipping test.\n");
6396 goto done;
6399 memset(&z_fmt, 0, sizeof(z_fmt));
6400 hr = IDirect3D7_EnumZBufferFormats(d3d, device_guid, enum_z_fmt, &z_fmt);
6401 if (FAILED(hr) || !z_fmt.dwSize)
6403 skip("No depth buffer formats available, software_device %u, skipping test.\n", software_device);
6404 IDirect3D7_Release(d3d);
6405 goto done;
6408 memset(palette_entries, 0, sizeof(palette_entries));
6409 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
6410 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6412 memset(&hal_caps, 0, sizeof(hal_caps));
6413 hal_caps.dwSize = sizeof(hal_caps);
6414 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
6415 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
6417 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
6419 IDirectDrawSurface7 *surface, *rt, *expected_rt, *tmp;
6420 DDSURFACEDESC2 surface_desc;
6421 DWORD caps_in, expected_caps;
6422 IDirect3DDevice7 *device;
6423 HRESULT expected_hr;
6425 caps_in = test_data[i].caps_in;
6427 memset(&surface_desc, 0, sizeof(surface_desc));
6428 surface_desc.dwSize = sizeof(surface_desc);
6429 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6430 surface_desc.ddsCaps.dwCaps = caps_in;
6431 surface_desc.ddsCaps.dwCaps2 = test_data[i].caps2_in;
6432 if (test_data[i].pf)
6434 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
6435 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
6437 surface_desc.dwWidth = 640;
6438 surface_desc.dwHeight = 480;
6439 if ((caps_in & DDSCAPS_VIDEOMEMORY) && !(hal_caps.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
6440 expected_hr = DDERR_NODIRECTDRAWHW;
6441 else
6442 expected_hr = DD_OK;
6443 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6444 ok(hr == expected_hr || (software_device && (surface_desc.ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER))
6445 == (DDSCAPS_VIDEOMEMORY | DDSCAPS_ZBUFFER) && hr == DDERR_UNSUPPORTED)
6446 || broken(software_device && test_data[i].pf == &p8_fmt && hr == DDERR_INVALIDPIXELFORMAT),
6447 "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
6448 if (FAILED(hr))
6449 continue;
6451 memset(&surface_desc, 0, sizeof(surface_desc));
6452 surface_desc.dwSize = sizeof(surface_desc);
6453 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
6454 ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
6456 if ((caps_in & DDSCAPS_SYSTEMMEMORY) || (test_data[i].caps2_in & (DDSCAPS2_D3DTEXTUREMANAGE
6457 | DDSCAPS2_TEXTUREMANAGE)) || !(hal_caps.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
6458 expected_caps = caps_in | DDSCAPS_SYSTEMMEMORY;
6459 else
6460 expected_caps = caps_in | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
6462 ok(surface_desc.ddsCaps.dwCaps == expected_caps || (test_data[i].pf == &p8_fmt
6463 && surface_desc.ddsCaps.dwCaps == (caps_in | DDSCAPS_SYSTEMMEMORY))
6464 || (software_device && test_data[i].pf == &z_fmt
6465 && surface_desc.ddsCaps.dwCaps == (caps_in | DDSCAPS_SYSTEMMEMORY)),
6466 "Got unexpected caps %#x, expected %#x, test %u, software_device %u.\n",
6467 surface_desc.ddsCaps.dwCaps, expected_caps, i, software_device);
6469 ok(surface_desc.ddsCaps.dwCaps2 == test_data[i].caps2_in,
6470 "Got unexpected caps2 %#x, expected %#x, test %u, software_device %u.\n",
6471 surface_desc.ddsCaps.dwCaps2, test_data[i].caps2_in, i, software_device);
6473 hr = IDirect3D7_CreateDevice(d3d, device_guid, surface, &device);
6474 ok((!software_device && hr == test_data[i].create_device_hr)
6475 || (software_device && (hr == (test_data[i].create_device_hr == D3DERR_SURFACENOTINVIDMEM
6476 ? DD_OK : test_data[i].create_device_hr))),
6477 "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
6478 if (FAILED(hr))
6480 if (hr == DDERR_NOPALETTEATTACHED)
6482 hr = IDirectDrawSurface7_SetPalette(surface, palette);
6483 ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
6484 hr = IDirect3D7_CreateDevice(d3d, device_guid, surface, &device);
6485 if (surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
6486 ok(hr == DDERR_INVALIDPIXELFORMAT, "Got unexpected hr %#x, test %u, software_device %u.\n",
6487 hr, i, software_device);
6488 else if (software_device)
6489 todo_wine
6490 ok(hr == E_FAIL, "Got unexpected hr %#x, test %u, software_device %u.\n",
6491 hr, i, software_device);
6492 else
6493 ok(hr == D3DERR_SURFACENOTINVIDMEM, "Got unexpected hr %#x, test %u, software_device %u.\n",
6494 hr, i, software_device);
6496 IDirectDrawSurface7_Release(surface);
6498 memset(&surface_desc, 0, sizeof(surface_desc));
6499 surface_desc.dwSize = sizeof(surface_desc);
6500 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6501 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
6502 surface_desc.dwWidth = 640;
6503 surface_desc.dwHeight = 480;
6504 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6505 ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
6507 hr = IDirect3D7_CreateDevice(d3d, device_guid, surface, &device);
6508 ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
6511 memset(&surface_desc, 0, sizeof(surface_desc));
6512 surface_desc.dwSize = sizeof(surface_desc);
6513 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6514 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
6515 surface_desc.ddsCaps.dwCaps2 = test_data[i].caps2_in;
6516 if (test_data[i].pf)
6518 surface_desc.dwFlags |= DDSD_PIXELFORMAT;
6519 U4(surface_desc).ddpfPixelFormat = *test_data[i].pf;
6521 surface_desc.dwWidth = 640;
6522 surface_desc.dwHeight = 480;
6523 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &rt, NULL);
6524 ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
6526 hr = IDirect3DDevice7_SetRenderTarget(device, rt, 0);
6527 ok(hr == test_data[i].set_rt_hr || (software_device && hr == DDERR_NOPALETTEATTACHED)
6528 || hr == test_data[i].alternative_set_rt_hr,
6529 "Got unexpected hr %#x, test %u, software_device %u.\n",
6530 hr, i, software_device);
6531 if (SUCCEEDED(hr) || hr == DDERR_INVALIDPIXELFORMAT)
6532 expected_rt = rt;
6533 else
6534 expected_rt = surface;
6536 hr = IDirect3DDevice7_GetRenderTarget(device, &tmp);
6537 ok(hr == DD_OK, "Got unexpected hr %#x, test %u, software_device %u.\n", hr, i, software_device);
6538 ok(tmp == expected_rt, "Got unexpected rt %p, test %u, software_device %u.\n", tmp, i, software_device);
6540 IDirectDrawSurface7_Release(tmp);
6541 IDirectDrawSurface7_Release(rt);
6542 refcount = IDirect3DDevice7_Release(device);
6543 ok(refcount == 0, "Test %u: The device was not properly freed, refcount %u.\n", i, refcount);
6544 refcount = IDirectDrawSurface7_Release(surface);
6545 ok(refcount == 0, "Test %u: The surface was not properly freed, refcount %u.\n", i, refcount);
6548 refcount = IDirectDrawPalette_Release(palette);
6549 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
6550 IDirect3D7_Release(d3d);
6552 done:
6553 refcount = IDirectDraw7_Release(ddraw);
6554 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
6555 DestroyWindow(window);
6558 static void test_primary_caps(void)
6560 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
6561 IDirectDrawSurface7 *surface;
6562 DDSURFACEDESC2 surface_desc;
6563 IDirectDraw7 *ddraw;
6564 unsigned int i;
6565 ULONG refcount;
6566 HWND window;
6567 HRESULT hr;
6569 static const struct
6571 DWORD coop_level;
6572 DWORD caps_in;
6573 DWORD back_buffer_count;
6574 HRESULT hr;
6575 DWORD caps_out;
6577 test_data[] =
6580 DDSCL_NORMAL,
6581 DDSCAPS_PRIMARYSURFACE,
6582 ~0u,
6583 DD_OK,
6584 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE,
6587 DDSCL_NORMAL,
6588 DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE,
6589 ~0u,
6590 DDERR_INVALIDCAPS,
6591 ~0u,
6594 DDSCL_NORMAL,
6595 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER,
6596 ~0u,
6597 DDERR_INVALIDCAPS,
6598 ~0u,
6601 DDSCL_NORMAL,
6602 DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER,
6603 ~0u,
6604 DDERR_INVALIDCAPS,
6605 ~0u,
6608 DDSCL_NORMAL,
6609 DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP,
6610 ~0u,
6611 DDERR_INVALIDCAPS,
6612 ~0u,
6615 DDSCL_NORMAL,
6616 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX,
6617 ~0u,
6618 DDERR_INVALIDCAPS,
6619 ~0u,
6622 DDSCL_NORMAL,
6623 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
6624 ~0u,
6625 DDERR_INVALIDCAPS,
6626 ~0u,
6629 DDSCL_NORMAL,
6630 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
6632 DDERR_INVALIDCAPS,
6633 ~0u,
6636 DDSCL_NORMAL,
6637 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
6639 DDERR_NOEXCLUSIVEMODE,
6640 ~0u,
6643 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
6644 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
6646 DDERR_INVALIDCAPS,
6647 ~0u,
6650 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
6651 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP,
6653 DD_OK,
6654 DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP | DDSCAPS_COMPLEX,
6657 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
6658 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER,
6660 DDERR_INVALIDCAPS,
6661 ~0u,
6664 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,
6665 DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_BACKBUFFER,
6667 DDERR_INVALIDCAPS,
6668 ~0u,
6672 window = create_window();
6673 ddraw = create_ddraw();
6674 ok(!!ddraw, "Failed to create a ddraw object.\n");
6676 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
6678 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, test_data[i].coop_level);
6679 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6681 memset(&surface_desc, 0, sizeof(surface_desc));
6682 surface_desc.dwSize = sizeof(surface_desc);
6683 surface_desc.dwFlags = DDSD_CAPS;
6684 if (test_data[i].back_buffer_count != ~0u)
6685 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
6686 surface_desc.ddsCaps.dwCaps = test_data[i].caps_in;
6687 U5(surface_desc).dwBackBufferCount = test_data[i].back_buffer_count;
6688 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
6689 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
6690 if (FAILED(hr))
6691 continue;
6693 memset(&surface_desc, 0, sizeof(surface_desc));
6694 surface_desc.dwSize = sizeof(surface_desc);
6695 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
6696 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
6697 ok((surface_desc.ddsCaps.dwCaps & ~placement) == test_data[i].caps_out,
6698 "Test %u: Got unexpected caps %#x, expected %#x.\n",
6699 i, surface_desc.ddsCaps.dwCaps, test_data[i].caps_out);
6701 IDirectDrawSurface7_Release(surface);
6704 refcount = IDirectDraw7_Release(ddraw);
6705 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
6706 DestroyWindow(window);
6709 static void test_surface_lock(void)
6711 IDirectDraw7 *ddraw;
6712 IDirect3D7 *d3d = NULL;
6713 IDirectDrawSurface7 *surface;
6714 IDirect3DDevice7 *device;
6715 HRESULT hr, expected_hr;
6716 HWND window;
6717 unsigned int i;
6718 DDSURFACEDESC2 ddsd;
6719 ULONG refcount;
6720 DDPIXELFORMAT z_fmt;
6721 BOOL hal_ok = FALSE;
6722 const GUID *devtype = &IID_IDirect3DHALDevice;
6723 D3DDEVICEDESC7 device_desc;
6724 BOOL cubemap_supported;
6725 static const struct
6727 DWORD caps;
6728 DWORD caps2;
6729 const char *name;
6731 tests[] =
6734 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY,
6736 "videomemory offscreenplain"
6739 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY,
6741 "systemmemory offscreenplain"
6744 DDSCAPS_PRIMARYSURFACE,
6746 "primary"
6749 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
6751 "videomemory texture"
6754 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY,
6755 DDSCAPS2_OPAQUE,
6756 "opaque videomemory texture"
6759 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY,
6761 "systemmemory texture"
6764 DDSCAPS_TEXTURE,
6765 DDSCAPS2_TEXTUREMANAGE,
6766 "managed texture"
6769 DDSCAPS_TEXTURE,
6770 DDSCAPS2_D3DTEXTUREMANAGE,
6771 "managed texture"
6774 DDSCAPS_TEXTURE,
6775 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_OPAQUE,
6776 "opaque managed texture"
6779 DDSCAPS_TEXTURE,
6780 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_OPAQUE,
6781 "opaque managed texture"
6784 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE,
6786 "render target"
6789 DDSCAPS_ZBUFFER,
6791 "Z buffer"
6794 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY,
6795 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
6796 "videomemory cube"
6799 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY,
6800 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_OPAQUE,
6801 "opaque videomemory cube"
6804 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_SYSTEMMEMORY,
6805 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
6806 "systemmemory cube"
6809 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
6810 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
6811 "managed cube"
6814 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
6815 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES,
6816 "managed cube"
6819 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
6820 DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_OPAQUE,
6821 "opaque managed cube"
6824 DDSCAPS_TEXTURE | DDSCAPS_COMPLEX,
6825 DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_OPAQUE,
6826 "opaque managed cube"
6830 window = create_window();
6831 ddraw = create_ddraw();
6832 ok(!!ddraw, "Failed to create a ddraw object.\n");
6833 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
6834 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
6836 if (FAILED(IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d)))
6838 skip("D3D interface is not available, skipping test.\n");
6839 goto done;
6842 hr = IDirect3D7_EnumDevices(d3d, enum_devtype_cb, &hal_ok);
6843 ok(SUCCEEDED(hr), "Failed to enumerate devices, hr %#x.\n", hr);
6844 if (hal_ok)
6845 devtype = &IID_IDirect3DTnLHalDevice;
6847 memset(&z_fmt, 0, sizeof(z_fmt));
6848 hr = IDirect3D7_EnumZBufferFormats(d3d, devtype, enum_z_fmt, &z_fmt);
6849 if (FAILED(hr) || !z_fmt.dwSize)
6851 skip("No depth buffer formats available, skipping test.\n");
6852 goto done;
6855 memset(&ddsd, 0, sizeof(ddsd));
6856 ddsd.dwSize = sizeof(ddsd);
6857 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6858 ddsd.dwWidth = 64;
6859 ddsd.dwHeight = 64;
6860 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
6861 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6862 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6864 hr = IDirect3D7_CreateDevice(d3d, devtype, surface, &device);
6865 ok(SUCCEEDED(hr), "Failed to create device, hr %#x.\n", hr);
6866 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
6867 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6868 cubemap_supported = !!(device_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP);
6869 IDirect3DDevice7_Release(device);
6871 IDirectDrawSurface7_Release(surface);
6873 for (i = 0; i < ARRAY_SIZE(tests); ++i)
6875 if (!cubemap_supported && tests[i].caps2 & DDSCAPS2_CUBEMAP)
6876 continue;
6878 memset(&ddsd, 0, sizeof(ddsd));
6879 ddsd.dwSize = sizeof(ddsd);
6880 ddsd.dwFlags = DDSD_CAPS;
6881 if (!(tests[i].caps & DDSCAPS_PRIMARYSURFACE))
6883 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
6884 ddsd.dwWidth = 64;
6885 ddsd.dwHeight = 64;
6887 if (tests[i].caps & DDSCAPS_ZBUFFER)
6889 ddsd.dwFlags |= DDSD_PIXELFORMAT;
6890 U4(ddsd).ddpfPixelFormat = z_fmt;
6892 ddsd.ddsCaps.dwCaps = tests[i].caps;
6893 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
6895 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6896 ok(SUCCEEDED(hr), "Failed to create surface, type %s, hr %#x.\n", tests[i].name, hr);
6898 memset(&ddsd, 0, sizeof(ddsd));
6899 ddsd.dwSize = sizeof(ddsd);
6900 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
6901 ok(SUCCEEDED(hr), "Failed to lock surface, type %s, hr %#x.\n", tests[i].name, hr);
6902 if (SUCCEEDED(hr))
6904 ok(ddsd.dwSize == sizeof(ddsd), "Got unexpected dwSize %u, type %s.\n", ddsd.dwSize, tests[i].name);
6905 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6906 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
6909 memset(&ddsd, 0, sizeof(ddsd));
6910 expected_hr = tests[i].caps & DDSCAPS_TEXTURE && !(tests[i].caps & DDSCAPS_VIDEOMEMORY)
6911 ? DD_OK : DDERR_INVALIDPARAMS;
6912 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL);
6913 ok(hr == expected_hr, "Got hr %#x, expected %#x, type %s.\n", hr, expected_hr, tests[i].name);
6914 if (SUCCEEDED(hr))
6916 ok(!ddsd.dwSize, "Got unexpected dwSize %u, type %s.\n", ddsd.dwSize, tests[i].name);
6917 ok(!!ddsd.lpSurface, "Got NULL lpSurface, type %s.\n", tests[i].name);
6918 hr = IDirectDrawSurface7_Unlock(surface, NULL);
6919 ok(SUCCEEDED(hr), "Failed to unlock surface, type %s, hr %#x.\n", tests[i].name, hr);
6922 IDirectDrawSurface7_Release(surface);
6925 done:
6926 if (d3d)
6927 IDirect3D7_Release(d3d);
6928 refcount = IDirectDraw7_Release(ddraw);
6929 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
6930 DestroyWindow(window);
6933 static void test_surface_discard(void)
6935 IDirect3DDevice7 *device;
6936 IDirect3D7 *d3d;
6937 IDirectDraw7 *ddraw;
6938 HRESULT hr;
6939 HWND window;
6940 DDSURFACEDESC2 ddsd;
6941 IDirectDrawSurface7 *surface, *target;
6942 void *addr;
6943 static const struct
6945 DWORD caps, caps2;
6946 BOOL discard;
6948 tests[] =
6950 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, TRUE},
6951 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
6952 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, TRUE},
6953 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, FALSE},
6954 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE},
6955 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
6956 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE},
6957 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE},
6959 unsigned int i;
6961 window = create_window();
6963 for (i = 0; i < ARRAY_SIZE(tests); ++i)
6965 BOOL discarded;
6967 /* Sigh. Anything other than the first run of the loop randomly fails with
6968 * DDERR_SURFACELOST on my Radeon Pro 560 on Win10 19.09. Most of the time
6969 * the blit fails, but with sleeps added between surface creation and lock
6970 * the lock can fail too. Interestingly ddraw claims the render target has
6971 * been lost, not the test surface.
6973 * Recreating ddraw every iteration seems to fix this. */
6974 if (!(device = create_device(window, DDSCL_NORMAL)))
6976 skip("Failed to create a 3D device, skipping test.\n");
6977 DestroyWindow(window);
6978 return;
6980 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
6981 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
6982 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
6983 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
6984 hr = IDirect3DDevice7_GetRenderTarget(device, &target);
6985 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
6987 memset(&ddsd, 0, sizeof(ddsd));
6988 ddsd.dwSize = sizeof(ddsd);
6989 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
6990 ddsd.ddsCaps.dwCaps = tests[i].caps;
6991 ddsd.ddsCaps.dwCaps2 = tests[i].caps2;
6992 ddsd.dwWidth = 64;
6993 ddsd.dwHeight = 64;
6994 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
6995 ok(SUCCEEDED(hr), "Failed to create offscreen surface, hr %#x, case %u.\n", hr, i);
6997 memset(&ddsd, 0, sizeof(ddsd));
6998 ddsd.dwSize = sizeof(ddsd);
6999 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, 0, NULL);
7000 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7001 addr = ddsd.lpSurface;
7002 hr = IDirectDrawSurface7_Unlock(surface, NULL);
7003 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7005 memset(&ddsd, 0, sizeof(ddsd));
7006 ddsd.dwSize = sizeof(ddsd);
7007 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
7008 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7009 discarded = ddsd.lpSurface != addr;
7010 hr = IDirectDrawSurface7_Unlock(surface, NULL);
7011 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7013 hr = IDirectDrawSurface7_Blt(target, NULL, surface, NULL, DDBLT_WAIT, NULL);
7014 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
7016 memset(&ddsd, 0, sizeof(ddsd));
7017 ddsd.dwSize = sizeof(ddsd);
7018 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL);
7019 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7020 discarded |= ddsd.lpSurface != addr;
7021 hr = IDirectDrawSurface7_Unlock(surface, NULL);
7022 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7024 IDirectDrawSurface7_Release(surface);
7026 /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler,
7027 * AMD r500, evergreen). Windows XP, at least on AMD r200, does not. */
7028 ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i);
7030 IDirectDrawSurface7_Release(target);
7031 IDirectDraw7_Release(ddraw);
7032 IDirect3D7_Release(d3d);
7033 IDirect3DDevice7_Release(device);
7036 DestroyWindow(window);
7039 static void test_flip(void)
7041 const DWORD placement = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
7042 IDirectDrawSurface7 *frontbuffer, *backbuffer1, *backbuffer2, *backbuffer3, *surface;
7043 DDSCAPS2 caps = {DDSCAPS_FLIP, 0, 0, {0}};
7044 DDSURFACEDESC2 surface_desc;
7045 D3DDEVICEDESC7 device_desc;
7046 IDirect3DDevice7 *device;
7047 BOOL sysmem_primary;
7048 IDirectDraw7 *ddraw;
7049 DWORD expected_caps;
7050 unsigned int i;
7051 D3DCOLOR color;
7052 ULONG refcount;
7053 HWND window;
7054 HRESULT hr;
7056 static const struct
7058 const char *name;
7059 DWORD caps;
7061 test_data[] =
7063 {"PRIMARYSURFACE", DDSCAPS_PRIMARYSURFACE},
7064 {"OFFSCREENPLAIN", DDSCAPS_OFFSCREENPLAIN},
7065 {"TEXTURE", DDSCAPS_TEXTURE},
7068 window = create_window();
7069 ddraw = create_ddraw();
7070 ok(!!ddraw, "Failed to create a ddraw object.\n");
7072 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7073 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7075 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
7077 /* Creating a flippable texture induces a BSoD on some versions of the
7078 * Intel graphics driver. At least Intel GMA 950 with driver version
7079 * 6.14.10.4926 on Windows XP SP3 is affected. */
7080 if ((test_data[i].caps & DDSCAPS_TEXTURE) && ddraw_is_intel(ddraw))
7082 win_skip("Skipping flippable texture test.\n");
7083 continue;
7086 memset(&surface_desc, 0, sizeof(surface_desc));
7087 surface_desc.dwSize = sizeof(surface_desc);
7088 surface_desc.dwFlags = DDSD_CAPS;
7089 if (!(test_data[i].caps & DDSCAPS_PRIMARYSURFACE))
7090 surface_desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
7091 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
7092 surface_desc.dwWidth = 512;
7093 surface_desc.dwHeight = 512;
7094 U5(surface_desc).dwBackBufferCount = 3;
7095 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
7096 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
7098 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_FLIP;
7099 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
7100 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
7101 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
7103 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_COMPLEX;
7104 surface_desc.ddsCaps.dwCaps |= DDSCAPS_FLIP;
7105 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
7106 ok(hr == DDERR_INVALIDCAPS, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
7108 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
7109 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
7110 if (is_ddraw64 && test_data[i].caps & DDSCAPS_TEXTURE)
7111 todo_wine ok(hr == E_NOINTERFACE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
7112 else todo_wine_if(test_data[i].caps & DDSCAPS_TEXTURE)
7113 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
7114 if (FAILED(hr))
7115 continue;
7117 memset(&surface_desc, 0, sizeof(surface_desc));
7118 surface_desc.dwSize = sizeof(surface_desc);
7119 hr = IDirectDrawSurface7_GetSurfaceDesc(frontbuffer, &surface_desc);
7120 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
7121 expected_caps = DDSCAPS_FRONTBUFFER | DDSCAPS_COMPLEX | DDSCAPS_FLIP | test_data[i].caps;
7122 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
7123 expected_caps |= DDSCAPS_VISIBLE;
7124 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
7125 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
7126 sysmem_primary = surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY;
7128 hr = IDirectDrawSurface7_GetAttachedSurface(frontbuffer, &caps, &backbuffer1);
7129 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
7130 memset(&surface_desc, 0, sizeof(surface_desc));
7131 surface_desc.dwSize = sizeof(surface_desc);
7132 hr = IDirectDrawSurface7_GetSurfaceDesc(backbuffer1, &surface_desc);
7133 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
7134 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
7135 test_data[i].name, U5(surface_desc).dwBackBufferCount);
7136 expected_caps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER);
7137 expected_caps |= DDSCAPS_BACKBUFFER;
7138 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
7139 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
7141 hr = IDirectDrawSurface7_GetAttachedSurface(backbuffer1, &caps, &backbuffer2);
7142 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
7143 memset(&surface_desc, 0, sizeof(surface_desc));
7144 surface_desc.dwSize = sizeof(surface_desc);
7145 hr = IDirectDrawSurface7_GetSurfaceDesc(backbuffer2, &surface_desc);
7146 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
7147 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
7148 test_data[i].name, U5(surface_desc).dwBackBufferCount);
7149 expected_caps &= ~DDSCAPS_BACKBUFFER;
7150 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
7151 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
7153 hr = IDirectDrawSurface7_GetAttachedSurface(backbuffer2, &caps, &backbuffer3);
7154 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
7155 memset(&surface_desc, 0, sizeof(surface_desc));
7156 surface_desc.dwSize = sizeof(surface_desc);
7157 hr = IDirectDrawSurface7_GetSurfaceDesc(backbuffer3, &surface_desc);
7158 ok(SUCCEEDED(hr), "%s: Failed to get surface desc, hr %#x.\n", test_data[i].name, hr);
7159 ok(!U5(surface_desc).dwBackBufferCount, "%s: Got unexpected back buffer count %u.\n",
7160 test_data[i].name, U5(surface_desc).dwBackBufferCount);
7161 ok((surface_desc.ddsCaps.dwCaps & ~placement) == expected_caps,
7162 "%s: Got unexpected caps %#x.\n", test_data[i].name, surface_desc.ddsCaps.dwCaps);
7164 hr = IDirectDrawSurface7_GetAttachedSurface(backbuffer3, &caps, &surface);
7165 ok(SUCCEEDED(hr), "%s: Failed to get attached surface, hr %#x.\n", test_data[i].name, hr);
7166 ok(surface == frontbuffer, "%s: Got unexpected surface %p, expected %p.\n",
7167 test_data[i].name, surface, frontbuffer);
7168 IDirectDrawSurface7_Release(surface);
7170 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL | DDSCL_FULLSCREEN);
7171 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
7172 hr = IDirectDrawSurface7_IsLost(frontbuffer);
7173 ok(hr == DD_OK, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
7174 hr = IDirectDrawSurface7_Flip(frontbuffer, NULL, DDFLIP_WAIT);
7175 if (test_data[i].caps & DDSCAPS_PRIMARYSURFACE)
7176 ok(hr == DDERR_NOEXCLUSIVEMODE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
7177 else
7178 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
7179 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7180 ok(SUCCEEDED(hr), "%s: Failed to set cooperative level, hr %#x.\n", test_data[i].name, hr);
7181 hr = IDirectDrawSurface7_IsLost(frontbuffer);
7182 todo_wine ok(hr == DDERR_SURFACELOST, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
7183 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
7184 ok(SUCCEEDED(hr), "%s: Failed to restore surfaces, hr %#x.\n", test_data[i].name, hr);
7186 memset(&surface_desc, 0, sizeof(surface_desc));
7187 surface_desc.dwSize = sizeof(surface_desc);
7188 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7189 surface_desc.ddsCaps.dwCaps = 0;
7190 surface_desc.dwWidth = 640;
7191 surface_desc.dwHeight = 480;
7192 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
7193 ok(SUCCEEDED(hr), "%s: Failed to create surface, hr %#x.\n", test_data[i].name, hr);
7194 hr = IDirectDrawSurface7_Flip(frontbuffer, surface, DDFLIP_WAIT);
7195 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
7196 IDirectDrawSurface7_Release(surface);
7198 hr = IDirectDrawSurface7_Flip(frontbuffer, frontbuffer, DDFLIP_WAIT);
7199 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
7200 hr = IDirectDrawSurface7_Flip(backbuffer1, NULL, DDFLIP_WAIT);
7201 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
7202 hr = IDirectDrawSurface7_Flip(backbuffer2, NULL, DDFLIP_WAIT);
7203 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
7204 hr = IDirectDrawSurface7_Flip(backbuffer3, NULL, DDFLIP_WAIT);
7205 ok(hr == DDERR_NOTFLIPPABLE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
7207 /* The Nvidia Geforce 7 driver cannot do a color fill on a texture backbuffer after
7208 * the backbuffer has been locked. Do it ourselves as a workaround. Unlike ddraw1
7209 * and 2 GetSurfaceDesc does not cause issues in ddraw4 and ddraw7. */
7210 fill_surface(backbuffer1, 0xffff0000);
7211 fill_surface(backbuffer2, 0xff00ff00);
7212 fill_surface(backbuffer3, 0xff0000ff);
7214 hr = IDirectDrawSurface7_Flip(frontbuffer, NULL, DDFLIP_WAIT);
7215 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
7216 color = get_surface_color(backbuffer1, 320, 240);
7217 /* The testbot seems to just copy the contents of one surface to all the
7218 * others, instead of properly flipping. */
7219 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
7220 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7221 color = get_surface_color(backbuffer2, 320, 240);
7222 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7223 fill_surface(backbuffer3, 0xffff0000);
7225 hr = IDirectDrawSurface7_Flip(frontbuffer, NULL, DDFLIP_WAIT);
7226 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
7227 color = get_surface_color(backbuffer1, 320, 240);
7228 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
7229 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7230 color = get_surface_color(backbuffer2, 320, 240);
7231 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7232 fill_surface(backbuffer3, 0xff00ff00);
7234 hr = IDirectDrawSurface7_Flip(frontbuffer, NULL, DDFLIP_WAIT);
7235 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
7236 color = get_surface_color(backbuffer1, 320, 240);
7237 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
7238 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7239 color = get_surface_color(backbuffer2, 320, 240);
7240 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7241 fill_surface(backbuffer3, 0xff0000ff);
7243 hr = IDirectDrawSurface7_Flip(frontbuffer, backbuffer1, DDFLIP_WAIT);
7244 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
7245 color = get_surface_color(backbuffer2, 320, 240);
7246 ok(compare_color(color, 0x0000ff00, 1) || broken(sysmem_primary && compare_color(color, 0x000000ff, 1)),
7247 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7248 color = get_surface_color(backbuffer3, 320, 240);
7249 ok(compare_color(color, 0x000000ff, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7250 fill_surface(backbuffer1, 0xffff0000);
7252 hr = IDirectDrawSurface7_Flip(frontbuffer, backbuffer2, DDFLIP_WAIT);
7253 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
7254 color = get_surface_color(backbuffer1, 320, 240);
7255 ok(compare_color(color, 0x00ff0000, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7256 color = get_surface_color(backbuffer3, 320, 240);
7257 ok(compare_color(color, 0x000000ff, 1) || broken(sysmem_primary && compare_color(color, 0x00ff0000, 1)),
7258 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7259 fill_surface(backbuffer2, 0xff00ff00);
7261 hr = IDirectDrawSurface7_Flip(frontbuffer, backbuffer3, DDFLIP_WAIT);
7262 ok(SUCCEEDED(hr), "%s: Failed to flip, hr %#x.\n", test_data[i].name, hr);
7263 color = get_surface_color(backbuffer1, 320, 240);
7264 ok(compare_color(color, 0x00ff0000, 1) || broken(sysmem_primary && compare_color(color, 0x0000ff00, 1)),
7265 "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7266 color = get_surface_color(backbuffer2, 320, 240);
7267 ok(compare_color(color, 0x0000ff00, 1), "%s: Got unexpected color 0x%08x.\n", test_data[i].name, color);
7269 IDirectDrawSurface7_Release(backbuffer3);
7270 IDirectDrawSurface7_Release(backbuffer2);
7271 IDirectDrawSurface7_Release(backbuffer1);
7272 IDirectDrawSurface7_Release(frontbuffer);
7275 if (!(device = create_device(window, DDSCL_NORMAL)))
7277 skip("Failed to create 3D device.\n");
7278 goto done;
7280 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
7281 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
7282 IDirect3DDevice7_Release(device);
7283 if (!(device_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP))
7285 skip("Cubemaps are not supported.\n");
7286 goto done;
7289 memset(&surface_desc, 0, sizeof(surface_desc));
7290 surface_desc.dwSize = sizeof(surface_desc);
7291 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
7292 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_TEXTURE;
7293 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
7294 surface_desc.dwWidth = 128;
7295 surface_desc.dwHeight = 128;
7296 U5(surface_desc).dwBackBufferCount = 3;
7297 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
7298 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x.\n", hr);
7300 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_FLIP;
7301 surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
7302 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
7303 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7305 surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_COMPLEX;
7306 surface_desc.ddsCaps.dwCaps |= DDSCAPS_FLIP;
7307 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
7308 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x.\n", hr);
7310 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
7311 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
7312 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7314 U5(surface_desc).dwBackBufferCount = 1;
7315 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
7316 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7318 U5(surface_desc).dwBackBufferCount = 0;
7319 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &frontbuffer, NULL);
7320 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x.\n", hr);
7322 done:
7323 refcount = IDirectDraw7_Release(ddraw);
7324 ok(refcount == 0, "The ddraw object was not properly freed, refcount %u.\n", refcount);
7325 DestroyWindow(window);
7328 static void reset_ddsd(DDSURFACEDESC2 *ddsd)
7330 memset(ddsd, 0, sizeof(*ddsd));
7331 ddsd->dwSize = sizeof(*ddsd);
7334 static void test_set_surface_desc(void)
7336 IDirectDraw7 *ddraw;
7337 HWND window;
7338 HRESULT hr;
7339 DDSURFACEDESC2 ddsd;
7340 IDirectDrawSurface7 *surface;
7341 BYTE data[16*16*4];
7342 ULONG ref;
7343 unsigned int i;
7344 static const struct
7346 DWORD caps, caps2;
7347 BOOL supported;
7348 const char *name;
7350 invalid_caps_tests[] =
7352 {DDSCAPS_VIDEOMEMORY, 0, FALSE, "videomemory plain"},
7353 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, TRUE, "systemmemory texture"},
7354 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE, "managed texture"},
7355 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE, "managed texture"},
7356 {DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY, 0, FALSE, "systemmemory primary"},
7359 window = create_window();
7360 ddraw = create_ddraw();
7361 ok(!!ddraw, "Failed to create a ddraw object.\n");
7362 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7363 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7365 reset_ddsd(&ddsd);
7366 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
7367 ddsd.dwWidth = 8;
7368 ddsd.dwHeight = 8;
7369 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
7370 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
7371 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
7372 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7373 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7374 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7375 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
7377 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
7378 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7380 reset_ddsd(&ddsd);
7381 ddsd.dwFlags = DDSD_LPSURFACE;
7382 ddsd.lpSurface = data;
7383 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7384 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7386 /* Redundantly setting the same lpSurface is not an error. */
7387 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7388 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7390 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
7391 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7392 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
7393 ok(ddsd.lpSurface == NULL, "lpSurface is %p, expected NULL.\n", ddsd.lpSurface);
7395 hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, 0, NULL);
7396 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7397 ok(!(ddsd.dwFlags & DDSD_LPSURFACE), "DDSD_LPSURFACE is set.\n");
7398 ok(ddsd.lpSurface == data, "lpSurface is %p, expected %p.\n", data, data);
7399 hr = IDirectDrawSurface7_Unlock(surface, NULL);
7400 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7402 reset_ddsd(&ddsd);
7403 ddsd.dwFlags = DDSD_LPSURFACE;
7404 ddsd.lpSurface = data;
7405 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 1);
7406 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with flags=1 returned %#x.\n", hr);
7408 ddsd.lpSurface = NULL;
7409 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7410 ok(hr == DDERR_INVALIDPARAMS, "Setting lpSurface=NULL returned %#x.\n", hr);
7412 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, NULL, 0);
7413 ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc with NULL desc returned %#x.\n", hr);
7415 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
7416 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7417 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
7418 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
7419 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#x.\n", 0);
7421 /* Setting the caps is an error. This also means the original description cannot be reapplied. */
7422 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7423 ok(hr == DDERR_INVALIDPARAMS, "Setting the original desc returned %#x.\n", hr);
7425 ddsd.dwFlags = DDSD_CAPS;
7426 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7427 ok(hr == DDERR_INVALIDPARAMS, "Setting DDSD_CAPS returned %#x.\n", hr);
7429 /* dwCaps = 0 is allowed, but ignored. Caps2 can be anything and is ignored too. */
7430 ddsd.dwFlags = DDSD_CAPS | DDSD_LPSURFACE;
7431 ddsd.lpSurface = data;
7432 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7433 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
7434 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
7435 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7436 ok(hr == DDERR_INVALIDCAPS, "Setting DDSD_CAPS returned %#x.\n", hr);
7437 ddsd.ddsCaps.dwCaps = 0;
7438 ddsd.ddsCaps.dwCaps2 = 0xdeadbeef;
7439 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7440 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7442 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
7443 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7444 ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN),
7445 "Got unexpected caps %#x.\n", ddsd.ddsCaps.dwCaps);
7446 ok(ddsd.ddsCaps.dwCaps2 == 0, "Got unexpected caps2 %#x.\n", 0);
7448 /* Setting the height is allowed, but it cannot be set to 0, and only if LPSURFACE is set too. */
7449 reset_ddsd(&ddsd);
7450 ddsd.dwFlags = DDSD_HEIGHT;
7451 ddsd.dwHeight = 16;
7452 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7453 ok(hr == DDERR_INVALIDPARAMS, "Setting height without lpSurface returned %#x.\n", hr);
7455 ddsd.lpSurface = data;
7456 ddsd.dwFlags = DDSD_HEIGHT | DDSD_LPSURFACE;
7457 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7458 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7460 ddsd.dwHeight = 0;
7461 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7462 ok(hr == DDERR_INVALIDPARAMS, "Setting height=0 returned %#x.\n", hr);
7464 reset_ddsd(&ddsd);
7465 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
7466 ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr);
7467 ok(ddsd.dwWidth == 8, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
7468 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
7470 /* Pitch and width can be set, but only together, and only with LPSURFACE. They must not be 0. */
7471 reset_ddsd(&ddsd);
7472 ddsd.dwFlags = DDSD_PITCH;
7473 U1(ddsd).lPitch = 8 * 4;
7474 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7475 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch without lpSurface or width returned %#x.\n", hr);
7477 ddsd.dwFlags = DDSD_WIDTH;
7478 ddsd.dwWidth = 16;
7479 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7480 ok(hr == DDERR_INVALIDPARAMS, "Setting width without lpSurface or pitch returned %#x.\n", hr);
7482 ddsd.dwFlags = DDSD_PITCH | DDSD_LPSURFACE;
7483 ddsd.lpSurface = data;
7484 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7485 ok(hr == DDERR_INVALIDPARAMS, "Setting pitch and lpSurface without width returned %#x.\n", hr);
7487 ddsd.dwFlags = DDSD_WIDTH | DDSD_LPSURFACE;
7488 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7489 ok(hr == DDERR_INVALIDPARAMS, "Setting width and lpSurface without pitch returned %#x.\n", hr);
7491 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
7492 U1(ddsd).lPitch = 16 * 4;
7493 ddsd.dwWidth = 16;
7494 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7495 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7497 reset_ddsd(&ddsd);
7498 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
7499 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7500 ok(ddsd.dwWidth == 16, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
7501 ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
7502 ok(U1(ddsd).lPitch == 16 * 4, "SetSurfaceDesc: Expected pitch 64, got %u.\n", U1(ddsd).lPitch);
7504 /* The pitch must be 32 bit aligned and > 0, but is not verified for sanity otherwise.
7506 * VMware rejects those calls, but all real drivers accept it. Mark the VMware behavior broken. */
7507 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
7508 U1(ddsd).lPitch = 4 * 4;
7509 ddsd.lpSurface = data;
7510 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7511 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
7513 U1(ddsd).lPitch = 4;
7514 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7515 ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "Failed to set surface desc, hr %#x.\n", hr);
7517 U1(ddsd).lPitch = 16 * 4 + 1;
7518 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7519 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
7521 U1(ddsd).lPitch = 16 * 4 + 3;
7522 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7523 ok(hr == DDERR_INVALIDPARAMS, "Setting misaligned pitch returned %#x.\n", hr);
7525 U1(ddsd).lPitch = -4;
7526 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7527 ok(hr == DDERR_INVALIDPARAMS, "Setting negative pitch returned %#x.\n", hr);
7529 U1(ddsd).lPitch = 16 * 4;
7530 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7531 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7533 reset_ddsd(&ddsd);
7534 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
7535 U1(ddsd).lPitch = 0;
7536 ddsd.dwWidth = 16;
7537 ddsd.lpSurface = data;
7538 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7539 ok(hr == DDERR_INVALIDPARAMS, "Setting zero pitch returned %#x.\n", hr);
7541 ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
7542 U1(ddsd).lPitch = 16 * 4;
7543 ddsd.dwWidth = 0;
7544 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7545 ok(hr == DDERR_INVALIDPARAMS, "Setting zero width returned %#x.\n", hr);
7547 /* Setting the pixelformat without LPSURFACE is an error, but with LPSURFACE it works. */
7548 ddsd.dwFlags = DDSD_PIXELFORMAT;
7549 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
7550 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
7551 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
7552 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7553 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7554 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7555 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7556 ok(hr == DDERR_INVALIDPARAMS, "Setting the pixel format returned %#x.\n", hr);
7558 ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_LPSURFACE;
7559 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7560 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7562 /* Can't set color keys. */
7563 reset_ddsd(&ddsd);
7564 ddsd.dwFlags = DDSD_CKSRCBLT;
7565 ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff0000;
7566 ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff0000;
7567 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7568 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
7570 ddsd.dwFlags = DDSD_CKSRCBLT | DDSD_LPSURFACE;
7571 ddsd.lpSurface = data;
7572 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7573 ok(hr == DDERR_INVALIDPARAMS, "Setting ddckCKSrcBlt returned %#x.\n", hr);
7575 IDirectDrawSurface7_Release(surface);
7577 /* Test mipmap texture. */
7578 reset_ddsd(&ddsd);
7579 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_MIPMAPCOUNT;
7580 ddsd.dwWidth = 8;
7581 ddsd.dwHeight = 8;
7582 U2(ddsd).dwMipMapCount = 3;
7583 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7585 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
7586 ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWHW || hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
7588 if (FAILED(hr))
7590 skip("Mipmaps are not supported.\n");
7592 else
7594 /* Changing surface desc for mipmap fails even without changing any
7595 * parameters. */
7596 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7597 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x.\n", hr);
7599 reset_ddsd(&ddsd);
7600 ddsd.dwFlags = DDSD_LPSURFACE;
7601 ddsd.lpSurface = data;
7602 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7603 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x.\n", hr);
7604 IDirectDrawSurface7_Release(surface);
7607 reset_ddsd(&ddsd);
7608 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_MIPMAPCOUNT;
7609 ddsd.dwWidth = 8;
7610 ddsd.dwHeight = 8;
7611 U2(ddsd).dwMipMapCount = 3;
7612 ddsd.lpSurface = data;
7613 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
7615 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
7616 ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWHW || hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
7618 if (hr == DD_OK)
7620 static DDSCAPS2 caps = {DDSCAPS_TEXTURE, 0, 0, {0}};
7621 void *surface2_system_mem;
7622 IDirectDrawSurface7 *surface2;
7624 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &surface2);
7625 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7626 reset_ddsd(&ddsd);
7627 hr = IDirectDrawSurface7_GetSurfaceDesc(surface2, &ddsd);
7628 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7629 ok(ddsd.dwWidth == 4, "Got unexpected dwWidth %u.\n", ddsd.dwWidth);
7631 hr = IDirectDrawSurface7_Lock(surface2, NULL, &ddsd, 0, NULL);
7632 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7633 surface2_system_mem = ddsd.lpSurface;
7634 IDirectDrawSurface7_Unlock(surface2, NULL);
7636 reset_ddsd(&ddsd);
7637 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_LPSURFACE;
7638 ddsd.dwWidth = 16;
7639 ddsd.dwHeight = 16;
7640 U1(ddsd).lPitch = 16 * 4;
7641 ddsd.lpSurface = data;
7642 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7643 todo_wine ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7645 reset_ddsd(&ddsd);
7646 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_LPSURFACE;
7647 ddsd.dwWidth = 8;
7648 ddsd.dwHeight = 8;
7649 U1(ddsd).lPitch = 8 * 4;
7650 ddsd.lpSurface = data;
7651 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7652 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7654 reset_ddsd(&ddsd);
7655 hr = IDirectDrawSurface7_Lock(surface2, NULL, &ddsd, 0, NULL);
7656 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7657 ok(ddsd.lpSurface == surface2_system_mem, "Got unexpected lpSurface %p.\n", ddsd.lpSurface);
7658 IDirectDrawSurface7_Unlock(surface2, NULL);
7660 reset_ddsd(&ddsd);
7661 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_LPSURFACE;
7662 ddsd.dwWidth = 4;
7663 ddsd.dwHeight = 4;
7664 U1(ddsd).lPitch = 4 * 4;
7665 ddsd.lpSurface = data;
7666 hr = IDirectDrawSurface7_SetSurfaceDesc(surface2, &ddsd, 0);
7667 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7669 reset_ddsd(&ddsd);
7670 hr = IDirectDrawSurface7_Lock(surface2, NULL, &ddsd, 0, NULL);
7671 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7672 ok(ddsd.lpSurface == data, "Got unexpected lpSurface %p.\n", ddsd.lpSurface);
7673 IDirectDrawSurface7_Unlock(surface2, NULL);
7675 reset_ddsd(&ddsd);
7676 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_LPSURFACE;
7677 ddsd.dwWidth = 16;
7678 ddsd.dwHeight = 16;
7679 U1(ddsd).lPitch = 16 * 4;
7680 ddsd.lpSurface = data;
7681 hr = IDirectDrawSurface7_SetSurfaceDesc(surface2, &ddsd, 0);
7682 todo_wine ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7684 IDirectDrawSurface7_Release(surface2);
7685 IDirectDrawSurface7_Release(surface);
7688 /* Test surface created with DDSD_LPSURFACE. */
7689 reset_ddsd(&ddsd);
7690 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LPSURFACE | DDSD_PITCH;
7691 ddsd.dwWidth = 8;
7692 ddsd.dwHeight = 8;
7693 ddsd.lpSurface = data;
7694 U1(ddsd).lPitch = 8 * 4;
7695 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
7696 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
7697 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7699 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7700 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x.\n", hr);
7702 reset_ddsd(&ddsd);
7703 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
7704 ddsd.dwWidth = 8;
7705 ddsd.dwHeight = 8;
7706 /* Cannot reset lpSurface. */
7707 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7708 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
7710 reset_ddsd(&ddsd);
7711 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_LPSURFACE | DDSD_PITCH;
7712 ddsd.dwWidth = 4;
7713 ddsd.dwHeight = 4;
7714 ddsd.lpSurface = data;
7715 U1(ddsd).lPitch = 8 * 4;
7716 /* Can change the parameters of surface created with DDSD_LPSURFACE. */
7717 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7718 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
7720 IDirectDrawSurface7_Release(surface);
7722 /* SetSurfaceDesc needs systemmemory surfaces.
7724 * As a sidenote, fourcc surfaces aren't allowed in sysmem, thus testing
7725 * DDSD_LINEARSIZE is moot. */
7726 for (i = 0; i < ARRAY_SIZE(invalid_caps_tests); ++i)
7728 reset_ddsd(&ddsd);
7729 ddsd.dwFlags = DDSD_CAPS;
7730 ddsd.ddsCaps.dwCaps = invalid_caps_tests[i].caps;
7731 ddsd.ddsCaps.dwCaps2 = invalid_caps_tests[i].caps2;
7732 if (!(invalid_caps_tests[i].caps & DDSCAPS_PRIMARYSURFACE))
7734 ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
7735 ddsd.dwWidth = 8;
7736 ddsd.dwHeight = 8;
7737 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
7738 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
7739 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
7740 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7741 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7742 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7745 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
7746 if (is_ddraw64 && (invalid_caps_tests[i].caps & DDSCAPS_TEXTURE))
7747 todo_wine ok(hr == E_NOINTERFACE, "Test %u: Got unexpected hr %#x.\n", i, hr);
7748 else
7749 ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWHW, "Test %u: Got unexpected hr %#x.\n", i, hr);
7750 if (FAILED(hr))
7751 continue;
7753 reset_ddsd(&ddsd);
7754 ddsd.dwFlags = DDSD_LPSURFACE;
7755 ddsd.lpSurface = data;
7756 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7757 if (invalid_caps_tests[i].supported)
7759 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7761 else
7763 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
7764 invalid_caps_tests[i].name, hr);
7766 /* Check priority of error conditions. */
7767 ddsd.dwFlags = DDSD_WIDTH;
7768 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7769 ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc on a %s surface returned %#x.\n",
7770 invalid_caps_tests[i].name, hr);
7773 IDirectDrawSurface7_Release(surface);
7776 ref = IDirectDraw7_Release(ddraw);
7777 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
7778 DestroyWindow(window);
7781 static void test_user_memory_getdc(void)
7783 IDirectDraw7 *ddraw;
7784 HWND window;
7785 HRESULT hr;
7786 DDSURFACEDESC2 ddsd;
7787 IDirectDrawSurface7 *surface;
7788 DWORD data[16][16];
7789 HGDIOBJ *bitmap;
7790 DIBSECTION dib;
7791 ULONG ref;
7792 int size;
7793 HDC dc;
7794 unsigned int x, y;
7796 window = create_window();
7797 ddraw = create_ddraw();
7798 ok(!!ddraw, "Failed to create a ddraw object.\n");
7799 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7800 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7802 reset_ddsd(&ddsd);
7803 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
7804 ddsd.dwWidth = 16;
7805 ddsd.dwHeight = 16;
7806 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
7807 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
7808 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
7809 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7810 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7811 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7812 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
7813 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
7814 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7816 memset(data, 0xaa, sizeof(data));
7817 reset_ddsd(&ddsd);
7818 ddsd.dwFlags = DDSD_LPSURFACE;
7819 ddsd.lpSurface = data;
7820 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7821 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7823 hr = IDirectDrawSurface7_GetDC(surface, &dc);
7824 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7825 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
7826 ok(!!bitmap, "Failed to get bitmap.\n");
7827 size = GetObjectA(bitmap, sizeof(dib), &dib);
7828 ok(size == sizeof(dib), "Got unexpected size %d.\n", size);
7829 ok(dib.dsBm.bmBits == data, "Got unexpected bits %p, expected %p.\n", dib.dsBm.bmBits, data);
7830 BitBlt(dc, 0, 0, 16, 8, NULL, 0, 0, WHITENESS);
7831 BitBlt(dc, 0, 8, 16, 8, NULL, 0, 0, BLACKNESS);
7832 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
7833 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7835 ok(data[0][0] == 0xffffffff, "Expected color 0xffffffff, got %#x.\n", data[0][0]);
7836 ok(data[15][15] == 0x00000000, "Expected color 0x00000000, got %#x.\n", data[15][15]);
7838 ddsd.dwFlags = DDSD_LPSURFACE | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH;
7839 ddsd.lpSurface = data;
7840 ddsd.dwWidth = 4;
7841 ddsd.dwHeight = 8;
7842 U1(ddsd).lPitch = sizeof(*data);
7843 hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0);
7844 ok(SUCCEEDED(hr), "Failed to set surface desc, hr %#x.\n", hr);
7846 memset(data, 0xaa, sizeof(data));
7847 hr = IDirectDrawSurface7_GetDC(surface, &dc);
7848 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
7849 BitBlt(dc, 0, 0, 4, 8, NULL, 0, 0, BLACKNESS);
7850 BitBlt(dc, 1, 1, 2, 2, NULL, 0, 0, WHITENESS);
7851 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
7852 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
7854 for (y = 0; y < 4; y++)
7856 for (x = 0; x < 4; x++)
7858 if ((x == 1 || x == 2) && (y == 1 || y == 2))
7859 ok(data[y][x] == 0xffffffff, "Expected color 0xffffffff on position %ux%u, got %#x.\n",
7860 x, y, data[y][x]);
7861 else
7862 ok(data[y][x] == 0x00000000, "Expected color 0x00000000 on position %ux%u, got %#x.\n",
7863 x, y, data[y][x]);
7866 ok(data[0][5] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 5x0, got %#x.\n",
7867 data[0][5]);
7868 ok(data[7][3] == 0x00000000, "Expected color 0x00000000 on position 3x7, got %#x.\n",
7869 data[7][3]);
7870 ok(data[7][4] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 4x7, got %#x.\n",
7871 data[7][4]);
7872 ok(data[8][0] == 0xaaaaaaaa, "Expected color 0xaaaaaaaa on position 0x8, got %#x.\n",
7873 data[8][0]);
7875 IDirectDrawSurface7_Release(surface);
7876 ref = IDirectDraw7_Release(ddraw);
7877 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
7878 DestroyWindow(window);
7881 static void test_sysmem_overlay(void)
7883 IDirectDraw7 *ddraw;
7884 HWND window;
7885 HRESULT hr;
7886 DDSURFACEDESC2 ddsd;
7887 IDirectDrawSurface7 *surface;
7888 ULONG ref;
7890 window = create_window();
7891 ddraw = create_ddraw();
7892 ok(!!ddraw, "Failed to create a ddraw object.\n");
7893 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
7894 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7896 reset_ddsd(&ddsd);
7897 ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
7898 ddsd.dwWidth = 16;
7899 ddsd.dwHeight = 16;
7900 ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OVERLAY;
7901 U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
7902 U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
7903 U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
7904 U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
7905 U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
7906 U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000ff;
7907 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
7908 ok(hr == DDERR_NOOVERLAYHW, "Got unexpected hr %#x.\n", hr);
7910 ref = IDirectDraw7_Release(ddraw);
7911 ok(ref == 0, "Ddraw object not properly released, refcount %u.\n", ref);
7912 DestroyWindow(window);
7915 static void test_primary_palette(void)
7917 DDSCAPS2 surface_caps = {DDSCAPS_FLIP, 0, 0, {0}};
7918 IDirectDrawSurface7 *primary, *backbuffer;
7919 PALETTEENTRY palette_entries[256];
7920 IDirectDrawPalette *palette, *tmp;
7921 DDSURFACEDESC2 surface_desc;
7922 IDirectDraw7 *ddraw;
7923 DWORD palette_caps;
7924 ULONG refcount;
7925 HWND window;
7926 HRESULT hr;
7928 window = create_window();
7929 ddraw = create_ddraw();
7930 ok(!!ddraw, "Failed to create a ddraw object.\n");
7931 if (FAILED(IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
7933 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
7934 IDirectDraw7_Release(ddraw);
7935 DestroyWindow(window);
7936 return;
7938 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
7939 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
7941 memset(&surface_desc, 0, sizeof(surface_desc));
7942 surface_desc.dwSize = sizeof(surface_desc);
7943 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
7944 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
7945 U5(surface_desc).dwBackBufferCount = 1;
7946 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
7947 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7948 hr = IDirectDrawSurface7_GetAttachedSurface(primary, &surface_caps, &backbuffer);
7949 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
7951 memset(palette_entries, 0, sizeof(palette_entries));
7952 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256, palette_entries, &palette, NULL);
7953 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
7954 refcount = get_refcount((IUnknown *)palette);
7955 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7957 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
7958 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
7959 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
7961 hr = IDirectDrawSurface7_SetPalette(primary, palette);
7962 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7964 /* The Windows 8 testbot attaches the palette to the backbuffer as well,
7965 * and is generally somewhat broken with respect to 8 bpp / palette
7966 * handling. */
7967 if (SUCCEEDED(IDirectDrawSurface7_GetPalette(backbuffer, &tmp)))
7969 win_skip("Broken palette handling detected, skipping tests.\n");
7970 IDirectDrawPalette_Release(tmp);
7971 IDirectDrawPalette_Release(palette);
7972 /* The Windows 8 testbot keeps extra references to the primary and
7973 * backbuffer while in 8 bpp mode. */
7974 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
7975 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
7976 goto done;
7979 refcount = get_refcount((IUnknown *)palette);
7980 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
7982 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
7983 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
7984 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE | DDPCAPS_ALLOW256),
7985 "Got unexpected palette caps %#x.\n", palette_caps);
7987 hr = IDirectDrawSurface7_SetPalette(primary, NULL);
7988 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7989 refcount = get_refcount((IUnknown *)palette);
7990 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
7992 hr = IDirectDrawPalette_GetCaps(palette, &palette_caps);
7993 ok(SUCCEEDED(hr), "Failed to get palette caps, hr %#x.\n", hr);
7994 ok(palette_caps == (DDPCAPS_8BIT | DDPCAPS_ALLOW256), "Got unexpected palette caps %#x.\n", palette_caps);
7996 hr = IDirectDrawSurface7_SetPalette(primary, palette);
7997 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
7998 refcount = get_refcount((IUnknown *)palette);
7999 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
8001 hr = IDirectDrawSurface7_GetPalette(primary, &tmp);
8002 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
8003 ok(tmp == palette, "Got unexpected palette %p, expected %p.\n", tmp, palette);
8004 IDirectDrawPalette_Release(tmp);
8005 hr = IDirectDrawSurface7_GetPalette(backbuffer, &tmp);
8006 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
8008 refcount = IDirectDrawPalette_Release(palette);
8009 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
8010 refcount = IDirectDrawPalette_Release(palette);
8011 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8013 /* Note that this only seems to work when the palette is attached to the
8014 * primary surface. When attached to a regular surface, attempting to get
8015 * the palette here will cause an access violation. */
8016 hr = IDirectDrawSurface7_GetPalette(primary, &tmp);
8017 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
8019 hr = IDirectDrawSurface7_IsLost(primary);
8020 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
8022 memset(&surface_desc, 0, sizeof(surface_desc));
8023 surface_desc.dwSize = sizeof(surface_desc);
8024 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &surface_desc);
8025 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8026 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
8027 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
8028 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 8, "Got unexpected bit count %u.\n",
8029 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
8031 hr = set_display_mode(ddraw, 640, 480);
8032 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
8034 memset(&surface_desc, 0, sizeof(surface_desc));
8035 surface_desc.dwSize = sizeof(surface_desc);
8036 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &surface_desc);
8037 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8038 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
8039 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
8040 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 32
8041 || U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 24,
8042 "Got unexpected bit count %u.\n", U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
8044 hr = IDirectDrawSurface7_IsLost(primary);
8045 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8046 hr = IDirectDrawSurface7_Restore(primary);
8047 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
8048 hr = IDirectDrawSurface7_IsLost(primary);
8049 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
8051 memset(&surface_desc, 0, sizeof(surface_desc));
8052 surface_desc.dwSize = sizeof(surface_desc);
8053 hr = IDirectDrawSurface7_GetSurfaceDesc(primary, &surface_desc);
8054 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8055 ok(surface_desc.dwWidth == 640, "Got unexpected surface width %u.\n", surface_desc.dwWidth);
8056 ok(surface_desc.dwHeight == 480, "Got unexpected surface height %u.\n", surface_desc.dwHeight);
8057 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 32
8058 || U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == 24,
8059 "Got unexpected bit count %u.\n", U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount);
8061 done:
8062 refcount = IDirectDrawSurface7_Release(backbuffer);
8063 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
8064 refcount = IDirectDrawSurface7_Release(primary);
8065 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8066 refcount = IDirectDraw7_Release(ddraw);
8067 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8068 DestroyWindow(window);
8071 static HRESULT WINAPI surface_counter(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
8073 UINT *surface_count = context;
8075 ++(*surface_count);
8076 IDirectDrawSurface_Release(surface);
8078 return DDENUMRET_OK;
8081 static void test_surface_attachment(void)
8083 IDirectDrawSurface7 *surface1, *surface2, *surface3, *surface4;
8084 IDirectDrawSurface *surface1v1, *surface2v1;
8085 DDSCAPS2 caps = {DDSCAPS_TEXTURE, 0, 0, {0}};
8086 DDSURFACEDESC2 surface_desc;
8087 IDirectDraw7 *ddraw;
8088 UINT surface_count;
8089 ULONG refcount;
8090 HWND window;
8091 HRESULT hr;
8093 window = create_window();
8094 ddraw = create_ddraw();
8095 ok(!!ddraw, "Failed to create a ddraw object.\n");
8096 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8097 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8099 memset(&surface_desc, 0, sizeof(surface_desc));
8100 surface_desc.dwSize = sizeof(surface_desc);
8101 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
8102 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
8103 U2(surface_desc).dwMipMapCount = 3;
8104 surface_desc.dwWidth = 128;
8105 surface_desc.dwHeight = 128;
8106 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL)))
8108 skip("Failed to create a texture, skipping tests.\n");
8109 IDirectDraw7_Release(ddraw);
8110 DestroyWindow(window);
8111 return;
8114 hr = IDirectDrawSurface7_GetAttachedSurface(surface1, &caps, &surface2);
8115 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
8116 hr = IDirectDrawSurface7_GetAttachedSurface(surface2, &caps, &surface3);
8117 ok(SUCCEEDED(hr), "Failed to get mip level, hr %#x.\n", hr);
8118 hr = IDirectDrawSurface7_GetAttachedSurface(surface3, &caps, &surface4);
8119 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
8121 surface_count = 0;
8122 IDirectDrawSurface7_EnumAttachedSurfaces(surface1, &surface_count, surface_counter);
8123 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
8124 surface_count = 0;
8125 IDirectDrawSurface7_EnumAttachedSurfaces(surface2, &surface_count, surface_counter);
8126 ok(surface_count == 1, "Got unexpected surface_count %u.\n", surface_count);
8127 surface_count = 0;
8128 IDirectDrawSurface7_EnumAttachedSurfaces(surface3, &surface_count, surface_counter);
8129 ok(!surface_count, "Got unexpected surface_count %u.\n", surface_count);
8131 memset(&surface_desc, 0, sizeof(surface_desc));
8132 surface_desc.dwSize = sizeof(surface_desc);
8133 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8134 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
8135 surface_desc.dwWidth = 16;
8136 surface_desc.dwHeight = 16;
8137 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
8138 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8140 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
8141 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8142 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
8143 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8144 hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface4);
8145 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8146 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface3);
8147 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8148 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface4);
8149 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8150 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface2);
8151 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8153 IDirectDrawSurface7_Release(surface4);
8155 memset(&surface_desc, 0, sizeof(surface_desc));
8156 surface_desc.dwSize = sizeof(surface_desc);
8157 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8158 surface_desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
8159 surface_desc.dwWidth = 16;
8160 surface_desc.dwHeight = 16;
8161 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
8162 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8164 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
8165 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8166 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
8167 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8168 hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface4);
8169 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8170 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface3);
8171 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8172 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface4);
8173 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8174 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface2);
8175 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8177 IDirectDrawSurface7_Release(surface4);
8178 IDirectDrawSurface7_Release(surface3);
8179 IDirectDrawSurface7_Release(surface2);
8180 IDirectDrawSurface7_Release(surface1);
8182 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
8183 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8185 /* Try a single primary and two offscreen plain surfaces. */
8186 memset(&surface_desc, 0, sizeof(surface_desc));
8187 surface_desc.dwSize = sizeof(surface_desc);
8188 surface_desc.dwFlags = DDSD_CAPS;
8189 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8190 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
8191 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8193 memset(&surface_desc, 0, sizeof(surface_desc));
8194 surface_desc.dwSize = sizeof(surface_desc);
8195 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8196 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8197 surface_desc.dwWidth = registry_mode.dmPelsWidth;
8198 surface_desc.dwHeight = registry_mode.dmPelsHeight;
8199 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
8200 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8202 memset(&surface_desc, 0, sizeof(surface_desc));
8203 surface_desc.dwSize = sizeof(surface_desc);
8204 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8205 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8206 surface_desc.dwWidth = registry_mode.dmPelsWidth;
8207 surface_desc.dwHeight = registry_mode.dmPelsHeight;
8208 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
8209 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8211 /* This one has a different size. */
8212 memset(&surface_desc, 0, sizeof(surface_desc));
8213 surface_desc.dwSize = sizeof(surface_desc);
8214 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8215 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8216 surface_desc.dwWidth = 128;
8217 surface_desc.dwHeight = 128;
8218 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
8219 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8221 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
8222 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8223 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface1);
8224 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8225 hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface3);
8226 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8227 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
8228 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8229 hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
8230 ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8232 IDirectDrawSurface7_Release(surface4);
8233 IDirectDrawSurface7_Release(surface3);
8234 IDirectDrawSurface7_Release(surface2);
8235 IDirectDrawSurface7_Release(surface1);
8237 /* Test depth surfaces of different sizes. */
8238 memset(&surface_desc, 0, sizeof(surface_desc));
8239 surface_desc.dwSize = sizeof(surface_desc);
8240 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8241 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
8242 surface_desc.dwWidth = 64;
8243 surface_desc.dwHeight = 64;
8244 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
8245 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
8247 memset(&surface_desc, 0, sizeof(surface_desc));
8248 surface_desc.dwSize = sizeof(surface_desc);
8249 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
8250 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
8251 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8252 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
8253 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = 16;
8254 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = 0x0000ffff;
8255 surface_desc.dwWidth = 32;
8256 surface_desc.dwHeight = 32;
8257 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
8258 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
8259 surface_desc.dwWidth = 64;
8260 surface_desc.dwHeight = 64;
8261 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
8262 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
8263 surface_desc.dwWidth = 128;
8264 surface_desc.dwHeight = 128;
8265 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface4, NULL);
8266 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
8268 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
8269 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8270 if (SUCCEEDED(hr))
8271 IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface2);
8272 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface3);
8273 ok(hr == D3D_OK, "Failed to attach depth buffer, hr %#x.\n", hr);
8274 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface3);
8275 ok(hr == D3D_OK, "Failed to detach depth buffer, hr %#x.\n", hr);
8276 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
8277 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8279 IDirectDrawSurface7_Release(surface4);
8280 IDirectDrawSurface7_Release(surface3);
8281 IDirectDrawSurface7_Release(surface2);
8282 IDirectDrawSurface7_Release(surface1);
8284 /* Test DeleteAttachedSurface() and automatic detachment of attached surfaces on release. */
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 | DDSD_PIXELFORMAT;
8288 surface_desc.dwWidth = 64;
8289 surface_desc.dwHeight = 64;
8290 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
8291 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8292 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
8293 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
8294 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
8295 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
8296 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
8297 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface1, NULL);
8298 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8299 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface3, NULL);
8300 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8302 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
8303 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
8304 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = 16;
8305 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = 0x0000ffff;
8306 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
8307 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8309 hr = IDirectDrawSurface7_QueryInterface(surface1, &IID_IDirectDrawSurface, (void **)&surface1v1);
8310 ok(SUCCEEDED(hr), "Failed to get interface, hr %#x.\n", hr);
8311 hr = IDirectDrawSurface7_QueryInterface(surface2, &IID_IDirectDrawSurface, (void **)&surface2v1);
8312 ok(SUCCEEDED(hr), "Failed to get interface, hr %#x.\n", hr);
8314 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
8315 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
8316 refcount = get_refcount((IUnknown *)surface2);
8317 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
8318 refcount = get_refcount((IUnknown *)surface2v1);
8319 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
8320 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
8321 ok(hr == DDERR_SURFACEALREADYATTACHED, "Got unexpected hr %#x.\n", hr);
8322 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
8323 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "Got unexpected hr %#x.\n", hr);
8324 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
8325 ok(hr == DDERR_SURFACENOTATTACHED, "Got unexpected hr %#x.\n", hr);
8327 /* Attaching while already attached to other surface. */
8328 hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface2);
8329 todo_wine ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
8330 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface3, 0, surface2);
8331 todo_wine ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
8332 IDirectDrawSurface7_Release(surface3);
8334 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface2);
8335 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
8336 refcount = get_refcount((IUnknown *)surface2);
8337 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
8338 refcount = get_refcount((IUnknown *)surface2v1);
8339 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
8341 /* DeleteAttachedSurface() when attaching via IDirectDrawSurface. */
8342 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
8343 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
8344 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface2);
8345 ok(hr == DDERR_SURFACENOTATTACHED, "Got unexpected hr %#x.\n", hr);
8346 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
8347 ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x.\n", hr);
8348 refcount = IDirectDrawSurface7_Release(surface2);
8349 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8350 refcount = IDirectDrawSurface7_Release(surface1);
8351 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8353 /* Automatic detachment on release. */
8354 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
8355 ok(SUCCEEDED(hr), "Failed to attach surface, hr %#x.\n", hr);
8356 refcount = get_refcount((IUnknown *)surface2v1);
8357 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
8358 refcount = IDirectDrawSurface_Release(surface1v1);
8359 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8360 refcount = IDirectDrawSurface_Release(surface2v1);
8361 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8362 refcount = IDirectDraw7_Release(ddraw);
8363 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8364 DestroyWindow(window);
8367 static void test_private_data(void)
8369 IDirectDraw7 *ddraw;
8370 IDirectDrawSurface7 *surface, *surface2;
8371 DDSURFACEDESC2 surface_desc;
8372 ULONG refcount, refcount2, refcount3;
8373 IUnknown *ptr;
8374 DWORD size = sizeof(ptr);
8375 HRESULT hr;
8376 HWND window;
8377 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
8378 DWORD data[] = {1, 2, 3, 4};
8379 DDCAPS hal_caps;
8380 static const GUID ddraw_private_data_test_guid =
8382 0xfdb37466,
8383 0x428f,
8384 0x4edf,
8385 {0xa3,0x7f,0x9b,0x1d,0xf4,0x88,0xc5,0xfc}
8387 static const GUID ddraw_private_data_test_guid2 =
8389 0x2e5afac2,
8390 0x87b5,
8391 0x4c10,
8392 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
8395 window = create_window();
8396 ddraw = create_ddraw();
8397 ok(!!ddraw, "Failed to create a ddraw object.\n");
8398 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8399 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8401 reset_ddsd(&surface_desc);
8402 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
8403 surface_desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
8404 surface_desc.dwHeight = 4;
8405 surface_desc.dwWidth = 4;
8406 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8407 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8409 /* NULL pointers are not valid, but don't cause a crash. */
8410 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL,
8411 sizeof(IUnknown *), DDSPD_IUNKNOWNPOINTER);
8412 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8413 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL, 0, 0);
8414 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8415 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, NULL, 1, 0);
8416 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8418 /* DDSPD_IUNKNOWNPOINTER needs sizeof(IUnknown *) bytes of data. */
8419 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
8420 0, DDSPD_IUNKNOWNPOINTER);
8421 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8422 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
8423 5, DDSPD_IUNKNOWNPOINTER);
8424 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8425 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
8426 sizeof(ddraw) * 2, DDSPD_IUNKNOWNPOINTER);
8427 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8429 /* Note that with a size != 0 and size != sizeof(IUnknown *) and
8430 * DDSPD_IUNKNOWNPOINTER set SetPrivateData in ddraw4 and ddraw7
8431 * erases the old content and returns an error. This behavior has
8432 * been fixed in d3d8 and d3d9. Unless an application is found
8433 * that depends on this we don't care about this behavior. */
8434 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
8435 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
8436 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
8437 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
8438 0, DDSPD_IUNKNOWNPOINTER);
8439 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8440 size = sizeof(ptr);
8441 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
8442 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
8443 hr = IDirectDrawSurface7_FreePrivateData(surface, &ddraw_private_data_test_guid);
8444 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
8446 refcount = get_refcount((IUnknown *)ddraw);
8447 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
8448 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
8449 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
8450 refcount2 = get_refcount((IUnknown *)ddraw);
8451 ok(refcount2 == refcount + 1, "Got unexpected refcount %u.\n", refcount2);
8453 hr = IDirectDrawSurface7_FreePrivateData(surface, &ddraw_private_data_test_guid);
8454 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
8455 refcount2 = get_refcount((IUnknown *)ddraw);
8456 ok(refcount2 == refcount, "Got unexpected refcount %u.\n", refcount2);
8458 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
8459 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
8460 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
8461 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, surface,
8462 sizeof(surface), DDSPD_IUNKNOWNPOINTER);
8463 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
8464 refcount2 = get_refcount((IUnknown *)ddraw);
8465 ok(refcount2 == refcount, "Got unexpected refcount %u.\n", refcount2);
8467 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, ddraw,
8468 sizeof(ddraw), DDSPD_IUNKNOWNPOINTER);
8469 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
8470 size = 2 * sizeof(ptr);
8471 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
8472 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
8473 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
8474 refcount2 = get_refcount(ptr);
8475 /* Object is NOT addref'ed by the getter. */
8476 ok(ptr == (IUnknown *)ddraw, "Returned interface pointer is %p, expected %p.\n", ptr, ddraw);
8477 ok(refcount2 == refcount + 1, "Got unexpected refcount %u.\n", refcount2);
8479 ptr = (IUnknown *)0xdeadbeef;
8480 size = 1;
8481 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, &size);
8482 ok(hr == DDERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
8483 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
8484 size = 2 * sizeof(ptr);
8485 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, &size);
8486 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8487 ok(size == 2 * sizeof(ptr), "Got unexpected size %u.\n", size);
8488 size = 1;
8489 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, &ptr, &size);
8490 ok(hr == DDERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
8491 ok(size == sizeof(ddraw), "Got unexpected size %u.\n", size);
8492 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
8493 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid2, NULL, NULL);
8494 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
8495 size = 0xdeadbabe;
8496 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid2, &ptr, &size);
8497 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
8498 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
8499 ok(size == 0xdeadbabe, "Got unexpected size %u.\n", size);
8500 hr = IDirectDrawSurface7_GetPrivateData(surface, &ddraw_private_data_test_guid, NULL, NULL);
8501 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
8503 refcount3 = IDirectDrawSurface7_Release(surface);
8504 ok(!refcount3, "Got unexpected refcount %u.\n", refcount3);
8506 /* Destroying the surface frees the reference held on the private data. It also frees
8507 * the reference the surface is holding on its creating object. */
8508 refcount2 = get_refcount((IUnknown *)ddraw);
8509 ok(refcount2 == refcount - 1, "Got unexpected refcount %u.\n", refcount2);
8511 memset(&hal_caps, 0, sizeof(hal_caps));
8512 hal_caps.dwSize = sizeof(hal_caps);
8513 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
8514 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8515 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) == (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)
8516 && !is_ddraw64)
8518 reset_ddsd(&surface_desc);
8519 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_MIPMAPCOUNT;
8520 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
8521 surface_desc.dwHeight = 4;
8522 surface_desc.dwWidth = 4;
8523 U2(surface_desc).dwMipMapCount = 2;
8524 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8525 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8526 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &surface2);
8527 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
8529 hr = IDirectDrawSurface7_SetPrivateData(surface, &ddraw_private_data_test_guid, data, sizeof(data), 0);
8530 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
8531 hr = IDirectDrawSurface7_GetPrivateData(surface2, &ddraw_private_data_test_guid, NULL, NULL);
8532 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
8534 IDirectDrawSurface7_Release(surface2);
8535 IDirectDrawSurface7_Release(surface);
8537 else
8538 skip("Mipmapped textures not supported, skipping mipmap private data test.\n");
8540 refcount = IDirectDraw7_Release(ddraw);
8541 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8542 DestroyWindow(window);
8545 static void test_pixel_format(void)
8547 HWND window, window2 = NULL;
8548 HDC hdc, hdc2 = NULL;
8549 HMODULE gl = NULL;
8550 int format, test_format;
8551 PIXELFORMATDESCRIPTOR pfd;
8552 IDirectDraw7 *ddraw = NULL;
8553 IDirectDrawClipper *clipper = NULL;
8554 DDSURFACEDESC2 ddsd;
8555 IDirectDrawSurface7 *primary = NULL, *offscreen;
8556 DDBLTFX fx;
8557 HRESULT hr;
8559 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
8560 100, 100, 160, 160, NULL, NULL, NULL, NULL);
8561 if (!window)
8563 skip("Failed to create window\n");
8564 return;
8567 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
8568 100, 100, 160, 160, NULL, NULL, NULL, NULL);
8570 hdc = GetDC(window);
8571 if (!hdc)
8573 skip("Failed to get DC\n");
8574 goto cleanup;
8577 if (window2)
8578 hdc2 = GetDC(window2);
8580 gl = LoadLibraryA("opengl32.dll");
8581 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
8583 format = GetPixelFormat(hdc);
8584 ok(format == 0, "new window has pixel format %d\n", format);
8586 ZeroMemory(&pfd, sizeof(pfd));
8587 pfd.nSize = sizeof(pfd);
8588 pfd.nVersion = 1;
8589 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
8590 pfd.iPixelType = PFD_TYPE_RGBA;
8591 pfd.iLayerType = PFD_MAIN_PLANE;
8592 format = ChoosePixelFormat(hdc, &pfd);
8593 if (format <= 0)
8595 skip("no pixel format available\n");
8596 goto cleanup;
8599 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
8601 skip("failed to set pixel format\n");
8602 goto cleanup;
8605 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
8607 skip("failed to set pixel format on second window\n");
8608 if (hdc2)
8610 ReleaseDC(window2, hdc2);
8611 hdc2 = NULL;
8615 ddraw = create_ddraw();
8616 ok(!!ddraw, "Failed to create a ddraw object.\n");
8618 test_format = GetPixelFormat(hdc);
8619 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8621 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8622 if (FAILED(hr))
8624 skip("Failed to set cooperative level, hr %#x.\n", hr);
8625 goto cleanup;
8628 test_format = GetPixelFormat(hdc);
8629 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8631 if (hdc2)
8633 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
8634 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
8635 hr = IDirectDrawClipper_SetHWnd(clipper, 0, window2);
8636 ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
8638 test_format = GetPixelFormat(hdc);
8639 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8641 test_format = GetPixelFormat(hdc2);
8642 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
8645 memset(&ddsd, 0, sizeof(ddsd));
8646 ddsd.dwSize = sizeof(ddsd);
8647 ddsd.dwFlags = DDSD_CAPS;
8648 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8650 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &primary, NULL);
8651 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
8653 test_format = GetPixelFormat(hdc);
8654 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8656 if (hdc2)
8658 test_format = GetPixelFormat(hdc2);
8659 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
8662 if (clipper)
8664 hr = IDirectDrawSurface7_SetClipper(primary, clipper);
8665 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
8667 test_format = GetPixelFormat(hdc);
8668 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8670 test_format = GetPixelFormat(hdc2);
8671 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
8674 memset(&ddsd, 0, sizeof(ddsd));
8675 ddsd.dwSize = sizeof(ddsd);
8676 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
8677 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
8678 ddsd.dwWidth = ddsd.dwHeight = 64;
8679 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &offscreen, NULL);
8680 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
8682 memset(&fx, 0, sizeof(fx));
8683 fx.dwSize = sizeof(fx);
8684 hr = IDirectDrawSurface7_Blt(offscreen, NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &fx);
8685 ok(SUCCEEDED(hr), "Failed to clear source surface, hr %#x.\n", hr);
8687 test_format = GetPixelFormat(hdc);
8688 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8690 hr = IDirectDrawSurface7_Blt(primary, NULL, offscreen, NULL, DDBLT_WAIT, NULL);
8691 ok(SUCCEEDED(hr), "Failed to blit to primary surface, hr %#x.\n", hr);
8693 test_format = GetPixelFormat(hdc);
8694 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
8696 if (hdc2)
8698 test_format = GetPixelFormat(hdc2);
8699 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
8702 IDirectDrawSurface7_Release(offscreen);
8704 cleanup:
8705 if (primary) IDirectDrawSurface7_Release(primary);
8706 if (clipper) IDirectDrawClipper_Release(clipper);
8707 if (ddraw) IDirectDraw7_Release(ddraw);
8708 if (gl) FreeLibrary(gl);
8709 if (hdc) ReleaseDC(window, hdc);
8710 if (hdc2) ReleaseDC(window2, hdc2);
8711 DestroyWindow(window);
8712 if (window2) DestroyWindow(window2);
8715 static void test_create_surface_pitch(void)
8717 IDirectDrawSurface7 *surface;
8718 DDSURFACEDESC2 surface_desc;
8719 IDirectDraw7 *ddraw;
8720 unsigned int i;
8721 ULONG refcount;
8722 HWND window;
8723 HRESULT hr;
8724 void *mem;
8726 static const struct
8728 DWORD caps;
8729 DWORD flags_in;
8730 DWORD pitch_in;
8731 HRESULT hr;
8732 DWORD flags_out;
8733 DWORD pitch_out32;
8734 DWORD pitch_out64;
8736 test_data[] =
8738 /* 0 */
8739 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
8740 0, 0, DD_OK,
8741 DDSD_PITCH, 0x100, 0x100},
8742 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
8743 DDSD_PITCH, 0x104, DD_OK,
8744 DDSD_PITCH, 0x100, 0x100},
8745 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
8746 DDSD_PITCH, 0x0f8, DD_OK,
8747 DDSD_PITCH, 0x100, 0x100},
8748 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN,
8749 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
8750 0, 0, 0 },
8751 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8752 0, 0, DD_OK,
8753 DDSD_PITCH, 0x100, 0x0fc},
8754 /* 5 */
8755 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8756 DDSD_PITCH, 0x104, DD_OK,
8757 DDSD_PITCH, 0x100, 0x0fc},
8758 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8759 DDSD_PITCH, 0x0f8, DD_OK,
8760 DDSD_PITCH, 0x100, 0x0fc},
8761 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8762 DDSD_PITCH | DDSD_LINEARSIZE, 0, DD_OK,
8763 DDSD_PITCH, 0x100, 0x0fc},
8764 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8765 DDSD_LPSURFACE, 0, DDERR_INVALIDPARAMS,
8766 0, 0, 0 },
8767 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8768 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DD_OK,
8769 DDSD_PITCH, 0x100, 0x100},
8770 /* 10 */
8771 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8772 DDSD_LPSURFACE | DDSD_PITCH, 0x0fe, DDERR_INVALIDPARAMS,
8773 0, 0, 0 },
8774 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8775 DDSD_LPSURFACE | DDSD_PITCH, 0x0fc, DD_OK,
8776 DDSD_PITCH, 0x0fc, 0x0fc},
8777 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8778 DDSD_LPSURFACE | DDSD_PITCH, 0x0f8, DDERR_INVALIDPARAMS,
8779 0, 0, 0 },
8780 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8781 DDSD_LPSURFACE | DDSD_LINEARSIZE, 0x100, DDERR_INVALIDPARAMS,
8782 0, 0, 0 },
8783 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8784 DDSD_LPSURFACE | DDSD_LINEARSIZE, 0x3f00, DDERR_INVALIDPARAMS,
8785 0, 0, 0 },
8786 /* 15 */
8787 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN,
8788 DDSD_LPSURFACE | DDSD_PITCH | DDSD_LINEARSIZE, 0x100, DD_OK,
8789 DDSD_PITCH, 0x100, 0x100},
8790 {DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
8791 0, 0, DDERR_INVALIDCAPS,
8792 0, 0, 0 },
8793 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
8794 0, 0, DD_OK,
8795 DDSD_PITCH, 0x100, 0 },
8796 {DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
8797 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DDERR_INVALIDCAPS,
8798 0, 0, 0 },
8799 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_ALLOCONLOAD,
8800 0, 0, DDERR_INVALIDCAPS,
8801 0, 0, 0 },
8802 /* 20 */
8803 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
8804 0, 0, DD_OK,
8805 DDSD_PITCH, 0x100, 0 },
8806 {DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
8807 DDSD_LPSURFACE | DDSD_PITCH, 0x100, DD_OK,
8808 DDSD_PITCH, 0x100, 0 },
8810 DWORD flags_mask = DDSD_PITCH | DDSD_LPSURFACE | DDSD_LINEARSIZE;
8812 window = create_window();
8813 ddraw = create_ddraw();
8814 ok(!!ddraw, "Failed to create a ddraw object.\n");
8815 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8816 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8818 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((63 * 4) + 8) * 63);
8820 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
8822 memset(&surface_desc, 0, sizeof(surface_desc));
8823 surface_desc.dwSize = sizeof(surface_desc);
8824 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | test_data[i].flags_in;
8825 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
8826 surface_desc.dwWidth = 63;
8827 surface_desc.dwHeight = 63;
8828 U1(surface_desc).lPitch = test_data[i].pitch_in;
8829 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
8830 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
8831 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
8832 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
8833 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
8834 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
8835 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8836 if (test_data[i].flags_in & DDSD_LPSURFACE)
8838 HRESULT expected_hr = SUCCEEDED(test_data[i].hr) ? DDERR_INVALIDPARAMS : test_data[i].hr;
8839 ok(hr == expected_hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, expected_hr);
8840 surface_desc.lpSurface = mem;
8841 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8843 if ((test_data[i].caps & DDSCAPS_VIDEOMEMORY) && hr == DDERR_NODIRECTDRAWHW)
8844 continue;
8845 if (is_ddraw64 && (test_data[i].caps & DDSCAPS_TEXTURE) && SUCCEEDED(test_data[i].hr))
8846 todo_wine ok(hr == E_NOINTERFACE, "Test %u: Got unexpected hr %#x.\n", i, hr);
8847 else
8848 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
8849 if (FAILED(hr))
8850 continue;
8852 memset(&surface_desc, 0, sizeof(surface_desc));
8853 surface_desc.dwSize = sizeof(surface_desc);
8854 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
8855 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
8856 ok((surface_desc.dwFlags & flags_mask) == test_data[i].flags_out,
8857 "Test %u: Got unexpected flags %#x, expected %#x.\n",
8858 i, surface_desc.dwFlags & flags_mask, test_data[i].flags_out);
8859 /* The pitch for textures seems to be implementation specific. */
8860 if (!(test_data[i].caps & DDSCAPS_TEXTURE))
8862 if (is_ddraw64 && test_data[i].pitch_out32 != test_data[i].pitch_out64)
8863 todo_wine ok(U1(surface_desc).lPitch == test_data[i].pitch_out64,
8864 "Test %u: Got unexpected pitch %u, expected %u.\n",
8865 i, U1(surface_desc).lPitch, test_data[i].pitch_out64);
8866 else
8867 ok(U1(surface_desc).lPitch == test_data[i].pitch_out32,
8868 "Test %u: Got unexpected pitch %u, expected %u.\n",
8869 i, U1(surface_desc).lPitch, test_data[i].pitch_out32);
8871 ok(!surface_desc.lpSurface, "Test %u: Got unexpected lpSurface %p.\n", i, surface_desc.lpSurface);
8873 IDirectDrawSurface7_Release(surface);
8876 HeapFree(GetProcessHeap(), 0, mem);
8877 refcount = IDirectDraw7_Release(ddraw);
8878 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
8879 DestroyWindow(window);
8882 static void test_mipmap(void)
8884 IDirectDrawSurface7 *surface, *surface_base, *surface_mip;
8885 unsigned int i, mipmap_count;
8886 DDSURFACEDESC2 surface_desc;
8887 IDirectDraw7 *ddraw;
8888 ULONG refcount;
8889 HWND window;
8890 HRESULT hr;
8891 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
8892 DDCAPS hal_caps;
8894 static const struct
8896 DWORD flags;
8897 DWORD caps;
8898 DWORD width;
8899 DWORD height;
8900 DWORD mipmap_count_in;
8901 HRESULT hr;
8902 DWORD mipmap_count_out;
8904 tests[] =
8906 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 3, DD_OK, 3},
8907 {DDSD_MIPMAPCOUNT, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDPARAMS, 0},
8908 {0, DDSCAPS_TEXTURE | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 1},
8909 {0, DDSCAPS_MIPMAP, 128, 32, 0, DDERR_INVALIDCAPS, 0},
8910 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 128, 32, 0, DD_OK, 8},
8911 {0, DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP, 32, 64, 0, DD_OK, 7},
8914 window = create_window();
8915 ddraw = create_ddraw();
8916 ok(!!ddraw, "Failed to create a ddraw object.\n");
8917 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
8918 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
8920 memset(&hal_caps, 0, sizeof(hal_caps));
8921 hal_caps.dwSize = sizeof(hal_caps);
8922 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
8923 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8924 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)
8925 || is_ddraw64)
8927 skip("Mipmapped textures not supported, skipping tests.\n");
8928 IDirectDraw7_Release(ddraw);
8929 DestroyWindow(window);
8930 return;
8933 for (i = 0; i < ARRAY_SIZE(tests); ++i)
8935 memset(&surface_desc, 0, sizeof(surface_desc));
8936 surface_desc.dwSize = sizeof(surface_desc);
8937 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | tests[i].flags;
8938 surface_desc.ddsCaps.dwCaps = tests[i].caps;
8939 surface_desc.dwWidth = tests[i].width;
8940 surface_desc.dwHeight = tests[i].height;
8941 if (tests[i].flags & DDSD_MIPMAPCOUNT)
8942 U2(surface_desc).dwMipMapCount = tests[i].mipmap_count_in;
8943 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
8944 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x.\n", i, hr);
8945 if (FAILED(hr))
8946 continue;
8948 memset(&surface_desc, 0, sizeof(surface_desc));
8949 surface_desc.dwSize = sizeof(surface_desc);
8950 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
8951 ok(SUCCEEDED(hr), "Test %u: Failed to get surface desc, hr %#x.\n", i, hr);
8952 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
8953 "Test %u: Got unexpected flags %#x.\n", i, surface_desc.dwFlags);
8954 ok(U2(surface_desc).dwMipMapCount == tests[i].mipmap_count_out,
8955 "Test %u: Got unexpected mipmap count %u.\n", i, U2(surface_desc).dwMipMapCount);
8957 surface_base = surface;
8958 IDirectDrawSurface7_AddRef(surface_base);
8959 mipmap_count = U2(surface_desc).dwMipMapCount;
8960 while (mipmap_count > 1)
8962 hr = IDirectDrawSurface7_GetAttachedSurface(surface_base, &caps, &surface_mip);
8963 ok(SUCCEEDED(hr), "Test %u, %u: Failed to get attached surface, hr %#x.\n", i, mipmap_count, hr);
8965 memset(&surface_desc, 0, sizeof(surface_desc));
8966 surface_desc.dwSize = sizeof(surface_desc);
8967 hr = IDirectDrawSurface7_GetSurfaceDesc(surface_base, &surface_desc);
8968 ok(SUCCEEDED(hr), "Test %u, %u: Failed to get surface desc, hr %#x.\n", i, mipmap_count, hr);
8969 ok(surface_desc.dwFlags & DDSD_MIPMAPCOUNT,
8970 "Test %u, %u: Got unexpected flags %#x.\n", i, mipmap_count, surface_desc.dwFlags);
8971 ok(U2(surface_desc).dwMipMapCount == mipmap_count,
8972 "Test %u, %u: Got unexpected mipmap count %u.\n",
8973 i, mipmap_count, U2(surface_desc).dwMipMapCount);
8975 memset(&surface_desc, 0, sizeof(surface_desc));
8976 surface_desc.dwSize = sizeof(surface_desc);
8977 hr = IDirectDrawSurface7_Lock(surface_base, NULL, &surface_desc, 0, NULL);
8978 ok(SUCCEEDED(hr), "Test %u, %u: Failed to lock surface, hr %#x.\n", i, mipmap_count, hr);
8979 ok(surface_desc.dwMipMapCount == mipmap_count,
8980 "Test %u, %u: unexpected change of mipmap count %u.\n",
8981 i, mipmap_count, surface_desc.dwMipMapCount);
8982 memset(&surface_desc, 0, sizeof(surface_desc));
8983 surface_desc.dwSize = sizeof(surface_desc);
8984 hr = IDirectDrawSurface7_Lock(surface_mip, NULL, &surface_desc, 0, NULL);
8985 ok(SUCCEEDED(hr), "Test %u, %u: Failed to lock surface, hr %#x.\n", i, mipmap_count, hr);
8986 ok(surface_desc.dwMipMapCount == mipmap_count - 1,
8987 "Test %u, %u: Child mipmap count unexpected %u\n", i, mipmap_count, surface_desc.dwMipMapCount);
8988 IDirectDrawSurface7_Unlock(surface_mip, NULL);
8989 IDirectDrawSurface7_Unlock(surface_base, NULL);
8991 IDirectDrawSurface7_Release(surface_base);
8992 surface_base = surface_mip;
8993 --mipmap_count;
8995 IDirectDrawSurface7_Release(surface_base);
8997 IDirectDrawSurface7_Release(surface);
9000 refcount = IDirectDraw7_Release(ddraw);
9001 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9002 DestroyWindow(window);
9005 static void test_palette_complex(void)
9007 IDirectDrawSurface7 *surface, *mipmap, *tmp;
9008 DDSURFACEDESC2 surface_desc;
9009 IDirectDraw7 *ddraw;
9010 IDirectDrawPalette *palette, *palette2;
9011 ULONG refcount;
9012 HWND window;
9013 HRESULT hr;
9014 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
9015 DDCAPS hal_caps;
9016 PALETTEENTRY palette_entries[256];
9017 unsigned int i;
9019 window = create_window();
9020 ddraw = create_ddraw();
9021 ok(!!ddraw, "Failed to create a ddraw object.\n");
9022 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9023 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9025 memset(&hal_caps, 0, sizeof(hal_caps));
9026 hal_caps.dwSize = sizeof(hal_caps);
9027 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
9028 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9029 if ((hal_caps.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)) != (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP)
9030 || is_ddraw64)
9032 skip("Mipmapped textures not supported, skipping mipmap palette test.\n");
9033 IDirectDraw7_Release(ddraw);
9034 DestroyWindow(window);
9035 return;
9038 memset(&surface_desc, 0, sizeof(surface_desc));
9039 surface_desc.dwSize = sizeof(surface_desc);
9040 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9041 surface_desc.dwWidth = 128;
9042 surface_desc.dwHeight = 128;
9043 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
9044 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9045 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
9046 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
9047 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9048 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9050 memset(palette_entries, 0, sizeof(palette_entries));
9051 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
9052 palette_entries, &palette, NULL);
9053 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
9055 palette2 = (void *)0xdeadbeef;
9056 hr = IDirectDrawSurface7_GetPalette(surface, &palette2);
9057 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
9058 ok(!palette2, "Got unexpected palette %p.\n", palette2);
9059 hr = IDirectDrawSurface7_SetPalette(surface, palette);
9060 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
9061 hr = IDirectDrawSurface7_GetPalette(surface, &palette2);
9062 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
9063 ok(palette == palette2, "Got unexpected palette %p.\n", palette2);
9064 IDirectDrawPalette_Release(palette2);
9066 mipmap = surface;
9067 IDirectDrawSurface7_AddRef(mipmap);
9068 for (i = 0; i < 7; ++i)
9070 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
9071 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
9072 palette2 = (void *)0xdeadbeef;
9073 hr = IDirectDrawSurface7_GetPalette(tmp, &palette2);
9074 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x, i %u.\n", hr, i);
9075 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
9077 hr = IDirectDrawSurface7_SetPalette(tmp, palette);
9078 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x, i %u.\n", hr, i);
9080 hr = IDirectDrawSurface7_GetPalette(tmp, &palette2);
9081 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x, i %u.\n", hr, i);
9082 ok(!palette2, "Got unexpected palette %p, i %u.\n", palette2, i);
9084 /* Ddraw7 uses the palette of the mipmap for GetDC, just like previous
9085 * ddraw versions. Combined with the test results above this means no
9086 * palette is available. So depending on the driver either GetDC fails
9087 * or the DIB color table contains random data. */
9089 IDirectDrawSurface7_Release(mipmap);
9090 mipmap = tmp;
9093 hr = IDirectDrawSurface7_GetAttachedSurface(mipmap, &caps, &tmp);
9094 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
9095 IDirectDrawSurface7_Release(mipmap);
9096 refcount = IDirectDrawSurface7_Release(surface);
9097 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9099 /* Test DDERR_INVALIDPIXELFORMAT vs DDERR_NOTONMIPMAPSUBLEVEL. */
9100 memset(&surface_desc, 0, sizeof(surface_desc));
9101 surface_desc.dwSize = sizeof(surface_desc);
9102 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9103 surface_desc.dwWidth = 128;
9104 surface_desc.dwHeight = 128;
9105 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
9106 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9107 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
9108 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
9109 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9110 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9111 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
9112 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9113 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9115 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
9116 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
9117 hr = IDirectDrawSurface7_SetPalette(mipmap, palette);
9118 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x.\n", hr);
9120 IDirectDrawSurface7_Release(mipmap);
9121 refcount = IDirectDrawSurface7_Release(surface);
9122 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9123 refcount = IDirectDrawPalette_Release(palette);
9124 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9126 refcount = IDirectDraw7_Release(ddraw);
9127 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9128 DestroyWindow(window);
9131 static void test_p8_blit(void)
9133 IDirectDrawSurface7 *src, *dst, *dst_p8;
9134 DDSURFACEDESC2 surface_desc;
9135 IDirectDraw7 *ddraw;
9136 IDirectDrawPalette *palette, *palette2;
9137 ULONG refcount;
9138 HWND window;
9139 HRESULT hr;
9140 PALETTEENTRY palette_entries[256];
9141 unsigned int x;
9142 DDBLTFX fx;
9143 BOOL is_warp;
9144 static const BYTE src_data[] = {0x10, 0x1, 0x2, 0x3, 0x4, 0x5, 0xff, 0x80};
9145 static const BYTE src_data2[] = {0x10, 0x5, 0x4, 0x3, 0x2, 0x1, 0xff, 0x80};
9146 static const BYTE expected_p8[] = {0x10, 0x1, 0x4, 0x3, 0x4, 0x5, 0xff, 0x80};
9147 static const D3DCOLOR expected[] =
9149 0x00101010, 0x00010101, 0x00020202, 0x00030303,
9150 0x00040404, 0x00050505, 0x00ffffff, 0x00808080,
9152 D3DCOLOR color;
9154 window = create_window();
9155 ddraw = create_ddraw();
9156 ok(!!ddraw, "Failed to create a ddraw object.\n");
9157 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9158 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9159 is_warp = ddraw_is_warp(ddraw);
9161 memset(palette_entries, 0, sizeof(palette_entries));
9162 palette_entries[1].peGreen = 0xff;
9163 palette_entries[2].peBlue = 0xff;
9164 palette_entries[3].peFlags = 0xff;
9165 palette_entries[4].peRed = 0xff;
9166 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
9167 palette_entries, &palette, NULL);
9168 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
9169 palette_entries[1].peBlue = 0xff;
9170 palette_entries[2].peGreen = 0xff;
9171 palette_entries[3].peRed = 0xff;
9172 palette_entries[4].peFlags = 0x0;
9173 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
9174 palette_entries, &palette2, NULL);
9175 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
9177 memset(&surface_desc, 0, sizeof(surface_desc));
9178 surface_desc.dwSize = sizeof(surface_desc);
9179 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9180 surface_desc.dwWidth = 8;
9181 surface_desc.dwHeight = 1;
9182 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9183 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9184 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
9185 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
9186 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
9187 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9188 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_p8, NULL);
9189 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9190 hr = IDirectDrawSurface7_SetPalette(dst_p8, palette2);
9191 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
9193 memset(&surface_desc, 0, sizeof(surface_desc));
9194 surface_desc.dwSize = sizeof(surface_desc);
9195 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9196 surface_desc.dwWidth = 8;
9197 surface_desc.dwHeight = 1;
9198 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9199 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9200 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
9201 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
9202 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9203 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9204 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
9205 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
9206 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
9207 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9209 memset(&surface_desc, 0, sizeof(surface_desc));
9210 surface_desc.dwSize = sizeof(surface_desc);
9211 hr = IDirectDrawSurface7_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
9212 ok(SUCCEEDED(hr), "Failed to lock source surface, hr %#x.\n", hr);
9213 memcpy(surface_desc.lpSurface, src_data, sizeof(src_data));
9214 hr = IDirectDrawSurface7_Unlock(src, NULL);
9215 ok(SUCCEEDED(hr), "Failed to unlock source surface, hr %#x.\n", hr);
9217 hr = IDirectDrawSurface7_Lock(dst_p8, NULL, &surface_desc, DDLOCK_WAIT, NULL);
9218 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#x.\n", hr);
9219 memcpy(surface_desc.lpSurface, src_data2, sizeof(src_data2));
9220 hr = IDirectDrawSurface7_Unlock(dst_p8, NULL);
9221 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#x.\n", hr);
9223 fx.dwSize = sizeof(fx);
9224 fx.dwFillColor = 0xdeadbeef;
9225 hr = IDirectDrawSurface7_Blt(dst, NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &fx);
9226 ok(SUCCEEDED(hr), "Failed to color fill %#x.\n", hr);
9228 hr = IDirectDrawSurface7_SetPalette(src, palette);
9229 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
9230 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_WAIT, NULL);
9231 /* The r500 Windows 7 driver returns E_NOTIMPL. r200 on Windows XP works.
9232 * The Geforce 7 driver on Windows Vista returns E_FAIL. Newer Nvidia GPUs work. */
9233 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL) || broken(hr == E_FAIL),
9234 "Failed to blit, hr %#x.\n", hr);
9236 if (SUCCEEDED(hr))
9238 for (x = 0; x < ARRAY_SIZE(expected); ++x)
9240 color = get_surface_color(dst, x, 0);
9241 /* WARP on 1709 and newer write zeroes on non-colorkeyed P8 -> RGB blits. For ckey
9242 * blits see below. */
9243 todo_wine ok(compare_color(color, expected[x], 0)
9244 || broken(is_warp && compare_color(color, 0x00000000, 0)),
9245 "Pixel %u: Got color %#x, expected %#x.\n",
9246 x, color, expected[x]);
9250 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x2;
9251 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x2;
9252 hr = IDirectDrawSurface7_Blt(dst_p8, NULL, src, NULL, DDBLT_WAIT | DDBLT_KEYSRCOVERRIDE, &fx);
9253 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
9255 hr = IDirectDrawSurface7_Lock(dst_p8, NULL, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
9256 ok(SUCCEEDED(hr), "Failed to lock destination surface, hr %#x.\n", hr);
9257 /* A color keyed P8 blit doesn't do anything on WARP - it just leaves the data in the destination
9258 * surface untouched. Error checking (DDBLT_KEYSRC without a key
9259 * for example) also works as expected.
9261 * Using DDBLT_KEYSRC instead of DDBLT_KEYSRCOVERRIDE doesn't change this. Doing this blit with
9262 * the display mode set to P8 doesn't help either. */
9263 ok(!memcmp(surface_desc.lpSurface, expected_p8, sizeof(expected_p8))
9264 || broken(is_warp && !memcmp(surface_desc.lpSurface, src_data2, sizeof(src_data2))),
9265 "Got unexpected P8 color key blit result.\n");
9266 hr = IDirectDrawSurface7_Unlock(dst_p8, NULL);
9267 ok(SUCCEEDED(hr), "Failed to unlock destination surface, hr %#x.\n", hr);
9269 IDirectDrawSurface7_Release(src);
9270 IDirectDrawSurface7_Release(dst);
9271 IDirectDrawSurface7_Release(dst_p8);
9272 IDirectDrawPalette_Release(palette);
9273 IDirectDrawPalette_Release(palette2);
9275 refcount = IDirectDraw7_Release(ddraw);
9276 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9277 DestroyWindow(window);
9280 static void test_material(void)
9282 static const D3DCOLORVALUE null_color;
9283 IDirect3DDevice7 *device;
9284 D3DMATERIAL7 material;
9285 ULONG refcount;
9286 HWND window;
9287 HRESULT hr;
9289 window = create_window();
9290 if (!(device = create_device(window, DDSCL_NORMAL)))
9292 skip("Failed to create a 3D device, skipping test.\n");
9293 DestroyWindow(window);
9294 return;
9297 hr = IDirect3DDevice7_GetMaterial(device, &material);
9298 ok(SUCCEEDED(hr), "Failed to get material, hr %#x.\n", hr);
9299 ok(!memcmp(&U(material).diffuse, &null_color, sizeof(null_color)),
9300 "Got unexpected diffuse color {%.8e, %.8e, %.8e, %.8e}.\n",
9301 U1(U(material).diffuse).r, U2(U(material).diffuse).g,
9302 U3(U(material).diffuse).b, U4(U(material).diffuse).a);
9303 ok(!memcmp(&U1(material).ambient, &null_color, sizeof(null_color)),
9304 "Got unexpected ambient color {%.8e, %.8e, %.8e, %.8e}.\n",
9305 U1(U1(material).ambient).r, U2(U1(material).ambient).g,
9306 U3(U1(material).ambient).b, U4(U1(material).ambient).a);
9307 ok(!memcmp(&U2(material).specular, &null_color, sizeof(null_color)),
9308 "Got unexpected specular color {%.8e, %.8e, %.8e, %.8e}.\n",
9309 U1(U2(material).specular).r, U2(U2(material).specular).g,
9310 U3(U2(material).specular).b, U4(U2(material).specular).a);
9311 ok(!memcmp(&U3(material).emissive, &null_color, sizeof(null_color)),
9312 "Got unexpected emissive color {%.8e, %.8e, %.8e, %.8e}.\n",
9313 U1(U3(material).emissive).r, U2(U3(material).emissive).g,
9314 U3(U3(material).emissive).b, U4(U3(material).emissive).a);
9315 ok(U4(material).power == 0.0f, "Got unexpected power %.8e.\n", U4(material).power);
9317 refcount = IDirect3DDevice7_Release(device);
9318 ok(!refcount, "Device has %u references left.\n", refcount);
9319 DestroyWindow(window);
9322 static void test_palette_gdi(void)
9324 IDirectDrawSurface7 *surface, *primary;
9325 DDSURFACEDESC2 surface_desc;
9326 IDirectDraw7 *ddraw;
9327 IDirectDrawPalette *palette, *palette2;
9328 ULONG refcount;
9329 HWND window;
9330 HRESULT hr;
9331 PALETTEENTRY palette_entries[256];
9332 UINT i;
9333 HDC dc;
9334 DDBLTFX fx;
9335 RECT r;
9336 COLORREF color;
9337 /* On the Windows 8 testbot palette index 0 of the onscreen palette is forced to
9338 * r = 0, g = 0, b = 0. Do not attempt to set it to something else as this is
9339 * not the point of this test. */
9340 static const RGBQUAD expected1[] =
9342 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
9343 {0x03, 0x00, 0x00, 0x00}, {0x15, 0x14, 0x13, 0x00},
9345 static const RGBQUAD expected2[] =
9347 {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00}, {0x00, 0x02, 0x00, 0x00},
9348 {0x03, 0x00, 0x00, 0x00}, {0x25, 0x24, 0x23, 0x00},
9350 static const RGBQUAD expected3[] =
9352 {0x00, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x40, 0x00},
9353 {0x00, 0x40, 0x00, 0x00}, {0x56, 0x34, 0x12, 0x00},
9355 HPALETTE ddraw_palette_handle;
9356 /* Similar to index 0, index 255 is r = 0xff, g = 0xff, b = 0xff on the Win8 VMs. */
9357 RGBQUAD rgbquad[255];
9358 static const RGBQUAD rgb_zero = {0, 0, 0, 0};
9360 window = create_window();
9361 ddraw = create_ddraw();
9362 ok(!!ddraw, "Failed to create a ddraw object.\n");
9363 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
9364 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9366 memset(&surface_desc, 0, sizeof(surface_desc));
9367 surface_desc.dwSize = sizeof(surface_desc);
9368 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9369 surface_desc.dwWidth = 16;
9370 surface_desc.dwHeight = 16;
9371 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9372 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9373 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
9374 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
9375 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9376 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9378 /* Avoid colors from the Windows default palette. */
9379 memset(palette_entries, 0, sizeof(palette_entries));
9380 palette_entries[1].peRed = 0x01;
9381 palette_entries[2].peGreen = 0x02;
9382 palette_entries[3].peBlue = 0x03;
9383 palette_entries[4].peRed = 0x13;
9384 palette_entries[4].peGreen = 0x14;
9385 palette_entries[4].peBlue = 0x15;
9386 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
9387 palette_entries, &palette, NULL);
9388 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
9390 /* If there is no palette assigned and the display mode is not 8 bpp, some
9391 * drivers refuse to create a DC while others allow it. If a DC is created,
9392 * the DIB color table is uninitialized and contains random colors. No error
9393 * is generated when trying to read pixels and random garbage is returned.
9395 * The most likely explanation is that if the driver creates a DC, it (or
9396 * the higher-level runtime) uses GetSystemPaletteEntries to find the
9397 * palette, but GetSystemPaletteEntries fails when bpp > 8 and the palette
9398 * contains uninitialized garbage. See comments below for the P8 case. */
9400 hr = IDirectDrawSurface7_SetPalette(surface, palette);
9401 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
9402 hr = IDirectDrawSurface7_GetDC(surface, &dc);
9403 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
9404 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
9405 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
9406 "Got unexpected palette %p, expected %p.\n",
9407 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
9409 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
9410 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
9411 for (i = 0; i < ARRAY_SIZE(expected1); ++i)
9413 ok(!memcmp(&rgbquad[i], &expected1[i], sizeof(rgbquad[i])),
9414 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
9415 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
9416 expected1[i].rgbRed, expected1[i].rgbGreen, expected1[i].rgbBlue);
9418 for (; i < ARRAY_SIZE(rgbquad); ++i)
9420 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
9421 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
9422 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
9425 /* Update the palette while the DC is in use. This does not modify the DC. */
9426 palette_entries[4].peRed = 0x23;
9427 palette_entries[4].peGreen = 0x24;
9428 palette_entries[4].peBlue = 0x25;
9429 hr = IDirectDrawPalette_SetEntries(palette, 0, 4, 1, &palette_entries[4]);
9430 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
9432 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
9433 ok(i == 1, "Expected count 1, got %u.\n", i);
9434 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
9435 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
9436 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
9437 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
9439 /* Neither does re-setting the palette. */
9440 hr = IDirectDrawSurface7_SetPalette(surface, NULL);
9441 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
9442 hr = IDirectDrawSurface7_SetPalette(surface, palette);
9443 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
9445 i = GetDIBColorTable(dc, 4, 1, &rgbquad[4]);
9446 ok(i == 1, "Expected count 1, got %u.\n", i);
9447 ok(!memcmp(&rgbquad[4], &expected1[4], sizeof(rgbquad[4])),
9448 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
9449 i, rgbquad[4].rgbRed, rgbquad[4].rgbGreen, rgbquad[4].rgbBlue,
9450 expected1[4].rgbRed, expected1[4].rgbGreen, expected1[4].rgbBlue);
9452 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
9453 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
9455 /* Refresh the DC. This updates the palette. */
9456 hr = IDirectDrawSurface7_GetDC(surface, &dc);
9457 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
9458 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
9459 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
9460 for (i = 0; i < ARRAY_SIZE(expected2); ++i)
9462 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
9463 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
9464 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
9465 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
9467 for (; i < ARRAY_SIZE(rgbquad); ++i)
9469 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
9470 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
9471 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
9473 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
9474 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
9476 refcount = IDirectDrawSurface7_Release(surface);
9477 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9479 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
9480 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9481 if (FAILED(IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
9483 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
9484 IDirectDrawPalette_Release(palette);
9485 IDirectDraw7_Release(ddraw);
9486 DestroyWindow(window);
9487 return;
9489 ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
9491 memset(&surface_desc, 0, sizeof(surface_desc));
9492 surface_desc.dwSize = sizeof(surface_desc);
9493 surface_desc.dwFlags = DDSD_CAPS;
9494 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
9495 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
9496 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9498 memset(&fx, 0, sizeof(fx));
9499 fx.dwSize = sizeof(fx);
9500 U5(fx).dwFillColor = 3;
9501 SetRect(&r, 0, 0, 319, 479);
9502 hr = IDirectDrawSurface7_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9503 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#x.\n", hr);
9504 SetRect(&r, 320, 0, 639, 479);
9505 U5(fx).dwFillColor = 4;
9506 hr = IDirectDrawSurface7_Blt(primary, &r, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
9507 ok(SUCCEEDED(hr), "Failed to clear surface, hr %#x.\n", hr);
9509 hr = IDirectDrawSurface7_SetPalette(primary, palette);
9510 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
9511 hr = IDirectDrawSurface7_GetDC(primary, &dc);
9512 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
9514 color = GetPixel(dc, 160, 240);
9515 ok(color == 0x00030000, "Clear index 3: Got unexpected color 0x%08x.\n", color);
9516 color = GetPixel(dc, 480, 240);
9517 ok(color == 0x00252423, "Clear index 4: Got unexpected color 0x%08x.\n", color);
9519 ddraw_palette_handle = SelectPalette(dc, GetStockObject(DEFAULT_PALETTE), FALSE);
9520 ok(ddraw_palette_handle == GetStockObject(DEFAULT_PALETTE),
9521 "Got unexpected palette %p, expected %p.\n",
9522 ddraw_palette_handle, GetStockObject(DEFAULT_PALETTE));
9523 SelectPalette(dc, ddraw_palette_handle, FALSE);
9525 /* The primary uses the system palette. In exclusive mode, the system palette matches
9526 * the ddraw palette attached to the primary, so the result is what you would expect
9527 * from a regular surface. Tests for the interaction between the ddraw palette and
9528 * the system palette are not included pending an application that depends on this.
9529 * The relation between those causes problems on Windows Vista and newer for games
9530 * like Age of Empires or StarcCaft. Don't emulate it without a real need. */
9531 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
9532 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
9533 for (i = 0; i < ARRAY_SIZE(expected2); ++i)
9535 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
9536 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
9537 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
9538 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
9540 for (; i < ARRAY_SIZE(rgbquad); ++i)
9542 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
9543 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
9544 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
9546 hr = IDirectDrawSurface7_ReleaseDC(primary, dc);
9547 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
9549 memset(&surface_desc, 0, sizeof(surface_desc));
9550 surface_desc.dwSize = sizeof(surface_desc);
9551 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
9552 surface_desc.dwWidth = 16;
9553 surface_desc.dwHeight = 16;
9554 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9555 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9556 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9558 /* Here the offscreen surface appears to use the primary's palette,
9559 * but in all likelihood it is actually the system palette. */
9560 hr = IDirectDrawSurface7_GetDC(surface, &dc);
9561 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
9562 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
9563 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
9564 for (i = 0; i < ARRAY_SIZE(expected2); ++i)
9566 ok(!memcmp(&rgbquad[i], &expected2[i], sizeof(rgbquad[i])),
9567 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
9568 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
9569 expected2[i].rgbRed, expected2[i].rgbGreen, expected2[i].rgbBlue);
9571 for (; i < ARRAY_SIZE(rgbquad); ++i)
9573 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
9574 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
9575 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
9577 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
9578 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
9580 /* On real hardware a change to the primary surface's palette applies immediately,
9581 * even on device contexts from offscreen surfaces that do not have their own
9582 * palette. On the testbot VMs this is not the case. Don't test this until we
9583 * know of an application that depends on this. */
9585 memset(palette_entries, 0, sizeof(palette_entries));
9586 palette_entries[1].peBlue = 0x40;
9587 palette_entries[2].peRed = 0x40;
9588 palette_entries[3].peGreen = 0x40;
9589 palette_entries[4].peRed = 0x12;
9590 palette_entries[4].peGreen = 0x34;
9591 palette_entries[4].peBlue = 0x56;
9592 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
9593 palette_entries, &palette2, NULL);
9594 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
9595 hr = IDirectDrawSurface7_SetPalette(surface, palette2);
9596 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
9598 /* A palette assigned to the offscreen surface overrides the primary / system
9599 * palette. */
9600 hr = IDirectDrawSurface7_GetDC(surface, &dc);
9601 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
9602 i = GetDIBColorTable(dc, 0, ARRAY_SIZE(rgbquad), rgbquad);
9603 ok(i == ARRAY_SIZE(rgbquad), "Expected count 255, got %u.\n", i);
9604 for (i = 0; i < ARRAY_SIZE(expected3); ++i)
9606 ok(!memcmp(&rgbquad[i], &expected3[i], sizeof(rgbquad[i])),
9607 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=%#x g=%#x b=%#x.\n",
9608 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue,
9609 expected3[i].rgbRed, expected3[i].rgbGreen, expected3[i].rgbBlue);
9611 for (; i < ARRAY_SIZE(rgbquad); ++i)
9613 ok(!memcmp(&rgbquad[i], &rgb_zero, sizeof(rgbquad[i])),
9614 "Got color table entry %u r=%#x g=%#x b=%#x, expected r=0 g=0 b=0.\n",
9615 i, rgbquad[i].rgbRed, rgbquad[i].rgbGreen, rgbquad[i].rgbBlue);
9617 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
9618 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
9620 refcount = IDirectDrawSurface7_Release(surface);
9621 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9623 /* The Windows 8 testbot keeps extra references to the primary and
9624 * backbuffer while in 8 bpp mode. */
9625 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
9626 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
9628 refcount = IDirectDrawSurface7_Release(primary);
9629 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9630 refcount = IDirectDrawPalette_Release(palette2);
9631 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9632 refcount = IDirectDrawPalette_Release(palette);
9633 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9634 refcount = IDirectDraw7_Release(ddraw);
9635 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9636 DestroyWindow(window);
9639 static void test_palette_alpha(void)
9641 IDirectDrawSurface7 *surface;
9642 DDSURFACEDESC2 surface_desc;
9643 IDirectDraw7 *ddraw;
9644 IDirectDrawPalette *palette;
9645 ULONG refcount;
9646 HWND window;
9647 HRESULT hr;
9648 PALETTEENTRY palette_entries[256];
9649 unsigned int i;
9650 static const struct
9652 DWORD caps, flags;
9653 BOOL attach_allowed;
9654 const char *name;
9656 test_data[] =
9658 {DDSCAPS_OFFSCREENPLAIN, DDSD_WIDTH | DDSD_HEIGHT, FALSE, "offscreenplain"},
9659 {DDSCAPS_TEXTURE, DDSD_WIDTH | DDSD_HEIGHT, TRUE, "texture"},
9660 {DDSCAPS_PRIMARYSURFACE, 0, FALSE, "primary"}
9663 window = create_window();
9664 ddraw = create_ddraw();
9665 ok(!!ddraw, "Failed to create a ddraw object.\n");
9666 if (FAILED(IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
9668 win_skip("Failed to set 8 bpp display mode, skipping test.\n");
9669 IDirectDraw7_Release(ddraw);
9670 DestroyWindow(window);
9671 return;
9673 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
9674 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
9676 memset(palette_entries, 0, sizeof(palette_entries));
9677 palette_entries[1].peFlags = 0x42;
9678 palette_entries[2].peFlags = 0xff;
9679 palette_entries[3].peFlags = 0x80;
9680 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, palette_entries, &palette, NULL);
9681 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
9683 memset(palette_entries, 0x66, sizeof(palette_entries));
9684 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
9685 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
9686 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
9687 palette_entries[0].peFlags);
9688 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
9689 palette_entries[1].peFlags);
9690 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
9691 palette_entries[2].peFlags);
9692 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
9693 palette_entries[3].peFlags);
9695 IDirectDrawPalette_Release(palette);
9697 memset(palette_entries, 0, sizeof(palette_entries));
9698 palette_entries[1].peFlags = 0x42;
9699 palette_entries[1].peRed = 0xff;
9700 palette_entries[2].peFlags = 0xff;
9701 palette_entries[3].peFlags = 0x80;
9702 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT | DDPCAPS_ALPHA,
9703 palette_entries, &palette, NULL);
9704 ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
9706 memset(palette_entries, 0x66, sizeof(palette_entries));
9707 hr = IDirectDrawPalette_GetEntries(palette, 0, 1, 4, palette_entries);
9708 ok(SUCCEEDED(hr), "Failed to get palette entries, hr %#x.\n", hr);
9709 ok(palette_entries[0].peFlags == 0x42, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
9710 palette_entries[0].peFlags);
9711 ok(palette_entries[1].peFlags == 0xff, "Got unexpected peFlags 0x%02x, expected 0xff.\n",
9712 palette_entries[1].peFlags);
9713 ok(palette_entries[2].peFlags == 0x80, "Got unexpected peFlags 0x%02x, expected 0x80.\n",
9714 palette_entries[2].peFlags);
9715 ok(palette_entries[3].peFlags == 0x00, "Got unexpected peFlags 0x%02x, expected 0x00.\n",
9716 palette_entries[3].peFlags);
9718 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
9720 memset(&surface_desc, 0, sizeof(surface_desc));
9721 surface_desc.dwSize = sizeof(surface_desc);
9722 surface_desc.dwFlags = DDSD_CAPS | test_data[i].flags;
9723 surface_desc.dwWidth = 128;
9724 surface_desc.dwHeight = 128;
9725 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
9726 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9727 if (is_ddraw64 && test_data[i].caps & DDSCAPS_TEXTURE)
9728 todo_wine ok(hr == E_NOINTERFACE, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
9729 else
9730 ok(hr == DD_OK, "%s: Got unexpected hr %#x.\n", test_data[i].name, hr);
9731 if (FAILED(hr))
9732 continue;
9734 hr = IDirectDrawSurface7_SetPalette(surface, palette);
9735 if (test_data[i].attach_allowed)
9736 ok(SUCCEEDED(hr), "Failed to attach palette to %s surface, hr %#x.\n", test_data[i].name, hr);
9737 else
9738 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x, %s surface.\n", hr, test_data[i].name);
9740 if (SUCCEEDED(hr))
9742 HDC dc;
9743 RGBQUAD rgbquad;
9744 UINT retval;
9746 hr = IDirectDrawSurface7_GetDC(surface, &dc);
9747 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x, %s surface.\n", hr, test_data[i].name);
9748 retval = GetDIBColorTable(dc, 1, 1, &rgbquad);
9749 ok(retval == 1, "GetDIBColorTable returned unexpected result %u.\n", retval);
9750 ok(rgbquad.rgbRed == 0xff, "Expected rgbRed = 0xff, got %#x, %s surface.\n",
9751 rgbquad.rgbRed, test_data[i].name);
9752 ok(rgbquad.rgbGreen == 0, "Expected rgbGreen = 0, got %#x, %s surface.\n",
9753 rgbquad.rgbGreen, test_data[i].name);
9754 ok(rgbquad.rgbBlue == 0, "Expected rgbBlue = 0, got %#x, %s surface.\n",
9755 rgbquad.rgbBlue, test_data[i].name);
9756 ok(rgbquad.rgbReserved == 0, "Expected rgbReserved = 0, got %u, %s surface.\n",
9757 rgbquad.rgbReserved, test_data[i].name);
9758 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
9759 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
9761 IDirectDrawSurface7_Release(surface);
9764 /* Test INVALIDSURFACETYPE vs INVALIDPIXELFORMAT. */
9765 memset(&surface_desc, 0, sizeof(surface_desc));
9766 surface_desc.dwSize = sizeof(surface_desc);
9767 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9768 surface_desc.dwWidth = 128;
9769 surface_desc.dwHeight = 128;
9770 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
9771 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9772 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
9773 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
9774 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9775 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9776 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
9777 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9778 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9779 hr = IDirectDrawSurface7_SetPalette(surface, palette);
9780 ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x.\n", hr);
9781 IDirectDrawSurface7_Release(surface);
9783 /* The Windows 8 testbot keeps extra references to the primary
9784 * while in 8 bpp mode. */
9785 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
9786 ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
9788 refcount = IDirectDrawPalette_Release(palette);
9789 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9790 refcount = IDirectDraw7_Release(ddraw);
9791 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
9792 DestroyWindow(window);
9795 static void test_vb_writeonly(void)
9797 IDirect3DDevice7 *device;
9798 IDirect3D7 *d3d;
9799 IDirect3DVertexBuffer7 *buffer;
9800 HWND window;
9801 HRESULT hr;
9802 D3DVERTEXBUFFERDESC desc;
9803 void *ptr;
9804 static const struct vec4 quad[] =
9806 { 0.0f, 480.0f, 0.0f, 1.0f},
9807 { 0.0f, 0.0f, 0.0f, 1.0f},
9808 {640.0f, 480.0f, 0.0f, 1.0f},
9809 {640.0f, 0.0f, 0.0f, 1.0f},
9812 window = create_window();
9813 if (!(device = create_device(window, DDSCL_NORMAL)))
9815 skip("Failed to create a 3D device, skipping test.\n");
9816 DestroyWindow(window);
9817 return;
9820 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
9821 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
9823 memset(&desc, 0, sizeof(desc));
9824 desc.dwSize = sizeof(desc);
9825 desc.dwCaps = D3DVBCAPS_WRITEONLY;
9826 desc.dwFVF = D3DFVF_XYZRHW;
9827 desc.dwNumVertices = ARRAY_SIZE(quad);
9828 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &buffer, 0);
9829 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
9831 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, &ptr, NULL);
9832 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
9833 memcpy(ptr, quad, sizeof(quad));
9834 hr = IDirect3DVertexBuffer7_Unlock(buffer);
9835 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
9837 hr = IDirect3DDevice7_BeginScene(device);
9838 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9839 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 4, 0);
9840 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9841 hr = IDirect3DDevice7_EndScene(device);
9842 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9844 hr = IDirect3DVertexBuffer7_Lock(buffer, 0, &ptr, NULL);
9845 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
9846 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
9847 hr = IDirect3DVertexBuffer7_Unlock(buffer);
9848 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
9850 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_READONLY, &ptr, NULL);
9851 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
9852 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
9853 hr = IDirect3DVertexBuffer7_Unlock(buffer);
9854 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
9856 IDirect3DVertexBuffer7_Release(buffer);
9857 IDirect3D7_Release(d3d);
9858 IDirect3DDevice7_Release(device);
9859 DestroyWindow(window);
9862 static void test_lost_device(void)
9864 IDirectDrawSurface7 *sysmem_surface, *vidmem_surface;
9865 IDirectDrawSurface7 *surface, *back_buffer;
9866 DDSURFACEDESC2 surface_desc;
9867 HWND window1, window2;
9868 IDirectDraw7 *ddraw;
9869 ULONG refcount;
9870 DDSCAPS2 caps;
9871 HRESULT hr;
9872 BOOL ret;
9874 window1 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9875 0, 0, 640, 480, 0, 0, 0, 0);
9876 window2 = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
9877 0, 0, 640, 480, 0, 0, 0, 0);
9878 ddraw = create_ddraw();
9879 ok(!!ddraw, "Failed to create a ddraw object.\n");
9880 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
9881 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9883 memset(&surface_desc, 0, sizeof(surface_desc));
9884 surface_desc.dwSize = sizeof(surface_desc);
9885 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
9886 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
9887 U5(surface_desc).dwBackBufferCount = 1;
9888 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
9889 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9891 memset(&surface_desc, 0, sizeof(surface_desc));
9892 surface_desc.dwSize = sizeof(surface_desc);
9893 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
9894 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
9895 surface_desc.dwWidth = 100;
9896 surface_desc.dwHeight = 100;
9897 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &sysmem_surface, NULL);
9898 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9900 memset(&surface_desc, 0, sizeof(surface_desc));
9901 surface_desc.dwSize = sizeof(surface_desc);
9902 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
9903 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
9904 surface_desc.dwWidth = 64;
9905 surface_desc.dwHeight = 64;
9906 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
9907 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
9908 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
9909 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
9910 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
9911 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
9912 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &surface_desc, &vidmem_surface, NULL)))
9914 skip("Failed to create video memory surface, skipping related tests.\n");
9915 vidmem_surface = NULL;
9918 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9919 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9920 hr = IDirectDrawSurface7_IsLost(surface);
9921 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9922 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9923 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9924 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
9925 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9926 if (vidmem_surface)
9928 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
9929 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9932 ret = SetForegroundWindow(GetDesktopWindow());
9933 ok(ret, "Failed to set foreground window.\n");
9934 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9935 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
9936 hr = IDirectDrawSurface7_IsLost(surface);
9937 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9938 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9939 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9940 hr = IDirectDrawSurface7_Restore(surface);
9941 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
9942 hr = IDirectDrawSurface7_IsLost(surface);
9943 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9944 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
9945 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9946 hr = IDirectDrawSurface7_Restore(sysmem_surface);
9947 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9948 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
9949 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9950 if (vidmem_surface)
9952 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
9953 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9954 hr = IDirectDrawSurface7_Restore(vidmem_surface);
9955 ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
9956 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
9957 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9960 ret = SetForegroundWindow(window1);
9961 ok(ret, "Failed to set foreground window.\n");
9962 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9963 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9964 hr = IDirectDrawSurface7_IsLost(surface);
9965 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9966 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9967 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9968 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
9969 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9970 if (vidmem_surface)
9972 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
9973 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9976 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
9977 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9978 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9979 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9980 hr = IDirectDrawSurface7_IsLost(surface);
9981 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9982 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9983 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9984 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
9985 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9986 if (vidmem_surface)
9988 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
9989 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9992 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
9993 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9994 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
9995 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
9996 hr = IDirectDrawSurface7_IsLost(surface);
9997 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
9998 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
9999 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
10000 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
10001 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10002 if (vidmem_surface)
10004 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
10005 todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
10008 /* Trying to restore the primary will crash, probably because flippable
10009 * surfaces can't exist in DDSCL_NORMAL. */
10010 IDirectDrawSurface7_Release(surface);
10011 memset(&surface_desc, 0, sizeof(surface_desc));
10012 surface_desc.dwSize = sizeof(surface_desc);
10013 surface_desc.dwFlags = DDSD_CAPS;
10014 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
10015 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10016 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10017 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
10018 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10019 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
10020 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10022 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
10023 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10024 hr = IDirectDrawSurface7_IsLost(surface);
10025 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10026 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
10027 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10028 if (vidmem_surface)
10030 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
10031 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10034 ret = SetForegroundWindow(GetDesktopWindow());
10035 ok(ret, "Failed to set foreground window.\n");
10036 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
10037 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10038 hr = IDirectDrawSurface7_IsLost(surface);
10039 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10040 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
10041 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10042 if (vidmem_surface)
10044 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
10045 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10048 ret = SetForegroundWindow(window1);
10049 ok(ret, "Failed to set foreground window.\n");
10050 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
10051 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10052 hr = IDirectDrawSurface7_IsLost(surface);
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 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
10063 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10064 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
10065 ok(hr == DD_OK, "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_IsLost(sysmem_surface);
10069 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10070 if (vidmem_surface)
10072 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
10073 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
10076 hr = IDirectDraw7_RestoreAllSurfaces(ddraw);
10077 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10078 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
10079 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10080 hr = IDirectDrawSurface7_IsLost(surface);
10081 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10082 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
10083 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10084 if (vidmem_surface)
10086 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
10087 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10090 IDirectDrawSurface7_Release(surface);
10091 memset(&surface_desc, 0, sizeof(surface_desc));
10092 surface_desc.dwSize = sizeof(surface_desc);
10093 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
10094 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
10095 U5(surface_desc).dwBackBufferCount = 1;
10096 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10097 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10099 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
10100 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10101 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
10102 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10103 hr = IDirectDrawSurface7_IsLost(surface);
10104 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10105 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
10106 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10107 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
10108 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10109 if (vidmem_surface)
10111 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
10112 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10115 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL | DDSCL_FULLSCREEN);
10116 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10117 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
10118 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10119 hr = IDirectDrawSurface7_IsLost(surface);
10120 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10121 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
10122 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
10123 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
10124 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10125 if (vidmem_surface)
10127 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
10128 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10131 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window1, DDSCL_NORMAL);
10132 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10133 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
10134 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10135 hr = IDirectDrawSurface7_IsLost(surface);
10136 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10137 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
10138 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
10139 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
10140 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10141 if (vidmem_surface)
10143 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
10144 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10147 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL);
10148 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10149 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
10150 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10151 hr = IDirectDrawSurface7_IsLost(surface);
10152 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10153 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
10154 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
10155 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
10156 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10157 if (vidmem_surface)
10159 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
10160 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10163 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_NORMAL | DDSCL_FULLSCREEN);
10164 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10165 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
10166 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10167 hr = IDirectDrawSurface7_IsLost(surface);
10168 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10169 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
10170 ok(hr == DDERR_NOEXCLUSIVEMODE, "Got unexpected hr %#x.\n", hr);
10171 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
10172 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10173 if (vidmem_surface)
10175 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
10176 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10179 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window2, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
10180 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10181 hr = IDirectDraw7_TestCooperativeLevel(ddraw);
10182 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10183 hr = IDirectDrawSurface7_IsLost(surface);
10184 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
10185 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
10186 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
10187 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
10188 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10189 if (vidmem_surface)
10191 hr = IDirectDrawSurface7_IsLost(vidmem_surface);
10192 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
10195 memset(&caps, 0, sizeof(caps));
10196 caps.dwCaps = DDSCAPS_FLIP;
10198 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &back_buffer);
10199 ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
10200 hr = IDirectDrawSurface7_Restore(surface);
10201 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10202 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &back_buffer);
10203 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10204 hr = IDirectDrawSurface7_IsLost(back_buffer);
10205 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
10207 IDirectDrawSurface7_Release(back_buffer);
10209 if (vidmem_surface)
10210 IDirectDrawSurface7_Release(vidmem_surface);
10211 IDirectDrawSurface7_Release(sysmem_surface);
10212 IDirectDrawSurface7_Release(surface);
10213 refcount = IDirectDraw7_Release(ddraw);
10214 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
10215 DestroyWindow(window2);
10216 DestroyWindow(window1);
10219 static void test_resource_priority(void)
10221 IDirectDrawSurface7 *surface, *mipmap;
10222 DDSURFACEDESC2 surface_desc;
10223 IDirectDraw7 *ddraw;
10224 ULONG refcount;
10225 HWND window;
10226 HRESULT hr;
10227 DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, {0}};
10228 DDCAPS hal_caps;
10229 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_MIPMAP;
10230 unsigned int i;
10231 DWORD priority;
10232 static const struct
10234 DWORD caps, caps2;
10235 const char *name;
10236 HRESULT hr;
10237 /* SetPriority on offscreenplain surfaces crashes on AMD GPUs on Win7. */
10238 BOOL crash;
10240 test_data[] =
10242 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, "vidmem texture", DDERR_INVALIDPARAMS, FALSE},
10243 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, "sysmem texture", DDERR_INVALIDPARAMS, FALSE},
10244 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, "managed texture", DD_OK, FALSE},
10245 {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, "managed texture", DD_OK, FALSE},
10246 {DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP,
10247 DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_TEXTUREMANAGE,
10248 "cubemap", DD_OK, FALSE},
10249 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, "vidmem offscreenplain", DDERR_INVALIDOBJECT, TRUE},
10250 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, "sysmem offscreenplain", DDERR_INVALIDOBJECT, TRUE},
10253 window = create_window();
10254 ddraw = create_ddraw();
10255 ok(!!ddraw, "Failed to create a ddraw object.\n");
10256 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10257 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
10259 memset(&hal_caps, 0, sizeof(hal_caps));
10260 hal_caps.dwSize = sizeof(hal_caps);
10261 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
10262 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
10263 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps
10264 || !(hal_caps.ddsCaps.dwCaps & DDSCAPS2_TEXTUREMANAGE))
10266 skip("Required surface types not supported, skipping test.\n");
10267 goto done;
10270 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
10272 memset(&surface_desc, 0, sizeof(surface_desc));
10273 surface_desc.dwSize = sizeof(surface_desc);
10274 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
10275 surface_desc.dwWidth = 32;
10276 surface_desc.dwHeight = 32;
10277 surface_desc.ddsCaps.dwCaps = test_data[i].caps;
10278 surface_desc.ddsCaps.dwCaps2 = test_data[i].caps2;
10279 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10280 if (is_ddraw64 && (test_data[i].caps & DDSCAPS_TEXTURE))
10282 todo_wine ok(hr == E_NOINTERFACE, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
10283 if (SUCCEEDED(hr))
10284 IDirectDrawSurface7_Release(surface);
10285 continue;
10287 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n", hr, test_data[i].name);
10289 /* Priority == NULL segfaults. */
10290 priority = 0xdeadbeef;
10291 hr = IDirectDrawSurface7_GetPriority(surface, &priority);
10292 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
10293 if (SUCCEEDED(test_data[i].hr))
10294 ok(priority == 0, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
10295 else
10296 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
10298 if (!test_data[i].crash)
10300 hr = IDirectDrawSurface7_SetPriority(surface, 1);
10301 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
10302 hr = IDirectDrawSurface7_GetPriority(surface, &priority);
10303 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
10304 if (SUCCEEDED(test_data[i].hr))
10306 ok(priority == 1, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
10307 hr = IDirectDrawSurface7_SetPriority(surface, 2);
10308 ok(hr == test_data[i].hr, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
10310 else
10311 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
10314 if (test_data[i].caps2 & DDSCAPS2_CUBEMAP)
10316 caps.dwCaps2 = DDSCAPS2_CUBEMAP_NEGATIVEZ;
10317 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
10318 ok(SUCCEEDED(hr), "Failed to get attached surface, i %u, hr %#x.\n", i, hr);
10319 /* IDirectDrawSurface7_SetPriority crashes when called on non-positive X surfaces on Windows */
10320 priority = 0xdeadbeef;
10321 hr = IDirectDrawSurface7_GetPriority(mipmap, &priority);
10322 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, test_data[i].name);
10323 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type %s.\n", priority, test_data[i].name);
10325 IDirectDrawSurface7_Release(mipmap);
10328 IDirectDrawSurface7_Release(surface);
10331 if (is_ddraw64)
10332 goto done;
10334 memset(&surface_desc, 0, sizeof(surface_desc));
10335 surface_desc.dwSize = sizeof(surface_desc);
10336 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_MIPMAPCOUNT;
10337 surface_desc.dwWidth = 32;
10338 surface_desc.dwHeight = 32;
10339 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
10340 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
10341 U2(surface_desc).dwMipMapCount = 2;
10342 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10343 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10344 caps.dwCaps2 = 0;
10345 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &mipmap);
10346 ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
10348 priority = 0xdeadbeef;
10349 hr = IDirectDrawSurface7_GetPriority(mipmap, &priority);
10350 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type managed mipmap.\n", hr);
10351 ok(priority == 0xdeadbeef, "Got unexpected priority %u, type managed mipmap.\n", priority);
10352 /* SetPriority on the mipmap surface crashes. */
10353 hr = IDirectDrawSurface7_GetPriority(surface, &priority);
10354 ok(SUCCEEDED(hr), "Failed to get priority, hr %#x.\n", hr);
10355 ok(priority == 0, "Got unexpected priority %u, type managed mipmap.\n", priority);
10357 IDirectDrawSurface7_Release(mipmap);
10358 refcount = IDirectDrawSurface7_Release(surface);
10359 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
10361 done:
10362 refcount = IDirectDraw7_Release(ddraw);
10363 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
10364 DestroyWindow(window);
10367 static void test_surface_desc_lock(void)
10369 IDirectDrawSurface7 *surface;
10370 DDSURFACEDESC2 surface_desc;
10371 IDirectDraw7 *ddraw;
10372 ULONG refcount;
10373 HWND window;
10374 HRESULT hr;
10376 window = create_window();
10377 ddraw = create_ddraw();
10378 ok(!!ddraw, "Failed to create a ddraw object.\n");
10379 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
10380 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
10382 memset(&surface_desc, 0, sizeof(surface_desc));
10383 surface_desc.dwSize = sizeof(surface_desc);
10384 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
10385 surface_desc.dwWidth = 16;
10386 surface_desc.dwHeight = 16;
10387 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
10388 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
10389 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10391 memset(&surface_desc, 0xaa, sizeof(surface_desc));
10392 surface_desc.dwSize = sizeof(surface_desc);
10393 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
10394 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
10395 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
10397 memset(&surface_desc, 0xaa, sizeof(surface_desc));
10398 surface_desc.dwSize = sizeof(surface_desc);
10399 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, 0, NULL);
10400 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10401 ok(surface_desc.lpSurface != NULL, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
10402 memset(&surface_desc, 0xaa, sizeof(surface_desc));
10403 surface_desc.dwSize = sizeof(surface_desc);
10404 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
10405 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
10406 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
10407 hr = IDirectDrawSurface7_Unlock(surface, NULL);
10408 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10410 memset(&surface_desc, 0xaa, sizeof(surface_desc));
10411 surface_desc.dwSize = sizeof(surface_desc);
10412 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
10413 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
10414 ok(!surface_desc.lpSurface, "Got unexpected lpSurface %p.\n", surface_desc.lpSurface);
10416 IDirectDrawSurface7_Release(surface);
10417 refcount = IDirectDraw7_Release(ddraw);
10418 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
10419 DestroyWindow(window);
10422 static void test_fog_interpolation(void)
10424 HRESULT hr;
10425 IDirect3DDevice7 *device;
10426 IDirectDrawSurface7 *rt;
10427 ULONG refcount;
10428 HWND window;
10429 D3DCOLOR color;
10430 static struct
10432 struct vec3 position;
10433 D3DCOLOR diffuse;
10434 D3DCOLOR specular;
10436 quad[] =
10438 {{-1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff000000},
10439 {{-1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff000000},
10440 {{ 1.0f, -1.0f, 1.0f}, 0xffff0000, 0x00000000},
10441 {{ 1.0f, 1.0f, 1.0f}, 0xffff0000, 0x00000000},
10443 union
10445 DWORD d;
10446 float f;
10447 } conv;
10448 unsigned int i;
10449 static const struct
10451 D3DFOGMODE vfog, tfog;
10452 D3DSHADEMODE shade;
10453 D3DCOLOR middle_color;
10454 BOOL todo;
10456 tests[] =
10458 {D3DFOG_NONE, D3DFOG_NONE, D3DSHADE_FLAT, 0x00007f80, FALSE},
10459 {D3DFOG_NONE, D3DFOG_NONE, D3DSHADE_GOURAUD, 0x00007f80, FALSE},
10460 {D3DFOG_EXP, D3DFOG_NONE, D3DSHADE_FLAT, 0x00007f80, TRUE},
10461 {D3DFOG_EXP, D3DFOG_NONE, D3DSHADE_GOURAUD, 0x00007f80, TRUE},
10462 {D3DFOG_NONE, D3DFOG_EXP, D3DSHADE_FLAT, 0x0000ea15, FALSE},
10463 {D3DFOG_NONE, D3DFOG_EXP, D3DSHADE_GOURAUD, 0x0000ea15, FALSE},
10464 {D3DFOG_EXP, D3DFOG_EXP, D3DSHADE_FLAT, 0x0000ea15, FALSE},
10465 {D3DFOG_EXP, D3DFOG_EXP, D3DSHADE_GOURAUD, 0x0000ea15, FALSE},
10467 D3DDEVICEDESC7 caps;
10469 window = create_window();
10470 if (!(device = create_device(window, DDSCL_NORMAL)))
10472 skip("Failed to create a 3D device, skipping test.\n");
10473 DestroyWindow(window);
10474 return;
10477 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
10478 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10479 hr = IDirect3DDevice7_GetCaps(device, &caps);
10480 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10481 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE))
10482 skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping some fog tests\n");
10484 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
10485 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10486 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
10487 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10488 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
10489 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10490 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x0000ff00);
10491 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10492 conv.f = 5.0;
10493 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGDENSITY, conv.d);
10494 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10496 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
10497 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
10498 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
10499 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
10500 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x000000ff);
10501 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10503 for (i = 0; i < ARRAY_SIZE(tests); ++i)
10505 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE) && tests[i].tfog)
10506 continue;
10508 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00808080, 0.0f, 0);
10509 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10511 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SHADEMODE, tests[i].shade);
10512 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10513 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, tests[i].vfog);
10514 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10515 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, tests[i].tfog);
10516 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10517 hr = IDirect3DDevice7_BeginScene(device);
10518 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10519 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
10520 D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR, quad, 4, 0);
10521 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10522 hr = IDirect3DDevice7_EndScene(device);
10523 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10525 color = get_surface_color(rt, 0, 240);
10526 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x, case %u.\n", color, i);
10527 color = get_surface_color(rt, 320, 240);
10528 todo_wine_if (tests[i].todo)
10529 ok(compare_color(color, tests[i].middle_color, 2),
10530 "Got unexpected color 0x%08x, case %u.\n", color, i);
10531 color = get_surface_color(rt, 639, 240);
10532 ok(compare_color(color, 0x0000fd02, 2), "Got unexpected color 0x%08x, case %u.\n", color, i);
10535 IDirectDrawSurface7_Release(rt);
10536 refcount = IDirect3DDevice7_Release(device);
10537 ok(!refcount, "Device has %u references left.\n", refcount);
10538 DestroyWindow(window);
10541 static void test_fog_process_vertices(void)
10543 static D3DMATRIX view_matrix =
10545 1.0f, 0.0f, 0.0f, 0.0f,
10546 0.0f, 1.0f, 0.0f, 0.0f,
10547 0.0f, 0.0f, 0.5f, 0.0f,
10548 0.0f, 0.0f, 0.0f, 1.0f
10550 static D3DMATRIX model_matrix =
10552 1.0f, 0.0f, 0.0f, 0.0f,
10553 0.0f, 1.0f, 0.0f, 0.0f,
10554 0.0f, 0.0f, 0.75f, 0.0f,
10555 0.0f, 0.0f, 0.0f, 1.0f
10557 static D3DMATRIX identity_matrix =
10559 1.0f, 0.0f, 0.0f, 0.0f,
10560 0.0f, 1.0f, 0.0f, 0.0f,
10561 0.0f, 0.0f, 1.0f, 0.0f,
10562 0.0f, 0.0f, 0.0f, 1.0f
10565 static D3DLIGHT7 directional_light =
10567 D3DLIGHT_DIRECTIONAL,
10568 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
10569 {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
10570 {{0.0f}, {0.0f}, {0.0f}, {0.0f}},
10571 {{0.0f}, {0.0f}, {0.0f}},
10572 {{0.0f}, {0.0f}, {1.0f}},
10575 struct vertex
10577 struct vec3 position;
10578 struct vec3 normal;
10580 static const struct
10582 struct vertex vertex;
10583 D3DFOGMODE fog_vertex_mode, fog_table_mode;
10584 BOOL range_fog;
10585 D3DCOLOR expected_color, expected_broken;
10587 tests[] =
10589 /* Some drivers ignore ranged fog state without an obvious reason, even with D3DPRASTERCAPS_FOGRANGE
10590 * set, while some others (including WARP driver on Windows 10) favour it.
10591 * Vertex fog result does not depend on table fog settings. */
10592 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_NONE, D3DFOG_NONE, FALSE, 0x8000ff00},
10593 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_NONE, D3DFOG_LINEAR, FALSE, 0x8000ff00},
10594 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_EXP, D3DFOG_NONE, FALSE, 0xaf00ff00},
10595 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_EXP2, D3DFOG_NONE, FALSE, 0xde00ff00},
10596 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_LINEAR, D3DFOG_NONE, FALSE, 0x9f00ff00},
10597 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_LINEAR, D3DFOG_LINEAR, FALSE, 0x9f00ff00},
10598 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_NONE, D3DFOG_NONE, TRUE, 0x8000ff00},
10599 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_EXP, D3DFOG_NONE, TRUE, 0x8800ff00, 0xaf00ff00},
10600 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_EXP2, D3DFOG_NONE, TRUE, 0xad00ff00, 0xde00ff00},
10601 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_LINEAR, D3DFOG_NONE, TRUE, 0x6000ff00, 0x9f00ff00},
10602 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_LINEAR, D3DFOG_EXP, TRUE, 0x6000ff00, 0x9f00ff00},
10603 {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_EXP, D3DFOG_LINEAR, TRUE, 0x8800ff00, 0xaf00ff00},
10606 struct
10608 struct vec4 position;
10609 D3DCOLOR diffuse, specular;
10611 *dst_data;
10613 IDirect3DVertexBuffer7 *src_vb, *dst_vb;
10614 D3DVERTEXBUFFERDESC vb_desc;
10615 IDirect3DDevice7 *device;
10616 struct vertex *src_data;
10617 D3DMATERIAL7 material;
10618 IDirect3D7 *d3d;
10619 ULONG refcount;
10620 unsigned int i;
10621 HWND window;
10622 HRESULT hr;
10624 window = create_window();
10625 if (!(device = create_device(window, DDSCL_NORMAL)))
10627 skip("Failed to create a 3D device, skipping test.\n");
10628 DestroyWindow(window);
10629 return;
10631 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
10632 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10634 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &model_matrix);
10635 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10636 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &view_matrix);
10637 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10638 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &identity_matrix);
10639 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10641 memset(&vb_desc, 0, sizeof(vb_desc));
10642 vb_desc.dwSize = sizeof(vb_desc);
10643 vb_desc.dwFVF = D3DFVF_XYZ | D3DFVF_NORMAL;
10644 vb_desc.dwNumVertices = 1;
10645 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &src_vb, 0);
10646 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10648 memset(&vb_desc, 0, sizeof(vb_desc));
10649 vb_desc.dwSize = sizeof(vb_desc);
10650 vb_desc.dwFVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR;
10651 vb_desc.dwNumVertices = 1;
10652 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &dst_vb, 0);
10653 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10655 hr = IDirect3DDevice7_LightEnable(device, 0, TRUE);
10656 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10657 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, TRUE);
10658 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10659 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
10660 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10661 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
10662 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10663 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
10664 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10666 hr = IDirect3DDevice7_SetLight(device, 0, &directional_light);
10667 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10669 memset(&material, 0, sizeof(material));
10670 U1(U2(material).specular).r = 0.0f;
10671 U2(U2(material).specular).g = 1.0f;
10672 U3(U2(material).specular).b = 0.0f;
10673 U4(U2(material).specular).a = 0.5f;
10674 U4(material).power = 5.0f;
10675 hr = IDirect3DDevice7_SetMaterial(device, &material);
10676 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10678 for (i = 0; i < ARRAY_SIZE(tests); ++i)
10680 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE,
10681 tests[i].fog_vertex_mode);
10682 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE,
10683 tests[i].fog_table_mode);
10684 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10685 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_RANGEFOGENABLE, tests[i].range_fog);
10686 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10688 hr = IDirect3DVertexBuffer7_Lock(src_vb, 0, (void **)&src_data, NULL);
10689 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10690 *src_data = tests[i].vertex;
10691 hr = IDirect3DVertexBuffer7_Unlock(src_vb);
10692 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10694 hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL);
10695 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10696 memset(dst_data, 0, sizeof(*dst_data));
10697 hr = IDirect3DVertexBuffer7_Unlock(dst_vb);
10698 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10699 hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 0,
10700 1, src_vb, 0, device, 0);
10701 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10703 hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL);
10704 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10706 ok(compare_color(dst_data->specular, tests[i].expected_color, 1)
10707 || broken(tests[i].expected_broken
10708 && compare_color(dst_data->specular, tests[i].expected_broken, 1)),
10709 "Expected color 0x%08x, got 0x%08x, test %u.\n",
10710 tests[i].expected_color, dst_data->specular, i);
10712 hr = IDirect3DVertexBuffer7_Unlock(dst_vb);
10713 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10716 IDirect3DVertexBuffer7_Release(dst_vb);
10717 IDirect3DVertexBuffer7_Release(src_vb);
10718 IDirect3D7_Release(d3d);
10719 refcount = IDirect3DDevice7_Release(device);
10720 ok(!refcount, "Device has %u references left.\n", refcount);
10721 DestroyWindow(window);
10724 static void test_negative_fixedfunction_fog(void)
10726 HRESULT hr;
10727 IDirect3DDevice7 *device;
10728 IDirectDrawSurface7 *rt;
10729 ULONG refcount;
10730 HWND window;
10731 D3DCOLOR color;
10732 static struct
10734 struct vec3 position;
10735 D3DCOLOR diffuse;
10737 quad[] =
10739 {{-1.0f, -1.0f, -0.5f}, 0xffff0000},
10740 {{-1.0f, 1.0f, -0.5f}, 0xffff0000},
10741 {{ 1.0f, -1.0f, -0.5f}, 0xffff0000},
10742 {{ 1.0f, 1.0f, -0.5f}, 0xffff0000},
10744 static struct
10746 struct vec4 position;
10747 D3DCOLOR diffuse;
10749 tquad[] =
10751 {{ 0.0f, 0.0f, -0.5f, 1.0f}, 0xffff0000},
10752 {{640.0f, 0.0f, -0.5f, 1.0f}, 0xffff0000},
10753 {{ 0.0f, 480.0f, -0.5f, 1.0f}, 0xffff0000},
10754 {{640.0f, 480.0f, -0.5f, 1.0f}, 0xffff0000},
10756 unsigned int i;
10757 static D3DMATRIX zero =
10759 1.0f, 0.0f, 0.0f, 0.0f,
10760 0.0f, 1.0f, 0.0f, 0.0f,
10761 0.0f, 0.0f, 0.0f, 0.0f,
10762 0.0f, 0.0f, 0.0f, 1.0f
10764 static D3DMATRIX identity =
10766 1.0f, 0.0f, 0.0f, 0.0f,
10767 0.0f, 1.0f, 0.0f, 0.0f,
10768 0.0f, 0.0f, 1.0f, 0.0f,
10769 0.0f, 0.0f, 0.0f, 1.0f
10771 static const struct
10773 DWORD pos_type;
10774 void *quad;
10775 D3DMATRIX *matrix;
10776 union
10778 float f;
10779 DWORD d;
10780 } start, end;
10781 D3DFOGMODE vfog, tfog;
10782 DWORD color, color_broken, color_broken2;
10784 tests[] =
10786 /* Run the XYZRHW tests first. Depth clamping is broken after RHW draws on the testbot.
10788 * Geforce8+ GPUs on Windows abs() table fog, everything else does not. */
10789 {D3DFVF_XYZRHW, tquad, &identity, { 0.0f}, {1.0f}, D3DFOG_NONE, D3DFOG_LINEAR,
10790 0x00ff0000, 0x00808000, 0x00808000},
10791 /* r200 GPUs and presumably all d3d8 and older HW clamp the fog
10792 * parameters to 0.0 and 1.0 in the table fog case. */
10793 {D3DFVF_XYZRHW, tquad, &identity, {-1.0f}, {0.0f}, D3DFOG_NONE, D3DFOG_LINEAR,
10794 0x00808000, 0x00ff0000, 0x0000ff00},
10795 /* test_fog_interpolation shows that vertex fog evaluates the fog
10796 * equation in the vertex pipeline. Start = -1.0 && end = 0.0 shows
10797 * that the abs happens before the fog equation is evaluated.
10799 * Vertex fog abs() behavior is the same on all GPUs. */
10800 {D3DFVF_XYZ, quad, &zero, { 0.0f}, {1.0f}, D3DFOG_LINEAR, D3DFOG_NONE,
10801 0x00808000, 0x00808000, 0x00808000},
10802 {D3DFVF_XYZ, quad, &zero, {-1.0f}, {0.0f}, D3DFOG_LINEAR, D3DFOG_NONE,
10803 0x0000ff00, 0x0000ff00, 0x0000ff00},
10804 {D3DFVF_XYZ, quad, &zero, { 0.0f}, {1.0f}, D3DFOG_EXP, D3DFOG_NONE,
10805 0x009b6400, 0x009b6400, 0x009b6400},
10807 D3DDEVICEDESC7 caps;
10809 window = create_window();
10810 if (!(device = create_device(window, DDSCL_NORMAL)))
10812 skip("Failed to create a 3D device, skipping test.\n");
10813 DestroyWindow(window);
10814 return;
10817 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
10818 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10819 hr = IDirect3DDevice7_GetCaps(device, &caps);
10820 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10821 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE))
10822 skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping some fog tests.\n");
10824 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
10825 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10826 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
10827 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10828 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
10829 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10830 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x0000ff00);
10831 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10832 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
10833 ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10835 for (i = 0; i < ARRAY_SIZE(tests); ++i)
10837 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE) && tests[i].tfog)
10838 continue;
10840 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0);
10841 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10843 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, tests[i].matrix);
10844 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
10845 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGSTART, tests[i].start.d);
10846 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10847 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGEND, tests[i].end.d);
10848 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10849 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, tests[i].vfog);
10850 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10851 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, tests[i].tfog);
10852 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10854 hr = IDirect3DDevice7_BeginScene(device);
10855 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10856 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
10857 tests[i].pos_type | D3DFVF_DIFFUSE, tests[i].quad, 4, 0);
10858 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10859 hr = IDirect3DDevice7_EndScene(device);
10860 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10862 color = get_surface_color(rt, 0, 240);
10863 ok(compare_color(color, tests[i].color, 2) || broken(compare_color(color, tests[i].color_broken, 2))
10864 || broken(compare_color(color, tests[i].color_broken2, 2)),
10865 "Got unexpected color 0x%08x, case %u.\n", color, i);
10868 IDirectDrawSurface7_Release(rt);
10869 refcount = IDirect3DDevice7_Release(device);
10870 ok(!refcount, "Device has %u references left.\n", refcount);
10871 DestroyWindow(window);
10874 static void test_table_fog_zw(void)
10876 HRESULT hr;
10877 IDirect3DDevice7 *device;
10878 IDirectDrawSurface7 *rt;
10879 ULONG refcount;
10880 HWND window;
10881 D3DCOLOR color;
10882 static struct
10884 struct vec4 position;
10885 D3DCOLOR diffuse;
10887 quad[] =
10889 {{ 0.0f, 0.0f, 0.0f, 0.0f}, 0xffff0000},
10890 {{640.0f, 0.0f, 0.0f, 0.0f}, 0xffff0000},
10891 {{ 0.0f, 480.0f, 0.0f, 0.0f}, 0xffff0000},
10892 {{640.0f, 480.0f, 0.0f, 0.0f}, 0xffff0000},
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 D3DDEVICEDESC7 caps;
10902 static const struct
10904 float z, w;
10905 D3DZBUFFERTYPE z_test;
10906 D3DCOLOR color;
10908 tests[] =
10910 {0.7f, 0.0f, D3DZB_TRUE, 0x004cb200},
10911 {0.7f, 0.0f, D3DZB_FALSE, 0x004cb200},
10912 {0.7f, 0.3f, D3DZB_TRUE, 0x004cb200},
10913 {0.7f, 0.3f, D3DZB_FALSE, 0x004cb200},
10914 {0.7f, 3.0f, D3DZB_TRUE, 0x004cb200},
10915 {0.7f, 3.0f, D3DZB_FALSE, 0x004cb200},
10916 {0.3f, 0.0f, D3DZB_TRUE, 0x00b24c00},
10917 {0.3f, 0.0f, D3DZB_FALSE, 0x00b24c00},
10919 unsigned int i;
10921 window = create_window();
10922 if (!(device = create_device(window, DDSCL_NORMAL)))
10924 skip("Failed to create a 3D device, skipping test.\n");
10925 DestroyWindow(window);
10926 return;
10929 hr = IDirect3DDevice7_GetCaps(device, &caps);
10930 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10931 if (!(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE))
10933 skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping POSITIONT table fog test.\n");
10934 goto done;
10936 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
10937 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
10939 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
10940 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10941 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
10942 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10943 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x0000ff00);
10944 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10945 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
10946 ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10947 /* Work around an AMD Windows driver bug. Needs a proj matrix applied redundantly. */
10948 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &identity);
10949 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
10950 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_LINEAR);
10951 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10953 for (i = 0; i < ARRAY_SIZE(tests); ++i)
10955 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x000000ff, 1.0f, 0);
10956 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
10958 quad[0].position.z = tests[i].z;
10959 quad[1].position.z = tests[i].z;
10960 quad[2].position.z = tests[i].z;
10961 quad[3].position.z = tests[i].z;
10962 quad[0].position.w = tests[i].w;
10963 quad[1].position.w = tests[i].w;
10964 quad[2].position.w = tests[i].w;
10965 quad[3].position.w = tests[i].w;
10966 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, tests[i].z_test);
10967 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
10969 hr = IDirect3DDevice7_BeginScene(device);
10970 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
10971 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
10972 D3DFVF_XYZRHW | D3DFVF_DIFFUSE, quad, 4, 0);
10973 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10974 hr = IDirect3DDevice7_EndScene(device);
10975 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
10977 color = get_surface_color(rt, 0, 240);
10978 ok(compare_color(color, tests[i].color, 2),
10979 "Got unexpected color 0x%08x, expected 0x%8x, case %u.\n", color, tests[i].color, i);
10982 IDirectDrawSurface7_Release(rt);
10983 done:
10984 refcount = IDirect3DDevice7_Release(device);
10985 ok(!refcount, "Device has %u references left.\n", refcount);
10986 DestroyWindow(window);
10989 static void test_signed_formats(void)
10991 HRESULT hr;
10992 IDirect3DDevice7 *device;
10993 IDirect3D7 *d3d;
10994 IDirectDraw7 *ddraw;
10995 IDirectDrawSurface7 *surface, *rt;
10996 DDSURFACEDESC2 surface_desc;
10997 ULONG refcount;
10998 HWND window;
10999 D3DCOLOR color, expected_color;
11000 static struct
11002 struct vec3 position;
11003 struct vec2 texcoord;
11005 quad[] =
11007 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
11008 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
11009 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
11010 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
11012 /* See test_signed_formats() in dlls/d3d9/tests/visual.c for an explanation
11013 * of these values. */
11014 static const USHORT content_v8u8[4][4] =
11016 {0x0000, 0x7f7f, 0x8880, 0x0000},
11017 {0x0080, 0x8000, 0x7f00, 0x007f},
11018 {0x193b, 0xe8c8, 0x0808, 0xf8f8},
11019 {0x4444, 0xc0c0, 0xa066, 0x22e0},
11021 static const DWORD content_x8l8v8u8[4][4] =
11023 {0x00000000, 0x00ff7f7f, 0x00008880, 0x00ff0000},
11024 {0x00000080, 0x00008000, 0x00007f00, 0x0000007f},
11025 {0x0041193b, 0x0051e8c8, 0x00040808, 0x00fff8f8},
11026 {0x00824444, 0x0000c0c0, 0x00c2a066, 0x009222e0},
11028 static const USHORT content_l6v5u5[4][4] =
11030 {0x0000, 0xfdef, 0x0230, 0xfc00},
11031 {0x0010, 0x0200, 0x01e0, 0x000f},
11032 {0x4067, 0x53b9, 0x0421, 0xffff},
11033 {0x8108, 0x0318, 0xc28c, 0x909c},
11035 static const struct
11037 const char *name;
11038 const void *content;
11039 SIZE_T pixel_size;
11040 BOOL blue;
11041 unsigned int slop, slop_broken;
11042 DDPIXELFORMAT format;
11044 formats[] =
11047 "D3DFMT_V8U8", content_v8u8, sizeof(WORD), FALSE, 1, 0,
11049 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV, 0,
11050 {16}, {0x000000ff}, {0x0000ff00}, {0x00000000}, {0x00000000}
11054 "D3DFMT_X8L8V8U8", content_x8l8v8u8, sizeof(DWORD), TRUE, 1, 0,
11056 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE, 0,
11057 {32}, {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}
11061 "D3DFMT_L6V5U5", content_l6v5u5, sizeof(WORD), TRUE, 4, 7,
11063 sizeof(DDPIXELFORMAT), DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE, 0,
11064 {16}, {0x0000001f}, {0x000003e0}, {0x0000fc00}, {0x00000000}
11068 /* No V16U16 or Q8W8V8U8 support in ddraw. */
11070 static const D3DCOLOR expected_colors[4][4] =
11072 {0x00808080, 0x00fefeff, 0x00010780, 0x008080ff},
11073 {0x00018080, 0x00800180, 0x0080fe80, 0x00fe8080},
11074 {0x00ba98a0, 0x004767a8, 0x00888881, 0x007878ff},
11075 {0x00c3c3c0, 0x003f3f80, 0x00e51fe1, 0x005fa2c8},
11077 unsigned int i, width, x, y;
11078 D3DDEVICEDESC7 device_desc;
11080 window = create_window();
11081 if (!(device = create_device(window, DDSCL_NORMAL)))
11083 skip("Failed to create a 3D device, skipping test.\n");
11084 DestroyWindow(window);
11085 return;
11088 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
11089 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
11090 if (!(device_desc.dwTextureOpCaps & D3DTEXOPCAPS_BLENDFACTORALPHA))
11092 skip("D3DTOP_BLENDFACTORALPHA not supported, skipping bumpmap format tests.\n");
11093 goto done;
11096 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
11097 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
11098 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
11099 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
11100 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
11101 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11103 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
11104 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
11106 /* dst = tex * 0.5 + 1.0 * (1.0 - 0.5) = tex * 0.5 + 0.5 */
11107 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x80ffffff);
11108 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
11109 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_BLENDFACTORALPHA);
11110 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
11111 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
11112 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
11113 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
11114 ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
11116 for (i = 0; i < ARRAY_SIZE(formats); ++i)
11118 for (width = 1; width < 5; width += 3)
11120 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
11121 ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
11123 memset(&surface_desc, 0, sizeof(surface_desc));
11124 surface_desc.dwSize = sizeof(surface_desc);
11125 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
11126 surface_desc.dwWidth = width;
11127 surface_desc.dwHeight = 4;
11128 U4(surface_desc).ddpfPixelFormat = formats[i].format;
11129 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
11130 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11131 if (FAILED(hr))
11133 skip("%s textures not supported, skipping.\n", formats[i].name);
11134 continue;
11136 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, format %s.\n", hr, formats[i].name);
11137 hr = IDirect3DDevice7_SetTexture(device, 0, surface);
11138 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x, format %s.\n", hr, formats[i].name);
11140 memset(&surface_desc, 0, sizeof(surface_desc));
11141 surface_desc.dwSize = sizeof(surface_desc);
11142 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, 0, NULL);
11143 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, format %s.\n", hr, formats[i].name);
11144 for (y = 0; y < 4; y++)
11146 memcpy((char *)surface_desc.lpSurface + y * U1(surface_desc).lPitch,
11147 (char *)formats[i].content + y * 4 * formats[i].pixel_size,
11148 width * formats[i].pixel_size);
11150 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11151 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, format %s.\n", hr, formats[i].name);
11153 hr = IDirect3DDevice7_BeginScene(device);
11154 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11155 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
11156 D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
11157 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11158 hr = IDirect3DDevice7_EndScene(device);
11159 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11161 for (y = 0; y < 4; y++)
11163 for (x = 0; x < width; x++)
11165 expected_color = expected_colors[y][x];
11166 if (!formats[i].blue)
11167 expected_color |= 0x000000ff;
11169 color = get_surface_color(rt, 80 + 160 * x, 60 + 120 * y);
11170 ok(compare_color(color, expected_color, formats[i].slop)
11171 || broken(compare_color(color, expected_color, formats[i].slop_broken)),
11172 "Expected color 0x%08x, got 0x%08x, format %s, location %ux%u.\n",
11173 expected_color, color, formats[i].name, x, y);
11177 IDirectDrawSurface7_Release(surface);
11182 IDirectDrawSurface7_Release(rt);
11183 IDirectDraw7_Release(ddraw);
11184 IDirect3D7_Release(d3d);
11186 done:
11187 refcount = IDirect3DDevice7_Release(device);
11188 ok(!refcount, "Device has %u references left.\n", refcount);
11189 DestroyWindow(window);
11192 static void test_color_fill(void)
11194 HRESULT hr;
11195 IDirect3DDevice7 *device;
11196 IDirect3D7 *d3d;
11197 IDirectDraw7 *ddraw;
11198 IDirectDrawSurface7 *surface, *surface2;
11199 DDSURFACEDESC2 surface_desc;
11200 DDPIXELFORMAT z_fmt;
11201 ULONG refcount;
11202 HWND window;
11203 unsigned int i;
11204 DDBLTFX fx;
11205 RECT rect = {5, 5, 7, 7};
11206 DWORD *color;
11207 DWORD supported_fmts = 0, num_fourcc_codes, *fourcc_codes;
11208 DDCAPS hal_caps;
11209 static const struct
11211 DWORD caps, caps2;
11212 HRESULT colorfill_hr, depthfill_hr;
11213 BOOL rop_success;
11214 const char *name;
11215 DWORD result;
11216 BOOL check_result;
11217 DDPIXELFORMAT format;
11219 tests[] =
11222 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
11223 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain RGB", 0xdeadbeef, TRUE,
11225 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
11226 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
11230 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0,
11231 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain RGB", 0xdeadbeef, TRUE,
11233 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
11234 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
11238 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0,
11239 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem texture RGB", 0xdeadbeef, TRUE,
11241 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
11242 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
11246 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0,
11247 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem texture RGB", 0xdeadbeef, TRUE,
11249 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
11250 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
11254 DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE,
11255 DD_OK, DDERR_INVALIDPARAMS, TRUE, "managed texture RGB", 0xdeadbeef, TRUE,
11257 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
11258 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
11262 DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY, 0,
11263 DDERR_INVALIDPARAMS, DD_OK, TRUE, "vidmem zbuffer", 0xdeadbeef, TRUE,
11264 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
11267 DDSCAPS_ZBUFFER | DDSCAPS_SYSTEMMEMORY, 0,
11268 DDERR_INVALIDPARAMS, DD_OK, TRUE, "sysmem zbuffer", 0xdeadbeef, TRUE,
11269 {0, 0, 0, {0}, {0}, {0}, {0}, {0}}
11272 /* Colorfill on YUV surfaces always returns DD_OK, but the content is
11273 * different afterwards. DX9+ GPUs set one of the two luminance values
11274 * in each block, but AMD and Nvidia GPUs disagree on which luminance
11275 * value they set. r200 (dx8) just sets the entire block to the clear
11276 * value. */
11277 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
11278 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain YUY2", 0, FALSE,
11280 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
11281 {0}, {0}, {0}, {0}, {0}
11285 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
11286 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem offscreenplain UYVY", 0, FALSE,
11288 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
11289 {0}, {0}, {0}, {0}, {0}
11293 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY, 0,
11294 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay YUY2", 0, FALSE,
11296 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y', 'U', 'Y', '2'),
11297 {0}, {0}, {0}, {0}, {0}
11301 DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY, 0,
11302 DD_OK, DDERR_INVALIDPARAMS, FALSE, "vidmem overlay UYVY", 0, FALSE,
11304 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U', 'Y', 'V', 'Y'),
11305 {0}, {0}, {0}, {0}, {0}
11309 DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0,
11310 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "vidmem texture DXT1", 0, FALSE,
11312 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
11313 {0}, {0}, {0}, {0}, {0}
11317 DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0,
11318 E_NOTIMPL, DDERR_INVALIDPARAMS, FALSE, "sysmem texture DXT1", 0, FALSE,
11320 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
11321 {0}, {0}, {0}, {0}, {0}
11325 /* The testbot fills this with 0x00 instead of the blue channel. The sysmem
11326 * surface works, presumably because it is handled by the runtime instead of
11327 * the driver. */
11328 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0,
11329 DD_OK, DDERR_INVALIDPARAMS, TRUE, "vidmem offscreenplain P8", 0xefefefef, FALSE,
11331 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
11332 {8}, {0}, {0}, {0}, {0}
11336 DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0,
11337 DD_OK, DDERR_INVALIDPARAMS, TRUE, "sysmem offscreenplain P8", 0xefefefef, TRUE,
11339 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_PALETTEINDEXED8, 0,
11340 {8}, {0}, {0}, {0}, {0}
11344 static const struct
11346 DWORD rop;
11347 const char *name;
11348 HRESULT hr;
11350 rops[] =
11352 {SRCCOPY, "SRCCOPY", DD_OK},
11353 {SRCPAINT, "SRCPAINT", DDERR_NORASTEROPHW},
11354 {SRCAND, "SRCAND", DDERR_NORASTEROPHW},
11355 {SRCINVERT, "SRCINVERT", DDERR_NORASTEROPHW},
11356 {SRCERASE, "SRCERASE", DDERR_NORASTEROPHW},
11357 {NOTSRCCOPY, "NOTSRCCOPY", DDERR_NORASTEROPHW},
11358 {NOTSRCERASE, "NOTSRCERASE", DDERR_NORASTEROPHW},
11359 {MERGECOPY, "MERGECOPY", DDERR_NORASTEROPHW},
11360 {MERGEPAINT, "MERGEPAINT", DDERR_NORASTEROPHW},
11361 {PATCOPY, "PATCOPY", DDERR_NORASTEROPHW},
11362 {PATPAINT, "PATPAINT", DDERR_NORASTEROPHW},
11363 {PATINVERT, "PATINVERT", DDERR_NORASTEROPHW},
11364 {DSTINVERT, "DSTINVERT", DDERR_NORASTEROPHW},
11365 {BLACKNESS, "BLACKNESS", DD_OK},
11366 {WHITENESS, "WHITENESS", DD_OK},
11367 {0xaa0029, "0xaa0029", DDERR_NORASTEROPHW} /* noop */
11370 window = create_window();
11371 if (!(device = create_device(window, DDSCL_NORMAL)))
11373 skip("Failed to create a 3D device, skipping test.\n");
11374 DestroyWindow(window);
11375 return;
11378 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
11379 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
11380 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
11381 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
11383 memset(&z_fmt, 0, sizeof(z_fmt));
11384 IDirect3D7_EnumZBufferFormats(d3d, &IID_IDirect3DHALDevice, enum_z_fmt, &z_fmt);
11385 if (!z_fmt.dwSize)
11386 skip("No Z buffer formats supported, skipping Z buffer colorfill test.\n");
11388 IDirect3DDevice7_EnumTextureFormats(device, test_block_formats_creation_cb, &supported_fmts);
11389 if (!(supported_fmts & SUPPORT_DXT1))
11390 skip("DXT1 textures not supported, skipping DXT1 colorfill test.\n");
11392 IDirect3D7_Release(d3d);
11394 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, NULL);
11395 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
11396 fourcc_codes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
11397 num_fourcc_codes * sizeof(*fourcc_codes));
11398 if (!fourcc_codes)
11399 goto done;
11400 hr = IDirectDraw7_GetFourCCCodes(ddraw, &num_fourcc_codes, fourcc_codes);
11401 ok(SUCCEEDED(hr), "Failed to get fourcc codes %#x.\n", hr);
11402 for (i = 0; i < num_fourcc_codes; i++)
11404 if (fourcc_codes[i] == MAKEFOURCC('Y', 'U', 'Y', '2'))
11405 supported_fmts |= SUPPORT_YUY2;
11406 else if (fourcc_codes[i] == MAKEFOURCC('U', 'Y', 'V', 'Y'))
11407 supported_fmts |= SUPPORT_UYVY;
11409 HeapFree(GetProcessHeap(), 0, fourcc_codes);
11411 memset(&hal_caps, 0, sizeof(hal_caps));
11412 hal_caps.dwSize = sizeof(hal_caps);
11413 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
11414 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
11416 if (!(supported_fmts & (SUPPORT_YUY2 | SUPPORT_UYVY)) || !(hal_caps.dwCaps & DDCAPS_OVERLAY))
11417 skip("Overlays or some YUV formats not supported, skipping YUV colorfill tests.\n");
11419 for (i = 0; i < ARRAY_SIZE(tests); ++i)
11421 DWORD expected_broken = tests[i].result;
11423 /* Some Windows drivers modify dwFillColor when it is used on P8 or FourCC formats. */
11424 memset(&fx, 0, sizeof(fx));
11425 fx.dwSize = sizeof(fx);
11426 U5(fx).dwFillColor = 0xdeadbeef;
11428 memset(&surface_desc, 0, sizeof(surface_desc));
11429 surface_desc.dwSize = sizeof(surface_desc);
11430 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
11431 surface_desc.dwWidth = 64;
11432 surface_desc.dwHeight = 64;
11433 U4(surface_desc).ddpfPixelFormat = tests[i].format;
11434 surface_desc.ddsCaps.dwCaps = tests[i].caps;
11435 surface_desc.ddsCaps.dwCaps2 = tests[i].caps2;
11437 if (tests[i].format.dwFourCC == MAKEFOURCC('D','X','T','1') && !(supported_fmts & SUPPORT_DXT1))
11438 continue;
11439 if (tests[i].format.dwFourCC == MAKEFOURCC('Y','U','Y','2') && !(supported_fmts & SUPPORT_YUY2))
11440 continue;
11441 if (tests[i].format.dwFourCC == MAKEFOURCC('U','Y','V','Y') && !(supported_fmts & SUPPORT_UYVY))
11442 continue;
11443 if (tests[i].caps & DDSCAPS_OVERLAY && !(hal_caps.dwCaps & DDCAPS_OVERLAY))
11444 continue;
11446 if (tests[i].caps & DDSCAPS_ZBUFFER)
11448 if (!z_fmt.dwSize)
11449 continue;
11451 U4(surface_desc).ddpfPixelFormat = z_fmt;
11452 /* Some drivers seem to convert depth values incorrectly or not at
11453 * all. Affects at least AMD PALM, 8.17.10.1247. */
11454 if (tests[i].caps & DDSCAPS_VIDEOMEMORY)
11456 DWORD expected;
11457 float f, g;
11459 expected = tests[i].result & U3(z_fmt).dwZBitMask;
11460 f = ceilf(logf(expected + 1.0f) / logf(2.0f));
11461 g = (f + 1.0f) / 2.0f;
11462 g -= (int)g;
11463 expected_broken = (expected / exp2f(f) - g) * 256;
11464 expected_broken *= 0x01010101;
11468 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11469 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, surface %s.\n", hr, tests[i].name);
11471 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11472 todo_wine_if (tests[i].format.dwFourCC)
11473 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
11474 hr, tests[i].colorfill_hr, tests[i].name);
11476 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11477 todo_wine_if (tests[i].format.dwFourCC)
11478 ok(hr == tests[i].colorfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
11479 hr, tests[i].colorfill_hr, tests[i].name);
11481 if (SUCCEEDED(hr) && tests[i].check_result)
11483 memset(&surface_desc, 0, sizeof(surface_desc));
11484 surface_desc.dwSize = sizeof(surface_desc);
11485 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
11486 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
11487 color = surface_desc.lpSurface;
11488 ok(*color == tests[i].result, "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
11489 *color, tests[i].result, tests[i].name);
11490 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11491 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
11494 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11495 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
11496 hr, tests[i].depthfill_hr, tests[i].name);
11497 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11498 ok(hr == tests[i].depthfill_hr, "Blt returned %#x, expected %#x, surface %s.\n",
11499 hr, tests[i].depthfill_hr, tests[i].name);
11501 if (SUCCEEDED(hr) && tests[i].check_result)
11503 memset(&surface_desc, 0, sizeof(surface_desc));
11504 surface_desc.dwSize = sizeof(surface_desc);
11505 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
11506 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
11507 color = surface_desc.lpSurface;
11508 ok((*color & U3(z_fmt).dwZBitMask) == (tests[i].result & U3(z_fmt).dwZBitMask)
11509 || broken((*color & U3(z_fmt).dwZBitMask) == (expected_broken & U3(z_fmt).dwZBitMask)),
11510 "Got clear result 0x%08x, expected 0x%08x, surface %s.\n",
11511 *color & U3(z_fmt).dwZBitMask, tests[i].result & U3(z_fmt).dwZBitMask, tests[i].name);
11512 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11513 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
11516 U5(fx).dwFillColor = 0xdeadbeef;
11517 fx.dwROP = BLACKNESS;
11518 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
11519 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
11520 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
11521 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
11522 U5(fx).dwFillColor, tests[i].name);
11524 if (SUCCEEDED(hr) && tests[i].check_result)
11526 memset(&surface_desc, 0, sizeof(surface_desc));
11527 surface_desc.dwSize = sizeof(surface_desc);
11528 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
11529 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
11530 color = surface_desc.lpSurface;
11531 ok(*color == 0, "Got clear result 0x%08x, expected 0x00000000, surface %s.\n",
11532 *color, tests[i].name);
11533 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11534 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
11537 fx.dwROP = WHITENESS;
11538 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
11539 ok(FAILED(hr) == !tests[i].rop_success, "Blt returned %#x, expected %s, surface %s.\n",
11540 hr, tests[i].rop_success ? "success" : "failure", tests[i].name);
11541 ok(U5(fx).dwFillColor == 0xdeadbeef, "dwFillColor was set to 0x%08x, surface %s\n",
11542 U5(fx).dwFillColor, tests[i].name);
11544 if (SUCCEEDED(hr) && tests[i].check_result)
11546 memset(&surface_desc, 0, sizeof(surface_desc));
11547 surface_desc.dwSize = sizeof(surface_desc);
11548 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_READONLY, 0);
11549 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, surface %s.\n", hr, tests[i].name);
11550 color = surface_desc.lpSurface;
11551 /* WHITENESS sets the alpha channel to 0x00. Ignore this for now. */
11552 ok((*color & 0x00ffffff) == 0x00ffffff, "Got clear result 0x%08x, expected 0xffffffff, surface %s.\n",
11553 *color, tests[i].name);
11554 hr = IDirectDrawSurface7_Unlock(surface, NULL);
11555 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, surface %s.\n", hr, tests[i].name);
11558 IDirectDrawSurface7_Release(surface);
11561 memset(&fx, 0, sizeof(fx));
11562 fx.dwSize = sizeof(fx);
11563 U5(fx).dwFillColor = 0xdeadbeef;
11564 fx.dwROP = WHITENESS;
11566 memset(&surface_desc, 0, sizeof(surface_desc));
11567 surface_desc.dwSize = sizeof(surface_desc);
11568 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
11569 surface_desc.dwWidth = 64;
11570 surface_desc.dwHeight = 64;
11571 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
11572 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
11573 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
11574 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
11575 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
11576 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
11577 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
11578 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11579 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11580 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
11581 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11583 /* No DDBLTFX. */
11584 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, NULL);
11585 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11586 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, NULL);
11587 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11589 /* Unused source rectangle. */
11590 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11591 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
11592 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
11593 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
11595 /* Unused source surface. */
11596 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11597 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11598 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
11599 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
11600 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11601 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11602 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
11603 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
11605 /* Inverted destination or source rectangle. */
11606 SetRect(&rect, 5, 7, 7, 5);
11607 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11608 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
11609 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11610 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
11611 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11612 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11613 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11614 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11615 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
11616 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
11618 /* Negative rectangle. */
11619 SetRect(&rect, -1, -1, 5, 5);
11620 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11621 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
11622 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11623 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
11624 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11625 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11626 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, &rect, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11627 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11628 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
11629 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
11631 /* Out of bounds rectangle. */
11632 SetRect(&rect, 0, 0, 65, 65);
11633 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
11634 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
11635 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_ROP | DDBLT_WAIT, &fx);
11636 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
11638 /* Combine multiple flags. */
11639 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11640 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
11641 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
11642 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11643 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ROP | DDBLT_WAIT, &fx);
11644 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11646 for (i = 0; i < ARRAY_SIZE(rops); ++i)
11648 fx.dwROP = rops[i].rop;
11649 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_ROP | DDBLT_WAIT, &fx);
11650 ok(hr == rops[i].hr, "Got unexpected hr %#x for rop %s.\n", hr, rops[i].name);
11653 IDirectDrawSurface7_Release(surface2);
11654 IDirectDrawSurface7_Release(surface);
11656 if (!z_fmt.dwSize)
11657 goto done;
11659 memset(&surface_desc, 0, sizeof(surface_desc));
11660 surface_desc.dwSize = sizeof(surface_desc);
11661 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
11662 surface_desc.dwWidth = 64;
11663 surface_desc.dwHeight = 64;
11664 U4(surface_desc).ddpfPixelFormat = z_fmt;
11665 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
11666 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
11667 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11668 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface2, NULL);
11669 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11671 /* No DDBLTFX. */
11672 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, NULL);
11673 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11675 /* Unused source rectangle. */
11676 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11677 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
11679 /* Unused source surface. */
11680 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11681 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11682 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11683 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11685 /* Inverted destination or source rectangle. */
11686 SetRect(&rect, 5, 7, 7, 5);
11687 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11688 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
11689 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11690 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
11691 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11692 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11693 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11694 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11696 /* Negative rectangle. */
11697 SetRect(&rect, -1, -1, 5, 5);
11698 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11699 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
11700 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11701 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
11702 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11703 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11704 hr = IDirectDrawSurface7_Blt(surface, &rect, surface2, &rect, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11705 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11707 /* Out of bounds rectangle. */
11708 SetRect(&rect, 0, 0, 65, 65);
11709 hr = IDirectDrawSurface7_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11710 ok(hr == DDERR_INVALIDRECT, "Got unexpected hr %#x.\n", hr);
11712 /* Combine multiple flags. */
11713 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_DEPTHFILL | DDBLT_WAIT, &fx);
11714 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
11716 IDirectDrawSurface7_Release(surface2);
11717 IDirectDrawSurface7_Release(surface);
11719 done:
11720 IDirectDraw7_Release(ddraw);
11721 refcount = IDirect3DDevice7_Release(device);
11722 ok(!refcount, "Device has %u references left.\n", refcount);
11723 DestroyWindow(window);
11726 static void test_texcoordindex(void)
11728 static D3DMATRIX mat =
11730 1.0f, 0.0f, 0.0f, 0.0f,
11731 0.0f, 0.0f, 0.0f, 0.0f,
11732 0.0f, 0.0f, 0.0f, 0.0f,
11733 0.0f, 0.0f, 0.0f, 0.0f,
11735 static struct
11737 struct vec3 pos;
11738 struct vec2 texcoord1;
11739 struct vec2 texcoord2;
11740 struct vec2 texcoord3;
11742 quad[] =
11744 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f}},
11745 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 0.0f}},
11746 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}},
11747 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}},
11749 static const DWORD fvf = D3DFVF_XYZ | D3DFVF_TEX3;
11750 IDirect3DDevice7 *device;
11751 IDirect3D7 *d3d;
11752 IDirectDraw7 *ddraw;
11753 IDirectDrawSurface7 *rt;
11754 HWND window;
11755 HRESULT hr;
11756 IDirectDrawSurface7 *texture1, *texture2;
11757 DDSURFACEDESC2 surface_desc;
11758 ULONG refcount;
11759 D3DCOLOR color;
11760 DWORD *ptr;
11762 window = create_window();
11763 if (!(device = create_device(window, DDSCL_NORMAL)))
11765 skip("Failed to create a 3D device, skipping test.\n");
11766 DestroyWindow(window);
11767 return;
11770 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
11771 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
11772 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
11773 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
11774 IDirect3D7_Release(d3d);
11776 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
11777 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11779 memset(&surface_desc, 0, sizeof(surface_desc));
11780 surface_desc.dwSize = sizeof(surface_desc);
11781 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
11782 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
11783 surface_desc.dwWidth = 2;
11784 surface_desc.dwHeight = 2;
11785 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
11786 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
11787 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
11788 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
11789 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
11790 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
11791 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
11792 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture1, NULL);
11793 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11794 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture2, NULL);
11795 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
11797 memset(&surface_desc, 0, sizeof(surface_desc));
11798 surface_desc.dwSize = sizeof(surface_desc);
11799 hr = IDirectDrawSurface7_Lock(texture1, 0, &surface_desc, 0, NULL);
11800 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11801 ptr = surface_desc.lpSurface;
11802 ptr[0] = 0xff000000;
11803 ptr[1] = 0xff00ff00;
11804 ptr += U1(surface_desc).lPitch / sizeof(*ptr);
11805 ptr[0] = 0xff0000ff;
11806 ptr[1] = 0xff00ffff;
11807 hr = IDirectDrawSurface7_Unlock(texture1, NULL);
11808 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11810 memset(&surface_desc, 0, sizeof(surface_desc));
11811 surface_desc.dwSize = sizeof(surface_desc);
11812 hr = IDirectDrawSurface7_Lock(texture2, 0, &surface_desc, 0, NULL);
11813 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11814 ptr = surface_desc.lpSurface;
11815 ptr[0] = 0xff000000;
11816 ptr[1] = 0xff0000ff;
11817 ptr += U1(surface_desc).lPitch / sizeof(*ptr);
11818 ptr[0] = 0xffff0000;
11819 ptr[1] = 0xffff00ff;
11820 hr = IDirectDrawSurface7_Unlock(texture2, 0);
11821 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11823 hr = IDirect3DDevice7_SetTexture(device, 0, texture1);
11824 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
11825 hr = IDirect3DDevice7_SetTexture(device, 1, texture2);
11826 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
11827 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
11828 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
11829 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
11830 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
11831 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
11832 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11833 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_ADD);
11834 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
11835 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
11836 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11837 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
11838 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
11839 hr = IDirect3DDevice7_SetTextureStageState(device, 2, D3DTSS_COLOROP, D3DTOP_DISABLE);
11840 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
11842 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_TEXCOORDINDEX, 1);
11843 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
11844 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXCOORDINDEX, 0);
11845 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
11847 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
11848 ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
11850 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
11851 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
11853 hr = IDirect3DDevice7_BeginScene(device);
11854 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11855 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
11856 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11857 hr = IDirect3DDevice7_EndScene(device);
11858 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11860 color = get_surface_color(rt, 160, 120);
11861 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
11862 color = get_surface_color(rt, 480, 120);
11863 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
11864 color = get_surface_color(rt, 160, 360);
11865 ok(compare_color(color, 0x00ff0000, 2), "Got unexpected color 0x%08x.\n", color);
11866 color = get_surface_color(rt, 480, 360);
11867 ok(compare_color(color, 0x00ffffff, 2), "Got unexpected color 0x%08x.\n", color);
11869 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
11870 ok(SUCCEEDED(hr), "Failed to set texture transform flags, hr %#x.\n", hr);
11871 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_TEXTURE1, &mat);
11872 ok(SUCCEEDED(hr), "Failed to set transformation matrix, hr %#x.\n", hr);
11874 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
11875 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
11877 hr = IDirect3DDevice7_BeginScene(device);
11878 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11879 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
11880 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11881 hr = IDirect3DDevice7_EndScene(device);
11882 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11884 color = get_surface_color(rt, 160, 120);
11885 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
11886 color = get_surface_color(rt, 480, 120);
11887 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
11888 color = get_surface_color(rt, 160, 360);
11889 ok(compare_color(color, 0x00000000, 2), "Got unexpected color 0x%08x.\n", color);
11890 color = get_surface_color(rt, 480, 360);
11891 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
11893 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
11894 ok(SUCCEEDED(hr), "Failed to set texture transform flags, hr %#x.\n", hr);
11895 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_TEXCOORDINDEX, 2);
11896 ok(SUCCEEDED(hr), "Failed to set texcoord index, hr %#x.\n", hr);
11898 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
11899 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
11901 hr = IDirect3DDevice7_BeginScene(device);
11902 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11903 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, fvf, quad, 4, 0);
11904 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11905 hr = IDirect3DDevice7_EndScene(device);
11906 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11908 color = get_surface_color(rt, 160, 120);
11909 ok(compare_color(color, 0x000000ff, 2), "Got unexpected color 0x%08x.\n", color);
11910 color = get_surface_color(rt, 480, 120);
11911 ok(compare_color(color, 0x0000ffff, 2), "Got unexpected color 0x%08x.\n", color);
11912 color = get_surface_color(rt, 160, 360);
11913 ok(compare_color(color, 0x00ff00ff, 2), "Got unexpected color 0x%08x.\n", color);
11914 color = get_surface_color(rt, 480, 360);
11915 ok(compare_color(color, 0x00ffff00, 2), "Got unexpected color 0x%08x.\n", color);
11917 IDirectDrawSurface7_Release(texture1);
11918 IDirectDrawSurface7_Release(texture2);
11920 IDirectDrawSurface7_Release(rt);
11921 IDirectDraw7_Release(ddraw);
11922 refcount = IDirect3DDevice7_Release(device);
11923 ok(!refcount, "Device has %u references left.\n", refcount);
11924 DestroyWindow(window);
11927 static void test_colorkey_precision(void)
11929 static struct
11931 struct vec3 pos;
11932 struct vec2 texcoord;
11934 quad[] =
11936 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
11937 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
11938 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
11939 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
11942 static const struct
11944 unsigned int max, shift, bpp, clear;
11945 const char *name;
11946 BOOL skip_nv;
11947 DDPIXELFORMAT fmt;
11949 tests[] =
11952 255, 0, 4, 0x00345678, "D3DFMT_X8R8G8B8", FALSE,
11954 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
11955 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
11960 63, 5, 2, 0x5678, "D3DFMT_R5G6B5, G channel", FALSE,
11962 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
11963 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
11968 31, 0, 2, 0x5678, "D3DFMT_R5G6B5, B channel", FALSE,
11970 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
11971 {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
11976 15, 0, 2, 0x0678, "D3DFMT_A4R4G4B4", TRUE,
11978 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
11979 {16}, {0x0f00}, {0x00f0}, {0x000f}, {0xf000}
11984 IDirectDrawSurface7 *src, *dst, *texture;
11985 DDSURFACEDESC2 surface_desc, lock_desc;
11986 DWORD data[4] = {0}, color_mask;
11987 IDirect3DDevice7 *device;
11988 IDirectDrawSurface7 *rt;
11989 IDirectDraw7 *ddraw;
11990 unsigned int t, c;
11991 DDCOLORKEY ckey;
11992 IDirect3D7 *d3d;
11993 BOOL is_nvidia;
11994 ULONG refcount;
11995 D3DCOLOR color;
11996 HWND window;
11997 HRESULT hr;
11998 DDBLTFX fx;
12000 window = create_window();
12001 if (!(device = create_device(window, DDSCL_NORMAL)))
12003 skip("Failed to create a 3D device, skipping test.\n");
12004 DestroyWindow(window);
12005 return;
12008 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
12009 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12010 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
12011 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12012 IDirect3D7_Release(d3d);
12013 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
12014 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12016 is_nvidia = ddraw_is_nvidia(ddraw);
12017 /* The Windows 8 WARP driver has plenty of false negatives in X8R8G8B8
12018 * (color key doesn't match although the values are equal), and a false
12019 * positive when the color key is 0 and the texture contains the value 1.
12020 * Also on random occasions 254 == 255 and 255 != 255.
12021 * Crashes on Windows 10 WARP. */
12022 if (ddraw_is_warp(ddraw))
12024 win_skip("Skipping test on WARP driver.\n");
12025 goto done;
12028 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
12029 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12030 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
12031 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12032 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
12033 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12034 /* Multiply the texture read result with 0, that way the result color if the key doesn't
12035 * match is constant. In theory color keying works without reading the texture result
12036 * (meaning we could just op=arg1, arg1=tfactor), but the Geforce7 Windows driver begs
12037 * to differ. */
12038 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
12039 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12040 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
12041 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12042 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
12043 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12044 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x00000000);
12045 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12047 memset(&fx, 0, sizeof(fx));
12048 fx.dwSize = sizeof(fx);
12049 memset(&lock_desc, 0, sizeof(lock_desc));
12050 lock_desc.dwSize = sizeof(lock_desc);
12052 for (t = 0; t < ARRAY_SIZE(tests); ++t)
12054 if (is_nvidia && tests[t].skip_nv)
12056 win_skip("Skipping test %s on Nvidia Windows drivers.\n", tests[t].name);
12057 continue;
12060 memset(&surface_desc, 0, sizeof(surface_desc));
12061 surface_desc.dwSize = sizeof(surface_desc);
12062 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
12063 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12064 surface_desc.dwWidth = 4;
12065 surface_desc.dwHeight = 1;
12066 U4(surface_desc).ddpfPixelFormat = tests[t].fmt;
12067 /* Windows XP (at least with the r200 driver, other drivers untested) produces
12068 * garbage when doing color keyed texture->texture blits. */
12069 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
12070 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12071 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
12072 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12074 U5(fx).dwFillColor = tests[t].clear;
12075 /* On the w8 testbot (WARP driver) the blit result has different values in the
12076 * X channel. */
12077 color_mask = U2(tests[t].fmt).dwRBitMask
12078 | U3(tests[t].fmt).dwGBitMask
12079 | U4(tests[t].fmt).dwBBitMask;
12081 for (c = 0; c <= tests[t].max; ++c)
12083 /* The idiotic Nvidia Windows driver can't change the color key on a d3d
12084 * texture after it has been set once... */
12085 surface_desc.dwFlags |= DDSD_CKSRCBLT;
12086 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
12087 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = c << tests[t].shift;
12088 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = c << tests[t].shift;
12089 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
12090 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12091 hr = IDirect3DDevice7_SetTexture(device, 0, texture);
12092 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12094 hr = IDirectDrawSurface7_Blt(dst, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
12095 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12097 hr = IDirectDrawSurface7_Lock(src, NULL, &lock_desc, DDLOCK_WAIT, NULL);
12098 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12099 switch (tests[t].bpp)
12101 case 4:
12102 ((DWORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
12103 ((DWORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
12104 ((DWORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
12105 ((DWORD *)lock_desc.lpSurface)[3] = 0xffffffff;
12106 break;
12108 case 2:
12109 ((WORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
12110 ((WORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
12111 ((WORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
12112 ((WORD *)lock_desc.lpSurface)[3] = 0xffff;
12113 break;
12115 hr = IDirectDrawSurface7_Unlock(src, 0);
12116 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12117 hr = IDirectDrawSurface7_Blt(texture, NULL, src, NULL, DDBLT_WAIT, NULL);
12118 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12120 ckey.dwColorSpaceLowValue = c << tests[t].shift;
12121 ckey.dwColorSpaceHighValue = c << tests[t].shift;
12122 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
12123 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12125 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_WAIT, NULL);
12126 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12128 /* Don't make this read only, it somehow breaks the detection of the Nvidia bug below. */
12129 hr = IDirectDrawSurface7_Lock(dst, NULL, &lock_desc, DDLOCK_WAIT, NULL);
12130 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12131 switch (tests[t].bpp)
12133 case 4:
12134 data[0] = ((DWORD *)lock_desc.lpSurface)[0] & color_mask;
12135 data[1] = ((DWORD *)lock_desc.lpSurface)[1] & color_mask;
12136 data[2] = ((DWORD *)lock_desc.lpSurface)[2] & color_mask;
12137 data[3] = ((DWORD *)lock_desc.lpSurface)[3] & color_mask;
12138 break;
12140 case 2:
12141 data[0] = ((WORD *)lock_desc.lpSurface)[0] & color_mask;
12142 data[1] = ((WORD *)lock_desc.lpSurface)[1] & color_mask;
12143 data[2] = ((WORD *)lock_desc.lpSurface)[2] & color_mask;
12144 data[3] = ((WORD *)lock_desc.lpSurface)[3] & color_mask;
12145 break;
12147 hr = IDirectDrawSurface7_Unlock(dst, 0);
12148 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12150 if (!c)
12152 ok(data[0] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
12153 tests[t].clear, data[0], tests[t].name, c);
12155 if (data[3] == tests[t].clear)
12157 /* My Geforce GTX 460 on Windows 7 misbehaves when A4R4G4B4 is blitted with color
12158 * keying: The blit takes ~0.5 seconds, and subsequent color keying draws are broken,
12159 * even when a different surface is used. The blit itself doesn't draw anything,
12160 * so we can detect the bug by looking at the otherwise unused 4th texel. It should
12161 * never be masked out by the key.
12163 * On Windows 10 the problem is worse, Blt just hangs. For this reason the ARGB4444
12164 * test is disabled on Nvidia.
12166 * Also appears to affect the testbot in some way with R5G6B5. Color keying is
12167 * terrible on WARP. */
12168 skip("Nvidia A4R4G4B4 color keying blit bug detected, skipping.\n");
12169 IDirectDrawSurface7_Release(texture);
12170 IDirectDrawSurface7_Release(src);
12171 IDirectDrawSurface7_Release(dst);
12172 goto done;
12175 else
12176 ok(data[0] == (c - 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
12177 (c - 1) << tests[t].shift, data[0], tests[t].name, c);
12179 ok(data[1] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
12180 tests[t].clear, data[1], tests[t].name, c);
12182 if (c == tests[t].max)
12183 ok(data[2] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
12184 tests[t].clear, data[2], tests[t].name, c);
12185 else
12186 ok(data[2] == (c + 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
12187 (c + 1) << tests[t].shift, data[2], tests[t].name, c);
12189 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x0000ff00, 1.0f, 0);
12190 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12192 hr = IDirect3DDevice7_BeginScene(device);
12193 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12194 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
12195 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12196 hr = IDirect3DDevice7_EndScene(device);
12197 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
12199 color = get_surface_color(rt, 80, 240);
12201 if (!c)
12202 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x, format %s, c=%u.\n",
12203 color, tests[t].name, c);
12204 else
12205 ok(compare_color(color, 0x00000000, 1), "Got unexpected color 0x%08x, format %s, c=%u.\n",
12206 color, tests[t].name, c);
12208 color = get_surface_color(rt, 240, 240);
12209 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x, format %s, c=%u.\n",
12210 color, tests[t].name, c);
12212 color = get_surface_color(rt, 400, 240);
12213 if (c == tests[t].max)
12214 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x, format %s, c=%u.\n",
12215 color, tests[t].name, c);
12216 else
12217 ok(compare_color(color, 0x00000000, 1), "Got unexpected color 0x%08x, format %s, c=%u.\n",
12218 color, tests[t].name, c);
12220 IDirectDrawSurface7_Release(texture);
12222 IDirectDrawSurface7_Release(src);
12223 IDirectDrawSurface7_Release(dst);
12225 done:
12227 IDirectDrawSurface7_Release(rt);
12228 IDirectDraw7_Release(ddraw);
12229 refcount = IDirect3DDevice7_Release(device);
12230 ok(!refcount, "Device has %u references left.\n", refcount);
12231 DestroyWindow(window);
12234 static void test_range_colorkey(void)
12236 IDirectDraw7 *ddraw;
12237 HWND window;
12238 HRESULT hr;
12239 IDirectDrawSurface7 *surface;
12240 DDSURFACEDESC2 surface_desc;
12241 ULONG refcount;
12242 DDCOLORKEY ckey;
12244 window = create_window();
12245 ddraw = create_ddraw();
12246 ok(!!ddraw, "Failed to create a ddraw object.\n");
12247 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12248 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12250 memset(&surface_desc, 0, sizeof(surface_desc));
12251 surface_desc.dwSize = sizeof(surface_desc);
12252 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
12253 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
12254 surface_desc.dwWidth = 1;
12255 surface_desc.dwHeight = 1;
12256 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
12257 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
12258 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
12259 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
12260 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
12261 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0x00000000;
12263 /* Creating a surface with a range color key fails with DDERR_NOCOLORKEY. */
12264 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
12265 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
12266 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12267 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
12269 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
12270 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
12271 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12272 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
12274 /* Same for DDSCAPS_OFFSCREENPLAIN. */
12275 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12276 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
12277 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
12278 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12279 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
12281 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
12282 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
12283 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12284 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
12286 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
12287 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
12288 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12289 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
12291 /* Setting a range color key without DDCKEY_COLORSPACE collapses the key. */
12292 ckey.dwColorSpaceLowValue = 0x00000000;
12293 ckey.dwColorSpaceHighValue = 0x00000001;
12294 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
12295 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12297 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
12298 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
12299 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
12300 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
12302 ckey.dwColorSpaceLowValue = 0x00000001;
12303 ckey.dwColorSpaceHighValue = 0x00000000;
12304 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
12305 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12307 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
12308 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
12309 ok(ckey.dwColorSpaceLowValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
12310 ok(ckey.dwColorSpaceHighValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
12312 /* DDCKEY_COLORSPACE is ignored if the key is a single value. */
12313 ckey.dwColorSpaceLowValue = 0x00000000;
12314 ckey.dwColorSpaceHighValue = 0x00000000;
12315 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
12316 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
12318 /* Using it with a range key results in DDERR_NOCOLORKEYHW. */
12319 ckey.dwColorSpaceLowValue = 0x00000001;
12320 ckey.dwColorSpaceHighValue = 0x00000000;
12321 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
12322 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
12323 ckey.dwColorSpaceLowValue = 0x00000000;
12324 ckey.dwColorSpaceHighValue = 0x00000001;
12325 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
12326 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
12327 /* Range destination keys don't work either. */
12328 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_DESTBLT | DDCKEY_COLORSPACE, &ckey);
12329 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
12331 /* Just to show it's not because of A, R, and G having equal values. */
12332 ckey.dwColorSpaceLowValue = 0x00000000;
12333 ckey.dwColorSpaceHighValue = 0x01010101;
12334 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
12335 ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
12337 /* None of these operations modified the key. */
12338 hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
12339 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
12340 ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
12341 ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
12343 IDirectDrawSurface7_Release(surface);
12344 refcount = IDirectDraw7_Release(ddraw);
12345 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
12346 DestroyWindow(window);
12349 static void test_shademode(void)
12351 IDirect3DVertexBuffer7 *vb_strip, *vb_list, *buffer;
12352 IDirect3DDevice7 *device;
12353 D3DVERTEXBUFFERDESC desc;
12354 IDirectDrawSurface7 *rt;
12355 DWORD color0, color1;
12356 void *data = NULL;
12357 IDirect3D7 *d3d;
12358 ULONG refcount;
12359 UINT i, count;
12360 HWND window;
12361 HRESULT hr;
12362 static const struct
12364 struct vec3 position;
12365 DWORD diffuse;
12367 quad_strip[] =
12369 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
12370 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
12371 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
12372 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
12374 quad_list[] =
12376 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
12377 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
12378 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
12380 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
12381 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
12382 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
12384 static const struct
12386 DWORD primtype;
12387 DWORD shademode;
12388 DWORD color0, color1;
12390 tests[] =
12392 {D3DPT_TRIANGLESTRIP, D3DSHADE_FLAT, 0x00ff0000, 0x0000ff00},
12393 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
12394 {D3DPT_TRIANGLESTRIP, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
12395 {D3DPT_TRIANGLESTRIP, D3DSHADE_PHONG, 0x000dca28, 0x000d45c7},
12396 {D3DPT_TRIANGLELIST, D3DSHADE_FLAT, 0x00ff0000, 0x000000ff},
12397 {D3DPT_TRIANGLELIST, D3DSHADE_GOURAUD, 0x000dca28, 0x000d45c7},
12400 window = create_window();
12401 if (!(device = create_device(window, DDSCL_NORMAL)))
12403 skip("Failed to create a 3D device, skipping test.\n");
12404 DestroyWindow(window);
12405 return;
12408 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
12409 ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr);
12410 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
12411 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
12413 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
12414 ok(hr == D3D_OK, "Failed to disable lighting, hr %#x.\n", hr);
12415 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
12416 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
12418 memset(&desc, 0, sizeof(desc));
12419 desc.dwSize = sizeof(desc);
12420 desc.dwCaps = D3DVBCAPS_WRITEONLY;
12421 desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
12422 desc.dwNumVertices = ARRAY_SIZE(quad_strip);
12423 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &vb_strip, 0);
12424 ok(hr == D3D_OK, "Failed to create vertex buffer, hr %#x.\n", hr);
12425 hr = IDirect3DVertexBuffer7_Lock(vb_strip, 0, &data, NULL);
12426 ok(hr == D3D_OK, "Failed to lock vertex buffer, hr %#x.\n", hr);
12427 memcpy(data, quad_strip, sizeof(quad_strip));
12428 hr = IDirect3DVertexBuffer7_Unlock(vb_strip);
12429 ok(hr == D3D_OK, "Failed to unlock vertex buffer, hr %#x.\n", hr);
12431 desc.dwNumVertices = ARRAY_SIZE(quad_list);
12432 hr = IDirect3D7_CreateVertexBuffer(d3d, &desc, &vb_list, 0);
12433 ok(hr == D3D_OK, "Failed to create vertex buffer, hr %#x.\n", hr);
12434 hr = IDirect3DVertexBuffer7_Lock(vb_list, 0, &data, NULL);
12435 ok(hr == D3D_OK, "Failed to lock vertex buffer, hr %#x.\n", hr);
12436 memcpy(data, quad_list, sizeof(quad_list));
12437 hr = IDirect3DVertexBuffer7_Unlock(vb_list);
12438 ok(hr == D3D_OK, "Failed to unlock vertex buffer, hr %#x.\n", hr);
12440 /* Try it first with a TRIANGLESTRIP. Do it with different geometry because
12441 * the color fixups we have to do for FLAT shading will be dependent on that. */
12443 for (i = 0; i < ARRAY_SIZE(tests); ++i)
12445 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
12446 ok(hr == D3D_OK, "Failed to clear, hr %#x.\n", hr);
12448 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SHADEMODE, tests[i].shademode);
12449 ok(hr == D3D_OK, "Failed to set shade mode, hr %#x.\n", hr);
12451 hr = IDirect3DDevice7_BeginScene(device);
12452 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12453 buffer = tests[i].primtype == D3DPT_TRIANGLESTRIP ? vb_strip : vb_list;
12454 count = tests[i].primtype == D3DPT_TRIANGLESTRIP ? 4 : 6;
12455 hr = IDirect3DDevice7_DrawPrimitiveVB(device, tests[i].primtype, buffer, 0, count, 0);
12456 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
12457 hr = IDirect3DDevice7_EndScene(device);
12458 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12460 color0 = get_surface_color(rt, 100, 100); /* Inside first triangle */
12461 color1 = get_surface_color(rt, 500, 350); /* Inside second triangle */
12463 /* For D3DSHADE_FLAT it should take the color of the first vertex of
12464 * each triangle. This requires EXT_provoking_vertex or similar
12465 * functionality being available. */
12466 /* PHONG should be the same as GOURAUD, since no hardware implements
12467 * this. */
12468 ok(compare_color(color0, tests[i].color0, 1), "Test %u shading has color0 %08x, expected %08x.\n",
12469 i, color0, tests[i].color0);
12470 ok(compare_color(color1, tests[i].color1, 1), "Test %u shading has color1 %08x, expected %08x.\n",
12471 i, color1, tests[i].color1);
12474 IDirect3DVertexBuffer7_Release(vb_strip);
12475 IDirect3DVertexBuffer7_Release(vb_list);
12476 IDirectDrawSurface7_Release(rt);
12477 IDirect3D7_Release(d3d);
12478 refcount = IDirect3DDevice7_Release(device);
12479 ok(!refcount, "Device has %u references left.\n", refcount);
12480 DestroyWindow(window);
12483 static void test_lockrect_invalid(void)
12485 unsigned int i, r;
12486 IDirectDraw7 *ddraw;
12487 IDirectDrawSurface7 *surface;
12488 HWND window;
12489 HRESULT hr;
12490 DDSURFACEDESC2 surface_desc;
12491 DDSURFACEDESC2 locked_desc;
12492 DDCAPS hal_caps;
12493 DWORD needed_caps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
12494 static RECT valid[] =
12496 {60, 60, 68, 68},
12497 {60, 60, 60, 68},
12498 {60, 60, 68, 60},
12499 {120, 60, 128, 68},
12500 {60, 120, 68, 128},
12502 static RECT invalid[] =
12504 {68, 60, 60, 68}, /* left > right */
12505 {60, 68, 68, 60}, /* top > bottom */
12506 {-8, 60, 0, 68}, /* left < surface */
12507 {60, -8, 68, 0}, /* top < surface */
12508 {-16, 60, -8, 68}, /* right < surface */
12509 {60, -16, 68, -8}, /* bottom < surface */
12510 {60, 60, 136, 68}, /* right > surface */
12511 {60, 60, 68, 136}, /* bottom > surface */
12512 {136, 60, 144, 68}, /* left > surface */
12513 {60, 136, 68, 144}, /* top > surface */
12515 static const struct
12517 DWORD caps, caps2;
12518 const char *name;
12519 BOOL allowed;
12520 HRESULT hr;
12522 resources[] =
12524 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, "sysmem offscreenplain", TRUE, DDERR_INVALIDPARAMS},
12525 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, "vidmem offscreenplain", TRUE, DDERR_INVALIDPARAMS},
12526 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, "sysmem texture", TRUE, DD_OK},
12527 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, "vidmem texture", TRUE, DDERR_INVALIDPARAMS},
12528 {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, "managed texture", TRUE, DD_OK},
12530 /* FWIW the SDK header mentions DDSCAPS_WRITEONLY as being a "READ
12531 * ONLY" flag. */
12532 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY | DDSCAPS_WRITEONLY, 0, "sysmem offscreenplain writeonly", FALSE, DDERR_INVALIDPARAMS},
12533 {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_WRITEONLY, 0, "vidmem offscreenplain writeonly", FALSE, DDERR_INVALIDPARAMS},
12534 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_WRITEONLY, 0, "sysmem texture writeonly", FALSE, DD_OK},
12535 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_WRITEONLY, 0, "vidmem texture writeonly", FALSE, DDERR_INVALIDPARAMS},
12536 {DDSCAPS_TEXTURE | DDSCAPS_WRITEONLY, DDSCAPS2_TEXTUREMANAGE, "managed texture writeonly", TRUE, DD_OK},
12539 window = create_window();
12540 ddraw = create_ddraw();
12541 ok(!!ddraw, "Failed to create a ddraw object.\n");
12542 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12543 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12545 memset(&hal_caps, 0, sizeof(hal_caps));
12546 hal_caps.dwSize = sizeof(hal_caps);
12547 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
12548 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
12549 if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps
12550 || !(hal_caps.ddsCaps.dwCaps & DDSCAPS2_TEXTUREMANAGE))
12552 skip("Required surface types not supported, skipping test.\n");
12553 goto done;
12556 for (r = 0; r < ARRAY_SIZE(resources); ++r)
12558 memset(&surface_desc, 0, sizeof(surface_desc));
12559 surface_desc.dwSize = sizeof(surface_desc);
12560 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
12561 surface_desc.ddsCaps.dwCaps = resources[r].caps;
12562 surface_desc.ddsCaps.dwCaps2 = resources[r].caps2;
12563 surface_desc.dwWidth = 128;
12564 surface_desc.dwHeight = 128;
12565 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
12566 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
12567 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
12568 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xff0000;
12569 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x00ff00;
12570 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x0000ff;
12572 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
12573 if (!resources[r].allowed)
12575 ok(hr == DDERR_INVALIDCAPS, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
12576 continue;
12578 if (is_ddraw64 && (resources[r].caps & DDSCAPS_TEXTURE))
12580 todo_wine ok(hr == E_NOINTERFACE, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
12581 if (SUCCEEDED(hr))
12582 IDirectDrawSurface7_Release(surface);
12583 continue;
12585 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n", hr, resources[r].name);
12587 /* Crashes in ddraw7
12588 hr = IDirectDrawSurface7_Lock(surface, NULL, NULL, DDLOCK_WAIT, NULL);
12589 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
12592 for (i = 0; i < ARRAY_SIZE(valid); ++i)
12594 RECT *rect = &valid[i];
12596 memset(&locked_desc, 0, sizeof(locked_desc));
12597 locked_desc.dwSize = sizeof(locked_desc);
12599 hr = IDirectDrawSurface7_Lock(surface, rect, &locked_desc, DDLOCK_WAIT, NULL);
12600 ok(SUCCEEDED(hr), "Lock failed (%#x) for rect %s, type %s.\n",
12601 hr, wine_dbgstr_rect(rect), resources[r].name);
12603 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12604 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
12607 for (i = 0; i < ARRAY_SIZE(invalid); ++i)
12609 RECT *rect = &invalid[i];
12611 memset(&locked_desc, 1, sizeof(locked_desc));
12612 locked_desc.dwSize = sizeof(locked_desc);
12614 hr = IDirectDrawSurface7_Lock(surface, rect, &locked_desc, DDLOCK_WAIT, NULL);
12615 todo_wine_if (SUCCEEDED(resources[r].hr))
12616 ok(hr == resources[r].hr, "Lock returned %#x for rect %s, type %s.\n",
12617 hr, wine_dbgstr_rect(rect), resources[r].name);
12618 if (SUCCEEDED(hr))
12620 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12621 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
12623 else
12624 ok(!locked_desc.lpSurface, "Got unexpected lpSurface %p.\n", locked_desc.lpSurface);
12627 hr = IDirectDrawSurface7_Lock(surface, NULL, &locked_desc, DDLOCK_WAIT, NULL);
12628 ok(SUCCEEDED(hr), "Lock(rect = NULL) failed, hr %#x, type %s.\n",
12629 hr, resources[r].name);
12630 hr = IDirectDrawSurface7_Lock(surface, NULL, &locked_desc, DDLOCK_WAIT, NULL);
12631 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = NULL) returned %#x, type %s.\n",
12632 hr, resources[r].name);
12633 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12634 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
12636 hr = IDirectDrawSurface7_Lock(surface, &valid[0], &locked_desc, DDLOCK_WAIT, NULL);
12637 ok(SUCCEEDED(hr), "Lock(rect = %s) failed (%#x).\n", wine_dbgstr_rect(&valid[0]), hr);
12638 hr = IDirectDrawSurface7_Lock(surface, &valid[0], &locked_desc, DDLOCK_WAIT, NULL);
12639 ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = %s) failed (%#x).\n",
12640 wine_dbgstr_rect(&valid[0]), hr);
12642 /* Locking a different rectangle returns DD_OK, but it seems to break the surface.
12643 * Afterwards unlocking the surface fails(NULL rectangle or both locked rectangles) */
12645 hr = IDirectDrawSurface7_Unlock(surface, NULL);
12646 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
12648 IDirectDrawSurface7_Release(surface);
12651 done:
12652 IDirectDraw7_Release(ddraw);
12653 DestroyWindow(window);
12656 static void test_yv12_overlay(void)
12658 IDirectDrawSurface7 *src_surface, *dst_surface;
12659 RECT rect = {13, 17, 14, 18};
12660 unsigned int offset, y;
12661 DDSURFACEDESC2 desc;
12662 unsigned char *base;
12663 IDirectDraw7 *ddraw;
12664 HWND window;
12665 HRESULT hr;
12667 window = create_window();
12668 ddraw = create_ddraw();
12669 ok(!!ddraw, "Failed to create a ddraw object.\n");
12670 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12671 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12673 if (!(src_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
12675 skip("Failed to create a YV12 overlay, skipping test.\n");
12676 goto done;
12679 memset(&desc, 0, sizeof(desc));
12680 desc.dwSize = sizeof(desc);
12681 hr = IDirectDrawSurface7_Lock(src_surface, NULL, &desc, DDLOCK_WAIT, NULL);
12682 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12684 ok(desc.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH),
12685 "Got unexpected flags %#x.\n", desc.dwFlags);
12686 ok(desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_HWCODEC)
12687 || desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
12688 "Got unexpected caps %#x.\n", desc.ddsCaps.dwCaps);
12689 ok(desc.dwWidth == 256, "Got unexpected width %u.\n", desc.dwWidth);
12690 ok(desc.dwHeight == 256, "Got unexpected height %u.\n", desc.dwHeight);
12691 /* The overlay pitch seems to have 256 byte alignment. */
12692 ok(!(U1(desc).lPitch & 0xff), "Got unexpected pitch %u.\n", U1(desc).lPitch);
12694 /* Fill the surface with some data for the blit test. */
12695 base = desc.lpSurface;
12696 /* Luminance */
12697 for (y = 0; y < desc.dwHeight; ++y)
12699 memset(base + U1(desc).lPitch * y, 0x10, desc.dwWidth);
12701 /* V */
12702 for (; y < desc.dwHeight + desc.dwHeight / 4; ++y)
12704 memset(base + U1(desc).lPitch * y, 0x20, desc.dwWidth);
12706 /* U */
12707 for (; y < desc.dwHeight + desc.dwHeight / 2; ++y)
12709 memset(base + U1(desc).lPitch * y, 0x30, desc.dwWidth);
12712 hr = IDirectDrawSurface7_Unlock(src_surface, NULL);
12713 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12715 /* YV12 uses 2x2 blocks with 6 bytes per block (4*Y, 1*U, 1*V). Unlike
12716 * other block-based formats like DXT the entire Y channel is stored in
12717 * one big chunk of memory, followed by the chroma channels. So partial
12718 * locks do not really make sense. Show that they are allowed nevertheless
12719 * and the offset points into the luminance data. */
12720 hr = IDirectDrawSurface7_Lock(src_surface, &rect, &desc, DDLOCK_WAIT, NULL);
12721 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12722 offset = ((const unsigned char *)desc.lpSurface - base);
12723 ok(offset == rect.top * U1(desc).lPitch + rect.left, "Got unexpected offset %u, expected %u.\n",
12724 offset, rect.top * U1(desc).lPitch + rect.left);
12725 hr = IDirectDrawSurface7_Unlock(src_surface, NULL);
12726 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12728 if (!(dst_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2'))))
12730 /* Windows XP with a Radeon X1600 GPU refuses to create a second
12731 * overlay surface, DDERR_NOOVERLAYHW, making the blit tests moot. */
12732 skip("Failed to create a second YV12 surface, skipping blit test.\n");
12733 IDirectDrawSurface7_Release(src_surface);
12734 goto done;
12737 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, src_surface, NULL, DDBLT_WAIT, NULL);
12738 /* VMware rejects YV12 blits. This behavior has not been seen on real
12739 * hardware yet, so mark it broken. */
12740 ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL), "Failed to blit, hr %#x.\n", hr);
12742 if (SUCCEEDED(hr))
12744 memset(&desc, 0, sizeof(desc));
12745 desc.dwSize = sizeof(desc);
12746 hr = IDirectDrawSurface7_Lock(dst_surface, NULL, &desc, DDLOCK_WAIT, NULL);
12747 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
12749 base = desc.lpSurface;
12750 ok(base[0] == 0x10, "Got unexpected Y data 0x%02x.\n", base[0]);
12751 base += desc.dwHeight * U1(desc).lPitch;
12752 todo_wine ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]);
12753 base += desc.dwHeight / 4 * U1(desc).lPitch;
12754 todo_wine ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]);
12756 hr = IDirectDrawSurface7_Unlock(dst_surface, NULL);
12757 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
12760 IDirectDrawSurface7_Release(dst_surface);
12761 IDirectDrawSurface7_Release(src_surface);
12762 done:
12763 IDirectDraw7_Release(ddraw);
12764 DestroyWindow(window);
12767 static BOOL dwm_enabled(void)
12769 BOOL ret = FALSE;
12771 if (!strcmp(winetest_platform, "wine"))
12772 return FALSE;
12773 if (!pDwmIsCompositionEnabled)
12774 return FALSE;
12775 if (FAILED(pDwmIsCompositionEnabled(&ret)))
12776 return FALSE;
12777 return ret;
12780 static void test_offscreen_overlay(void)
12782 IDirectDrawSurface7 *overlay, *offscreen, *primary;
12783 DDSURFACEDESC2 surface_desc;
12784 IDirectDraw7 *ddraw;
12785 HWND window;
12786 HRESULT hr;
12787 HDC dc;
12789 window = create_window();
12790 ddraw = create_ddraw();
12791 ok(!!ddraw, "Failed to create a ddraw object.\n");
12792 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12793 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12795 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
12797 skip("Failed to create a UYVY overlay, skipping test.\n");
12798 goto done;
12801 memset(&surface_desc, 0, sizeof(surface_desc));
12802 surface_desc.dwSize = sizeof(surface_desc);
12803 surface_desc.dwFlags = DDSD_CAPS;
12804 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
12805 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
12806 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
12808 /* On Windows 7, and probably Vista, UpdateOverlay() will return
12809 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
12810 * surface prevents this by disabling the dwm. */
12811 hr = IDirectDrawSurface7_GetDC(primary, &dc);
12812 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
12813 hr = IDirectDrawSurface7_ReleaseDC(primary, dc);
12814 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
12816 /* Try to overlay a NULL surface. */
12817 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_SHOW, NULL);
12818 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
12819 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, NULL, NULL, DDOVER_HIDE, NULL);
12820 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
12822 /* Try to overlay an offscreen surface. */
12823 memset(&surface_desc, 0, sizeof(surface_desc));
12824 surface_desc.dwSize = sizeof(surface_desc);
12825 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
12826 surface_desc.dwWidth = 64;
12827 surface_desc.dwHeight = 64;
12828 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
12829 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
12830 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
12831 U4(surface_desc).ddpfPixelFormat.dwFourCC = 0;
12832 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
12833 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0xf800;
12834 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x07e0;
12835 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x001f;
12836 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
12837 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
12839 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, offscreen, NULL, DDOVER_SHOW, NULL);
12840 ok(SUCCEEDED(hr) || broken(hr == DDERR_OUTOFCAPS && dwm_enabled())
12841 || broken(hr == E_NOTIMPL && ddraw_is_vmware(ddraw)),
12842 "Failed to update overlay, hr %#x.\n", hr);
12844 /* Try to overlay the primary with a non-overlay surface. */
12845 hr = IDirectDrawSurface7_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_SHOW, NULL);
12846 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
12847 hr = IDirectDrawSurface7_UpdateOverlay(offscreen, NULL, primary, NULL, DDOVER_HIDE, NULL);
12848 ok(hr == DDERR_NOTAOVERLAYSURFACE, "Got unexpected hr %#x.\n", hr);
12850 IDirectDrawSurface7_Release(offscreen);
12851 IDirectDrawSurface7_Release(primary);
12852 IDirectDrawSurface7_Release(overlay);
12853 done:
12854 IDirectDraw7_Release(ddraw);
12855 DestroyWindow(window);
12858 static void test_overlay_rect(void)
12860 IDirectDrawSurface7 *overlay, *primary = NULL;
12861 DDSURFACEDESC2 surface_desc;
12862 RECT rect = {0, 0, 64, 64};
12863 IDirectDraw7 *ddraw;
12864 LONG pos_x, pos_y;
12865 HRESULT hr, hr2;
12866 HWND window;
12867 HDC dc;
12869 window = create_window();
12870 ddraw = create_ddraw();
12871 ok(!!ddraw, "Failed to create a ddraw object.\n");
12872 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
12873 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
12875 if (!(overlay = create_overlay(ddraw, 64, 64, MAKEFOURCC('U','Y','V','Y'))))
12877 skip("Failed to create a UYVY overlay, skipping test.\n");
12878 goto done;
12881 memset(&surface_desc, 0, sizeof(surface_desc));
12882 surface_desc.dwSize = sizeof(surface_desc);
12883 surface_desc.dwFlags = DDSD_CAPS;
12884 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
12885 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
12886 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n",hr);
12888 /* On Windows 7, and probably Vista, UpdateOverlay() will return
12889 * DDERR_OUTOFCAPS if the dwm is active. Calling GetDC() on the primary
12890 * surface prevents this by disabling the dwm. */
12891 hr = IDirectDrawSurface7_GetDC(primary, &dc);
12892 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
12893 hr = IDirectDrawSurface7_ReleaseDC(primary, dc);
12894 ok(SUCCEEDED(hr), "Failed to release DC, hr %#x.\n", hr);
12896 /* On Windows 8 and newer DWM can't be turned off, making overlays unusable. */
12897 if (dwm_enabled())
12899 win_skip("Cannot disable DWM, skipping overlay test.\n");
12900 goto done;
12903 /* The dx sdk sort of implies that rect must be set when DDOVER_SHOW is
12904 * used. This is not true in Windows Vista and earlier, but changed in
12905 * Windows 7. */
12906 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
12907 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
12908 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_HIDE, NULL);
12909 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
12910 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, NULL, DDOVER_SHOW, NULL);
12911 ok(hr == DD_OK || hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
12913 /* Show that the overlay position is the (top, left) coordinate of the
12914 * destination rectangle. */
12915 OffsetRect(&rect, 32, 16);
12916 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_SHOW, NULL);
12917 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
12918 pos_x = -1; pos_y = -1;
12919 hr = IDirectDrawSurface7_GetOverlayPosition(overlay, &pos_x, &pos_y);
12920 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
12921 ok(pos_x == rect.left, "Got unexpected pos_x %d, expected %d.\n", pos_x, rect.left);
12922 ok(pos_y == rect.top, "Got unexpected pos_y %d, expected %d.\n", pos_y, rect.top);
12924 /* Passing a NULL dest rect sets the position to 0/0. Visually it can be
12925 * seen that the overlay overlays the whole primary(==screen). */
12926 hr2 = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, NULL, 0, NULL);
12927 ok(hr2 == DD_OK || hr2 == DDERR_INVALIDPARAMS || hr2 == DDERR_OUTOFCAPS, "Got unexpected hr %#x.\n", hr2);
12928 hr = IDirectDrawSurface7_GetOverlayPosition(overlay, &pos_x, &pos_y);
12929 ok(SUCCEEDED(hr), "Failed to get overlay position, hr %#x.\n", hr);
12930 if (SUCCEEDED(hr2))
12932 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
12933 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
12935 else
12937 ok(pos_x == 32, "Got unexpected pos_x %d.\n", pos_x);
12938 ok(pos_y == 16, "Got unexpected pos_y %d.\n", pos_y);
12941 /* The position cannot be retrieved when the overlay is not shown. */
12942 hr = IDirectDrawSurface7_UpdateOverlay(overlay, NULL, primary, &rect, DDOVER_HIDE, NULL);
12943 ok(SUCCEEDED(hr), "Failed to update overlay, hr %#x.\n", hr);
12944 pos_x = -1; pos_y = -1;
12945 hr = IDirectDrawSurface7_GetOverlayPosition(overlay, &pos_x, &pos_y);
12946 ok(hr == DDERR_OVERLAYNOTVISIBLE, "Got unexpected hr %#x.\n", hr);
12947 ok(!pos_x, "Got unexpected pos_x %d.\n", pos_x);
12948 ok(!pos_y, "Got unexpected pos_y %d.\n", pos_y);
12950 done:
12951 if (primary)
12952 IDirectDrawSurface7_Release(primary);
12953 if (overlay)
12954 IDirectDrawSurface7_Release(overlay);
12955 IDirectDraw7_Release(ddraw);
12956 DestroyWindow(window);
12959 static void test_blt(void)
12961 IDirectDrawSurface7 *surface, *rt;
12962 DDSURFACEDESC2 surface_desc;
12963 IDirect3DDevice7 *device;
12964 IDirectDraw7 *ddraw;
12965 IDirect3D7 *d3d;
12966 unsigned int i;
12967 ULONG refcount;
12968 HWND window;
12969 HRESULT hr;
12971 static struct
12973 RECT src_rect;
12974 RECT dst_rect;
12975 HRESULT hr;
12977 test_data[] =
12979 {{160, 0, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit. */
12980 {{160, 480, 640, 0}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, flipped source. */
12981 {{640, 0, 160, 480}, { 0, 0, 480, 480}, DDERR_INVALIDRECT}, /* Overlapped blit, mirrored source. */
12982 {{160, 0, 480, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched x. */
12983 {{160, 160, 640, 480}, { 0, 0, 480, 480}, DD_OK}, /* Overlapped blit, stretched y. */
12984 {{ 0, 0, 640, 480}, { 0, 0, 640, 480}, DD_OK}, /* Full surface blit. */
12985 {{ 0, 0, 640, 480}, { 0, 480, 640, 0}, DDERR_INVALIDRECT}, /* Full surface, flipped destination. */
12986 {{ 0, 0, 640, 480}, {640, 0, 0, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored destination. */
12987 {{ 0, 480, 640, 0}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, flipped source. */
12988 {{640, 0, 0, 480}, { 0, 0, 640, 480}, DDERR_INVALIDRECT}, /* Full surface, mirrored source. */
12991 window = create_window();
12992 if (!(device = create_device(window, DDSCL_NORMAL)))
12994 skip("Failed to create a 3D device, skipping test.\n");
12995 DestroyWindow(window);
12996 return;
12999 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
13000 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
13001 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
13002 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
13003 IDirect3D7_Release(d3d);
13004 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
13005 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
13007 memset(&surface_desc, 0, sizeof(surface_desc));
13008 surface_desc.dwSize = sizeof(surface_desc);
13009 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
13010 surface_desc.dwWidth = 640;
13011 surface_desc.dwHeight = 480;
13012 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13013 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
13014 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13016 hr = IDirectDrawSurface7_Blt(surface, NULL, surface, NULL, 0, NULL);
13017 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13019 hr = IDirectDrawSurface7_Blt(surface, NULL, rt, NULL, 0, NULL);
13020 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
13022 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
13024 hr = IDirectDrawSurface7_Blt(surface, &test_data[i].dst_rect,
13025 surface, &test_data[i].src_rect, DDBLT_WAIT, NULL);
13026 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
13028 hr = IDirectDrawSurface7_Blt(surface, &test_data[i].dst_rect,
13029 rt, &test_data[i].src_rect, DDBLT_WAIT, NULL);
13030 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
13032 hr = IDirectDrawSurface7_Blt(surface, &test_data[i].dst_rect,
13033 NULL, &test_data[i].src_rect, DDBLT_WAIT, NULL);
13034 ok(hr == DDERR_INVALIDPARAMS, "Test %u: Got unexpected hr %#x.\n", i, hr);
13036 hr = IDirectDrawSurface7_Blt(surface, &test_data[i].dst_rect, NULL, NULL, DDBLT_WAIT, NULL);
13037 ok(hr == DDERR_INVALIDPARAMS, "Test %u: Got unexpected hr %#x.\n", i, hr);
13040 IDirectDrawSurface7_Release(surface);
13041 IDirectDrawSurface7_Release(rt);
13042 IDirectDraw7_Release(ddraw);
13043 refcount = IDirect3DDevice7_Release(device);
13044 ok(!refcount, "Device has %u references left.\n", refcount);
13045 DestroyWindow(window);
13048 static void test_blt_z_alpha(void)
13050 DWORD blt_flags[] =
13052 /* 0 */
13053 DDBLT_ALPHADEST,
13054 DDBLT_ALPHADESTCONSTOVERRIDE,
13055 DDBLT_ALPHADESTNEG,
13056 DDBLT_ALPHADESTSURFACEOVERRIDE,
13057 DDBLT_ALPHAEDGEBLEND,
13058 /* 5 */
13059 DDBLT_ALPHASRC,
13060 DDBLT_ALPHASRCCONSTOVERRIDE,
13061 DDBLT_ALPHASRCNEG,
13062 DDBLT_ALPHASRCSURFACEOVERRIDE,
13063 DDBLT_ZBUFFER,
13064 /* 10 */
13065 DDBLT_ZBUFFERDESTCONSTOVERRIDE,
13066 DDBLT_ZBUFFERDESTOVERRIDE,
13067 DDBLT_ZBUFFERSRCCONSTOVERRIDE,
13068 DDBLT_ZBUFFERSRCOVERRIDE,
13070 IDirectDrawSurface7 *src_surface, *dst_surface;
13071 DDSURFACEDESC2 surface_desc;
13072 IDirectDraw7 *ddraw;
13073 DDPIXELFORMAT pf;
13074 ULONG refcount;
13075 unsigned int i;
13076 D3DCOLOR color;
13077 HWND window;
13078 HRESULT hr;
13079 DDBLTFX fx;
13081 window = create_window();
13082 ddraw = create_ddraw();
13083 ok(!!ddraw, "Failed to create a ddraw object.\n");
13084 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
13085 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13087 memset(&pf, 0, sizeof(pf));
13088 pf.dwSize = sizeof(pf);
13089 pf.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
13090 U1(pf).dwRGBBitCount = 32;
13091 U2(pf).dwRBitMask = 0x00ff0000;
13092 U3(pf).dwGBitMask = 0x0000ff00;
13093 U4(pf).dwBBitMask = 0x000000ff;
13094 U5(pf).dwRGBAlphaBitMask = 0xff000000;
13096 memset(&surface_desc, 0, sizeof(surface_desc));
13097 surface_desc.dwSize = sizeof(surface_desc);
13098 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
13099 surface_desc.dwWidth = 64;
13100 surface_desc.dwHeight = 64;
13101 U4(surface_desc).ddpfPixelFormat = pf;
13102 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13104 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
13105 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
13106 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
13107 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
13109 memset(&fx, 0, sizeof(fx));
13110 fx.dwSize = sizeof(fx);
13111 fx.dwZBufferOpCode = D3DCMP_NEVER;
13112 fx.dwZDestConstBitDepth = 32;
13113 U1(fx).dwZDestConst = 0x11111111;
13114 fx.dwZSrcConstBitDepth = 32;
13115 U2(fx).dwZSrcConst = 0xeeeeeeee;
13116 fx.dwAlphaEdgeBlendBitDepth = 8;
13117 fx.dwAlphaEdgeBlend = 0x7f;
13118 fx.dwAlphaDestConstBitDepth = 8;
13119 U3(fx).dwAlphaDestConst = 0xdd;
13120 fx.dwAlphaSrcConstBitDepth = 8;
13121 U4(fx).dwAlphaSrcConst = 0x22;
13123 for (i = 0; i < ARRAY_SIZE(blt_flags); ++i)
13125 U5(fx).dwFillColor = 0x3300ff00;
13126 hr = IDirectDrawSurface7_Blt(src_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
13127 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
13129 U5(fx).dwFillColor = 0xccff0000;
13130 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
13131 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
13133 hr = IDirectDrawSurface7_Blt(dst_surface, NULL, src_surface, NULL, blt_flags[i] | DDBLT_WAIT, &fx);
13134 ok(SUCCEEDED(hr), "Test %u: Got unexpected hr %#x.\n", i, hr);
13136 color = get_surface_color(dst_surface, 32, 32);
13137 ok(compare_color(color, 0x0000ff00, 0), "Test %u: Got unexpected color 0x%08x.\n", i, color);
13140 IDirectDrawSurface7_Release(dst_surface);
13141 IDirectDrawSurface7_Release(src_surface);
13142 refcount = IDirectDraw7_Release(ddraw);
13143 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
13144 DestroyWindow(window);
13147 static void test_cross_device_blt(void)
13149 IDirectDrawSurface7 *surface, *surface2, *sysmem_surface;
13150 IDirect3DDevice7 *device, *device2;
13151 IDirectDraw7 *ddraw, *ddraw2;
13152 DDSURFACEDESC2 surface_desc;
13153 HWND window, window2;
13154 IDirect3D7 *d3d;
13155 ULONG refcount;
13156 D3DCOLOR color;
13157 DDBLTFX fx;
13158 HRESULT hr;
13160 window = create_window();
13161 if (!(device = create_device(window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
13163 skip("Failed to create a 3D device.\n");
13164 DestroyWindow(window);
13165 return;
13168 window2 = create_window();
13169 if (!(device2 = create_device(window2, DDSCL_NORMAL)))
13171 skip("Failed to create a 3D device.\n");
13172 IDirect3DDevice7_Release(device);
13173 DestroyWindow(window);
13174 DestroyWindow(window2);
13175 return;
13178 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
13179 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
13180 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
13181 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
13182 IDirect3D7_Release(d3d);
13184 hr = IDirect3DDevice7_GetDirect3D(device2, &d3d);
13185 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
13186 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw2);
13187 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
13188 IDirect3D7_Release(d3d);
13190 memset(&surface_desc, 0, sizeof(surface_desc));
13191 surface_desc.dwSize = sizeof(surface_desc);
13192 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
13193 surface_desc.dwWidth = 640;
13194 surface_desc.dwHeight = 480;
13195 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
13196 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &sysmem_surface, NULL);
13197 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13199 memset(&surface_desc, 0, sizeof(surface_desc));
13200 surface_desc.dwSize = sizeof(surface_desc);
13201 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
13202 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_VIDEOMEMORY;
13203 U5(surface_desc).dwBackBufferCount = 2;
13204 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
13205 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13207 memset(&surface_desc, 0, sizeof(surface_desc));
13208 surface_desc.dwSize = sizeof(surface_desc);
13209 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
13210 surface_desc.dwWidth = 640;
13211 surface_desc.dwHeight = 480;
13212 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
13213 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
13214 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
13215 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
13216 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00007c00;
13217 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x000003e0;
13218 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x0000001f;
13219 hr = IDirectDraw7_CreateSurface(ddraw2, &surface_desc, &surface2, NULL);
13220 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13222 memset(&fx, 0, sizeof(fx));
13223 fx.dwSize = sizeof(fx);
13224 U5(fx).dwFillColor = 0xff0000ff;
13225 hr = IDirectDrawSurface7_Blt(surface2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
13226 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
13228 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
13229 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
13230 hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT);
13231 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
13232 hr = IDirectDrawSurface7_Blt(surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
13233 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
13234 color = get_surface_color(surface, 320, 240);
13235 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
13237 hr = IDirectDrawSurface7_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
13238 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
13239 color = get_surface_color(sysmem_surface, 320, 240);
13240 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
13242 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
13243 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13244 hr = IDirectDrawSurface7_IsLost(sysmem_surface);
13245 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
13247 hr = IDirectDrawSurface7_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
13248 ok(hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
13249 color = get_surface_color(sysmem_surface, 320, 240);
13250 ok(color == 0x00000000, "Got unexpected color 0x%08x.\n", color);
13252 IDirectDrawSurface7_Release(surface2);
13253 memset(&surface_desc, 0, sizeof(surface_desc));
13254 surface_desc.dwSize = sizeof(surface_desc);
13255 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
13256 surface_desc.dwWidth = 640;
13257 surface_desc.dwHeight = 480;
13258 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
13259 hr = IDirectDraw7_CreateSurface(ddraw2, &surface_desc, &surface2, NULL);
13260 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
13261 hr = IDirectDrawSurface7_Blt(surface2, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
13262 ok(SUCCEEDED(hr), "Failed to fill surface, hr %#x.\n", hr);
13264 hr = IDirectDrawSurface7_Blt(sysmem_surface, NULL, surface2, NULL, DDBLT_WAIT, NULL);
13265 todo_wine ok(hr == D3D_OK, "Failed to blit, hr %#x.\n", hr);
13266 color = get_surface_color(sysmem_surface, 320, 240);
13267 todo_wine ok(compare_color(color, 0x000000ff, 1), "Got unexpected color 0x%08x.\n", color);
13269 IDirectDrawSurface7_Release(surface);
13270 IDirectDrawSurface7_Release(surface2);
13271 IDirectDrawSurface7_Release(sysmem_surface);
13272 IDirectDraw7_Release(ddraw);
13273 IDirectDraw7_Release(ddraw2);
13274 refcount = IDirect3DDevice7_Release(device);
13275 ok(!refcount, "Device has %u references left.\n", refcount);
13276 refcount = IDirect3DDevice7_Release(device2);
13277 ok(!refcount, "Device has %u references left.\n", refcount);
13278 DestroyWindow(window);
13279 DestroyWindow(window2);
13282 static void test_color_clamping(void)
13284 static D3DMATRIX mat =
13286 1.0f, 0.0f, 0.0f, 0.0f,
13287 0.0f, 1.0f, 0.0f, 0.0f,
13288 0.0f, 0.0f, 1.0f, 0.0f,
13289 0.0f, 0.0f, 0.0f, 1.0f,
13291 static struct vec3 quad[] =
13293 {-1.0f, -1.0f, 0.1f},
13294 {-1.0f, 1.0f, 0.1f},
13295 { 1.0f, -1.0f, 0.1f},
13296 { 1.0f, 1.0f, 0.1f},
13298 IDirect3DDevice7 *device;
13299 IDirectDrawSurface7 *rt;
13300 ULONG refcount;
13301 D3DCOLOR color;
13302 HWND window;
13303 HRESULT hr;
13305 window = create_window();
13306 if (!(device = create_device(window, DDSCL_NORMAL)))
13308 skip("Failed to create a 3D device, skipping test.\n");
13309 DestroyWindow(window);
13310 return;
13313 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
13314 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
13316 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
13317 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
13318 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
13319 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
13320 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
13321 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
13322 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
13323 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
13324 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
13325 ok(SUCCEEDED(hr), "Failed to disable Z test, hr %#x.\n", hr);
13326 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
13327 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
13328 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
13329 ok(SUCCEEDED(hr), "Failed to disable stencil test, hr %#x.\n", hr);
13330 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
13331 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
13332 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
13333 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
13335 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0xff404040);
13336 ok(SUCCEEDED(hr), "Failed to set texture factor, hr %#x.\n", hr);
13337 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_ADD);
13338 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
13339 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
13340 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
13341 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_SPECULAR);
13342 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
13343 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_MODULATE);
13344 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
13345 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TFACTOR);
13346 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
13347 hr = IDirect3DDevice7_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
13348 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
13350 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
13351 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13353 hr = IDirect3DDevice7_BeginScene(device);
13354 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
13356 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
13357 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13359 hr = IDirect3DDevice7_EndScene(device);
13360 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
13362 color = get_surface_color(rt, 320, 240);
13363 ok(compare_color(color, 0x00404040, 1), "Got unexpected color 0x%08x.\n", color);
13365 IDirectDrawSurface7_Release(rt);
13366 refcount = IDirect3DDevice7_Release(device);
13367 ok(!refcount, "Device has %u references left.\n", refcount);
13368 DestroyWindow(window);
13371 static void test_getdc(void)
13373 DDSCAPS2 caps = {DDSCAPS_COMPLEX, DDSCAPS2_CUBEMAP_NEGATIVEZ, 0, {0}};
13374 IDirectDrawSurface7 *surface, *surface2, *tmp;
13375 DDSURFACEDESC2 surface_desc, map_desc;
13376 IDirectDraw7 *ddraw;
13377 unsigned int i, screen_bpp;
13378 HWND window;
13379 HDC dc, dc2;
13380 HRESULT hr;
13382 static const struct
13384 const char *name;
13385 DDPIXELFORMAT format;
13386 BOOL getdc_supported;
13387 HRESULT alt_result;
13389 test_data[] =
13391 {"D3DFMT_A8R8G8B8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
13392 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}}, TRUE},
13393 {"D3DFMT_X8R8G8B8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
13394 {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}}, TRUE},
13395 {"D3DFMT_R5G6B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
13396 {0x0000f800}, {0x000007e0}, {0x0000001f}, {0x00000000}}, TRUE},
13397 {"D3DFMT_X1R5G5B5", {sizeof(test_data->format), DDPF_RGB, 0, {16},
13398 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00000000}}, TRUE},
13399 {"D3DFMT_A1R5G5B5", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
13400 {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00008000}}, TRUE},
13401 {"D3DFMT_A4R4G4B4", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {16},
13402 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x0000f000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
13403 {"D3DFMT_X4R4G4B4", {sizeof(test_data->format), DDPF_RGB, 0, {16},
13404 {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
13405 {"D3DFMT_A2R10G10B10", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
13406 {0xc0000000}, {0x3ff00000}, {0x000ffc00}, {0x000003ff}}, TRUE},
13407 {"D3DFMT_A8B8G8R8", {sizeof(test_data->format), DDPF_RGB | DDPF_ALPHAPIXELS, 0, {32},
13408 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0xff000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
13409 {"D3DFMT_X8B8G8R8", {sizeof(test_data->format), DDPF_RGB, 0, {32},
13410 {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}}, TRUE, DDERR_CANTCREATEDC /* Vista+ */},
13411 {"D3DFMT_R3G3B2", {sizeof(test_data->format), DDPF_RGB, 0, {8},
13412 {0x000000e0}, {0x0000001c}, {0x00000003}, {0x00000000}}, FALSE},
13413 /* GetDC() on a P8 surface fails unless the display mode is 8 bpp.
13414 * This is not implemented in wine yet, so disable the test for now.
13415 * Succeeding P8 GetDC() calls are tested in the ddraw:visual test.
13416 {"D3DFMT_P8", {sizeof(test_data->format), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0, {8 },
13417 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
13419 {"D3DFMT_L8", {sizeof(test_data->format), DDPF_LUMINANCE, 0, {8},
13420 {0x000000ff}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
13421 {"D3DFMT_A8L8", {sizeof(test_data->format), DDPF_ALPHAPIXELS | DDPF_LUMINANCE, 0, {16},
13422 {0x000000ff}, {0x00000000}, {0x00000000}, {0x0000ff00}}, FALSE},
13423 {"D3DFMT_DXT1", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','1'), {0},
13424 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
13425 {"D3DFMT_DXT2", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','2'), {0},
13426 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
13427 {"D3DFMT_DXT3", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','3'), {0},
13428 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
13429 {"D3DFMT_DXT4", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','4'), {0},
13430 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
13431 {"D3DFMT_DXT5", {sizeof(test_data->format), DDPF_FOURCC, MAKEFOURCC('D','X','T','5'), {0},
13432 {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}}, FALSE},
13435 window = create_window();
13436 ddraw = create_ddraw();
13437 ok(!!ddraw, "Failed to create a ddraw object.\n");
13438 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
13439 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
13441 surface_desc.dwSize = sizeof(surface_desc);
13442 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
13443 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr);
13444 screen_bpp = U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount;
13446 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
13448 memset(&surface_desc, 0, sizeof(surface_desc));
13449 surface_desc.dwSize = sizeof(surface_desc);
13450 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
13451 surface_desc.dwWidth = 64;
13452 surface_desc.dwHeight = 64;
13453 U4(surface_desc).ddpfPixelFormat = test_data[i].format;
13454 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
13456 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
13458 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
13459 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
13460 if (FAILED(hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
13462 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", test_data[i].name, hr);
13463 continue;
13467 dc = (void *)0x1234;
13468 hr = IDirectDrawSurface7_GetDC(surface, &dc);
13469 if (test_data[i].getdc_supported)
13470 ok(SUCCEEDED(hr) || broken(hr == test_data[i].alt_result),
13471 "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
13472 else
13473 ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
13475 if (SUCCEEDED(hr))
13477 unsigned int width_bytes;
13478 DIBSECTION dib;
13479 HBITMAP bitmap;
13480 DWORD type;
13481 int size;
13483 type = GetObjectType(dc);
13484 ok(type == OBJ_MEMDC, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
13485 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
13486 type = GetObjectType(bitmap);
13487 ok(type == OBJ_BITMAP, "Got unexpected object type %#x for format %s.\n", type, test_data[i].name);
13489 size = GetObjectA(bitmap, sizeof(dib), &dib);
13490 ok(size == sizeof(dib), "Got unexpected size %d for format %s.\n", size, test_data[i].name);
13491 ok(!dib.dsBm.bmType, "Got unexpected type %#x for format %s.\n",
13492 dib.dsBm.bmType, test_data[i].name);
13493 ok(dib.dsBm.bmWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
13494 dib.dsBm.bmWidth, test_data[i].name);
13495 ok(dib.dsBm.bmHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
13496 dib.dsBm.bmHeight, test_data[i].name);
13497 width_bytes = ((dib.dsBm.bmWidth * U1(test_data[i].format).dwRGBBitCount + 31) >> 3) & ~3;
13498 ok(dib.dsBm.bmWidthBytes == width_bytes, "Got unexpected width bytes %d for format %s.\n",
13499 dib.dsBm.bmWidthBytes, test_data[i].name);
13500 ok(dib.dsBm.bmPlanes == 1, "Got unexpected plane count %d for format %s.\n",
13501 dib.dsBm.bmPlanes, test_data[i].name);
13502 ok(dib.dsBm.bmBitsPixel == U1(test_data[i].format).dwRGBBitCount,
13503 "Got unexpected bit count %d for format %s.\n",
13504 dib.dsBm.bmBitsPixel, test_data[i].name);
13505 /* Windows XP sets bmBits == NULL for formats that match the screen at least on my r200 GPU. I
13506 * suspect this applies to all HW accelerated pre-WDDM drivers because they can handle gdi access
13507 * to ddraw surfaces themselves instead of going through a sysmem DIB section. */
13508 ok(!!dib.dsBm.bmBits || broken(!pDwmIsCompositionEnabled && dib.dsBm.bmBitsPixel == screen_bpp),
13509 "Got unexpected bits %p for format %s.\n", dib.dsBm.bmBits, test_data[i].name);
13511 ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "Got unexpected size %u for format %s.\n",
13512 dib.dsBmih.biSize, test_data[i].name);
13513 ok(dib.dsBmih.biWidth == surface_desc.dwWidth, "Got unexpected width %d for format %s.\n",
13514 dib.dsBmih.biHeight, test_data[i].name);
13515 ok(dib.dsBmih.biHeight == surface_desc.dwHeight, "Got unexpected height %d for format %s.\n",
13516 dib.dsBmih.biHeight, test_data[i].name);
13517 ok(dib.dsBmih.biPlanes == 1, "Got unexpected plane count %u for format %s.\n",
13518 dib.dsBmih.biPlanes, test_data[i].name);
13519 ok(dib.dsBmih.biBitCount == U1(test_data[i].format).dwRGBBitCount,
13520 "Got unexpected bit count %u for format %s.\n",
13521 dib.dsBmih.biBitCount, test_data[i].name);
13522 ok(dib.dsBmih.biCompression == (U1(test_data[i].format).dwRGBBitCount == 16 ? BI_BITFIELDS : BI_RGB)
13523 || broken(U1(test_data[i].format).dwRGBBitCount == 32 && dib.dsBmih.biCompression == BI_BITFIELDS),
13524 "Got unexpected compression %#x for format %s.\n",
13525 dib.dsBmih.biCompression, test_data[i].name);
13526 ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
13527 dib.dsBmih.biSizeImage, test_data[i].name);
13528 ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n",
13529 dib.dsBmih.biXPelsPerMeter, test_data[i].name);
13530 ok(!dib.dsBmih.biYPelsPerMeter, "Got unexpected vertical resolution %d for format %s.\n",
13531 dib.dsBmih.biYPelsPerMeter, test_data[i].name);
13532 ok(!dib.dsBmih.biClrUsed, "Got unexpected used colour count %u for format %s.\n",
13533 dib.dsBmih.biClrUsed, test_data[i].name);
13534 ok(!dib.dsBmih.biClrImportant, "Got unexpected important colour count %u for format %s.\n",
13535 dib.dsBmih.biClrImportant, test_data[i].name);
13537 if (dib.dsBmih.biCompression == BI_BITFIELDS)
13539 ok((dib.dsBitfields[0] == U2(test_data[i].format).dwRBitMask
13540 && dib.dsBitfields[1] == U3(test_data[i].format).dwGBitMask
13541 && dib.dsBitfields[2] == U4(test_data[i].format).dwBBitMask)
13542 || broken(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2]),
13543 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
13544 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
13546 else
13548 ok(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2],
13549 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
13550 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], test_data[i].name);
13552 ok(!dib.dshSection, "Got unexpected section %p for format %s.\n", dib.dshSection, test_data[i].name);
13553 ok(!dib.dsOffset, "Got unexpected offset %u for format %s.\n", dib.dsOffset, test_data[i].name);
13555 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
13556 ok(hr == DD_OK, "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13558 else
13560 ok(!dc, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
13563 IDirectDrawSurface7_Release(surface);
13565 if (FAILED(hr))
13566 continue;
13568 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
13569 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_TEXTUREMANAGE;
13570 if (FAILED(hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL)))
13572 skip("Failed to create cube texture for format %s (hr %#x), skipping tests.\n", test_data[i].name, hr);
13573 continue;
13576 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &surface2);
13577 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
13578 hr = IDirectDrawSurface7_GetAttachedSurface(surface2, &caps, &tmp);
13579 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
13580 IDirectDrawSurface7_Release(surface2);
13581 hr = IDirectDrawSurface7_GetAttachedSurface(tmp, &caps, &surface2);
13582 ok(SUCCEEDED(hr), "Failed to get attached surface for format %s, hr %#x.\n", test_data[i].name, hr);
13583 IDirectDrawSurface7_Release(tmp);
13585 hr = IDirectDrawSurface7_GetDC(surface, &dc);
13586 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
13587 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
13588 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13589 hr = IDirectDrawSurface7_GetDC(surface2, &dc);
13590 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
13591 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc);
13592 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13594 hr = IDirectDrawSurface7_GetDC(surface, &dc);
13595 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
13596 dc2 = (void *)0x1234;
13597 hr = IDirectDrawSurface7_GetDC(surface, &dc2);
13598 ok(hr == DDERR_DCALREADYCREATED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
13599 ok(dc2 == (void *)0x1234, "Got unexpected dc %p for format %s.\n", dc, test_data[i].name);
13600 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
13601 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13602 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
13603 ok(hr == DDERR_NODC, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
13605 map_desc.dwSize = sizeof(map_desc);
13606 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13607 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
13608 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13609 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
13610 hr = IDirectDrawSurface7_Unlock(surface, NULL);
13611 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
13612 hr = IDirectDrawSurface7_Unlock(surface, NULL);
13613 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
13615 hr = IDirectDrawSurface7_GetDC(surface, &dc);
13616 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
13617 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13618 ok(hr == DDERR_SURFACEBUSY, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
13619 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
13620 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13622 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13623 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
13624 hr = IDirectDrawSurface7_GetDC(surface, &dc);
13625 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
13626 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
13627 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13628 hr = IDirectDrawSurface7_Unlock(surface, NULL);
13629 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
13631 hr = IDirectDrawSurface7_GetDC(surface, &dc);
13632 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
13633 hr = IDirectDrawSurface7_GetDC(surface2, &dc2);
13634 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
13635 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc2);
13636 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13637 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
13638 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13640 hr = IDirectDrawSurface7_GetDC(surface2, &dc);
13641 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
13642 hr = IDirectDrawSurface7_GetDC(surface, &dc2);
13643 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
13644 hr = IDirectDrawSurface7_ReleaseDC(surface, dc2);
13645 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13646 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc);
13647 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13649 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13650 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
13651 hr = IDirectDrawSurface7_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13652 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
13653 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
13654 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
13655 hr = IDirectDrawSurface7_Unlock(surface, NULL);
13656 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
13658 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13659 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
13660 hr = IDirectDrawSurface7_GetDC(surface, &dc);
13661 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
13662 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
13663 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13664 hr = IDirectDrawSurface7_Unlock(surface, NULL);
13665 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
13667 hr = IDirectDrawSurface7_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13668 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
13669 hr = IDirectDrawSurface7_GetDC(surface, &dc);
13670 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
13671 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
13672 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13673 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
13674 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
13676 hr = IDirectDrawSurface7_GetDC(surface, &dc);
13677 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
13678 hr = IDirectDrawSurface7_Lock(surface2, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13679 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
13680 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
13681 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
13682 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
13683 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13685 hr = IDirectDrawSurface7_GetDC(surface2, &dc);
13686 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
13687 hr = IDirectDrawSurface7_Lock(surface, NULL, &map_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
13688 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", test_data[i].name, hr);
13689 hr = IDirectDrawSurface7_Unlock(surface, NULL);
13690 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", test_data[i].name, hr);
13691 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc);
13692 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13694 hr = IDirectDrawSurface7_Unlock(surface, NULL);
13695 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
13696 hr = IDirectDrawSurface7_GetDC(surface2, &dc);
13697 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
13698 hr = IDirectDrawSurface7_Unlock(surface, NULL);
13699 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
13700 hr = IDirectDrawSurface7_ReleaseDC(surface2, dc);
13701 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13702 hr = IDirectDrawSurface7_Unlock(surface, NULL);
13703 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
13705 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
13706 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
13707 hr = IDirectDrawSurface7_GetDC(surface, &dc);
13708 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", test_data[i].name, hr);
13709 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
13710 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
13711 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
13712 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", test_data[i].name, hr);
13713 hr = IDirectDrawSurface7_Unlock(surface2, NULL);
13714 ok(hr == DDERR_NOTLOCKED, "Got unexpected hr %#x for format %s.\n", hr, test_data[i].name);
13716 IDirectDrawSurface7_Release(surface2);
13717 IDirectDrawSurface7_Release(surface);
13720 IDirectDraw7_Release(ddraw);
13721 DestroyWindow(window);
13724 static void test_draw_primitive(void)
13726 static WORD indices[] = {0, 1, 2, 3};
13727 static struct vec3 quad[] =
13729 {-1.0f, -1.0f, 0.0f},
13730 {-1.0f, 1.0f, 0.0f},
13731 { 1.0f, -1.0f, 0.0f},
13732 { 1.0f, 1.0f, 0.0f},
13734 D3DDRAWPRIMITIVESTRIDEDDATA strided;
13735 D3DVERTEXBUFFERDESC vb_desc;
13736 IDirect3DVertexBuffer7 *vb;
13737 IDirect3DDevice7 *device;
13738 IDirect3D7 *d3d;
13739 IDirectDraw7 *ddraw;
13740 ULONG refcount;
13741 HWND window;
13742 HRESULT hr;
13743 void *data;
13745 window = create_window();
13746 if (!(device = create_device(window, DDSCL_NORMAL)))
13748 skip("Failed to create a 3D device, skipping test.\n");
13749 DestroyWindow(window);
13750 return;
13753 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
13754 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
13755 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
13756 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
13758 memset(&vb_desc, 0, sizeof(vb_desc));
13759 vb_desc.dwSize = sizeof(vb_desc);
13760 vb_desc.dwFVF = D3DFVF_XYZ;
13761 vb_desc.dwNumVertices = 4;
13762 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &vb, 0);
13763 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
13765 IDirect3D7_Release(d3d);
13767 memset(&strided, 0, sizeof(strided));
13769 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, NULL, 0, 0);
13770 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13771 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device,
13772 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, NULL, 0, 0);
13773 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13774 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, NULL, 0, 0);
13775 todo_wine ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
13776 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, NULL, 0, 0);
13777 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13778 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, 0);
13779 /* r200 rejects 0 vertices */
13780 ok(SUCCEEDED(hr) || broken(ddraw_is_amd(ddraw) && hr == E_FAIL), "Failed to draw, hr %#x.\n", hr);
13781 hr = IDirect3DDevice7_DrawPrimitiveStrided(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, 0);
13782 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13783 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, 0);
13784 ok(SUCCEEDED(hr) || broken(ddraw_is_amd(ddraw) && hr == E_FAIL), "Failed to draw, hr %#x.\n", hr);
13786 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, NULL, 0, indices, 4, 0);
13787 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13788 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device,
13789 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 0, indices, 4, 0);
13790 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13791 /* Interestingly r200 rejects this, but not the call with a NULL index buffer and 0 indices. */
13792 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 0, indices, 4, 0);
13793 ok(SUCCEEDED(hr) || broken(ddraw_is_amd(ddraw) && hr == E_FAIL), "Failed to draw, hr %#x.\n", hr);
13795 strided.position.lpvData = quad;
13796 strided.position.dwStride = sizeof(*quad);
13797 hr = IDirect3DVertexBuffer7_Lock(vb, 0, &data, NULL);
13798 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
13799 memcpy(data, quad, sizeof(quad));
13800 hr = IDirect3DVertexBuffer7_Unlock(vb);
13801 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
13803 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, NULL, 0, 0);
13804 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13805 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device,
13806 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, NULL, 0, 0);
13807 /* r200 again fails this, this time with E_OUTOFMEMORY. */
13808 ok(SUCCEEDED(hr) || broken(ddraw_is_amd(ddraw) && hr == E_OUTOFMEMORY), "Failed to draw, hr %#x.\n", hr);
13809 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, NULL, 0, 0);
13810 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13811 /* Now this draw should work, but r200 rejects it too - presumably earlier tests broke
13812 * driver internal state. */
13813 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
13814 ok(SUCCEEDED(hr) || broken(ddraw_is_amd(ddraw) && hr == E_FAIL), "Failed to draw, hr %#x.\n", hr);
13815 hr = IDirect3DDevice7_DrawPrimitiveStrided(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, 0);
13816 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13817 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, 0);
13818 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13820 hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, indices, 4, 0);
13821 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13822 hr = IDirect3DDevice7_DrawIndexedPrimitiveStrided(device,
13823 D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, &strided, 4, indices, 4, 0);
13824 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13825 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, indices, 4, 0);
13826 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13828 IDirect3DVertexBuffer7_Release(vb);
13829 IDirectDraw7_Release(ddraw);
13830 refcount = IDirect3DDevice7_Release(device);
13831 ok(!refcount, "Device has %u references left.\n", refcount);
13832 DestroyWindow(window);
13835 static void test_edge_antialiasing_blending(void)
13837 IDirectDrawSurface7 *offscreen;
13838 DDSURFACEDESC2 surface_desc;
13839 D3DDEVICEDESC7 device_desc;
13840 IDirect3DDevice7 *device;
13841 IDirectDraw7 *ddraw;
13842 IDirect3D7 *d3d;
13843 ULONG refcount;
13844 D3DCOLOR color;
13845 HWND window;
13846 HRESULT hr;
13848 static D3DMATRIX mat =
13850 1.0f, 0.0f, 0.0f, 0.0f,
13851 0.0f, 1.0f, 0.0f, 0.0f,
13852 0.0f, 0.0f, 1.0f, 0.0f,
13853 0.0f, 0.0f, 0.0f, 1.0f,
13855 static struct
13857 struct vec3 position;
13858 DWORD diffuse;
13860 green_quad[] =
13862 {{-1.0f, -1.0f, 0.1f}, 0x7f00ff00},
13863 {{-1.0f, 1.0f, 0.1f}, 0x7f00ff00},
13864 {{ 1.0f, -1.0f, 0.1f}, 0x7f00ff00},
13865 {{ 1.0f, 1.0f, 0.1f}, 0x7f00ff00},
13867 static struct
13869 struct vec3 position;
13870 DWORD diffuse;
13872 red_quad[] =
13874 {{-1.0f, -1.0f, 0.1f}, 0xccff0000},
13875 {{-1.0f, 1.0f, 0.1f}, 0xccff0000},
13876 {{ 1.0f, -1.0f, 0.1f}, 0xccff0000},
13877 {{ 1.0f, 1.0f, 0.1f}, 0xccff0000},
13880 window = create_window();
13881 if (!(device = create_device(window, DDSCL_NORMAL)))
13883 skip("Failed to create a 3D device.\n");
13884 DestroyWindow(window);
13885 return;
13888 hr = IDirect3DDevice7_GetCaps(device, &device_desc);
13889 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
13890 trace("Line edge antialiasing support: %#x.\n",
13891 device_desc.dpcLineCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
13892 trace("Triangle edge antialiasing support: %#x.\n",
13893 device_desc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES);
13895 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
13896 ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
13897 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
13898 ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
13899 IDirect3D7_Release(d3d);
13901 memset(&surface_desc, 0, sizeof(surface_desc));
13902 surface_desc.dwSize = sizeof(surface_desc);
13903 surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
13904 surface_desc.dwWidth = 640;
13905 surface_desc.dwHeight = 480;
13906 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
13907 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
13908 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
13909 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
13910 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
13911 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
13912 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
13913 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &offscreen, NULL);
13914 ok(hr == D3D_OK, "Creating the offscreen render target failed, hr %#x.\n", hr);
13916 hr = IDirect3DDevice7_SetRenderTarget(device, offscreen, 0);
13917 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
13919 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
13920 ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
13921 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
13922 ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
13923 hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
13924 ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
13925 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
13926 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
13927 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
13928 ok(SUCCEEDED(hr), "Failed to disable Z test, hr %#x.\n", hr);
13929 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
13930 ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
13931 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
13932 ok(SUCCEEDED(hr), "Failed to disable stencil test, hr %#x.\n", hr);
13933 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
13934 ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
13935 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
13936 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
13938 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
13939 ok(SUCCEEDED(hr), "Failed to enable blending, hr %#x.\n", hr);
13940 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
13941 ok(SUCCEEDED(hr), "Failed to set src blend, hr %#x.\n", hr);
13942 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_DESTALPHA);
13943 ok(SUCCEEDED(hr), "Failed to set dest blend, hr %#x.\n", hr);
13945 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
13946 ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
13947 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
13948 ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
13949 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
13950 ok(SUCCEEDED(hr), "Failed to set alpha op, hr %#x.\n", hr);
13951 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
13952 ok(SUCCEEDED(hr), "Failed to set alpha arg, hr %#x.\n", hr);
13954 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
13955 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13956 hr = IDirect3DDevice7_BeginScene(device);
13957 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
13958 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
13959 green_quad, 4, 0);
13960 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13961 hr = IDirect3DDevice7_EndScene(device);
13962 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
13963 color = get_surface_color(offscreen, 320, 240);
13964 ok(compare_color(color, 0x00cc7f00, 1), "Got unexpected color 0x%08x.\n", color);
13966 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
13967 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13968 hr = IDirect3DDevice7_BeginScene(device);
13969 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
13970 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
13971 red_quad, 4, 0);
13972 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13973 hr = IDirect3DDevice7_EndScene(device);
13974 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
13975 color = get_surface_color(offscreen, 320, 240);
13976 ok(compare_color(color, 0x00cc7f00, 1), "Got unexpected color 0x%08x.\n", color);
13978 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
13979 ok(SUCCEEDED(hr), "Failed to disable blending, hr %#x.\n", hr);
13981 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
13982 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13983 hr = IDirect3DDevice7_BeginScene(device);
13984 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
13985 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
13986 green_quad, 4, 0);
13987 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
13988 hr = IDirect3DDevice7_EndScene(device);
13989 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
13990 color = get_surface_color(offscreen, 320, 240);
13991 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
13993 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
13994 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
13995 hr = IDirect3DDevice7_BeginScene(device);
13996 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
13997 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
13998 red_quad, 4, 0);
13999 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14000 hr = IDirect3DDevice7_EndScene(device);
14001 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14002 color = get_surface_color(offscreen, 320, 240);
14003 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
14005 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_EDGEANTIALIAS, TRUE);
14006 ok(SUCCEEDED(hr), "Failed to enable edge antialiasing, hr %#x.\n", hr);
14008 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xccff0000, 0.0f, 0);
14009 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14010 hr = IDirect3DDevice7_BeginScene(device);
14011 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14012 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
14013 green_quad, 4, 0);
14014 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14015 hr = IDirect3DDevice7_EndScene(device);
14016 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14017 color = get_surface_color(offscreen, 320, 240);
14018 ok(compare_color(color, 0x0000ff00, 1), "Got unexpected color 0x%08x.\n", color);
14020 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x7f00ff00, 0.0f, 0);
14021 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
14022 hr = IDirect3DDevice7_BeginScene(device);
14023 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
14024 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE,
14025 red_quad, 4, 0);
14026 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
14027 hr = IDirect3DDevice7_EndScene(device);
14028 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
14029 color = get_surface_color(offscreen, 320, 240);
14030 ok(compare_color(color, 0x00ff0000, 1), "Got unexpected color 0x%08x.\n", color);
14032 IDirectDrawSurface7_Release(offscreen);
14033 IDirectDraw7_Release(ddraw);
14034 refcount = IDirect3DDevice7_Release(device);
14035 ok(!refcount, "Device has %u references left.\n", refcount);
14036 DestroyWindow(window);
14039 static void test_display_mode_surface_pixel_format(void)
14041 unsigned int width, height, bpp;
14042 IDirectDrawSurface7 *surface;
14043 DDSURFACEDESC2 surface_desc;
14044 IDirectDraw7 *ddraw;
14045 ULONG refcount;
14046 HWND window;
14047 HRESULT hr;
14049 if (!(ddraw = create_ddraw()))
14051 skip("Failed to create ddraw.\n");
14052 return;
14055 surface_desc.dwSize = sizeof(surface_desc);
14056 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
14057 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14058 width = surface_desc.dwWidth;
14059 height = surface_desc.dwHeight;
14061 window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
14062 0, 0, width, height, NULL, NULL, NULL, NULL);
14063 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
14064 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14066 bpp = 0;
14067 if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 16, 0, 0)))
14068 bpp = 16;
14069 if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 24, 0, 0)))
14070 bpp = 24;
14071 if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
14072 bpp = 32;
14073 ok(bpp, "Set display mode failed.\n");
14075 surface_desc.dwSize = sizeof(surface_desc);
14076 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
14077 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14078 ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width);
14079 ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height);
14080 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
14081 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
14083 memset(&surface_desc, 0, sizeof(surface_desc));
14084 surface_desc.dwSize = sizeof(surface_desc);
14085 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
14086 U5(surface_desc).dwBackBufferCount = 1;
14087 surface_desc.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE;
14088 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
14089 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14090 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
14091 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14092 ok(surface_desc.dwWidth == width, "Got width %u, expected %u.\n", surface_desc.dwWidth, width);
14093 ok(surface_desc.dwHeight == height, "Got height %u, expected %u.\n", surface_desc.dwHeight, height);
14094 ok(U4(surface_desc).ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n",
14095 U4(surface_desc).ddpfPixelFormat.dwFlags);
14096 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
14097 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
14098 IDirectDrawSurface7_Release(surface);
14100 memset(&surface_desc, 0, sizeof(surface_desc));
14101 surface_desc.dwSize = sizeof(surface_desc);
14102 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
14103 surface_desc.dwWidth = width;
14104 surface_desc.dwHeight = height;
14105 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
14106 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
14107 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14108 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
14109 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
14110 ok(U4(surface_desc).ddpfPixelFormat.dwFlags == DDPF_RGB, "Got unexpected pixel format flags %#x.\n",
14111 U4(surface_desc).ddpfPixelFormat.dwFlags);
14112 ok(U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount == bpp, "Got bpp %u, expected %u.\n",
14113 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount, bpp);
14114 IDirectDrawSurface7_Release(surface);
14116 /* Test compatibility mode mipmap texture creation. */
14117 hr = IDirectDraw7_SetDisplayMode(ddraw, width, height, 16, 0, 0);
14118 ok(hr == DD_OK || hr == E_NOTIMPL, "Got unexpected hr %#x.\n", hr);
14119 if (FAILED(hr))
14121 win_skip("SetDisplayMode failed, skipping test.");
14122 goto done;
14124 bpp = 16;
14126 memset(&surface_desc, 0, sizeof(surface_desc));
14127 surface_desc.dwSize = sizeof(surface_desc);
14128 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_MIPMAPCOUNT | DDSD_PITCH;
14129 U2(surface_desc).dwMipMapCount = 2;
14130 surface_desc.dwWidth = 4;
14131 surface_desc.dwHeight = 4;
14132 U1(surface_desc).lPitch = surface_desc.dwWidth * bpp / 8;
14133 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP | DDSCAPS_VIDEOMEMORY;
14134 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
14135 ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWHW, "Got unexpected hr %#x.\n", hr);
14136 if (surface)
14137 IDirectDrawSurface7_Release(surface);
14139 done:
14140 refcount = IDirectDraw7_Release(ddraw);
14141 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
14142 DestroyWindow(window);
14145 static void test_surface_desc_size(void)
14147 union
14149 DWORD dwSize;
14150 DDSURFACEDESC desc1;
14151 DDSURFACEDESC2 desc2;
14152 BYTE blob[1024];
14153 } desc;
14154 IDirectDrawSurface7 *surface7;
14155 IDirectDrawSurface3 *surface3;
14156 IDirectDrawSurface *surface;
14157 DDSURFACEDESC2 surface_desc;
14158 HRESULT expected_hr, hr;
14159 IDirectDraw7 *ddraw;
14160 unsigned int i, j;
14161 ULONG refcount;
14163 static const struct
14165 unsigned int caps;
14166 const char *name;
14168 surface_caps[] =
14170 {DDSCAPS_OFFSCREENPLAIN, "offscreenplain"},
14171 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, "systemmemory texture"},
14172 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, "videomemory texture"},
14174 static const unsigned int desc_sizes[] =
14176 sizeof(DDSURFACEDESC),
14177 sizeof(DDSURFACEDESC2),
14178 sizeof(DDSURFACEDESC) + 1,
14179 sizeof(DDSURFACEDESC2) + 1,
14180 2 * sizeof(DDSURFACEDESC),
14181 2 * sizeof(DDSURFACEDESC2),
14182 sizeof(DDSURFACEDESC) - 1,
14183 sizeof(DDSURFACEDESC2) - 1,
14184 sizeof(DDSURFACEDESC) / 2,
14185 sizeof(DDSURFACEDESC2) / 2,
14189 sizeof(desc) / 2,
14190 sizeof(desc) - 100,
14193 if (!(ddraw = create_ddraw()))
14195 skip("Failed to create ddraw.\n");
14196 return;
14198 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
14199 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
14201 for (i = 0; i < ARRAY_SIZE(surface_caps); ++i)
14203 memset(&surface_desc, 0, sizeof(surface_desc));
14204 surface_desc.dwSize = sizeof(surface_desc);
14205 surface_desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
14206 surface_desc.ddsCaps.dwCaps = surface_caps[i].caps;
14207 surface_desc.dwHeight = 128;
14208 surface_desc.dwWidth = 128;
14209 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface7, NULL)))
14211 skip("Failed to create surface, type %s.\n", surface_caps[i].name);
14212 continue;
14214 hr = IDirectDrawSurface_QueryInterface(surface7, &IID_IDirectDrawSurface, (void **)&surface);
14215 ok(hr == DD_OK, "Failed to query IDirectDrawSurface, hr %#x, type %s.\n", hr, surface_caps[i].name);
14216 hr = IDirectDrawSurface_QueryInterface(surface7, &IID_IDirectDrawSurface3, (void **)&surface3);
14217 ok(hr == DD_OK, "Failed to query IDirectDrawSurface3, hr %#x, type %s.\n", hr, surface_caps[i].name);
14219 /* GetSurfaceDesc() */
14220 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
14222 memset(&desc, 0, sizeof(desc));
14223 desc.dwSize = desc_sizes[j];
14224 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC) ? DD_OK : DDERR_INVALIDPARAMS;
14225 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &desc.desc1);
14226 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
14227 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
14229 memset(&desc, 0, sizeof(desc));
14230 desc.dwSize = desc_sizes[j];
14231 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC) ? DD_OK : DDERR_INVALIDPARAMS;
14232 hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &desc.desc1);
14233 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
14234 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
14236 memset(&desc, 0, sizeof(desc));
14237 desc.dwSize = desc_sizes[j];
14238 expected_hr = desc.dwSize == sizeof(DDSURFACEDESC2) ? DD_OK : DDERR_INVALIDPARAMS;
14239 hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &desc.desc2);
14240 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
14241 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
14244 /* Lock() */
14245 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
14247 const BOOL ignore_size = surface_caps[i].caps & DDSCAPS_TEXTURE
14248 && !(surface_caps[i].caps & DDSCAPS_VIDEOMEMORY);
14249 const BOOL valid_size = desc_sizes[j] == sizeof(DDSURFACEDESC)
14250 || desc_sizes[j] == sizeof(DDSURFACEDESC2);
14251 DWORD expected_texture_stage;
14253 memset(&desc, 0, sizeof(desc));
14254 desc.dwSize = desc_sizes[j];
14255 desc.desc2.dwTextureStage = 0xdeadbeef;
14256 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
14257 hr = IDirectDrawSurface_Lock(surface, NULL, &desc.desc1, 0, 0);
14258 expected_hr = ignore_size || valid_size ? DD_OK : DDERR_INVALIDPARAMS;
14259 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
14260 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
14261 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
14262 desc_sizes[j], desc.dwSize, surface_caps[i].name);
14263 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
14264 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
14265 if (SUCCEEDED(hr))
14267 ok(desc.desc1.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
14268 desc.desc1.dwWidth, desc_sizes[j], surface_caps[i].name);
14269 ok(desc.desc1.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
14270 desc.desc1.dwHeight, desc_sizes[j], surface_caps[i].name);
14271 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
14272 todo_wine_if(!expected_texture_stage)
14273 ok(desc.desc2.dwTextureStage == expected_texture_stage,
14274 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
14275 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
14276 IDirectDrawSurface_Unlock(surface, NULL);
14279 memset(&desc, 0, sizeof(desc));
14280 desc.dwSize = desc_sizes[j];
14281 desc.desc2.dwTextureStage = 0xdeadbeef;
14282 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
14283 hr = IDirectDrawSurface3_Lock(surface3, NULL, &desc.desc1, 0, 0);
14284 expected_hr = ignore_size || valid_size ? DD_OK : DDERR_INVALIDPARAMS;
14285 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
14286 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
14287 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
14288 desc_sizes[j], desc.dwSize, surface_caps[i].name);
14289 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
14290 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
14291 if (SUCCEEDED(hr))
14293 ok(desc.desc1.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
14294 desc.desc1.dwWidth, desc_sizes[j], surface_caps[i].name);
14295 ok(desc.desc1.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
14296 desc.desc1.dwHeight, desc_sizes[j], surface_caps[i].name);
14297 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
14298 todo_wine_if(!expected_texture_stage)
14299 ok(desc.desc2.dwTextureStage == expected_texture_stage,
14300 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
14301 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
14302 IDirectDrawSurface3_Unlock(surface3, NULL);
14305 memset(&desc, 0, sizeof(desc));
14306 desc.dwSize = desc_sizes[j];
14307 desc.desc2.dwTextureStage = 0xdeadbeef;
14308 desc.blob[sizeof(DDSURFACEDESC2)] = 0xef;
14309 hr = IDirectDrawSurface7_Lock(surface7, NULL, &desc.desc2, 0, 0);
14310 expected_hr = ignore_size || valid_size ? DD_OK : DDERR_INVALIDPARAMS;
14311 ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n",
14312 hr, expected_hr, desc_sizes[j], surface_caps[i].name);
14313 ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",
14314 desc_sizes[j], desc.dwSize, surface_caps[i].name);
14315 ok(desc.blob[sizeof(DDSURFACEDESC2)] == 0xef, "Got unexpected byte %02x, dwSize %u, type %s.\n",
14316 desc.blob[sizeof(DDSURFACEDESC2)], desc_sizes[j], surface_caps[i].name);
14317 if (SUCCEEDED(hr))
14319 ok(desc.desc2.dwWidth == 128, "Got unexpected width %u, dwSize %u, type %s.\n",
14320 desc.desc2.dwWidth, desc_sizes[j], surface_caps[i].name);
14321 ok(desc.desc2.dwHeight == 128, "Got unexpected height %u, dwSize %u, type %s.\n",
14322 desc.desc2.dwHeight, desc_sizes[j], surface_caps[i].name);
14323 expected_texture_stage = desc_sizes[j] >= sizeof(DDSURFACEDESC2) ? 0 : 0xdeadbeef;
14324 ok(desc.desc2.dwTextureStage == expected_texture_stage,
14325 "Got unexpected texture stage %#x, dwSize %u, type %s.\n",
14326 desc.desc2.dwTextureStage, desc_sizes[j], surface_caps[i].name);
14327 IDirectDrawSurface7_Unlock(surface7, NULL);
14331 IDirectDrawSurface7_Release(surface7);
14332 IDirectDrawSurface3_Release(surface3);
14333 IDirectDrawSurface_Release(surface);
14336 /* GetDisplayMode() */
14337 for (j = 0; j < ARRAY_SIZE(desc_sizes); ++j)
14339 memset(&desc, 0xcc, sizeof(desc));
14340 desc.dwSize = desc_sizes[j];
14341 expected_hr = (desc.dwSize == sizeof(DDSURFACEDESC) || desc.dwSize == sizeof(DDSURFACEDESC2))
14342 ? DD_OK : DDERR_INVALIDPARAMS;
14343 hr = IDirectDraw7_GetDisplayMode(ddraw, &desc.desc2);
14344 ok(hr == expected_hr, "Got hr %#x, expected %#x, size %u.\n", hr, expected_hr, desc_sizes[j]);
14345 if (SUCCEEDED(hr))
14347 ok(desc.dwSize == sizeof(DDSURFACEDESC2), "Wrong size %u for %u.\n", desc.dwSize, desc_sizes[j]);
14348 ok(desc.blob[desc_sizes[j]] == 0xcc, "Overflow for size %u.\n", desc_sizes[j]);
14349 ok(desc.blob[desc_sizes[j] - 1] != 0xcc, "Struct not cleared for size %u.\n", desc_sizes[j]);
14353 refcount = IDirectDraw7_Release(ddraw);
14354 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
14357 static void test_get_surface_from_dc(void)
14359 IDirectDrawSurface *surface1, *tmp1;
14360 IDirectDrawSurface7 *surface, *tmp;
14361 DDSURFACEDESC2 surface_desc;
14362 IDirectDraw7 *ddraw;
14363 HDC dc, device_dc;
14364 ULONG refcount;
14365 HWND window;
14366 HRESULT hr;
14367 DWORD ret;
14369 window = create_window();
14370 ddraw = create_ddraw();
14371 ok(!!ddraw, "Failed to create a ddraw object.\n");
14372 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
14373 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
14375 memset(&surface_desc, 0, sizeof(surface_desc));
14376 surface_desc.dwSize = sizeof(surface_desc);
14377 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
14378 surface_desc.dwWidth = 64;
14379 surface_desc.dwHeight = 64;
14380 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
14382 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
14383 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
14384 hr = IDirectDrawSurface7_QueryInterface(surface, &IID_IDirectDrawSurface, (void **)&surface1);
14385 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
14387 refcount = get_refcount((IUnknown *)surface1);
14388 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
14389 refcount = get_refcount((IUnknown *)surface);
14390 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
14392 hr = IDirectDrawSurface7_GetDC(surface, &dc);
14393 ok(SUCCEEDED(hr), "Failed to get DC, hr %#x.\n", hr);
14395 tmp1 = (void *)0xdeadbeef;
14396 device_dc = (void *)0xdeadbeef;
14397 hr = GetSurfaceFromDC(NULL, &tmp1, &device_dc);
14398 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
14399 ok(!tmp1, "Got unexpected surface %p.\n", tmp1);
14400 ok(!device_dc, "Got unexpected device_dc %p.\n", device_dc);
14402 device_dc = (void *)0xdeadbeef;
14403 hr = GetSurfaceFromDC(dc, NULL, &device_dc);
14404 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
14405 ok(device_dc == (void *)0xdeadbeef, "Got unexpected device_dc %p.\n", device_dc);
14407 tmp1 = (void *)0xdeadbeef;
14408 hr = GetSurfaceFromDC(dc, &tmp1, NULL);
14409 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
14410 ok(!tmp1, "Got unexpected surface %p.\n", tmp1);
14412 hr = GetSurfaceFromDC(dc, &tmp1, &device_dc);
14413 ok(SUCCEEDED(hr), "GetSurfaceFromDC failed, hr %#x.\n", hr);
14414 ok(tmp1 == surface1, "Got unexpected surface %p, expected %p.\n", tmp1, surface1);
14415 IDirectDrawSurface_Release(tmp1);
14417 ret = GetObjectType(device_dc);
14418 todo_wine ok(ret == OBJ_DC, "Got unexpected object type %#x.\n", ret);
14419 ret = GetDeviceCaps(device_dc, TECHNOLOGY);
14420 todo_wine ok(ret == DT_RASDISPLAY, "Got unexpected technology %#x.\n", ret);
14422 hr = IDirectDraw7_GetSurfaceFromDC(ddraw, dc, NULL);
14423 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
14425 hr = IDirectDraw7_GetSurfaceFromDC(ddraw, dc, &tmp);
14426 ok(SUCCEEDED(hr), "GetSurfaceFromDC failed, hr %#x.\n", hr);
14427 ok(tmp == surface, "Got unexpected surface %p, expected %p.\n", tmp, surface);
14429 refcount = get_refcount((IUnknown *)surface1);
14430 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
14431 refcount = get_refcount((IUnknown *)surface);
14432 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
14434 hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
14435 ok(SUCCEEDED(hr), "ReleaseDC failed, hr %#x.\n", hr);
14437 IDirectDrawSurface_Release(tmp);
14439 dc = CreateCompatibleDC(NULL);
14440 ok(!!dc, "CreateCompatibleDC failed.\n");
14442 tmp1 = (void *)0xdeadbeef;
14443 device_dc = (void *)0xdeadbeef;
14444 hr = GetSurfaceFromDC(dc, &tmp1, &device_dc);
14445 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
14446 ok(!tmp1, "Got unexpected surface %p.\n", tmp1);
14447 ok(!device_dc, "Got unexpected device_dc %p.\n", device_dc);
14449 tmp = (void *)0xdeadbeef;
14450 hr = IDirectDraw7_GetSurfaceFromDC(ddraw, dc, &tmp);
14451 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
14452 ok(!tmp, "Got unexpected surface %p.\n", tmp);
14454 ok(DeleteDC(dc), "DeleteDC failed.\n");
14456 tmp = (void *)0xdeadbeef;
14457 hr = IDirectDraw7_GetSurfaceFromDC(ddraw, NULL, &tmp);
14458 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
14459 ok(!tmp, "Got unexpected surface %p.\n", tmp);
14461 IDirectDrawSurface7_Release(surface);
14462 IDirectDrawSurface_Release(surface1);
14463 IDirectDraw7_Release(ddraw);
14464 DestroyWindow(window);
14467 static void test_ck_operation(void)
14469 IDirectDrawSurface7 *src, *dst;
14470 IDirectDrawSurface *src1, *dst1;
14471 DDSURFACEDESC2 surface_desc;
14472 IDirectDraw7 *ddraw;
14473 ULONG refcount;
14474 HWND window;
14475 HRESULT hr;
14476 D3DCOLOR *color;
14477 unsigned int i;
14478 DDCOLORKEY ckey;
14479 DDBLTFX fx;
14481 window = create_window();
14482 ddraw = create_ddraw();
14483 ok(!!ddraw, "Failed to create a ddraw object.\n");
14484 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
14485 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
14487 memset(&surface_desc, 0, sizeof(surface_desc));
14488 surface_desc.dwSize = sizeof(surface_desc);
14489 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
14490 surface_desc.dwWidth = 4;
14491 surface_desc.dwHeight = 1;
14492 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
14493 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
14494 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
14495 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
14496 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
14497 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
14498 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
14499 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
14501 surface_desc.dwFlags |= DDSD_CKSRCBLT;
14502 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff00ff;
14503 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff00ff;
14504 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
14505 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
14507 hr = IDirectDrawSurface7_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14508 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14509 ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n");
14510 color = surface_desc.lpSurface;
14511 color[0] = 0x77010203;
14512 color[1] = 0x00010203;
14513 color[2] = 0x77ff00ff;
14514 color[3] = 0x00ff00ff;
14515 hr = IDirectDrawSurface7_Unlock(src, NULL);
14516 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14518 for (i = 0; i < 2; ++i)
14520 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14521 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14522 color = surface_desc.lpSurface;
14523 color[0] = 0xcccccccc;
14524 color[1] = 0xcccccccc;
14525 color[2] = 0xcccccccc;
14526 color[3] = 0xcccccccc;
14527 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14528 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14530 if (i)
14532 hr = IDirectDrawSurface7_BltFast(dst, 0, 0, src, NULL, DDBLTFAST_SRCCOLORKEY);
14533 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14535 else
14537 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, NULL);
14538 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14541 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT | DDLOCK_READONLY, NULL);
14542 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14543 ok(!(surface_desc.dwFlags & DDSD_LPSURFACE), "Surface desc has LPSURFACE Flags set.\n");
14544 color = surface_desc.lpSurface;
14545 /* Different behavior on some drivers / windows versions. Some versions ignore the X channel when
14546 * color keying, but copy it to the destination surface. Others (sysmem surfaces) apply it for
14547 * color keying, but do not copy it into the destination surface. Nvidia neither uses it for
14548 * color keying nor copies it. */
14549 ok((color[0] == 0x77010203 && color[1] == 0x00010203
14550 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* AMD, Wine */
14551 || broken(color[0] == 0x00010203 && color[1] == 0x00010203
14552 && color[2] == 0x00ff00ff && color[3] == 0xcccccccc) /* Sysmem surfaces? */
14553 || broken(color[0] == 0x00010203 && color[1] == 0x00010203
14554 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Nvidia */
14555 || broken(color[0] == 0xff010203 && color[1] == 0xff010203
14556 && color[2] == 0xcccccccc && color[3] == 0xcccccccc) /* Testbot */,
14557 "Destination data after blitting is %08x %08x %08x %08x, i=%u.\n",
14558 color[0], color[1], color[2], color[3], i);
14559 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14560 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14563 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
14564 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
14565 ok(ckey.dwColorSpaceLowValue == 0x00ff00ff && ckey.dwColorSpaceHighValue == 0x00ff00ff,
14566 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
14568 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0x0000ff00;
14569 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
14570 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14572 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
14573 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
14574 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
14575 ok(ckey.dwColorSpaceLowValue == 0x0000ff00 && ckey.dwColorSpaceHighValue == 0x0000ff00,
14576 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
14578 surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0;
14579 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0;
14580 hr = IDirectDrawSurface7_GetSurfaceDesc(src, &surface_desc);
14581 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
14582 ok(surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue == 0x0000ff00
14583 && surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue == 0x0000ff00,
14584 "Got unexpected color key low=%08x high=%08x.\n", surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue,
14585 surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue);
14587 /* Test SetColorKey with dwColorSpaceHighValue < dwColorSpaceLowValue */
14588 ckey.dwColorSpaceLowValue = 0x000000ff;
14589 ckey.dwColorSpaceHighValue = 0x00000000;
14590 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
14591 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14593 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
14594 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
14595 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
14596 ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff,
14597 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
14599 ckey.dwColorSpaceLowValue = 0x000000ff;
14600 ckey.dwColorSpaceHighValue = 0x00000001;
14601 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
14602 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14604 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
14605 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
14606 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
14607 ok(ckey.dwColorSpaceLowValue == 0x000000ff && ckey.dwColorSpaceHighValue == 0x000000ff,
14608 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
14610 ckey.dwColorSpaceLowValue = 0x000000fe;
14611 ckey.dwColorSpaceHighValue = 0x000000fd;
14612 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
14613 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14615 ckey.dwColorSpaceLowValue = ckey.dwColorSpaceHighValue = 0;
14616 hr = IDirectDrawSurface7_GetColorKey(src, DDCKEY_SRCBLT, &ckey);
14617 ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
14618 ok(ckey.dwColorSpaceLowValue == 0x000000fe && ckey.dwColorSpaceHighValue == 0x000000fe,
14619 "Got unexpected color key low=%08x high=%08x.\n", ckey.dwColorSpaceLowValue, ckey.dwColorSpaceHighValue);
14621 IDirectDrawSurface7_Release(src);
14622 IDirectDrawSurface7_Release(dst);
14624 /* Test source and destination keys and where they are read from. Use a surface with alpha
14625 * to avoid driver-dependent content in the X channel. */
14626 memset(&surface_desc, 0, sizeof(surface_desc));
14627 surface_desc.dwSize = sizeof(surface_desc);
14628 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
14629 surface_desc.dwWidth = 6;
14630 surface_desc.dwHeight = 1;
14631 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
14632 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
14633 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
14634 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
14635 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
14636 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
14637 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
14638 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
14639 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
14640 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
14641 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
14643 ckey.dwColorSpaceLowValue = 0x0000ff00;
14644 ckey.dwColorSpaceHighValue = 0x0000ff00;
14645 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_SRCBLT, &ckey);
14646 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14647 ckey.dwColorSpaceLowValue = 0x00ff0000;
14648 ckey.dwColorSpaceHighValue = 0x00ff0000;
14649 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_DESTBLT, &ckey);
14650 ok(SUCCEEDED(hr) || hr == DDERR_NOCOLORKEYHW, "Failed to set color key, hr %#x.\n", hr);
14651 if (FAILED(hr))
14653 /* Nvidia reject dest keys, AMD allows them. This applies to vidmem and sysmem surfaces. */
14654 skip("Failed to set destination color key, skipping related tests.\n");
14655 goto done;
14658 ckey.dwColorSpaceLowValue = 0x000000ff;
14659 ckey.dwColorSpaceHighValue = 0x000000ff;
14660 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
14661 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14662 ckey.dwColorSpaceLowValue = 0x000000aa;
14663 ckey.dwColorSpaceHighValue = 0x000000aa;
14664 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_DESTBLT, &ckey);
14665 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14667 memset(&fx, 0, sizeof(fx));
14668 fx.dwSize = sizeof(fx);
14669 fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x00110000;
14670 fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x00110000;
14671 fx.ddckDestColorkey.dwColorSpaceHighValue = 0x00001100;
14672 fx.ddckDestColorkey.dwColorSpaceLowValue = 0x00001100;
14674 hr = IDirectDrawSurface7_Lock(src, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14675 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14676 color = surface_desc.lpSurface;
14677 color[0] = 0x000000ff; /* Applies to src blt key in src surface. */
14678 color[1] = 0x000000aa; /* Applies to dst blt key in src surface. */
14679 color[2] = 0x00ff0000; /* Dst color key in dst surface. */
14680 color[3] = 0x0000ff00; /* Src color key in dst surface. */
14681 color[4] = 0x00001100; /* Src color key in ddbltfx. */
14682 color[5] = 0x00110000; /* Dst color key in ddbltfx. */
14683 hr = IDirectDrawSurface7_Unlock(src, NULL);
14684 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14686 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14687 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14688 color = surface_desc.lpSurface;
14689 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
14690 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14691 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14693 /* Test a blit without keying. */
14694 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, 0, &fx);
14695 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14697 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14698 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14699 color = surface_desc.lpSurface;
14700 /* Should have copied src data unmodified to dst. */
14701 ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
14702 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
14703 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14704 color[0], color[1], color[2], color[3], color[4], color[5]);
14706 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
14707 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14708 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14710 /* Src key. */
14711 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx);
14712 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14714 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14715 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14716 color = surface_desc.lpSurface;
14717 /* Src key applied to color[0]. It is unmodified, the others are copied. */
14718 ok(color[0] == 0x55555555 && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
14719 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
14720 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14721 color[0], color[1], color[2], color[3], color[4], color[5]);
14723 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
14724 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14725 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14727 /* Src override. */
14728 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, &fx);
14729 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14731 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14732 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14733 color = surface_desc.lpSurface;
14734 /* Override key applied to color[5]. It is unmodified, the others are copied. */
14735 ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
14736 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x55555555,
14737 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14738 color[0], color[1], color[2], color[3], color[4], color[5]);
14740 color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0x55555555;
14741 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14742 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14744 /* Src override AND src key. That is not supposed to work. */
14745 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE, &fx);
14746 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14748 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14749 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14750 color = surface_desc.lpSurface;
14751 /* Ensure the destination was not changed. */
14752 ok(color[0] == 0x55555555 && color[1] == 0x55555555 && color[2] == 0x55555555 &&
14753 color[3] == 0x55555555 && color[4] == 0x55555555 && color[5] == 0x55555555,
14754 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14755 color[0], color[1], color[2], color[3], color[4], color[5]);
14757 /* Use different dst colors for the dst key test. */
14758 color[0] = 0x00ff0000; /* Dest key in dst surface. */
14759 color[1] = 0x00ff0000; /* Dest key in dst surface. */
14760 color[2] = 0x00001100; /* Dest key in override. */
14761 color[3] = 0x00001100; /* Dest key in override. */
14762 color[4] = 0x000000aa; /* Dest key in src surface. */
14763 color[5] = 0x000000aa; /* Dest key in src surface. */
14764 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14765 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14767 /* Dest key blit. The key is taken from the DESTINATION surface in v7! */
14768 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
14769 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14771 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14772 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14773 color = surface_desc.lpSurface;
14774 /* Dst key applied to color[0,1], they are the only changed pixels. */
14775 todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 &&
14776 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
14777 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14778 color[0], color[1], color[2], color[3], color[4], color[5]);
14780 color[0] = 0x00ff0000; /* Dest key in dst surface. */
14781 color[1] = 0x00ff0000; /* Dest key in dst surface. */
14782 color[2] = 0x00001100; /* Dest key in override. */
14783 color[3] = 0x00001100; /* Dest key in override. */
14784 color[4] = 0x000000aa; /* Dest key in src surface. */
14785 color[5] = 0x000000aa; /* Dest key in src surface. */
14786 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14787 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14789 /* What happens with a QI'd older version of the interface? It takes the key
14790 * from the source surface. */
14791 hr = IDirectDrawSurface7_QueryInterface(src, &IID_IDirectDrawSurface, (void **)&src1);
14792 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
14793 hr = IDirectDrawSurface7_QueryInterface(dst, &IID_IDirectDrawSurface, (void **)&dst1);
14794 ok(SUCCEEDED(hr), "Failed to query IDirectDrawSurface interface, hr %#x.\n", hr);
14796 hr = IDirectDrawSurface_Blt(dst1, NULL, src1, NULL, DDBLT_KEYDEST, &fx);
14797 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14799 IDirectDrawSurface_Release(dst1);
14800 IDirectDrawSurface_Release(src1);
14802 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14803 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14804 color = surface_desc.lpSurface;
14805 /* Dst key applied to color[4,5], they are the only changed pixels. */
14806 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
14807 color[3] == 0x00001100 && color[4] == 0x00001100 && color[5] == 0x00110000,
14808 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14809 color[0], color[1], color[2], color[3], color[4], color[5]);
14811 color[0] = 0x00ff0000; /* Dest key in dst surface. */
14812 color[1] = 0x00ff0000; /* Dest key in dst surface. */
14813 color[2] = 0x00001100; /* Dest key in override. */
14814 color[3] = 0x00001100; /* Dest key in override. */
14815 color[4] = 0x000000aa; /* Dest key in src surface. */
14816 color[5] = 0x000000aa; /* Dest key in src surface. */
14817 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14818 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14820 /* Dest override key blit. */
14821 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, &fx);
14822 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14824 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14825 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14826 color = surface_desc.lpSurface;
14827 /* Dst key applied to color[2,3], they are the only changed pixels. */
14828 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00ff0000 &&
14829 color[3] == 0x0000ff00 && color[4] == 0x000000aa && color[5] == 0x000000aa,
14830 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14831 color[0], color[1], color[2], color[3], color[4], color[5]);
14833 color[0] = 0x00ff0000; /* Dest key in dst surface. */
14834 color[1] = 0x00ff0000; /* Dest key in dst surface. */
14835 color[2] = 0x00001100; /* Dest key in override. */
14836 color[3] = 0x00001100; /* Dest key in override. */
14837 color[4] = 0x000000aa; /* Dest key in src surface. */
14838 color[5] = 0x000000aa; /* Dest key in src surface. */
14839 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14840 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14842 /* Dest override together with surface key. Supposed to fail. */
14843 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYDESTOVERRIDE, &fx);
14844 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14846 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14847 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14848 color = surface_desc.lpSurface;
14849 /* Destination is unchanged. */
14850 ok(color[0] == 0x00ff0000 && color[1] == 0x00ff0000 && color[2] == 0x00001100 &&
14851 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
14852 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14853 color[0], color[1], color[2], color[3], color[4], color[5]);
14854 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14855 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14857 /* Source and destination key. This is driver dependent. New HW treats it like
14858 * DDBLT_KEYSRC. Older HW and some software renderers apply both keys. */
14859 if (0)
14861 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST | DDBLT_KEYSRC, &fx);
14862 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14864 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14865 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14866 color = surface_desc.lpSurface;
14867 /* Color[0] is filtered by the src key, 2-5 are filtered by the dst key, if
14868 * the driver applies it. */
14869 ok(color[0] == 0x00ff0000 && color[1] == 0x000000aa && color[2] == 0x00ff0000 &&
14870 color[3] == 0x0000ff00 && color[4] == 0x00001100 && color[5] == 0x00110000,
14871 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14872 color[0], color[1], color[2], color[3], color[4], color[5]);
14874 color[0] = 0x00ff0000; /* Dest key in dst surface. */
14875 color[1] = 0x00ff0000; /* Dest key in dst surface. */
14876 color[2] = 0x00001100; /* Dest key in override. */
14877 color[3] = 0x00001100; /* Dest key in override. */
14878 color[4] = 0x000000aa; /* Dest key in src surface. */
14879 color[5] = 0x000000aa; /* Dest key in src surface. */
14880 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14881 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14884 /* Override keys without ddbltfx parameter fail */
14885 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDESTOVERRIDE, NULL);
14886 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14887 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRCOVERRIDE, NULL);
14888 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14890 /* Try blitting without keys in the source surface. */
14891 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, NULL);
14892 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14893 hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_DESTBLT, NULL);
14894 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14896 /* That fails now. Do not bother to check that the data is unmodified. */
14897 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC, &fx);
14898 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14900 /* Dest key blit still works, the destination surface key is used in v7. */
14901 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
14902 ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
14904 hr = IDirectDrawSurface7_Lock(dst, NULL, &surface_desc, DDLOCK_WAIT, NULL);
14905 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
14906 color = surface_desc.lpSurface;
14907 /* Dst key applied to color[0,1], they are the only changed pixels. */
14908 todo_wine ok(color[0] == 0x000000ff && color[1] == 0x000000aa && color[2] == 0x00001100 &&
14909 color[3] == 0x00001100 && color[4] == 0x000000aa && color[5] == 0x000000aa,
14910 "Got unexpected content %08x %08x %08x %08x %08x %08x.\n",
14911 color[0], color[1], color[2], color[3], color[4], color[5]);
14912 hr = IDirectDrawSurface7_Unlock(dst, NULL);
14913 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
14915 /* Try blitting without keys in the destination surface. */
14916 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_SRCBLT, NULL);
14917 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14918 hr = IDirectDrawSurface7_SetColorKey(dst, DDCKEY_DESTBLT, NULL);
14919 ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
14921 /* This fails, as sanity would dictate. */
14922 hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYDEST, &fx);
14923 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
14925 done:
14926 IDirectDrawSurface7_Release(src);
14927 IDirectDrawSurface7_Release(dst);
14928 refcount = IDirectDraw7_Release(ddraw);
14929 ok(!refcount, "DirectDraw has %u references left.\n", refcount);
14930 DestroyWindow(window);
14933 static void test_vb_refcount(void)
14935 ULONG prev_d3d_refcount, prev_device_refcount;
14936 ULONG cur_d3d_refcount, cur_device_refcount;
14937 IDirect3DVertexBuffer7 *vb, *vb7;
14938 D3DVERTEXBUFFERDESC vb_desc;
14939 IDirect3DVertexBuffer *vb1;
14940 IDirect3DDevice7 *device;
14941 IDirect3D7 *d3d;
14942 ULONG refcount;
14943 IUnknown *unk;
14944 HWND window;
14945 HRESULT hr;
14947 window = create_window();
14948 if (!(device = create_device(window, DDSCL_NORMAL)))
14950 skip("Failed to create a 3D device, skipping test.\n");
14951 DestroyWindow(window);
14952 return;
14955 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
14956 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
14958 prev_d3d_refcount = get_refcount((IUnknown *)d3d);
14959 prev_device_refcount = get_refcount((IUnknown *)device);
14961 memset(&vb_desc, 0, sizeof(vb_desc));
14962 vb_desc.dwSize = sizeof(vb_desc);
14963 vb_desc.dwFVF = D3DFVF_XYZ;
14964 vb_desc.dwNumVertices = 4;
14965 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &vb, 0);
14966 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
14968 cur_d3d_refcount = get_refcount((IUnknown *)d3d);
14969 cur_device_refcount = get_refcount((IUnknown *)device);
14970 ok(cur_d3d_refcount > prev_d3d_refcount, "D3D object refcount didn't change from %u.\n", prev_d3d_refcount);
14971 ok(cur_device_refcount == prev_device_refcount, "Device refcount changed from %u to %u.\n",
14972 prev_device_refcount, cur_device_refcount);
14974 prev_d3d_refcount = cur_d3d_refcount;
14975 hr = IDirect3DVertexBuffer7_QueryInterface(vb, &IID_IDirect3DVertexBuffer7, (void **)&vb7);
14976 ok(hr == DD_OK, "Failed to query IDirect3DVertexBuffer7, hr %#x.\n", hr);
14977 cur_d3d_refcount = get_refcount((IUnknown *)d3d);
14978 ok(cur_d3d_refcount == prev_d3d_refcount, "D3D object refcount changed from %u to %u.\n",
14979 prev_d3d_refcount, cur_d3d_refcount);
14980 IDirect3DVertexBuffer7_Release(vb7);
14982 hr = IDirect3DVertexBuffer7_QueryInterface(vb, &IID_IDirect3DVertexBuffer, (void **)&vb1);
14983 ok(hr == E_NOINTERFACE, "Querying IDirect3DVertexBuffer returned unexpected hr %#x.\n", hr);
14985 hr = IDirect3DVertexBuffer_QueryInterface(vb, &IID_IUnknown, (void **)&unk);
14986 ok(hr == DD_OK, "Failed to query IUnknown, hr %#x.\n", hr);
14987 ok((IUnknown *)vb == unk,
14988 "IDirect3DVertexBuffer7 and IUnknown interface pointers don't match, %p != %p.\n", vb, unk);
14989 IUnknown_Release(unk);
14991 refcount = IDirect3DVertexBuffer7_Release(vb);
14992 ok(!refcount, "Vertex buffer has %u references left.\n", refcount);
14994 IDirect3D7_Release(d3d);
14995 refcount = IDirect3DDevice7_Release(device);
14996 ok(!refcount, "Device has %u references left.\n", refcount);
14997 DestroyWindow(window);
15000 static void test_compute_sphere_visibility(void)
15002 static D3DVALUE clip_plane[4] = {1.0f, 0.0f, 0.0f, 0.5f};
15003 static D3DMATRIX proj_1 =
15005 1.810660f, 0.000000f, 0.000000f, 0.000000f,
15006 0.000000f, 2.414213f, 0.000000f, 0.000000f,
15007 0.000000f, 0.000000f, 1.020408f, 1.000000f,
15008 0.000000f, 0.000000f, -0.102041f, 0.000000f,
15010 static D3DMATRIX proj_2 =
15012 10.0f, 0.0f, 0.0f, 0.0f,
15013 0.0f, 10.0f, 0.0f, 0.0f,
15014 0.0f, 0.0f, 10.0f, 0.0f,
15015 0.0f, 0.0f, 0.0f, 1.0f,
15017 static D3DMATRIX view_1 =
15019 1.000000f, 0.000000f, 0.000000f, 0.000000f,
15020 0.000000f, 0.768221f, -0.640185f, 0.000000f,
15021 -0.000000f, 0.640185f, 0.768221f, 0.000000f,
15022 -14.852037f, 9.857489f, 11.600972f, 1.000000f,
15024 static D3DMATRIX identity =
15026 1.0f, 0.0f, 0.0f, 0.0f,
15027 0.0f, 1.0f, 0.0f, 0.0f,
15028 0.0f, 0.0f, 1.0f, 0.0f,
15029 0.0f, 0.0f, 0.0f, 1.0f,
15031 static struct
15033 D3DMATRIX *view, *proj;
15034 unsigned int sphere_count;
15035 D3DVECTOR center[3];
15036 D3DVALUE radius[3];
15037 DWORD enable_planes;
15038 const DWORD expected[3];
15040 tests[] =
15042 {&view_1, &proj_1, 1, {{{11.461533f}, {-4.761727f}, {-1.171646f}}}, {38.252632f}, 0, {0x3f}},
15043 {&view_1, &proj_1, 3, {{{-3.515620f}, {-1.560661f}, {-12.464638f}},
15044 {{14.290396f}, {-2.981143f}, {-24.311312f}},
15045 {{1.461626f}, {-6.093709f}, {-13.901010f}}},
15046 {4.354097f, 12.500704f, 17.251318f}, 0, {0x103d, 0x3f, 0x3f}},
15047 {&identity, &proj_2, 1, {{{0.0f}, {0.0f}, {0.05f}}}, {0.04f}, 0, {0}},
15048 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.5f}}}, {0.5f}, 0, {0}},
15049 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.0f}}}, {0.0f}, 0, {0}},
15050 {&identity, &identity, 1, {{{-1.0f}, {-1.0f}, {0.5f}}}, {0.25f}, 0, {0x9}}, /* 5 */
15051 {&identity, &identity, 1, {{{-20.0f}, {0.0f}, {0.5f}}}, {3.0f}, 0, {0x103d}},
15052 {&identity, &identity, 1, {{{20.0f}, {0.0f}, {0.5f}}}, {3.0f}, 0, {0x203e}},
15053 {&identity, &identity, 1, {{{0.0f}, {-20.0f}, {0.5f}}}, {3.0f}, 0, {0x803b}},
15054 {&identity, &identity, 1, {{{0.0f}, {20.0f}, {0.5f}}}, {3.0f}, 0, {0x4037}},
15055 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {-20.0f}}}, {3.0f}, 0, {0x1001f}}, /* 10 */
15056 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {20.0f}}}, {3.0f}, 0, {0x2002f}},
15057 {&identity, &identity, 1, {{{0.0f}, {0.0f}, {0.0f}}}, {5.0f}, 1, {0x7f}},
15058 {&identity, &identity, 1, {{{-0.5f}, {0.0f}, {0.0f}}}, {5.0f}, 1, {0x7f}},
15059 {&identity, &identity, 1, {{{-0.5f}, {0.0f}, {0.0f}}}, {1.0f}, 1, {0x51}},
15060 {&identity, &identity, 1, {{{-2.5f}, {0.0f}, {0.0f}}}, {1.0f}, 1, {0x41051}}, /* 15 */
15062 IDirect3DDevice7 *device;
15063 unsigned int i, j;
15064 DWORD result[3];
15065 ULONG refcount;
15066 HWND window;
15067 HRESULT hr;
15069 window = create_window();
15070 if (!(device = create_device(window, DDSCL_NORMAL)))
15072 skip("Failed to create a 3D device, skipping test.\n");
15073 DestroyWindow(window);
15074 return;
15077 hr = IDirect3DDevice7_SetClipPlane(device, 0, clip_plane);
15078 ok(SUCCEEDED(hr), "Failed to set user clip plane, hr %#x.\n", hr);
15080 IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &identity);
15082 for (i = 0; i < ARRAY_SIZE(tests); ++i)
15084 IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, tests[i].view);
15085 IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, tests[i].proj);
15087 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE,
15088 tests[i].enable_planes);
15089 ok(SUCCEEDED(hr), "Failed to enable / disable user clip planes, hr %#x.\n", hr);
15091 hr = IDirect3DDevice7_ComputeSphereVisibility(device, tests[i].center, tests[i].radius,
15092 tests[i].sphere_count, 0, result);
15093 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
15095 for (j = 0; j < tests[i].sphere_count; ++j)
15096 ok(result[j] == tests[i].expected[j], "Test %u sphere %u: expected %#x, got %#x.\n",
15097 i, j, tests[i].expected[j], result[j]);
15100 refcount = IDirect3DDevice7_Release(device);
15101 ok(!refcount, "Device has %u references left.\n", refcount);
15102 DestroyWindow(window);
15105 static void test_clip_planes_limits(void)
15107 IDirect3DDevice7 *device;
15108 D3DDEVICEDESC7 caps;
15109 unsigned int i;
15110 ULONG refcount;
15111 float plane[4];
15112 HWND window;
15113 DWORD state;
15114 HRESULT hr;
15116 window = create_window();
15117 if (!(device = create_device(window, DDSCL_NORMAL)))
15119 skip("Failed to create 3D device.\n");
15120 DestroyWindow(window);
15121 return;
15124 memset(&caps, 0, sizeof(caps));
15125 hr = IDirect3DDevice7_GetCaps(device, &caps);
15126 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
15128 trace("Max user clip planes: %u.\n", caps.wMaxUserClipPlanes);
15130 for (i = 0; i < caps.wMaxUserClipPlanes; ++i)
15132 memset(plane, 0xff, sizeof(plane));
15133 hr = IDirect3DDevice7_GetClipPlane(device, i, plane);
15134 ok(hr == D3D_OK, "Failed to get clip plane %u, hr %#x.\n", i, hr);
15135 ok(!plane[0] && !plane[1] && !plane[2] && !plane[3],
15136 "Got unexpected plane %u: %.8e, %.8e, %.8e, %.8e.\n",
15137 i, plane[0], plane[1], plane[2], plane[3]);
15140 plane[0] = 2.0f;
15141 plane[1] = 8.0f;
15142 plane[2] = 5.0f;
15143 for (i = 0; i < caps.wMaxUserClipPlanes; ++i)
15145 plane[3] = i;
15146 hr = IDirect3DDevice7_SetClipPlane(device, i, plane);
15147 ok(hr == D3D_OK, "Failed to set clip plane %u, hr %#x.\n", i, hr);
15149 for (i = 0; i < caps.wMaxUserClipPlanes; ++i)
15151 memset(plane, 0xff, sizeof(plane));
15152 hr = IDirect3DDevice7_GetClipPlane(device, i, plane);
15153 ok(hr == D3D_OK, "Failed to get clip plane %u, hr %#x.\n", i, hr);
15154 ok(plane[0] == 2.0f && plane[1] == 8.0f && plane[2] == 5.0f && plane[3] == i,
15155 "Got unexpected plane %u: %.8e, %.8e, %.8e, %.8e.\n",
15156 i, plane[0], plane[1], plane[2], plane[3]);
15159 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE, 0xffffffff);
15160 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
15161 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE, &state);
15162 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
15163 ok(state == 0xffffffff, "Got unexpected state %#x.\n", state);
15164 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE, 0x80000000);
15165 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
15166 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_CLIPPLANEENABLE, &state);
15167 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
15168 ok(state == 0x80000000, "Got unexpected state %#x.\n", state);
15170 refcount = IDirect3DDevice7_Release(device);
15171 ok(!refcount, "Device has %u references left.\n", refcount);
15172 DestroyWindow(window);
15175 static void test_texture_stages_limits(void)
15177 IDirectDrawSurface7 *texture;
15178 DDSURFACEDESC2 surface_desc;
15179 IDirect3DDevice7 *device;
15180 IDirectDraw7 *ddraw;
15181 IDirect3D7 *d3d;
15182 unsigned int i;
15183 ULONG refcount;
15184 HWND window;
15185 HRESULT hr;
15187 window = create_window();
15188 if (!(device = create_device(window, DDSCL_NORMAL)))
15190 skip("Failed to create 3D device.\n");
15191 DestroyWindow(window);
15192 return;
15194 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
15195 ok(SUCCEEDED(hr), "Failed to get Direct3D interface, hr %#x.\n", hr);
15196 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
15197 ok(SUCCEEDED(hr), "Failed to get DirectDraw interface, hr %#x.\n", hr);
15198 IDirect3D7_Release(d3d);
15200 memset(&surface_desc, 0, sizeof(surface_desc));
15201 surface_desc.dwSize = sizeof(surface_desc);
15202 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
15203 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
15204 surface_desc.dwWidth = 16;
15205 surface_desc.dwHeight = 16;
15206 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
15207 ok(hr == DD_OK, "Failed to create surface, hr %#x.\n", hr);
15209 for (i = 0; i < 8; ++i)
15211 hr = IDirect3DDevice7_SetTexture(device, i, texture);
15212 ok(hr == D3D_OK, "Failed to set texture %u, hr %#x.\n", i, hr);
15213 hr = IDirect3DDevice7_SetTexture(device, i, NULL);
15214 ok(hr == D3D_OK, "Failed to set texture %u, hr %#x.\n", i, hr);
15215 hr = IDirect3DDevice7_SetTextureStageState(device, i, D3DTSS_COLOROP, D3DTOP_ADD);
15216 ok(hr == D3D_OK, "Failed to set texture stage state %u, hr %#x.\n", i, hr);
15219 IDirectDrawSurface7_Release(texture);
15220 IDirectDraw7_Release(ddraw);
15221 refcount = IDirect3DDevice7_Release(device);
15222 ok(!refcount, "Device has %u references left.\n", refcount);
15223 DestroyWindow(window);
15226 static void test_set_render_state(void)
15228 IDirect3DDevice7 *device;
15229 ULONG refcount;
15230 HWND window;
15231 DWORD state;
15232 HRESULT hr;
15234 window = create_window();
15235 if (!(device = create_device(window, DDSCL_NORMAL)))
15237 skip("Failed to create 3D device.\n");
15238 DestroyWindow(window);
15239 return;
15242 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZVISIBLE, TRUE);
15243 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
15244 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZVISIBLE, FALSE);
15245 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
15247 /* States deprecated in D3D7 */
15248 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
15249 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
15250 state = 0xdeadbeef;
15251 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, &state);
15252 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
15253 ok(state == 0xdeadbeef, "Got unexpected render state %#x.\n", state);
15254 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
15255 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
15256 state = 0xdeadbeef;
15257 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, &state);
15258 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
15259 ok(state == 0xdeadbeef, "Got unexpected render state %#x.\n", state);
15261 refcount = IDirect3DDevice7_Release(device);
15262 ok(!refcount, "Device has %u references left.\n", refcount);
15263 DestroyWindow(window);
15266 static void test_map_synchronisation(void)
15268 LARGE_INTEGER frequency, diff, ts[3];
15269 IDirect3DVertexBuffer7 *buffer;
15270 unsigned int i, j, tri_count;
15271 D3DVERTEXBUFFERDESC vb_desc;
15272 IDirect3DDevice7 *device;
15273 BOOL unsynchronised, ret;
15274 IDirectDrawSurface7 *rt;
15275 IDirectDraw7 *ddraw;
15276 IDirect3D7 *d3d;
15277 D3DCOLOR colour;
15278 ULONG refcount;
15279 HWND window;
15280 HRESULT hr;
15282 static const struct
15284 unsigned int flags;
15285 BOOL unsynchronised;
15287 tests[] =
15289 {0, FALSE},
15290 {DDLOCK_NOOVERWRITE, TRUE},
15291 {DDLOCK_DISCARDCONTENTS, FALSE},
15292 {DDLOCK_NOOVERWRITE | DDLOCK_DISCARDCONTENTS, TRUE},
15295 static const struct quad
15297 struct
15299 struct vec3 position;
15300 DWORD diffuse;
15301 } strip[4];
15303 quad1 =
15306 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
15307 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
15308 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
15309 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
15312 quad2 =
15315 {{-1.0f, -1.0f, 0.0f}, 0xffffff00},
15316 {{-1.0f, 1.0f, 0.0f}, 0xffffff00},
15317 {{ 1.0f, -1.0f, 0.0f}, 0xffffff00},
15318 {{ 1.0f, 1.0f, 0.0f}, 0xffffff00},
15321 struct quad *quads;
15323 window = create_window();
15324 ok(!!window, "Failed to create a window.\n");
15326 if (!(device = create_device(window, DDSCL_NORMAL)))
15328 skip("Failed to create a D3D device, skipping tests.\n");
15329 DestroyWindow(window);
15330 return;
15333 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
15334 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
15335 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
15336 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
15337 /* Maps are always synchronised on WARP. */
15338 if (ddraw_is_warp(ddraw))
15340 skip("Running on WARP, skipping test.\n");
15341 goto done;
15344 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
15345 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
15347 tri_count = 0x1000;
15349 ret = QueryPerformanceFrequency(&frequency);
15350 ok(ret, "Failed to get performance counter frequency.\n");
15352 vb_desc.dwSize = sizeof(vb_desc);
15353 vb_desc.dwCaps = D3DVBCAPS_WRITEONLY;
15354 vb_desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
15355 vb_desc.dwNumVertices = tri_count + 2;
15356 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &buffer, 0);
15357 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
15358 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&quads, NULL);
15359 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
15360 for (j = 0; j < vb_desc.dwNumVertices / 4; ++j)
15362 quads[j] = quad1;
15364 hr = IDirect3DVertexBuffer7_Unlock(buffer);
15365 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
15367 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
15368 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
15370 /* Initial draw to initialise states, compile shaders, etc. */
15371 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
15372 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15373 hr = IDirect3DDevice7_BeginScene(device);
15374 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
15375 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, vb_desc.dwNumVertices, 0);
15376 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
15377 hr = IDirect3DDevice7_EndScene(device);
15378 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
15379 /* Read the result to ensure the GPU has finished drawing. */
15380 colour = get_surface_color(rt, 320, 240);
15382 /* Time drawing tri_count triangles. */
15383 ret = QueryPerformanceCounter(&ts[0]);
15384 ok(ret, "Failed to read performance counter.\n");
15385 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
15386 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15387 hr = IDirect3DDevice7_BeginScene(device);
15388 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
15389 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, vb_desc.dwNumVertices, 0);
15390 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
15391 hr = IDirect3DDevice7_EndScene(device);
15392 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
15393 colour = get_surface_color(rt, 320, 240);
15394 /* Time drawing a single triangle. */
15395 ret = QueryPerformanceCounter(&ts[1]);
15396 ok(ret, "Failed to read performance counter.\n");
15397 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
15398 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15399 hr = IDirect3DDevice7_BeginScene(device);
15400 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
15401 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, 3, 0);
15402 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
15403 hr = IDirect3DDevice7_EndScene(device);
15404 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
15405 colour = get_surface_color(rt, 320, 240);
15406 ret = QueryPerformanceCounter(&ts[2]);
15407 ok(ret, "Failed to read performance counter.\n");
15409 IDirect3DVertexBuffer7_Release(buffer);
15411 /* Estimate the number of triangles we can draw in 100ms. */
15412 diff.QuadPart = ts[1].QuadPart - ts[0].QuadPart + ts[1].QuadPart - ts[2].QuadPart;
15413 tri_count = (tri_count * frequency.QuadPart) / (diff.QuadPart * 10);
15414 tri_count = ((tri_count + 2 + 3) & ~3) - 2;
15415 vb_desc.dwNumVertices = tri_count + 2;
15417 for (i = 0; i < ARRAY_SIZE(tests); ++i)
15419 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &buffer, 0);
15420 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
15421 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_DISCARDCONTENTS, (void **)&quads, NULL);
15422 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
15423 for (j = 0; j < vb_desc.dwNumVertices / 4; ++j)
15425 quads[j] = quad1;
15427 hr = IDirect3DVertexBuffer7_Unlock(buffer);
15428 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
15430 /* Start a draw operation. */
15431 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
15432 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15433 hr = IDirect3DDevice7_BeginScene(device);
15434 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
15435 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, vb_desc.dwNumVertices, 0);
15436 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
15437 hr = IDirect3DDevice7_EndScene(device);
15438 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
15440 /* Map the last quad while the draw is in progress. */
15441 hr = IDirect3DVertexBuffer7_Lock(buffer, DDLOCK_WAIT | tests[i].flags, (void **)&quads, NULL);
15442 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
15443 quads[(vb_desc.dwNumVertices / 4) - 1] = quad2;
15444 hr = IDirect3DVertexBuffer7_Unlock(buffer);
15445 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
15447 colour = get_surface_color(rt, 320, 240);
15448 unsynchronised = compare_color(colour, 0x00ffff00, 1);
15449 ok(tests[i].unsynchronised == unsynchronised, "Expected %s map for flags %#x.\n",
15450 tests[i].unsynchronised ? "unsynchronised" : "synchronised", tests[i].flags);
15452 IDirect3DVertexBuffer7_Release(buffer);
15455 IDirectDrawSurface7_Release(rt);
15456 done:
15457 IDirectDraw7_Release(ddraw);
15458 IDirect3D7_Release(d3d);
15459 refcount = IDirect3DDevice7_Release(device);
15460 ok(!refcount, "Device has %u references left.\n", refcount);
15461 DestroyWindow(window);
15464 static void test_depth_readback(void)
15466 DWORD depth, expected_depth, max_diff, raw_value, passed_fmts = 0;
15467 IDirectDrawSurface7 *rt, *ds;
15468 DDSURFACEDESC2 surface_desc;
15469 IDirect3DDevice7 *device;
15470 unsigned int i, x, y;
15471 IDirectDraw7 *ddraw;
15472 IDirect3D7 *d3d;
15473 ULONG refcount;
15474 HWND window;
15475 HRESULT hr;
15476 RECT r;
15477 BOOL all_zero, all_one, all_pass;
15479 static struct
15481 struct vec3 position;
15482 DWORD diffuse;
15484 quad[] =
15486 {{-1.0f, -1.0f, 0.1f}, 0xff00ff00},
15487 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
15488 {{ 1.0f, -1.0f, 1.0f}, 0xff00ff00},
15489 {{ 1.0f, 1.0f, 0.9f}, 0xff00ff00},
15492 static const struct
15494 unsigned int z_depth, s_depth, z_mask, s_mask;
15495 BOOL todo;
15497 tests[] =
15499 {16, 0, 0x0000ffff, 0x00000000},
15500 {24, 0, 0x00ffffff, 0x00000000},
15501 {32, 0, 0x00ffffff, 0x00000000},
15502 {32, 8, 0x00ffffff, 0xff000000, TRUE},
15503 {32, 0, 0xffffffff, 0x00000000},
15506 window = create_window();
15507 ok(!!window, "Failed to create a window.\n");
15509 if (!(device = create_device(window, DDSCL_NORMAL)))
15511 skip("Failed to create a D3D device, skipping tests.\n");
15512 DestroyWindow(window);
15513 return;
15516 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
15517 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
15518 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
15519 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
15521 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
15522 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
15524 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
15525 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
15527 ds = get_depth_stencil(device);
15528 hr = IDirectDrawSurface7_DeleteAttachedSurface(rt, 0, ds);
15529 ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
15530 IDirectDrawSurface7_Release(ds);
15532 for (i = 0; i < ARRAY_SIZE(tests); ++i)
15534 memset(&surface_desc, 0, sizeof(surface_desc));
15535 surface_desc.dwSize = sizeof(surface_desc);
15536 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
15537 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
15538 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
15539 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
15540 if (tests[i].s_depth)
15541 U4(surface_desc).ddpfPixelFormat.dwFlags |= DDPF_STENCILBUFFER;
15542 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = tests[i].z_depth;
15543 U2(U4(surface_desc).ddpfPixelFormat).dwStencilBitDepth = tests[i].s_depth;
15544 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = tests[i].z_mask;
15545 U4(U4(surface_desc).ddpfPixelFormat).dwStencilBitMask = tests[i].s_mask;
15546 surface_desc.dwWidth = 640;
15547 surface_desc.dwHeight = 480;
15548 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL);
15549 if (FAILED(hr))
15551 skip("Format %u not supported, skipping test.\n", i);
15552 continue;
15555 hr = IDirectDrawSurface_AddAttachedSurface(rt, ds);
15556 ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
15557 hr = IDirect3DDevice7_SetRenderTarget(device, rt, 0);
15558 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
15560 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 1.0f, 0);
15561 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15562 hr = IDirect3DDevice7_BeginScene(device);
15563 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
15564 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, 4, 0);
15565 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
15566 hr = IDirect3DDevice7_EndScene(device);
15567 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
15569 all_zero = all_one = all_pass = TRUE;
15570 for (y = 60; y < 480; y += 120)
15572 for (x = 80; x < 640; x += 160)
15574 SetRect(&r, x, y, x + 1, y + 1);
15575 memset(&surface_desc, 0, sizeof(surface_desc));
15576 surface_desc.dwSize = sizeof(surface_desc);
15577 hr = IDirectDrawSurface7_Lock(ds, &r, &surface_desc, DDLOCK_READONLY, NULL);
15578 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
15580 raw_value = *((DWORD *)surface_desc.lpSurface);
15581 if (raw_value)
15582 all_zero = FALSE;
15583 if (raw_value != 0x00ffffff)
15584 all_one = FALSE;
15586 depth = raw_value & tests[i].z_mask;
15587 expected_depth = (x * (0.9 / 640.0) + y * (0.1 / 480.0)) * tests[i].z_mask;
15588 max_diff = ((0.5f * 0.9f) / 640.0f) * tests[i].z_mask;
15589 /* This test is very reliably on AMD, but fails in a number of interesting ways on Nvidia GPUs:
15591 * Geforce 7 GPUs work only with D16. D24 and D24S8 return 0, D24X8 broken data.
15593 * Geforce 9 GPUs return broken data for D16 that resembles the expected data in
15594 * the lower 8 bits and has 0xff in the upper 8 bits. D24X8 works, D24 and D24S8 return
15595 * 0x00ffffff.
15597 * Geforce GTX 650 has working D16 and D24, but D24S8 returns 0.
15599 * Arx Fatalis is broken on the Geforce 9 in the same way it was broken in Wine (bug 43654).
15600 * The !tests[i].s_depth is supposed to rule out D16 on GF9 and D24X8 on GF7. */
15601 todo_wine_if(tests[i].todo)
15602 ok(compare_uint(expected_depth, depth, max_diff)
15603 || (ddraw_is_nvidia(ddraw) && (all_zero || all_one || !tests[i].s_depth)),
15604 "Test %u: Got depth 0x%08x (diff %d), expected 0x%08x+/-%u, at %u, %u.\n",
15605 i, depth, expected_depth - depth, expected_depth, max_diff, x, y);
15606 if (!compare_uint(expected_depth, depth, max_diff))
15607 all_pass = FALSE;
15609 hr = IDirectDrawSurface7_Unlock(ds, &r);
15610 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
15613 if (all_pass)
15614 passed_fmts++;
15616 hr = IDirectDrawSurface7_DeleteAttachedSurface(rt, 0, ds);
15617 ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
15618 IDirectDrawSurface7_Release(ds);
15621 ok(passed_fmts, "Not a single format passed the tests, this is bad even by Nvidia's standards.\n");
15623 IDirectDrawSurface7_Release(rt);
15624 IDirectDraw7_Release(ddraw);
15625 IDirect3D7_Release(d3d);
15626 refcount = IDirect3DDevice7_Release(device);
15627 ok(!refcount, "Device has %u references left.\n", refcount);
15628 DestroyWindow(window);
15631 static void test_clear(void)
15633 IDirect3DDevice7 *device;
15634 IDirectDrawSurface7 *rt;
15635 D3DVIEWPORT7 vp, old_vp;
15636 IDirectDraw7 *ddraw;
15637 D3DRECT rect_negneg;
15638 IDirect3D7 *d3d;
15639 D3DRECT rect[2];
15640 D3DCOLOR color;
15641 ULONG refcount;
15642 HWND window;
15643 HRESULT hr;
15645 window = create_window();
15646 if (!(device = create_device(window, DDSCL_NORMAL)))
15648 skip("Failed to create 3D device.\n");
15649 DestroyWindow(window);
15650 return;
15653 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
15654 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
15655 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
15656 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
15658 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
15659 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
15661 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
15662 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15664 /* Positive x, negative y. */
15665 U1(rect[0]).x1 = 0;
15666 U2(rect[0]).y1 = 480;
15667 U3(rect[0]).x2 = 320;
15668 U4(rect[0]).y2 = 240;
15670 /* Positive x, positive y. */
15671 U1(rect[1]).x1 = 0;
15672 U2(rect[1]).y1 = 0;
15673 U3(rect[1]).x2 = 320;
15674 U4(rect[1]).y2 = 240;
15676 /* Clear 2 rectangles with one call. Unlike d3d8/9, the refrast does not
15677 * refuse negative rectangles, but it will not clear them either. */
15678 hr = IDirect3DDevice7_Clear(device, 2, rect, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0);
15679 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15681 color = get_surface_color(rt, 160, 360);
15682 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 3 (pos, neg) has color 0x%08x.\n", color);
15683 color = get_surface_color(rt, 160, 120);
15684 ok(compare_color(color, 0x00ff0000, 0), "Clear rectangle 1 (pos, pos) has color 0x%08x.\n", color);
15685 color = get_surface_color(rt, 480, 360);
15686 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 4 (NULL) has color 0x%08x.\n", color);
15687 color = get_surface_color(rt, 480, 120);
15688 ok(compare_color(color, 0x00ffffff, 0), "Clear rectangle 4 (neg, neg) has color 0x%08x.\n", color);
15690 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
15691 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15692 /* negative x, negative y.
15693 * Also ignored, except on WARP, which clears the entire screen. */
15694 U1(rect_negneg).x1 = 640;
15695 U2(rect_negneg).y1 = 240;
15696 U3(rect_negneg).x2 = 320;
15697 U4(rect_negneg).y2 = 0;
15698 hr = IDirect3DDevice7_Clear(device, 1, &rect_negneg, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
15699 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15701 color = get_surface_color(rt, 160, 360);
15702 ok(compare_color(color, 0x00ffffff, 0)
15703 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
15704 "Got unexpected color 0x%08x.\n", color);
15705 color = get_surface_color(rt, 160, 120);
15706 ok(compare_color(color, 0x00ffffff, 0)
15707 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
15708 "Got unexpected color 0x%08x.\n", color);
15709 color = get_surface_color(rt, 480, 360);
15710 ok(compare_color(color, 0x00ffffff, 0)
15711 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
15712 "Got unexpected color 0x%08x.\n", color);
15713 color = get_surface_color(rt, 480, 120);
15714 ok(compare_color(color, 0x00ffffff, 0)
15715 || broken(ddraw_is_warp(ddraw) && compare_color(color, 0x0000ff00, 0)),
15716 "Got unexpected color 0x%08x.\n", color);
15718 /* Test how the viewport affects clears. */
15719 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
15720 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15721 hr = IDirect3DDevice7_GetViewport(device, &old_vp);
15722 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
15724 vp.dwX = 160;
15725 vp.dwY = 120;
15726 vp.dwWidth = 160;
15727 vp.dwHeight = 120;
15728 vp.dvMinZ = 0.0f;
15729 vp.dvMaxZ = 1.0f;
15730 hr = IDirect3DDevice7_SetViewport(device, &vp);
15731 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
15732 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
15733 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15735 vp.dwX = 320;
15736 vp.dwY = 240;
15737 vp.dwWidth = 320;
15738 vp.dwHeight = 240;
15739 vp.dvMinZ = 0.0f;
15740 vp.dvMaxZ = 1.0f;
15741 hr = IDirect3DDevice7_SetViewport(device, &vp);
15742 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
15744 U1(rect[0]).x1 = 160;
15745 U2(rect[0]).y1 = 120;
15746 U3(rect[0]).x2 = 480;
15747 U4(rect[0]).y2 = 360;
15748 hr = IDirect3DDevice7_Clear(device, 1, &rect[0], D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
15749 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
15751 hr = IDirect3DDevice7_SetViewport(device, &old_vp);
15752 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
15754 color = get_surface_color(rt, 158, 118);
15755 ok(compare_color(color, 0x00ffffff, 0), "(158, 118) has color 0x%08x.\n", color);
15756 color = get_surface_color(rt, 162, 118);
15757 ok(compare_color(color, 0x00ffffff, 0), "(162, 118) has color 0x%08x.\n", color);
15758 color = get_surface_color(rt, 158, 122);
15759 ok(compare_color(color, 0x00ffffff, 0), "(158, 122) has color 0x%08x.\n", color);
15760 color = get_surface_color(rt, 162, 122);
15761 ok(compare_color(color, 0x000000ff, 0), "(162, 122) has color 0x%08x.\n", color);
15763 color = get_surface_color(rt, 318, 238);
15764 ok(compare_color(color, 0x000000ff, 0), "(318, 238) has color 0x%08x.\n", color);
15765 color = get_surface_color(rt, 322, 238);
15766 ok(compare_color(color, 0x00ffffff, 0), "(322, 328) has color 0x%08x.\n", color);
15767 color = get_surface_color(rt, 318, 242);
15768 ok(compare_color(color, 0x00ffffff, 0), "(318, 242) has color 0x%08x.\n", color);
15769 color = get_surface_color(rt, 322, 242);
15770 ok(compare_color(color, 0x0000ff00, 0), "(322, 242) has color 0x%08x.\n", color);
15772 color = get_surface_color(rt, 478, 358);
15773 ok(compare_color(color, 0x0000ff00, 0), "(478, 358) has color 0x%08x.\n", color);
15774 color = get_surface_color(rt, 482, 358);
15775 ok(compare_color(color, 0x00ffffff, 0), "(482, 358) has color 0x%08x.\n", color);
15776 color = get_surface_color(rt, 478, 362);
15777 ok(compare_color(color, 0x00ffffff, 0), "(478, 362) has color 0x%08x.\n", color);
15778 color = get_surface_color(rt, 482, 362);
15779 ok(compare_color(color, 0x00ffffff, 0), "(482, 362) has color 0x%08x.\n", color);
15781 /* COLORWRITEENABLE, SRGBWRITEENABLE and scissor rectangles do not exist
15782 * in d3d7. */
15784 IDirectDrawSurface7_Release(rt);
15785 IDirectDraw7_Release(ddraw);
15786 IDirect3D7_Release(d3d);
15787 refcount = IDirect3DDevice7_Release(device);
15788 ok(!refcount, "Device has %u references left.\n", refcount);
15789 DestroyWindow(window);
15792 struct enum_surfaces_param
15794 IDirectDraw7 *ddraw;
15795 DDSURFACEDESC2 modes[20];
15796 unsigned int mode_count;
15798 IDirectDrawSurface7 *surfaces[8];
15799 unsigned int count;
15802 static HRESULT CALLBACK build_mode_list_cb(DDSURFACEDESC2 *desc, void *context)
15804 struct enum_surfaces_param *param = context;
15805 IDirectDrawSurface7 *surface;
15807 if (SUCCEEDED(IDirectDraw7_CreateSurface(param->ddraw, desc, &surface, NULL)))
15809 if (param->mode_count < ARRAY_SIZE(param->modes))
15810 param->modes[param->mode_count] = *desc;
15811 ++param->mode_count;
15812 IDirectDrawSurface7_Release(surface);
15815 return DDENUMRET_OK;
15818 static HRESULT WINAPI enum_surfaces_cb(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
15820 struct enum_surfaces_param *param = context;
15821 BOOL found = FALSE;
15822 unsigned int i;
15824 for (i = 0; i < ARRAY_SIZE(param->surfaces); ++i)
15826 if (param->surfaces[i] == surface)
15828 found = TRUE;
15829 break;
15833 ok(found, "Unexpected surface %p enumerated.\n", surface);
15834 IDirectDrawSurface7_Release(surface);
15835 ++param->count;
15837 return DDENUMRET_OK;
15840 static HRESULT WINAPI enum_surfaces_create_cb(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
15842 static const DWORD expect_flags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_PIXELFORMAT;
15843 struct enum_surfaces_param *param = context;
15845 ok(!surface, "Unexpected surface %p.\n", surface);
15846 ok((desc->dwFlags & expect_flags) == expect_flags, "Got unexpected flags %#x.\n", desc->dwFlags);
15847 if (param->count < ARRAY_SIZE(param->modes))
15849 const DDSURFACEDESC2 *expect = &param->modes[param->count];
15850 ok(desc->dwWidth == expect->dwWidth, "Expected width %u, got %u.\n", expect->dwWidth, desc->dwWidth);
15851 ok(desc->dwHeight == expect->dwHeight, "Expected height %u, got %u.\n", expect->dwHeight, desc->dwHeight);
15852 ok(!memcmp(&U4(*desc).ddpfPixelFormat, &U4(*expect).ddpfPixelFormat, sizeof(U4(*desc).ddpfPixelFormat)),
15853 "Pixel formats didn't match.\n");
15856 ++param->count;
15858 return DDENUMRET_OK;
15861 static void test_enum_surfaces(void)
15863 struct enum_surfaces_param param = {0};
15864 DDPIXELFORMAT current_format;
15865 DDSURFACEDESC2 desc;
15866 IDirectDraw7 *ddraw;
15867 HRESULT hr;
15869 ddraw = create_ddraw();
15870 ok(!!ddraw, "Failed to create a ddraw object.\n");
15871 param.ddraw = ddraw;
15873 memset(&desc, 0, sizeof(desc));
15874 desc.dwSize = sizeof(desc);
15875 hr = IDirectDraw7_GetDisplayMode(ddraw, &desc);
15876 ok(hr == DD_OK, "Failed to get display mode, hr %#x.\n", hr);
15877 current_format = U4(desc).ddpfPixelFormat;
15879 hr = IDirectDraw7_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
15880 ok(hr == DD_OK, "Failed to set cooperative level, hr %#x.\n", hr);
15882 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL, NULL, NULL, NULL);
15883 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
15885 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_ALL, NULL, NULL, enum_surfaces_cb);
15886 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
15888 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_ALL,
15889 NULL, NULL, enum_surfaces_cb);
15890 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
15892 memset(&desc, 0, sizeof(desc));
15893 desc.dwSize = sizeof(desc);
15894 desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
15895 desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
15896 U2(desc).dwMipMapCount = 3;
15897 desc.dwWidth = 32;
15898 desc.dwHeight = 32;
15899 if (FAILED(IDirectDraw7_CreateSurface(ddraw, &desc, &param.surfaces[0], NULL)))
15901 win_skip("Failed to create a texture, skipping tests.\n");
15902 IDirectDraw7_Release(ddraw);
15903 return;
15906 hr = IDirectDrawSurface7_GetAttachedSurface(param.surfaces[0], &desc.ddsCaps, &param.surfaces[1]);
15907 ok(hr == DD_OK, "Failed to get attached surface, hr %#x.\n", hr);
15908 hr = IDirectDrawSurface7_GetAttachedSurface(param.surfaces[1], &desc.ddsCaps, &param.surfaces[2]);
15909 ok(hr == DD_OK, "Failed to get attached surface, hr %#x.\n", hr);
15910 hr = IDirectDrawSurface7_GetAttachedSurface(param.surfaces[2], &desc.ddsCaps, &param.surfaces[3]);
15911 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
15912 ok(!param.surfaces[3], "Got unexpected pointer %p.\n", param.surfaces[3]);
15914 param.count = 0;
15915 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
15916 &desc, &param, enum_surfaces_cb);
15917 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
15918 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
15920 param.count = 0;
15921 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
15922 NULL, &param, enum_surfaces_cb);
15923 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
15924 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
15926 desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
15927 param.count = 0;
15928 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_MATCH,
15929 &desc, &param, enum_surfaces_cb);
15930 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
15931 ok(param.count == 1, "Got unexpected number of enumerated surfaces %u.\n", param.count);
15933 param.count = 0;
15934 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_NOMATCH,
15935 &desc, &param, enum_surfaces_cb);
15936 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
15937 ok(param.count == 2, "Got unexpected number of enumerated surfaces %u.\n", param.count);
15939 desc.dwFlags = 0;
15940 param.count = 0;
15941 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_MATCH,
15942 &desc, &param, enum_surfaces_cb);
15943 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
15944 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
15946 desc.dwFlags = 0;
15947 param.count = 0;
15948 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST, &desc, &param, enum_surfaces_cb);
15949 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
15950 ok(param.count == 3, "Got unexpected number of enumerated surfaces %u.\n", param.count);
15952 IDirectDrawSurface7_Release(param.surfaces[2]);
15953 IDirectDrawSurface7_Release(param.surfaces[1]);
15954 IDirectDrawSurface7_Release(param.surfaces[0]);
15956 param.count = 0;
15957 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL,
15958 NULL, &param, enum_surfaces_cb);
15959 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
15960 ok(!param.count, "Got unexpected number of enumerated surfaces %u.\n", param.count);
15962 memset(&desc, 0, sizeof(desc));
15963 desc.dwSize = sizeof(desc);
15964 desc.dwFlags = DDSD_CAPS;
15965 desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
15967 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_ALL,
15968 &desc, &param, enum_surfaces_create_cb);
15969 ok(hr == DDERR_INVALIDPARAMS, "Failed to enumerate surfaces, hr %#x.\n", hr);
15971 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_NOMATCH,
15972 &desc, &param, enum_surfaces_create_cb);
15973 ok(hr == DDERR_INVALIDPARAMS, "Failed to enumerate surfaces, hr %#x.\n", hr);
15975 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED,
15976 &desc, &param, enum_surfaces_create_cb);
15977 ok(hr == DDERR_INVALIDPARAMS, "Failed to enumerate surfaces, hr %#x.\n", hr);
15979 /* When not passed width and height, the callback is called with every
15980 * available display resolution. */
15982 param.mode_count = 0;
15983 desc.dwFlags |= DDSD_PIXELFORMAT;
15984 U4(desc).ddpfPixelFormat = current_format;
15985 hr = IDirectDraw7_EnumDisplayModes(ddraw, 0, &desc, &param, build_mode_list_cb);
15986 ok(hr == DD_OK, "Failed to build mode list, hr %#x.\n", hr);
15988 param.count = 0;
15989 desc.dwFlags &= ~DDSD_PIXELFORMAT;
15990 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_MATCH,
15991 &desc, &param, enum_surfaces_create_cb);
15992 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
15993 ok(param.count == param.mode_count, "Expected %u surfaces, got %u.\n", param.mode_count, param.count);
15995 desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
15996 desc.dwWidth = desc.dwHeight = 32;
15998 param.modes[0].dwWidth = param.modes[0].dwHeight = 32;
16000 param.count = 0;
16001 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_MATCH,
16002 &desc, &param, enum_surfaces_create_cb);
16003 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
16004 ok(param.count == 1, "Got unexpected number of enumerated surfaces %u.\n", param.count);
16006 hr = IDirectDraw7_CreateSurface(ddraw, &desc, &param.surfaces[0], NULL);
16007 ok(hr == DD_OK, "Failed to create surface, hr %#x.\n", hr);
16008 param.count = 0;
16009 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_MATCH,
16010 &desc, &param, enum_surfaces_create_cb);
16011 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
16012 ok(param.count == 1, "Got unexpected number of enumerated surfaces %u.\n", param.count);
16013 IDirectDrawSurface7_Release(param.surfaces[0]);
16015 desc.dwFlags |= DDSD_PIXELFORMAT;
16016 U4(desc).ddpfPixelFormat.dwSize = sizeof(U4(desc).ddpfPixelFormat);
16017 U4(desc).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
16018 U4(desc).ddpfPixelFormat.dwFourCC = 0xdeadbeef;
16020 param.count = 0;
16021 hr = IDirectDraw7_EnumSurfaces(ddraw, DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_MATCH,
16022 &desc, &param, enum_surfaces_create_cb);
16023 ok(hr == DD_OK, "Failed to enumerate surfaces, hr %#x.\n", hr);
16024 ok(!param.count, "Got unexpected number of enumerated surfaces %u.\n", param.count);
16026 IDirectDraw7_Release(ddraw);
16029 static void test_viewport(void)
16031 static struct
16033 D3DVIEWPORT7 vp;
16034 float expected_z;
16035 RECT expected_rect;
16036 const char *message;
16038 tests[] =
16040 {{ 0, 0, 640, 480}, 0.001f, { 0, 120, 479, 359}, "Viewport (0, 0) - (640, 480)"},
16041 {{ 0, 0, 320, 240}, 0.001f, { 0, 60, 239, 179}, "Viewport (0, 0) - (320, 240)"},
16042 /* Don't run this right after the other 640x480 test, it breaks r500. */
16043 {{ 0, 0, 640, 480, 0.5f, 0.0f}, 0.501f,
16044 {0, 120, 479, 359}, "Viewport (0, 0, 0.5) - (640, 480, 0.0)"},
16045 {{ 0, 0, 1280, 960}, 0.001f, { 0, 240, 639, 479}, "Viewport (0, 0) - (1280, 960)"},
16046 {{ 0, 0, 2000, 1600}, 0.001f, {-10, -10, -10, -10}, "Viewport (0, 0) - (2000, 1600)"},
16047 {{100, 100, 640, 480}, 0.001f, {100, 220, 579, 459}, "Viewport (100, 100) - (640, 480)"},
16048 {{ 0, 0, 8192, 8192}, 0.001f, {-10, -10, -10, -10}, "Viewport (0, 0) - (8192, 8192)"},
16050 static struct vec3 quad[] =
16052 {-1.5f, -0.5f, 1.0f},
16053 {-1.5f, 0.5f, 1.0f},
16054 { 0.5f, -0.5f, 1.0f},
16055 { 0.5f, 0.5f, 1.0f},
16057 static const struct vec2 rt_sizes[] =
16059 {640, 480}, {1280, 960}, {320, 240}, {800, 600},
16061 IDirectDrawSurface7 *rt, *ds;
16062 DDSURFACEDESC2 surface_desc;
16063 const float z_eps = 0.0001;
16064 IDirect3DDevice7 *device;
16065 IDirectDraw7 *ddraw;
16066 DDPIXELFORMAT z_fmt;
16067 unsigned int i, j;
16068 IDirect3D7 *d3d;
16069 ULONG refcount;
16070 HWND window;
16071 HRESULT hr;
16073 window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
16074 0, 0, 640, 480, 0, 0, 0, 0);
16075 if (!(device = create_device(window, DDSCL_NORMAL)))
16077 skip("Failed to create a 3D device, skipping test.\n");
16078 DestroyWindow(window);
16079 return;
16082 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
16083 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16084 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
16085 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16086 IDirect3D7_Release(d3d);
16088 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
16089 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16091 /* Well, by default the vertices without color info should be white, and without any texture
16092 * ops this should just show up in the output, but the r200 driver begs to differ and draws a
16093 * random color. */
16094 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
16095 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16096 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
16097 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16098 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x00ffffff);
16099 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16101 hr = IDirect3DDevice7_SetViewport(device, NULL);
16102 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
16104 ds = get_depth_stencil(device);
16105 memset(&surface_desc, 0, sizeof(surface_desc));
16106 surface_desc.dwSize = sizeof(surface_desc);
16107 hr = IDirectDrawSurface7_GetSurfaceDesc(ds, &surface_desc);
16108 z_fmt = U4(surface_desc).ddpfPixelFormat;
16110 for (i = 0; i < ARRAY_SIZE(rt_sizes); ++i)
16112 if (i)
16114 memset(&surface_desc, 0, sizeof(surface_desc));
16115 surface_desc.dwSize = sizeof(surface_desc);
16116 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
16117 surface_desc.dwWidth = rt_sizes[i].x;
16118 surface_desc.dwHeight = rt_sizes[i].y;
16119 surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
16120 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &rt, NULL);
16121 ok(hr == DD_OK, "Got unexpected hr %#x (i %u).\n", hr, i);
16123 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
16124 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
16125 U4(surface_desc).ddpfPixelFormat = z_fmt;
16126 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL);
16127 ok(hr == DD_OK, "Got unexpected hr %#x (i %u).\n", hr, i);
16128 hr = IDirectDrawSurface7_AddAttachedSurface(rt, ds);
16129 ok(hr == DD_OK, "Got unexpected hr %#x (i %u).\n", hr, i);
16131 hr = IDirect3DDevice7_SetRenderTarget(device, rt, 0);
16132 ok(hr == DD_OK, "Got unexpected hr %#x (i %u).\n", hr, i);
16134 else
16136 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
16137 ok(hr == DD_OK, "Got unexpected hr %#x (i %u).\n", hr, i);
16140 for (j = 0; j < ARRAY_SIZE(tests); ++j)
16142 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff000000,
16143 tests[j].expected_z - z_eps, 0);
16144 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
16145 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_GREATER);
16146 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
16148 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, !i);
16149 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
16151 hr = IDirect3DDevice7_SetViewport(device, &tests[j].vp);
16152 if (tests[j].vp.dwX + tests[j].vp.dwWidth > rt_sizes[i].x
16153 || tests[j].vp.dwY + tests[j].vp.dwHeight > rt_sizes[i].y)
16155 ok(hr == E_INVALIDARG, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
16156 continue;
16158 else
16160 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
16163 hr = IDirect3DDevice7_BeginScene(device);
16164 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
16165 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
16166 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
16167 hr = IDirect3DDevice7_EndScene(device);
16168 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
16170 check_rect(rt, tests[j].expected_rect, tests[j].message);
16172 if (!i)
16174 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff000000,
16175 tests[j].expected_z + z_eps, 0);
16176 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
16177 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESS);
16178 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
16180 hr = IDirect3DDevice7_BeginScene(device);
16181 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
16182 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0);
16183 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
16184 hr = IDirect3DDevice7_EndScene(device);
16185 ok(hr == DD_OK, "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j);
16187 check_rect(rt, tests[j].expected_rect, tests[j].message);
16191 hr = IDirectDrawSurface7_DeleteAttachedSurface(rt, 0, ds);
16192 ok(hr == DD_OK, "Got unexpected hr %#x (i %u).\n", hr, i);
16193 IDirectDrawSurface7_Release(ds);
16194 IDirectDrawSurface7_Release(rt);
16197 refcount = IDirect3DDevice7_Release(device);
16198 ok(!refcount, "Device has %u references left.\n", refcount);
16199 IDirectDraw7_Release(ddraw);
16200 DestroyWindow(window);
16203 static unsigned int validate_loaded_surface(IDirectDrawSurface7 *surface, unsigned int face,
16204 unsigned int level, const RECT *src_rect, const POINT *dst_point)
16206 DDSURFACEDESC2 surface_desc;
16207 unsigned int diff, x, y;
16208 HRESULT hr;
16210 memset(&surface_desc, 0, sizeof(surface_desc));
16211 surface_desc.dwSize = sizeof(surface_desc);
16212 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
16213 ok(SUCCEEDED(hr), "Failed to map surface, hr %#x.\n", hr);
16215 for (y = 0, diff = 0; y < surface_desc.dwHeight; ++y)
16217 DWORD *texture_row = (DWORD *)((char *)surface_desc.lpSurface + y * U1(surface_desc).lPitch);
16219 for (x = 0; x < surface_desc.dwWidth; ++x)
16221 DWORD colour = texture_row[x];
16222 DWORD r = (colour & 0xff0000) >> 16;
16223 DWORD g = (colour & 0xff00) >> 8;
16224 DWORD b = (colour & 0xff);
16226 if (x < dst_point->x || x >= dst_point->x + src_rect->right - src_rect->left
16227 || y < dst_point->y || y >= dst_point->y + src_rect->bottom - src_rect->top)
16229 if (colour & 0xffffff)
16230 ++diff;
16232 else
16234 if (r != ((face << 4) | level)
16235 || g != x + src_rect->left - dst_point->x
16236 || b != y + src_rect->top - dst_point->y)
16237 ++diff;
16242 hr = IDirectDrawSurface7_Unlock(surface, NULL);
16243 ok(SUCCEEDED(hr), "Failed to unmap surface, hr %#x.\n", hr);
16245 return diff;
16248 static void test_device_load(void)
16250 IDirectDrawSurface7 *src_surface, *dst_surface, *surface, *tmp;
16251 DDSCAPS2 mip_caps = {0, DDSCAPS2_MIPMAPSUBLEVEL, 0, {0}};
16252 IDirectDrawPalette *src_palette, *dst_palette, *palette;
16253 unsigned int i, j, k, l, x, y;
16254 DDSURFACEDESC2 surface_desc;
16255 IDirect3DDevice7 *device;
16256 PALETTEENTRY table1[256];
16257 D3DDEVICEDESC7 d3d_caps;
16258 DDCOLORKEY colour_key;
16259 IDirectDraw7 *ddraw;
16260 BOOL cube_support;
16261 IDirect3D7 *d3d;
16262 ULONG refcount;
16263 HWND window;
16264 DDBLTFX fx;
16265 HRESULT hr;
16267 #define TEX_MIP 0x01
16268 #define TEX_CUBE 0x02
16269 #define NULL_COORDS 0x04
16271 /* Creating partial cube maps (e.g. created with just
16272 * DDSCAPS2_CUBEMAP_POSITIVEX) BSODs some Windows machines. (Radeon X1600,
16273 * Windows XP, Catalyst 10.2 driver, 6.14.10.6925)
16275 * Passing non-toplevel surfaces to IDirect3DDevice7_Load() crashes on
16276 * native. (Windows XP / NVIDIA, Windows 98 / RGB software rasteriser) */
16277 static const struct
16279 unsigned int src_w, src_h, src_mip_count;
16280 RECT src_rect;
16281 DWORD src_flags;
16282 unsigned int dst_w, dst_h, dst_mip_count;
16283 POINT dst_point;
16284 DWORD dst_flags;
16285 HRESULT hr;
16287 tests[] =
16289 {128, 128, 0, { 0, 0, 0, 0}, TEX_MIP, 128, 128, 0, { 0, 0}, TEX_MIP, DDERR_INVALIDPARAMS},
16290 {128, 128, 0, { 0, 0, 100, 100}, TEX_MIP, 128, 128, 0, {50, 50}, TEX_MIP, DDERR_INVALIDPARAMS},
16291 {128, 128, 0, {30, 20, 93, 52}, TEX_MIP, 128, 128, 0, {31, 31}, TEX_MIP, D3D_OK},
16292 {128, 128, 0, { 0, 0, 0, 0}, NULL_COORDS, 128, 128, 0, { 0, 0}, NULL_COORDS, D3D_OK},
16293 {128, 128, 0, { 0, 0, 0, 0}, NULL_COORDS, 256, 128, 0, { 0, 0}, NULL_COORDS, DDERR_INVALIDPARAMS},
16294 {256, 128, 0, { 0, 0, 0, 0}, NULL_COORDS, 128, 128, 0, { 0, 0}, NULL_COORDS, DDERR_INVALIDPARAMS},
16295 {128, 128, 0, {30, 20, 93, 52}, TEX_MIP | TEX_CUBE, 128, 128, 0, {10, 10}, TEX_MIP | TEX_CUBE, D3D_OK},
16296 {128, 128, 0, { 0, 0, 0, 0}, NULL_COORDS, 128, 128, 0, { 0, 0}, TEX_CUBE | NULL_COORDS, DDERR_INVALIDPARAMS},
16297 {128, 128, 0, {30, 20, 93, 52}, TEX_MIP, 128, 128, 4, {31, 31}, TEX_MIP, D3D_OK},
16298 {128, 128, 4, {30, 20, 93, 52}, TEX_MIP, 128, 128, 0, {31, 31}, TEX_MIP, DDERR_INVALIDPARAMS},
16299 {128, 128, 0, {32, 32, 96, 96}, TEX_MIP, 32, 32, 0, {32, 32}, 0, D3D_OK},
16300 {128, 128, 0, { 0, 0, 64, 64}, TEX_MIP, 32, 32, 4, { 0, 0}, TEX_MIP, D3D_OK},
16303 window = create_window();
16304 if (!(device = create_device(window, DDSCL_NORMAL)))
16306 skip("Failed to create a 3D device, skipping test.\n");
16307 DestroyWindow(window);
16308 return;
16311 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
16312 ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
16313 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
16314 ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
16315 IDirect3D7_Release(d3d);
16317 memset(&d3d_caps, 0, sizeof(d3d_caps));
16318 hr = IDirect3DDevice7_GetCaps(device, &d3d_caps);
16319 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
16320 cube_support = d3d_caps.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP;
16322 for (i = 0; i < ARRAY_SIZE(tests); ++i)
16324 unsigned int src_count, dst_count;
16325 POINT dst_point, dst_point_broken;
16326 RECT src_rect, src_rect_broken;
16328 if ((tests[i].src_flags | tests[i].dst_flags) & TEX_CUBE && !cube_support)
16330 skip("No cubemap support, skipping test %u.\n", i);
16331 continue;
16334 memset(&surface_desc, 0, sizeof(surface_desc));
16335 surface_desc.dwSize = sizeof(surface_desc);
16336 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
16337 if (tests[i].src_mip_count)
16338 surface_desc.dwFlags |= DDSD_MIPMAPCOUNT;
16339 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
16340 if (tests[i].src_flags & (TEX_MIP | TEX_CUBE))
16341 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
16342 if (tests[i].src_flags & TEX_MIP)
16343 surface_desc.ddsCaps.dwCaps |= DDSCAPS_MIPMAP;
16344 if (tests[i].src_flags & TEX_CUBE)
16345 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
16346 surface_desc.dwWidth = tests[i].src_w;
16347 surface_desc.dwHeight = tests[i].src_h;
16348 U2(surface_desc).dwMipMapCount = tests[i].src_mip_count;
16349 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
16350 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
16351 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
16352 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
16353 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
16354 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
16355 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
16356 ok(SUCCEEDED(hr), "Test %u: Failed to create source surface, hr %#x.\n", i, hr);
16358 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
16359 if (tests[i].dst_mip_count)
16360 surface_desc.dwFlags |= DDSD_MIPMAPCOUNT;
16361 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
16362 if (tests[i].dst_flags & (TEX_MIP | TEX_CUBE))
16363 surface_desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX;
16364 if (tests[i].dst_flags & TEX_MIP)
16365 surface_desc.ddsCaps.dwCaps |= DDSCAPS_MIPMAP;
16366 surface_desc.ddsCaps.dwCaps2 = 0;
16367 if (tests[i].dst_flags & TEX_CUBE)
16368 surface_desc.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
16369 surface_desc.dwWidth = tests[i].dst_w;
16370 surface_desc.dwHeight = tests[i].dst_h;
16371 U2(surface_desc).dwMipMapCount = tests[i].dst_mip_count;
16372 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
16373 ok(SUCCEEDED(hr), "Test %u: Failed to create destination surface, hr %#x.\n", i, hr);
16375 src_count = dst_count = 1;
16376 if (tests[i].src_flags & TEX_MIP)
16377 src_count = tests[i].src_mip_count ? tests[i].src_mip_count : 8;
16378 if (tests[i].dst_flags & TEX_MIP)
16379 dst_count = tests[i].dst_mip_count ? tests[i].dst_mip_count : 8;
16381 surface = src_surface;
16382 IDirectDrawSurface7_AddRef(surface);
16383 for (j = 0;;)
16385 DDSCAPS2 face_caps = {0, 0, 0, {0}};
16387 /* Check the number of created mipmaps. */
16388 if (tests[i].src_flags & TEX_MIP)
16390 memset(&surface_desc, 0, sizeof(surface_desc));
16391 surface_desc.dwSize = sizeof(surface_desc);
16392 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
16393 ok(SUCCEEDED(hr), "Test %u: Failed to get surface description, hr %#x.\n", i, hr);
16394 ok(U2(surface_desc).dwMipMapCount == src_count,
16395 "Test %u: Got unexpected mip count %u, expected %u.\n",
16396 i, U2(surface_desc).dwMipMapCount, src_count);
16399 for (k = 0; ; ++k)
16401 memset(&surface_desc, 0, sizeof(surface_desc));
16402 surface_desc.dwSize = sizeof(surface_desc);
16403 hr = IDirectDrawSurface7_Lock(surface, NULL, &surface_desc, DDLOCK_WAIT, NULL);
16404 ok(SUCCEEDED(hr), "Test %u: Failed to map surface, hr %#x.\n", i, hr);
16406 for (y = 0; y < surface_desc.dwHeight; ++y)
16408 DWORD *texture_row = (DWORD *)((BYTE *)surface_desc.lpSurface + y * U1(surface_desc).lPitch);
16410 for (x = 0; x < surface_desc.dwWidth; ++x)
16412 /* The face number is stored in the high 4 bits of the
16413 * red component, the mip-level in the low 4 bits. The
16414 * x-coordinate is stored in the green component, and
16415 * the y-coordinate in the blue component. */
16416 texture_row[x] = (j << 20) | (k << 16) | (x << 8) | y;
16420 hr = IDirectDrawSurface7_Unlock(surface, NULL);
16421 ok(SUCCEEDED(hr), "Test %u: Failed to unmap surface, hr %#x.\n", i, hr);
16423 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &mip_caps, &tmp);
16424 IDirectDrawSurface7_Release(surface);
16425 if (FAILED(hr))
16426 break;
16427 surface = tmp;
16430 if (!(tests[i].src_flags & TEX_CUBE) || ++j >= 6)
16431 break;
16433 face_caps.dwCaps2 = DDSCAPS2_CUBEMAP | (DDSCAPS2_CUBEMAP_POSITIVEX << j);
16434 hr = IDirectDrawSurface7_GetAttachedSurface(src_surface, &face_caps, &surface);
16435 ok(SUCCEEDED(hr), "Test %u: Failed to get face %u.\n", i, j);
16438 surface = dst_surface;
16439 IDirectDrawSurface7_AddRef(surface);
16440 for (j = 0;;)
16442 DDSCAPS2 face_caps = {0, 0, 0, {0}};
16444 /* Check the number of created mipmaps. */
16445 if (tests[i].dst_flags & TEX_MIP)
16447 memset(&surface_desc, 0, sizeof(surface_desc));
16448 surface_desc.dwSize = sizeof(surface_desc);
16449 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
16450 ok(SUCCEEDED(hr), "Test %u: Failed to get surface description, hr %#x.\n", i, hr);
16451 ok(U2(surface_desc).dwMipMapCount == dst_count,
16452 "Test %u: Got unexpected mip count %u, expected %u.\n",
16453 i, U2(surface_desc).dwMipMapCount, dst_count);
16456 for (;;)
16458 memset(&fx, 0, sizeof(fx));
16459 fx.dwSize = sizeof(fx);
16460 U5(fx).dwFillColor = 0x00000000;
16461 hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
16462 ok(SUCCEEDED(hr), "Test %u: Failed to clear surface, hr %#x.\n", i, hr);
16464 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &mip_caps, &tmp);
16465 IDirectDrawSurface7_Release(surface);
16466 if (FAILED(hr))
16467 break;
16468 surface = tmp;
16471 if (!(tests[i].dst_flags & TEX_CUBE) || ++j >= 6)
16472 break;
16474 face_caps.dwCaps2 = DDSCAPS2_CUBEMAP | (DDSCAPS2_CUBEMAP_POSITIVEX << j);
16475 hr = IDirectDrawSurface7_GetAttachedSurface(dst_surface, &face_caps, &surface);
16476 ok(SUCCEEDED(hr), "Test %u: Failed to get face %u.\n", i, j);
16479 src_rect = tests[i].src_rect;
16480 dst_point = tests[i].dst_point;
16481 hr = IDirect3DDevice7_Load(device,
16482 dst_surface, tests[i].dst_flags & NULL_COORDS ? NULL : &dst_point,
16483 src_surface, tests[i].src_flags & NULL_COORDS ? NULL : &src_rect,
16484 tests[i].dst_flags & TEX_CUBE ? DDSCAPS2_CUBEMAP_ALLFACES : 0);
16485 ok(hr == tests[i].hr, "Test %u: Got unexpected hr %#x.\n", i, hr);
16487 if (SUCCEEDED(hr))
16489 unsigned int level_offset, level_offset_broken;
16491 for (level_offset = 0, k = tests[i].src_w; k > tests[i].dst_w; ++level_offset, k /= 2);
16492 level_offset_broken = src_count - dst_count;
16494 surface = dst_surface;
16495 IDirectDrawSurface7_AddRef(surface);
16496 for (j = 0;;)
16498 DDSCAPS2 face_caps = {0, 0, 0, {0}};
16500 if (tests[i].src_flags & NULL_COORDS)
16501 SetRect(&src_rect, 0, 0, tests[i].src_w, tests[i].src_h);
16502 else
16503 src_rect = tests[i].src_rect;
16505 if (tests[i].dst_flags & NULL_COORDS)
16506 dst_point.x = dst_point.y = 0;
16507 else
16508 dst_point = tests[i].dst_point;
16510 for (k = 0; k < level_offset; ++k)
16512 dst_point.x /= 2;
16513 dst_point.y /= 2;
16514 src_rect.top /= 2;
16515 src_rect.left /= 2;
16516 src_rect.right = (src_rect.right + 1) / 2;
16517 src_rect.bottom = (src_rect.bottom + 1) / 2;
16520 for (k = 0; ; ++k)
16522 unsigned int diff, diff2, diff3;
16524 diff = validate_loaded_surface(surface, j, k + level_offset, &src_rect, &dst_point);
16526 /* On some newer (XP+) versions of Windows, it appears the
16527 * source/destination coordinates are divided too often.
16528 * This works correctly on Windows 98 with the RGB
16529 * software rasteriser. */
16530 src_rect_broken = src_rect;
16531 dst_point_broken = dst_point;
16532 for (l = 0; l < level_offset; ++l)
16534 dst_point_broken.x /= 2;
16535 dst_point_broken.y /= 2;
16536 src_rect_broken.top /= 2;
16537 src_rect_broken.left /= 2;
16538 src_rect_broken.right = (src_rect_broken.right + 1) / 2;
16539 src_rect_broken.bottom = (src_rect_broken.bottom + 1) / 2;
16541 diff2 = validate_loaded_surface(surface, j, k + level_offset,
16542 &src_rect_broken, &dst_point_broken);
16544 /* On Windows 8+ things are slightly worse still. Instead
16545 * of applying the correct level offset twice, like on
16546 * XP+, an incorrect offset is applied in addition to the
16547 * correct one. Additionally, on Windows 8+, this offset
16548 * also affects the selected source mip-level, as opposed
16549 * to Windows XP+ where it only affects the
16550 * source/destination coordinates. */
16551 src_rect_broken = src_rect;
16552 dst_point_broken = dst_point;
16553 for (l = 0; l < level_offset_broken; ++l)
16555 dst_point_broken.x /= 2;
16556 dst_point_broken.y /= 2;
16557 src_rect_broken.top /= 2;
16558 src_rect_broken.left /= 2;
16559 src_rect_broken.right = (src_rect_broken.right + 1) / 2;
16560 src_rect_broken.bottom = (src_rect_broken.bottom + 1) / 2;
16562 diff3 = validate_loaded_surface(surface, j, k + level_offset_broken,
16563 &src_rect_broken, &dst_point_broken);
16565 ok(!diff || broken(!diff2 || !diff3), "Test %u, face %u, level %u: "
16566 "Unexpected destination texture level pixels; %u/%u/%u differences.\n",
16567 i, j, k, diff, diff2, diff3);
16569 hr = IDirectDrawSurface7_GetAttachedSurface(surface, &mip_caps, &tmp);
16570 IDirectDrawSurface7_Release(surface);
16571 if (FAILED(hr))
16572 break;
16573 surface = tmp;
16575 dst_point.x /= 2;
16576 dst_point.y /= 2;
16577 src_rect.top /= 2;
16578 src_rect.left /= 2;
16579 src_rect.right = (src_rect.right + 1) / 2;
16580 src_rect.bottom = (src_rect.bottom + 1) / 2;
16583 if (!(tests[i].dst_flags & TEX_CUBE) || ++j >= 6)
16584 break;
16586 face_caps.dwCaps2 = DDSCAPS2_CUBEMAP | (DDSCAPS2_CUBEMAP_POSITIVEX << j);
16587 hr = IDirectDrawSurface7_GetAttachedSurface(dst_surface, &face_caps, &surface);
16588 ok(SUCCEEDED(hr), "Test %u: Failed to get face %u.\n", i, j);
16592 IDirectDrawSurface7_Release(dst_surface);
16593 IDirectDrawSurface7_Release(src_surface);
16595 #undef TEX_MIP
16596 #undef TEX_CUBE
16597 #undef NULL_COORDS
16599 memset(&surface_desc, 0, sizeof(surface_desc));
16600 surface_desc.dwSize = sizeof(surface_desc);
16601 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
16602 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
16603 surface_desc.dwWidth = 128;
16604 surface_desc.dwHeight = 128;
16605 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
16606 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
16607 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 8;
16608 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surface, NULL);
16609 ok(SUCCEEDED(hr), "Failed to create source surface, hr %#x.\n", hr);
16610 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surface, NULL);
16611 ok(SUCCEEDED(hr), "Failed to create destination surface, hr %#x.\n", hr);
16612 hr = IDirectDrawSurface7_GetAttachedSurface(src_surface, &mip_caps, &surface);
16613 ok(SUCCEEDED(hr), "Failed to get surface, hr %#x.\n", hr);
16615 /* Test palette copying. */
16616 memset(table1, 0, sizeof(table1));
16617 table1[0].peBlue = 1;
16618 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &src_palette, NULL);
16619 ok(SUCCEEDED(hr), "Failed to create source palette, hr %#x.\n", hr);
16620 table1[0].peBlue = 3;
16621 hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &dst_palette, NULL);
16622 ok(SUCCEEDED(hr), "Failed to create destination palette, hr %#x.\n", hr);
16624 hr = IDirectDrawSurface7_SetPalette(src_surface, src_palette);
16625 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
16627 hr = IDirect3DDevice7_Load(device, dst_surface, NULL, src_surface, NULL, 0);
16628 ok(SUCCEEDED(hr), "Failed to load texture, hr %#x.\n", hr);
16630 hr = IDirectDrawSurface7_GetPalette(surface, &palette);
16631 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
16632 hr = IDirectDrawSurface7_GetPalette(dst_surface, &palette);
16633 ok(hr == DDERR_NOPALETTEATTACHED, "Got unexpected hr %#x.\n", hr);
16635 hr = IDirectDrawSurface7_SetPalette(surface, src_palette);
16636 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x.\n", hr);
16637 hr = IDirectDrawSurface7_SetPalette(dst_surface, dst_palette);
16638 ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
16640 hr = IDirect3DDevice7_Load(device, dst_surface, NULL, src_surface, NULL, 0);
16641 ok(SUCCEEDED(hr), "Failed to load texture, hr %#x.\n", hr);
16643 hr = IDirectDrawSurface7_GetPalette(dst_surface, &palette);
16644 ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
16645 ok(palette == dst_palette, "Got unexpected palette %p, expected %p.\n", palette, dst_palette);
16646 memset(table1, 0, sizeof(table1));
16647 hr = IDirectDrawPalette_GetEntries(palette, 0, 0, 256, table1);
16648 ok(SUCCEEDED(hr), "Failed to retrieve palette entries, hr %#x.\n", hr);
16649 ok(table1[0].peBlue == 1, "Got unexpected palette colour %#x.\n", (unsigned int)table1[0].peBlue);
16650 IDirectDrawPalette_Release(palette);
16652 IDirectDrawPalette_Release(dst_palette);
16653 IDirectDrawPalette_Release(src_palette);
16655 /* Test colour-key copying. */
16656 colour_key.dwColorSpaceLowValue = 32;
16657 colour_key.dwColorSpaceHighValue = 64;
16658 hr = IDirectDrawSurface7_SetColorKey(src_surface, DDCKEY_SRCBLT, &colour_key);
16659 ok(SUCCEEDED(hr), "Failed to set colour-key, hr %#x.\n", hr);
16660 hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &colour_key);
16661 ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x.\n", hr);
16663 hr = IDirectDrawSurface7_GetColorKey(dst_surface, DDCKEY_SRCBLT, &colour_key);
16664 ok(hr == DDERR_NOCOLORKEY, "Got unexpected hr %#x.\n", hr);
16666 hr = IDirect3DDevice7_Load(device, dst_surface, NULL, src_surface, NULL, 0);
16667 ok(SUCCEEDED(hr), "Failed to load texture, hr %#x.\n", hr);
16669 hr = IDirectDrawSurface7_GetColorKey(dst_surface, DDCKEY_SRCBLT, &colour_key);
16670 ok(SUCCEEDED(hr), "Failed to get colour-key, hr %#x.\n", hr);
16671 ok(colour_key.dwColorSpaceLowValue == 32, "Got unexpected value %u.\n", colour_key.dwColorSpaceLowValue);
16672 ok(colour_key.dwColorSpaceHighValue == 32, "Got unexpected value %u.\n", colour_key.dwColorSpaceHighValue);
16674 IDirectDrawSurface7_Release(surface);
16675 IDirectDrawSurface7_Release(dst_surface);
16676 IDirectDrawSurface7_Release(src_surface);
16678 IDirectDraw7_Release(ddraw);
16679 refcount = IDirect3DDevice7_Release(device);
16680 ok(!refcount, "Device has %u references left.\n", refcount);
16681 DestroyWindow(window);
16684 static void test_color_vertex(void)
16686 IDirect3DDevice7 *device;
16687 IDirectDrawSurface7 *rt;
16688 D3DMATERIAL7 material;
16689 D3DCOLOR colour;
16690 unsigned int i;
16691 ULONG refcount;
16692 HWND window;
16693 HRESULT hr;
16695 static struct
16697 struct vec3 position;
16698 DWORD diffuse;
16699 DWORD specular;
16701 quad_2c[] =
16703 {{-1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff00ff00},
16704 {{-1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff00ff00},
16705 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000, 0xff00ff00},
16706 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000, 0xff00ff00},
16708 static struct
16710 struct vec3 position;
16711 DWORD colour;
16713 quad_1c[] =
16715 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
16716 {{-1.0f, 1.0f, 0.0f}, 0xffff0000},
16717 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000},
16718 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000},
16720 static struct
16722 struct vec3 position;
16724 quad_0c[] =
16726 {{-1.0f, -1.0f, 0.0f}},
16727 {{-1.0f, 1.0f, 0.0f}},
16728 {{ 1.0f, -1.0f, 0.0f}},
16729 {{ 1.0f, 1.0f, 0.0f}},
16732 /* The idea here is to set up ambient light parameters in a way that the
16733 * ambient colour from the material is just passed through. The emissive
16734 * colour is just passed through anyway. The sum of ambient + emissive
16735 * should allow deduction of where the material colour came from. */
16736 static const struct
16738 DWORD fvf, color_vertex, ambient, emissive, result;
16739 void *vtx;
16741 tests[] =
16743 {D3DFVF_DIFFUSE | D3DFVF_SPECULAR, FALSE, D3DMCS_COLOR1, D3DMCS_COLOR2, 0x000000c0, quad_2c},
16745 {D3DFVF_DIFFUSE | D3DFVF_SPECULAR, TRUE, D3DMCS_COLOR1, D3DMCS_COLOR2, 0x00ffff00, quad_2c},
16746 {D3DFVF_DIFFUSE | D3DFVF_SPECULAR, TRUE, D3DMCS_MATERIAL, D3DMCS_COLOR2, 0x0000ff80, quad_2c},
16747 {D3DFVF_DIFFUSE | D3DFVF_SPECULAR, TRUE, D3DMCS_COLOR1, D3DMCS_MATERIAL, 0x00ff0040, quad_2c},
16748 {D3DFVF_DIFFUSE | D3DFVF_SPECULAR, TRUE, D3DMCS_COLOR1, D3DMCS_COLOR1, 0x00ff0000, quad_2c},
16749 {D3DFVF_DIFFUSE | D3DFVF_SPECULAR, TRUE, D3DMCS_COLOR2, D3DMCS_COLOR2, 0x0000ff00, quad_2c},
16751 {D3DFVF_SPECULAR, TRUE, D3DMCS_COLOR1, D3DMCS_COLOR2, 0x00ff0080, quad_1c},
16752 {D3DFVF_SPECULAR, TRUE, D3DMCS_COLOR1, D3DMCS_MATERIAL, 0x000000c0, quad_1c},
16753 {D3DFVF_SPECULAR, TRUE, D3DMCS_MATERIAL, D3DMCS_COLOR2, 0x00ff0080, quad_1c},
16754 {D3DFVF_DIFFUSE, TRUE, D3DMCS_COLOR1, D3DMCS_COLOR2, 0x00ff0040, quad_1c},
16755 {D3DFVF_DIFFUSE, TRUE, D3DMCS_COLOR1, D3DMCS_MATERIAL, 0x00ff0040, quad_1c},
16756 {D3DFVF_DIFFUSE, TRUE, D3DMCS_COLOR2, D3DMCS_MATERIAL, 0x000000c0, quad_1c},
16758 {0, TRUE, D3DMCS_COLOR1, D3DMCS_COLOR2, 0x000000c0, quad_0c},
16761 window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW,
16762 0, 0, 640, 480, 0, 0, 0, 0);
16763 if (!(device = create_device(window, DDSCL_NORMAL)))
16765 skip("Failed to create a 3D device, skipping test.\n");
16766 DestroyWindow(window);
16767 return;
16769 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
16770 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
16772 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
16773 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
16774 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_AMBIENT, 0xffffffff);
16775 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
16777 memset(&material, 0, sizeof(material));
16778 U3(U1(material).ambient).b = 0.5f;
16779 U3(U3(material).emissive).b = 0.25f;
16780 hr = IDirect3DDevice7_SetMaterial(device, &material);
16781 ok(SUCCEEDED(hr), "Failed to set material, hr %#x\n", hr);
16783 for (i = 0; i < ARRAY_SIZE(tests); ++i)
16785 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORVERTEX, tests[i].color_vertex);
16786 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
16787 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_AMBIENTMATERIALSOURCE, tests[i].ambient);
16788 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
16789 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_EMISSIVEMATERIALSOURCE, tests[i].emissive);
16790 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
16791 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
16792 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
16794 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x77777777, 0.0f, 0);
16795 ok(SUCCEEDED(hr), "Failed to clear depth/stencil, hr %#x.\n", hr);
16797 hr = IDirect3DDevice7_BeginScene(device);
16798 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
16799 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
16800 D3DFVF_XYZ | tests[i].fvf, tests[i].vtx, 4, 0);
16801 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
16802 hr = IDirect3DDevice7_EndScene(device);
16803 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
16805 colour = get_surface_color(rt, 320, 240);
16806 ok(compare_color(colour, tests[i].result, 1),
16807 "Expected colour 0x%08x for test %u, got 0x%08x.\n",
16808 tests[i].result, i, colour);
16811 IDirectDrawSurface7_Release(rt);
16812 refcount = IDirect3DDevice7_Release(device);
16813 ok(!refcount, "Device has %u references left.\n", refcount);
16814 DestroyWindow(window);
16817 static IDirectDraw7 *killfocus_ddraw;
16818 static IDirectDrawSurface7 *killfocus_surface;
16820 static LRESULT CALLBACK killfocus_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
16822 ULONG ref;
16824 if (message == WM_KILLFOCUS)
16826 ref = IDirectDrawSurface7_Release(killfocus_surface);
16827 ok(!ref, "Unexpected surface refcount %u.\n", ref);
16828 ref = IDirectDraw7_Release(killfocus_ddraw);
16829 ok(!ref, "Unexpected ddraw refcount %u.\n", ref);
16830 killfocus_ddraw = NULL;
16833 return DefWindowProcA(window, message, wparam, lparam);
16836 static void test_killfocus(void)
16838 DDSURFACEDESC2 surface_desc;
16839 HRESULT hr;
16840 HWND window;
16841 WNDCLASSA wc = {0};
16843 wc.lpfnWndProc = killfocus_proc;
16844 wc.lpszClassName = "ddraw_killfocus_wndproc_wc";
16845 ok(RegisterClassA(&wc), "Failed to register window class.\n");
16847 window = CreateWindowA("ddraw_killfocus_wndproc_wc", "d3d7_test", WS_OVERLAPPEDWINDOW,
16848 0, 0, 640, 480, 0, 0, 0, 0);
16850 killfocus_ddraw = create_ddraw();
16851 ok(!!killfocus_ddraw, "Failed to create a ddraw object.\n");
16853 hr = IDirectDraw7_SetCooperativeLevel(killfocus_ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
16854 ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
16856 memset(&surface_desc, 0, sizeof(surface_desc));
16857 surface_desc.dwSize = sizeof(surface_desc);
16858 surface_desc.dwFlags = DDSD_CAPS;
16859 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
16860 hr = IDirectDraw7_CreateSurface(killfocus_ddraw, &surface_desc, &killfocus_surface, NULL);
16861 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
16863 SetForegroundWindow(GetDesktopWindow());
16864 ok(!killfocus_ddraw, "WM_KILLFOCUS was not received.\n");
16866 DestroyWindow(window);
16867 UnregisterClassA("ddraw_killfocus_wndproc_wc", GetModuleHandleA(NULL));
16870 static void test_sysmem_draw(void)
16872 IDirectDrawSurface7 *rt, *texture;
16873 DDSURFACEDESC2 surface_desc;
16874 D3DVERTEXBUFFERDESC vb_desc;
16875 IDirect3DVertexBuffer7 *vb;
16876 IDirect3DDevice7 *device;
16877 IDirectDraw7 *ddraw;
16878 IDirect3D7 *d3d;
16879 D3DCOLOR colour;
16880 ULONG refcount;
16881 HWND window;
16882 HRESULT hr;
16883 BYTE *data;
16885 static const struct
16887 struct vec3 position;
16888 DWORD diffuse;
16890 quad[] =
16892 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
16893 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
16894 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
16895 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
16897 static WORD indices[] = {0, 1, 2, 3};
16899 window = create_window();
16900 ok(!!window, "Failed to create a window.\n");
16902 if (!(device = create_device(window, DDSCL_NORMAL)))
16904 skip("Failed to create a 3D device, skipping test.\n");
16905 DestroyWindow(window);
16906 return;
16909 hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
16910 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16911 hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
16912 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16913 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
16914 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16916 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
16917 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16919 vb_desc.dwSize = sizeof(vb_desc);
16920 vb_desc.dwCaps = D3DVBCAPS_SYSTEMMEMORY;
16921 vb_desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
16922 vb_desc.dwNumVertices = 4;
16923 hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &vb, 0);
16924 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16926 hr = IDirect3DVertexBuffer7_Lock(vb, 0, (void **)&data, NULL);
16927 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16928 memcpy(data, quad, sizeof(quad));
16929 hr = IDirect3DVertexBuffer7_Unlock(vb);
16930 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16932 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x77777777, 0.0f, 0);
16933 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16935 hr = IDirect3DDevice7_BeginScene(device);
16936 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16937 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, 0);
16938 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16939 hr = IDirect3DDevice7_EndScene(device);
16940 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16942 colour = get_surface_color(rt, 320, 240);
16943 ok(compare_color(colour, 0x00007f7f, 1), "Got unexpected colour 0x%08x.\n", colour);
16945 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x77777777, 0.0f, 0);
16946 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16948 hr = IDirect3DDevice7_BeginScene(device);
16949 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16950 hr = IDirect3DDevice7_DrawIndexedPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, indices, 4, 0);
16951 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16952 hr = IDirect3DDevice7_EndScene(device);
16953 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16955 colour = get_surface_color(rt, 320, 240);
16956 ok(compare_color(colour, 0x00007f7f, 1), "Got unexpected colour 0x%08x.\n", colour);
16958 memset(&surface_desc, 0, sizeof(surface_desc));
16959 surface_desc.dwSize = sizeof(surface_desc);
16960 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
16961 surface_desc.dwHeight = 2;
16962 surface_desc.dwWidth = 2;
16963 surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
16964 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
16965 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
16966 U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
16967 U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
16968 U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
16969 U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
16970 U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0xff000000;
16971 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
16972 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
16973 hr = IDirect3DDevice7_SetTexture(device, 0, texture);
16974 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16976 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x77777777, 0.0f, 0);
16977 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16979 hr = IDirect3DDevice7_BeginScene(device);
16980 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16981 hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, vb, 0, 4, 0);
16982 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
16983 hr = IDirect3DDevice7_EndScene(device);
16984 ok(hr == D3D_OK || hr == D3DERR_SCENE_END_FAILED, "Got unexpected hr %#x.\n", hr);
16986 IDirectDrawSurface7_Release(texture);
16987 IDirect3DVertexBuffer7_Release(vb);
16988 IDirectDrawSurface7_Release(rt);
16989 IDirectDraw7_Release(ddraw);
16990 IDirect3D7_Release(d3d);
16991 refcount = IDirect3DDevice7_Release(device);
16992 ok(!refcount, "Device has %u references left.\n", refcount);
16993 DestroyWindow(window);
16996 static void test_gdi_surface(void)
16998 IDirectDrawSurface7 *primary, *backbuffer, *gdi_surface;
16999 DDSCAPS2 caps = {DDSCAPS_BACKBUFFER, 0, 0, {0}};
17000 DDSURFACEDESC2 surface_desc;
17001 IDirectDraw7 *ddraw;
17002 ULONG refcount;
17003 HWND window;
17004 HRESULT hr;
17006 window = create_window();
17007 ddraw = create_ddraw();
17008 ok(!!ddraw, "Failed to create a ddraw object.\n");
17009 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
17010 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17012 /* Retrieving the GDI surface requires a primary surface to exist. */
17013 gdi_surface = (void *)0xc0dec0de;
17014 hr = IDirectDraw7_GetGDISurface(ddraw, &gdi_surface);
17015 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
17016 ok(!gdi_surface, "Got unexpected surface %p.\n", gdi_surface);
17018 hr = IDirectDraw7_FlipToGDISurface(ddraw);
17019 ok(hr == DDERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
17021 memset(&surface_desc, 0, sizeof(surface_desc));
17022 surface_desc.dwSize = sizeof(surface_desc);
17023 surface_desc.dwFlags = DDSD_CAPS;
17024 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
17025 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
17026 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17028 hr = IDirectDraw7_GetGDISurface(ddraw, &gdi_surface);
17029 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17030 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
17031 IDirectDrawSurface7_Release(gdi_surface);
17033 /* Flipping to the GDI surface requires the primary surface to be
17034 * flippable. */
17035 hr = IDirectDraw7_FlipToGDISurface(ddraw);
17036 ok(hr == DDERR_NOTFLIPPABLE, "Got unexpected hr %#x.\n", hr);
17038 IDirectDrawSurface7_Release(primary);
17040 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
17041 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17043 memset(&surface_desc, 0, sizeof(surface_desc));
17044 surface_desc.dwSize = sizeof(surface_desc);
17045 surface_desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
17046 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
17047 U5(surface_desc).dwBackBufferCount = 1;
17048 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
17049 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17050 hr = IDirectDrawSurface7_GetAttachedSurface(primary, &caps, &backbuffer);
17051 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17052 ok(backbuffer != primary, "Got unexpected backbuffer %p.\n", backbuffer);
17054 hr = IDirectDraw7_GetGDISurface(ddraw, &gdi_surface);
17055 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17056 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
17057 IDirectDrawSurface7_Release(gdi_surface);
17059 hr = IDirectDrawSurface7_Flip(primary, NULL, DDFLIP_WAIT);
17060 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17061 hr = IDirectDraw7_GetGDISurface(ddraw, &gdi_surface);
17062 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17063 ok(gdi_surface == backbuffer || broken(gdi_surface == primary),
17064 "Got unexpected surface %p, expected %p.\n", gdi_surface, backbuffer);
17065 IDirectDrawSurface7_Release(gdi_surface);
17067 hr = IDirectDraw7_FlipToGDISurface(ddraw);
17068 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17070 hr = IDirectDraw7_GetGDISurface(ddraw, &gdi_surface);
17071 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17072 ok(gdi_surface == primary, "Got unexpected surface %p, expected %p.\n", gdi_surface, primary);
17073 IDirectDrawSurface7_Release(gdi_surface);
17075 hr = IDirectDraw7_FlipToGDISurface(ddraw);
17076 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17078 IDirectDrawSurface7_Release(backbuffer);
17079 IDirectDrawSurface7_Release(primary);
17081 refcount = IDirectDraw7_Release(ddraw);
17082 ok(!refcount, "%u references left.\n", refcount);
17083 DestroyWindow(window);
17086 static void test_multiply_transform(void)
17088 IDirect3DDevice7 *device;
17089 D3DMATRIX ret_mat;
17090 DWORD stateblock;
17091 unsigned int i;
17092 ULONG refcount;
17093 HWND window;
17094 HRESULT hr;
17096 static const D3DTRANSFORMSTATETYPE tests[] =
17098 D3DTRANSFORMSTATE_WORLD,
17099 D3DTRANSFORMSTATE_VIEW,
17100 D3DTRANSFORMSTATE_PROJECTION,
17101 D3DTRANSFORMSTATE_WORLD1,
17102 D3DTRANSFORMSTATE_WORLD2,
17103 D3DTRANSFORMSTATE_WORLD3,
17104 D3DTRANSFORMSTATE_TEXTURE0,
17105 D3DTRANSFORMSTATE_TEXTURE1,
17106 D3DTRANSFORMSTATE_TEXTURE2,
17107 D3DTRANSFORMSTATE_TEXTURE3,
17108 D3DTRANSFORMSTATE_TEXTURE4,
17109 D3DTRANSFORMSTATE_TEXTURE5,
17110 D3DTRANSFORMSTATE_TEXTURE6,
17111 D3DTRANSFORMSTATE_TEXTURE7,
17114 D3DMATRIX mat1 =
17116 1.0f, 0.0f, 0.0f, 0.0f,
17117 0.0f, 1.0f, 0.0f, 0.0f,
17118 0.0f, 0.0f, 1.0f, 0.0f,
17119 0.0f, 0.0f, 0.0f, 1.0f,
17121 mat2 =
17123 2.0f, 0.0f, 0.0f, 0.0f,
17124 0.0f, 2.0f, 0.0f, 0.0f,
17125 0.0f, 0.0f, 2.0f, 0.0f,
17126 0.0f, 0.0f, 0.0f, 2.0f,
17129 window = create_window();
17130 if (!(device = create_device(window, DDSCL_NORMAL)))
17132 skip("Failed to create 3D device.\n");
17133 DestroyWindow(window);
17134 return;
17137 for (i = 0; i < ARRAY_SIZE(tests); ++i)
17139 hr = IDirect3DDevice7_GetTransform(device, tests[i], &ret_mat);
17140 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
17141 ok(!memcmp(&ret_mat, &mat1, sizeof(mat1)), "Test %u: Got unexpected transform matrix.\n", i);
17143 hr = IDirect3DDevice7_MultiplyTransform(device, tests[i], &mat2);
17144 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
17146 hr = IDirect3DDevice7_GetTransform(device, tests[i], &ret_mat);
17147 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
17148 ok(!memcmp(&ret_mat, &mat2, sizeof(mat2)), "Test %u: Got unexpected transform matrix.\n", i);
17150 /* MultiplyTransform() goes directly into the primary stateblock. */
17152 hr = IDirect3DDevice7_SetTransform(device, tests[i], &mat1);
17153 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
17155 hr = IDirect3DDevice7_BeginStateBlock(device);
17156 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
17158 hr = IDirect3DDevice7_MultiplyTransform(device, tests[i], &mat2);
17159 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
17161 hr = IDirect3DDevice7_EndStateBlock(device, &stateblock);
17162 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
17164 hr = IDirect3DDevice7_GetTransform(device, tests[i], &ret_mat);
17165 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
17166 ok(!memcmp(&ret_mat, &mat2, sizeof(mat2)), "Test %u: Got unexpected transform matrix.\n", i);
17168 hr = IDirect3DDevice7_CaptureStateBlock(device, stateblock);
17169 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
17171 hr = IDirect3DDevice7_SetTransform(device, tests[i], &mat1);
17172 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
17174 hr = IDirect3DDevice7_ApplyStateBlock(device, stateblock);
17175 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
17177 hr = IDirect3DDevice7_GetTransform(device, tests[i], &ret_mat);
17178 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
17179 ok(!memcmp(&ret_mat, &mat1, sizeof(mat1)), "Test %u: Got unexpected transform matrix.\n", i);
17181 IDirect3DDevice7_DeleteStateBlock(device, stateblock);
17184 refcount = IDirect3DDevice7_Release(device);
17185 ok(!refcount, "Device has %u references left.\n", refcount);
17186 DestroyWindow(window);
17189 static void test_alphatest(void)
17191 #define ALPHATEST_PASSED 0x0000ff00
17192 #define ALPHATEST_FAILED 0x00ff0000
17193 IDirect3DDevice7 *device;
17194 IDirectDrawSurface7 *rt;
17195 unsigned int i;
17196 D3DCOLOR color;
17197 ULONG refcount;
17198 HWND window;
17199 DWORD value;
17200 HRESULT hr;
17202 static const struct
17204 D3DCMPFUNC func;
17205 D3DCOLOR color_less;
17206 D3DCOLOR color_equal;
17207 D3DCOLOR color_greater;
17209 test_data[] =
17211 {D3DCMP_NEVER, ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_FAILED},
17212 {D3DCMP_LESS, ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_FAILED},
17213 {D3DCMP_EQUAL, ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_FAILED},
17214 {D3DCMP_LESSEQUAL, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_FAILED},
17215 {D3DCMP_GREATER, ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_PASSED},
17216 {D3DCMP_NOTEQUAL, ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_PASSED},
17217 {D3DCMP_GREATEREQUAL, ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_PASSED},
17218 {D3DCMP_ALWAYS, ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_PASSED},
17220 static struct
17222 struct vec3 position;
17223 DWORD diffuse;
17225 quad[] =
17227 {{-1.0f, -1.0f, 0.1f}, ALPHATEST_PASSED | 0x80000000},
17228 {{-1.0f, 1.0f, 0.1f}, ALPHATEST_PASSED | 0x80000000},
17229 {{ 1.0f, -1.0f, 0.1f}, ALPHATEST_PASSED | 0x80000000},
17230 {{ 1.0f, 1.0f, 0.1f}, ALPHATEST_PASSED | 0x80000000},
17233 window = create_window();
17234 if (!(device = create_device(window, DDSCL_NORMAL)))
17236 skip("Failed to create a 3D device.\n");
17237 DestroyWindow(window);
17238 return;
17240 hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
17241 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17243 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
17244 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17245 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
17246 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17247 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
17248 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17249 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHATESTENABLE, TRUE);
17250 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17252 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
17254 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHAFUNC, test_data[i].func);
17255 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17257 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, ALPHATEST_FAILED, 0.0f, 0);
17258 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17259 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHAREF, 0x70);
17260 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17261 hr = IDirect3DDevice7_BeginScene(device);
17262 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17263 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
17264 D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, ARRAY_SIZE(quad), 0);
17265 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17266 hr = IDirect3DDevice7_EndScene(device);
17267 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17268 color = get_surface_color(rt, 320, 240);
17269 ok(compare_color(color, test_data[i].color_greater, 0),
17270 "Alphatest failed, color 0x%08x, expected 0x%08x, alpha > ref, func %u.\n",
17271 color, test_data[i].color_greater, test_data[i].func);
17273 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, ALPHATEST_FAILED, 0.0f, 0);
17274 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17275 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHAREF, 0xff70);
17276 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17277 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_ALPHAREF, &value);
17278 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17279 ok(value == 0xff70, "Got unexpected value %#x.\n", value);
17280 hr = IDirect3DDevice7_BeginScene(device);
17281 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17282 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
17283 D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, ARRAY_SIZE(quad), 0);
17284 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17285 hr = IDirect3DDevice7_EndScene(device);
17286 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17287 color = get_surface_color(rt, 320, 240);
17288 ok(compare_color(color, test_data[i].color_greater, 0),
17289 "Alphatest failed, color 0x%08x, expected 0x%08x, alpha > ref, func %u.\n",
17290 color, test_data[i].color_greater, test_data[i].func);
17293 IDirectDrawSurface7_Release(rt);
17294 refcount = IDirect3DDevice7_Release(device);
17295 ok(!refcount, "Device has %u references left.\n", refcount);
17296 DestroyWindow(window);
17299 static void test_clipper_refcount(void)
17301 IDirectDrawSurface7 *surface;
17302 IDirectDrawClipper *clipper, *clipper2;
17303 DDSURFACEDESC2 surface_desc;
17304 IDirectDraw7 *ddraw;
17305 IDirectDraw *ddraw1;
17306 ULONG refcount;
17307 HWND window;
17308 HRESULT hr;
17309 BOOL changed;
17310 const IDirectDrawClipperVtbl *orig_vtbl;
17312 window = create_window();
17313 ddraw = create_ddraw();
17314 ok(!!ddraw, "Failed to create a ddraw object.\n");
17315 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
17316 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17318 memset(&surface_desc, 0, sizeof(surface_desc));
17319 surface_desc.dwSize = sizeof(surface_desc);
17320 surface_desc.dwFlags = DDSD_CAPS;
17321 surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
17322 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
17323 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17325 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
17326 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
17327 refcount = get_refcount((IUnknown *)clipper);
17328 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
17330 /* Show that clipper validation doesn't somehow happen through per-clipper vtable
17331 * pointers. */
17332 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper2, NULL);
17333 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
17334 ok(clipper->lpVtbl == clipper2->lpVtbl, "Got different clipper vtables %p and %p.\n",
17335 clipper->lpVtbl, clipper2->lpVtbl);
17336 orig_vtbl = clipper->lpVtbl;
17337 IDirectDrawClipper_Release(clipper2);
17339 /* Surfaces hold a reference to clippers. No surprises there. */
17340 hr = IDirectDrawSurface7_SetClipper(surface, clipper);
17341 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
17342 refcount = get_refcount((IUnknown *)clipper);
17343 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
17345 hr = IDirectDrawSurface7_GetClipper(surface, &clipper2);
17346 ok(SUCCEEDED(hr), "Failed to get clipper, hr %#x.\n", hr);
17347 ok(clipper == clipper2, "Got clipper %p, expected %p.\n", clipper2, clipper);
17348 refcount = IDirectDrawClipper_Release(clipper2);
17349 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
17351 hr = IDirectDrawSurface7_SetClipper(surface, NULL);
17352 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
17353 refcount = get_refcount((IUnknown *)clipper);
17354 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
17356 hr = IDirectDrawSurface7_SetClipper(surface, clipper);
17357 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
17358 refcount = get_refcount((IUnknown *)clipper);
17359 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
17361 refcount = IDirectDrawSurface7_Release(surface);
17362 ok(!refcount, "%u references left.\n", refcount);
17363 refcount = get_refcount((IUnknown *)clipper);
17364 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
17366 /* SetClipper with an invalid pointer crashes. */
17368 /* Clipper methods work with a broken vtable, with the exception of Release. */
17369 clipper->lpVtbl = (void *)0xdeadbeef;
17370 refcount = orig_vtbl->AddRef(clipper);
17371 todo_wine ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
17372 refcount = orig_vtbl->Release(clipper);
17373 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
17375 clipper->lpVtbl = orig_vtbl;
17376 refcount = orig_vtbl->Release(clipper);
17377 todo_wine ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
17379 /* Fix the refcount difference because Wine did not increase the ref in the
17380 * AddRef call above. */
17381 if (refcount)
17383 refcount = IDirectDrawClipper_Release(clipper);
17384 ok(!refcount, "Got unexpected refcount %u.\n", refcount);
17387 /* Steal the reference and see what happens - releasing the surface works fine.
17388 * The clipper is destroyed and not kept alive by a hidden refcount - trying to
17389 * release it after the GetClipper call is likely to crash, and certain to crash
17390 * if we allocate and zero as much heap memory as we can get. */
17391 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
17392 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17393 hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL);
17394 ok(SUCCEEDED(hr), "Failed to create clipper, hr %#x.\n", hr);
17395 hr = IDirectDrawSurface7_SetClipper(surface, clipper);
17396 ok(SUCCEEDED(hr), "Failed to set clipper, hr %#x.\n", hr);
17398 IDirectDrawClipper_Release(clipper);
17399 IDirectDrawClipper_Release(clipper);
17401 if (0)
17403 /* Disabled because it causes heap corruption (HeapValidate fails and random
17404 * hangs in a later HeapFree) on Windows on one of my Machines: MacbookPro 10,1
17405 * running Windows 10 18363.535 and Nvidia driver 425.31. Driver version 441.66
17406 * is affected too. Some testbot machines have crashes directly in GetClipper
17407 * or proceed with a corrupted heap too.
17409 * The same Windows and driver versions run the test without heap corruption on
17410 * a Geforce 1060 GTX card. I have not seen the problem on AMD GPUs either. */
17411 hr = IDirectDrawSurface7_GetClipper(surface, &clipper2);
17412 ok(SUCCEEDED(hr), "Failed to get clipper, hr %#x.\n", hr);
17413 ok(clipper == clipper2, "Got clipper %p, expected %p.\n", clipper2, clipper);
17416 /* Show that invoking the Release method does not crash, but don't get the
17417 * vtable through the clipper pointer because it is no longer pointing to
17418 * valid memory. */
17419 refcount = orig_vtbl->Release(clipper);
17420 ok(!refcount, "%u references left.\n", refcount);
17422 refcount = IDirectDrawSurface7_Release(surface);
17423 ok(!refcount, "%u references left.\n", refcount);
17425 /* It looks like the protection against invalid thispointers is part of
17426 * the IDirectDrawClipper method implementation, not IDirectDrawSurface. */
17427 clipper = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 0x1000);
17428 ok(!!clipper, "failed to allocate memory\n");
17430 /* Assigning the vtable to our fake clipper does NOT make a difference on
17431 * native - there is a different member of the clipper implementation struct
17432 * that is used to determine if a clipper is valid. */
17433 clipper->lpVtbl = orig_vtbl;
17435 refcount = orig_vtbl->AddRef(clipper);
17436 todo_wine ok(!refcount, "Got refcount %u.\n", refcount);
17437 refcount = orig_vtbl->AddRef((IDirectDrawClipper *)(ULONG_PTR)0xdeadbeef);
17438 ok(!refcount, "Got refcount %u.\n", refcount);
17440 changed = 0x1234;
17441 hr = orig_vtbl->IsClipListChanged(clipper, &changed);
17442 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
17443 todo_wine ok(changed == 0x1234, "'changed' changed: %x.\n", changed);
17445 changed = 0x1234;
17446 hr = orig_vtbl->IsClipListChanged((IDirectDrawClipper *)(ULONG_PTR)0xdeadbeef, &changed);
17447 ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
17448 ok(changed == 0x1234, "'changed' changed: %x.\n", changed);
17450 /* Nope, we can't initialize our fake clipper. */
17451 hr = IDirectDraw7_QueryInterface(ddraw, &IID_IDirectDraw, (void **)&ddraw1);
17452 ok(SUCCEEDED(hr), "Failed to get ddraw1 interface, hr %#x.\n", hr);
17454 hr = orig_vtbl->Initialize(clipper, ddraw1, 0);
17455 todo_wine ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
17457 IDirectDraw_Release(ddraw1);
17459 HeapFree(GetProcessHeap(), 0, clipper);
17461 refcount = IDirectDraw7_Release(ddraw);
17462 ok(!refcount, "%u references left.\n", refcount);
17463 DestroyWindow(window);
17466 static void test_begin_end_state_block(void)
17468 DWORD stateblock, stateblock2;
17469 IDirect3DDevice7 *device;
17470 ULONG refcount;
17471 DWORD value;
17472 HWND window;
17473 HRESULT hr;
17475 window = create_window();
17476 if (!(device = create_device(window, DDSCL_NORMAL)))
17478 skip("Failed to create 3D device.\n");
17479 DestroyWindow(window);
17480 return;
17483 hr = IDirect3DDevice7_BeginStateBlock(device);
17484 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17486 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
17487 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17489 stateblock = 0xdeadbeef;
17490 hr = IDirect3DDevice7_EndStateBlock(device, &stateblock);
17491 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17492 ok(!!stateblock && stateblock != 0xdeadbeef, "Got unexpected stateblock %#x.\n", stateblock);
17494 stateblock2 = 0xdeadbeef;
17495 hr = IDirect3DDevice7_EndStateBlock(device, &stateblock2);
17496 ok(hr == D3DERR_NOTINBEGINSTATEBLOCK, "Got unexpected hr %#x.\n", hr);
17497 ok(stateblock2 == 0xdeadbeef, "Got unexpected stateblock %#x.\n", stateblock2);
17499 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &value);
17500 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17501 ok(value == TRUE, "Got unexpected value %#x.\n", value);
17503 hr = IDirect3DDevice7_BeginStateBlock(device);
17504 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17506 hr = IDirect3DDevice7_BeginStateBlock(device);
17507 ok(hr == D3DERR_INBEGINSTATEBLOCK, "Got unexpected hr %#x.\n", hr);
17509 hr = IDirect3DDevice7_ApplyStateBlock(device, stateblock);
17510 ok(hr == D3DERR_INBEGINSTATEBLOCK, "Got unexpected hr %#x.\n", hr);
17512 hr = IDirect3DDevice7_CaptureStateBlock(device, stateblock);
17513 ok(hr == D3DERR_INBEGINSTATEBLOCK, "Got unexpected hr %#x.\n", hr);
17515 hr = IDirect3DDevice7_CreateStateBlock(device, D3DSBT_ALL, &stateblock2);
17516 ok(hr == D3DERR_INBEGINSTATEBLOCK, "Got unexpected hr %#x.\n", hr);
17518 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &value);
17519 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17520 ok(value == TRUE, "Got unexpected value %#x.\n", value);
17522 hr = IDirect3DDevice7_EndStateBlock(device, &stateblock2);
17523 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17525 hr = IDirect3DDevice7_ApplyStateBlock(device, stateblock2);
17526 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17528 hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &value);
17529 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
17530 ok(value == TRUE, "Got unexpected value %#x.\n", value);
17532 refcount = IDirect3DDevice7_Release(device);
17533 ok(!refcount, "Device has %u references left.\n", refcount);
17534 DestroyWindow(window);
17537 static void test_caps(void)
17539 DWORD caps_never, caps_always, caps_hal;
17540 DDCAPS hal_caps, hel_caps;
17541 IDirectDraw7 *ddraw;
17542 HRESULT hr;
17543 BOOL no3d;
17545 caps_never = DDSCAPS_RESERVED1
17546 | DDSCAPS_ALPHA
17547 | DDSCAPS_PRIMARYSURFACELEFT
17548 | DDSCAPS_SYSTEMMEMORY
17549 | DDSCAPS_VISIBLE
17550 | DDSCAPS_WRITEONLY
17551 | DDSCAPS_LIVEVIDEO
17552 | DDSCAPS_HWCODEC
17553 | DDSCAPS_MODEX
17554 | DDSCAPS_RESERVED2
17555 | 0x01000000u
17556 | 0x02000000u
17557 | DDSCAPS_ALLOCONLOAD
17558 | DDSCAPS_VIDEOPORT
17559 | DDSCAPS_STANDARDVGAMODE
17560 | DDSCAPS_OPTIMIZED;
17562 caps_always = DDSCAPS_FLIP
17563 | DDSCAPS_OFFSCREENPLAIN
17564 | DDSCAPS_PRIMARYSURFACE
17565 | DDSCAPS_TEXTURE
17566 | DDSCAPS_ZBUFFER
17567 | DDSCAPS_MIPMAP;
17569 caps_hal = DDSCAPS_BACKBUFFER
17570 | DDSCAPS_COMPLEX
17571 | DDSCAPS_FRONTBUFFER
17572 | DDSCAPS_3DDEVICE
17573 | DDSCAPS_VIDEOMEMORY
17574 | DDSCAPS_LOCALVIDMEM
17575 | DDSCAPS_NONLOCALVIDMEM;
17577 ddraw = create_ddraw();
17578 ok(!!ddraw, "Failed to create a ddraw object.\n");
17580 memset(&hal_caps, 0, sizeof(hal_caps));
17581 memset(&hel_caps, 0, sizeof(hel_caps));
17582 hal_caps.dwSize = sizeof(hal_caps);
17583 hel_caps.dwSize = sizeof(hel_caps);
17584 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, &hel_caps);
17585 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17586 ok(hal_caps.ddsOldCaps.dwCaps == hal_caps.ddsCaps.dwCaps,
17587 "Got unexpected caps %#x, expected %#x.\n",
17588 hal_caps.ddsOldCaps.dwCaps, hal_caps.ddsCaps.dwCaps);
17589 ok(hel_caps.ddsOldCaps.dwCaps == hel_caps.ddsCaps.dwCaps,
17590 "Got unexpected caps %#x, expected %#x.\n",
17591 hel_caps.ddsOldCaps.dwCaps, hel_caps.ddsCaps.dwCaps);
17593 no3d = !(hal_caps.ddsCaps.dwCaps & DDSCAPS_3DDEVICE);
17594 if (hal_caps.ddsCaps.dwCaps)
17596 ok(!(hal_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
17597 ok(!(~hal_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
17598 todo_wine_if(no3d) ok(!(~hal_caps.ddsCaps.dwCaps & caps_hal),
17599 "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
17601 ok(!(hel_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
17602 ok(!(~hel_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
17603 todo_wine_if(!no3d) ok(!(hel_caps.ddsCaps.dwCaps & caps_hal),
17604 "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
17606 IDirectDraw7_Release(ddraw);
17608 if (hal_caps.ddsCaps.dwCaps)
17610 hr = pDirectDrawCreateEx((GUID *)DDCREATE_HARDWAREONLY, (void **)&ddraw, &IID_IDirectDraw7, NULL);
17611 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17613 memset(&hal_caps, 0, sizeof(hal_caps));
17614 memset(&hel_caps, 0, sizeof(hel_caps));
17615 hal_caps.dwSize = sizeof(hal_caps);
17616 hel_caps.dwSize = sizeof(hel_caps);
17617 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, &hel_caps);
17618 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17619 ok(hal_caps.ddsOldCaps.dwCaps == hal_caps.ddsCaps.dwCaps,
17620 "Got unexpected caps %#x, expected %#x.\n",
17621 hal_caps.ddsOldCaps.dwCaps, hal_caps.ddsCaps.dwCaps);
17622 ok(hel_caps.ddsOldCaps.dwCaps == hel_caps.ddsCaps.dwCaps,
17623 "Got unexpected caps %#x, expected %#x.\n",
17624 hel_caps.ddsOldCaps.dwCaps, hel_caps.ddsCaps.dwCaps);
17626 ok(!(hal_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
17627 ok(!(~hal_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
17628 todo_wine_if(no3d) ok(!(~hal_caps.ddsCaps.dwCaps & caps_hal),
17629 "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
17630 todo_wine ok(!hel_caps.ddsCaps.dwCaps, "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
17632 IDirectDraw7_Release(ddraw);
17635 hr = pDirectDrawCreateEx((GUID *)DDCREATE_EMULATIONONLY, (void **)&ddraw, &IID_IDirectDraw7, NULL);
17636 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17638 memset(&hal_caps, 0, sizeof(hal_caps));
17639 memset(&hel_caps, 0, sizeof(hel_caps));
17640 hal_caps.dwSize = sizeof(hal_caps);
17641 hel_caps.dwSize = sizeof(hel_caps);
17642 hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, &hel_caps);
17643 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17644 ok(hal_caps.ddsOldCaps.dwCaps == hal_caps.ddsCaps.dwCaps,
17645 "Got unexpected caps %#x, expected %#x.\n",
17646 hal_caps.ddsOldCaps.dwCaps, hal_caps.ddsCaps.dwCaps);
17647 ok(hel_caps.ddsOldCaps.dwCaps == hel_caps.ddsCaps.dwCaps,
17648 "Got unexpected caps %#x, expected %#x.\n",
17649 hel_caps.ddsOldCaps.dwCaps, hel_caps.ddsCaps.dwCaps);
17651 todo_wine ok(!hal_caps.ddsCaps.dwCaps, "Got unexpected caps %#x.\n", hal_caps.ddsCaps.dwCaps);
17652 ok(!(hel_caps.ddsCaps.dwCaps & caps_never), "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
17653 ok(!(~hel_caps.ddsCaps.dwCaps & caps_always), "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
17654 todo_wine_if(!no3d) ok(!(hel_caps.ddsCaps.dwCaps & caps_hal),
17655 "Got unexpected caps %#x.\n", hel_caps.ddsCaps.dwCaps);
17657 IDirectDraw7_Release(ddraw);
17660 static void test_d32_support(void)
17662 IDirectDrawSurface7 *surface;
17663 DDSURFACEDESC2 surface_desc;
17664 IDirectDraw7 *ddraw;
17665 ULONG refcount;
17666 HWND window;
17667 HRESULT hr;
17669 window = create_window();
17670 ddraw = create_ddraw();
17671 ok(!!ddraw, "Failed to create a ddraw object.\n");
17672 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
17673 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17675 memset(&surface_desc, 0, sizeof(surface_desc));
17676 surface_desc.dwSize = sizeof(surface_desc);
17677 surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
17678 surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
17679 U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
17680 U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
17681 U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = 32;
17682 U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = 0xffffffff;
17683 surface_desc.dwWidth = 64;
17684 surface_desc.dwHeight = 64;
17685 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
17686 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17688 memset(&surface_desc, 0, sizeof(surface_desc));
17689 surface_desc.dwSize = sizeof(surface_desc);
17690 hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
17691 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17692 ok((surface_desc.dwFlags & DDSD_PIXELFORMAT), "Got unexpected flags %#x.\n", surface_desc.dwFlags);
17693 ok(U4(surface_desc).ddpfPixelFormat.dwFlags & DDPF_ZBUFFER,
17694 "Got unexpected format flags %#x.\n", U4(surface_desc).ddpfPixelFormat.dwFlags);
17695 ok(U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth == 32,
17696 "Got unexpected dwZBufferBitDepth %u.\n", U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth);
17697 ok(U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask == 0xffffffff,
17698 "Got unexpected Z mask 0x%08x.\n", U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask);
17699 ok(!(surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY),
17700 "Got unexpected surface caps %#x.\n", surface_desc.ddsCaps.dwCaps);
17701 IDirectDrawSurface7_Release(surface);
17703 refcount = IDirectDraw7_Release(ddraw);
17704 ok(!refcount, "%u references left.\n", refcount);
17705 DestroyWindow(window);
17708 static void test_surface_format_conversion_alpha(void)
17710 static const unsigned int rgba_data[4 * 4] =
17712 0xff00ff00, 0xff0000ff, 0xff0000ff, 0xff0000ff,
17713 0xff0000ff, 0xff00ff00, 0xff0000ff, 0xff0000ff,
17714 0xff00ff00, 0xff0000ff, 0xff00ff00, 0xff0000ff,
17715 0xff00ff00, 0xff0000ff, 0xff0000ff, 0xff00ff00,
17717 static const unsigned int rgbx_data[4 * 4] =
17719 0x0000ff00, 0x000000ff, 0x000000ff, 0x000000ff,
17720 0x000000ff, 0x0000ff00, 0x000000ff, 0x000000ff,
17721 0x0000ff00, 0x000000ff, 0x0000ff00, 0x000000ff,
17722 0x0000ff00, 0x000000ff, 0x000000ff, 0x0000ff00,
17724 static const unsigned short int r5g6b5_data[4 * 4] =
17726 0x07e0, 0x001f, 0x001f, 0x001f,
17727 0x001f, 0x07e0, 0x001f, 0x001f,
17728 0x07e0, 0x001f, 0x07e0, 0x001f,
17729 0x07e0, 0x001f, 0x001f, 0x07e0,
17731 static const unsigned short int r5g5b5x1_data[4 * 4] =
17733 0x03e0, 0x001f, 0x001f, 0x001f,
17734 0x001f, 0x03e0, 0x001f, 0x001f,
17735 0x03e0, 0x001f, 0x03e0, 0x001f,
17736 0x03e0, 0x001f, 0x001f, 0x03e0,
17738 static const unsigned short int r5g5b5a1_data[4 * 4] =
17740 0x83e0, 0x801f, 0x801f, 0x801f,
17741 0x801f, 0x83e0, 0x801f, 0x801f,
17742 0x83e0, 0x801f, 0x83e0, 0x801f,
17743 0x83e0, 0x801f, 0x801f, 0x83e0,
17745 static const unsigned int dxt1_data[8] =
17747 0x001f07e0, 0x14445154,
17749 static const unsigned int dxt2_data[16] =
17751 0xffffffff, 0xffffffff, 0x001f07e0, 0x14445154,
17754 enum test_format_id
17756 FMT_RGBA,
17757 FMT_RGBX,
17758 FMT_R5G6B5,
17759 FMT_R5G5B5X1,
17760 FMT_R5G5B5A1,
17761 FMT_DXT1,
17762 FMT_DXT2,
17763 FMT_DXT3,
17766 static const struct test_format
17768 DDPIXELFORMAT fmt;
17769 const char *name;
17770 unsigned int block_size, x_blocks, y_blocks;
17771 DWORD support_flag;
17772 BOOL broken_software_blit, broken_hardware_blit;
17774 formats[] =
17778 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
17779 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
17781 "RGBA", 4, 4, 4,
17785 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
17786 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
17788 "RGBX", 4, 4, 4,
17792 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
17793 {16}, {0x0000f800}, {0x000007e0}, {0x0000001f}, {0x00000000}
17795 "R5G6B5", 2, 4, 4, 0, TRUE,
17796 /* Looks broken for sysmem texture conversions on Windows (at
17797 * least with hardware device), the result is either error from
17798 * _Blt() or a copy of the source data without any conversion. */
17802 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
17803 {16}, {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00000000}
17805 "R5G5B5X1", 2, 4, 4,
17809 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
17810 {16}, {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00008000}
17812 "R5G5B5A1", 2, 4, 4, 0, FALSE, TRUE,
17816 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
17817 {0}, {0}, {0}, {0}, {0}
17819 "DXT1", 8, 1, 1, SUPPORT_DXT1,
17823 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '2'),
17824 {0}, {0}, {0}, {0}, {0}
17826 "DXT2", 16, 1, 1, SUPPORT_DXT2,
17830 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '3'),
17831 {0}, {0}, {0}, {0}, {0}
17833 "DXT3", 16, 1, 1, SUPPORT_DXT3,
17837 static const struct
17839 DWORD src_caps, dst_caps;
17841 test_caps[] =
17843 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY},
17844 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY},
17845 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY},
17846 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY},
17849 static const struct
17851 enum test_format_id src_format;
17852 const void *src_data;
17853 enum test_format_id dst_format;
17854 const void *expected_data;
17855 BOOL todo;
17857 tests[] =
17859 #if 0
17860 /* The following 3 tests give different results on AMD and NVIDIA on Windows, disabling. */
17861 {FMT_RGBX, rgbx_data, FMT_RGBA, rgba_data},
17862 {FMT_RGBA, rgba_data, FMT_RGBX, rgbx_data},
17863 {FMT_R5G5B5X1, r5g5b5x1_data, FMT_RGBA, rgba_data},
17864 #endif
17865 {FMT_R5G6B5, r5g6b5_data, FMT_RGBA, rgba_data},
17866 {FMT_R5G6B5, r5g6b5_data, FMT_R5G5B5A1, r5g5b5a1_data},
17867 {FMT_R5G5B5X1, r5g5b5x1_data, FMT_R5G5B5A1, r5g5b5x1_data, TRUE},
17868 {FMT_R5G5B5A1, r5g5b5a1_data, FMT_R5G6B5, r5g6b5_data},
17869 {FMT_RGBA, rgba_data, FMT_DXT1, dxt1_data},
17870 {FMT_RGBX, rgbx_data, FMT_DXT1, dxt1_data},
17871 {FMT_RGBA, rgba_data, FMT_DXT2, dxt2_data},
17872 {FMT_RGBX, rgbx_data, FMT_DXT2, dxt2_data},
17873 {FMT_RGBA, rgba_data, FMT_DXT3, dxt2_data},
17874 {FMT_RGBX, rgbx_data, FMT_DXT3, dxt2_data},
17875 {FMT_DXT1, dxt1_data, FMT_DXT2, dxt2_data},
17876 {FMT_DXT1, dxt1_data, FMT_RGBA, rgba_data},
17877 {FMT_DXT1, dxt1_data, FMT_RGBX, rgba_data},
17878 {FMT_DXT3, dxt2_data, FMT_RGBA, rgba_data},
17879 {FMT_DXT3, dxt2_data, FMT_RGBX, rgba_data},
17882 const struct test_format *src_format, *dst_format;
17883 IDirectDrawSurface7 *src_surf, *dst_surf;
17884 DDSURFACEDESC2 surface_desc, lock;
17885 unsigned int i, j, x, y, pitch;
17886 IDirect3DDevice7 *device;
17887 DWORD supported_fmts;
17888 IDirectDraw7 *ddraw;
17889 ULONG refcount;
17890 BOOL is_wine;
17891 HWND window;
17892 BOOL passed;
17893 HRESULT hr;
17895 window = create_window();
17896 if (!(device = create_device(window, DDSCL_NORMAL)))
17898 skip("Failed to create a 3D device, skipping test.\n");
17899 DestroyWindow(window);
17900 return;
17903 ddraw = create_ddraw();
17904 ok(!!ddraw, "Failed to create a ddraw object.\n");
17905 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
17906 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17908 hr = IDirect3DDevice7_EnumTextureFormats(device, test_block_formats_creation_cb,
17909 &supported_fmts);
17910 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17912 is_wine = !strcmp(winetest_platform, "wine");
17914 memset(&surface_desc, 0, sizeof(surface_desc));
17915 surface_desc.dwSize = sizeof(surface_desc);
17916 surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
17917 surface_desc.dwWidth = 4;
17918 surface_desc.dwHeight = 4;
17920 for (i = 0; i < ARRAY_SIZE(tests); ++i)
17922 src_format = &formats[tests[i].src_format];
17923 dst_format = &formats[tests[i].dst_format];
17925 if (~supported_fmts & dst_format->support_flag)
17927 skip("%s format is not supported, skipping test %u.\n", dst_format->name, i);
17928 continue;
17930 if (~supported_fmts & src_format->support_flag)
17932 skip("%s format is not supported, skipping test %u.\n", src_format->name, i);
17933 continue;
17936 for (j = 0; j < ARRAY_SIZE(test_caps); ++j)
17938 if (!is_wine && ((test_caps[j].src_caps | test_caps[j].dst_caps) & DDSCAPS_SYSTEMMEMORY)
17939 && (src_format->broken_software_blit || dst_format->broken_software_blit))
17940 continue;
17941 if (!is_wine && (test_caps[j].dst_caps & DDSCAPS_VIDEOMEMORY)
17942 && dst_format->broken_hardware_blit)
17943 continue;
17945 U4(surface_desc).ddpfPixelFormat = src_format->fmt;
17946 surface_desc.ddsCaps.dwCaps = test_caps[j].src_caps;
17947 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src_surf, NULL);
17948 ok(hr == DD_OK, "Test (%u, %u), got unexpected hr %#x.\n", j, i, hr);
17950 U4(surface_desc).ddpfPixelFormat = dst_format->fmt;
17951 surface_desc.ddsCaps.dwCaps = test_caps[j].dst_caps;
17952 hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst_surf, NULL);
17953 ok(hr == DD_OK, "Test (%u, %u), got unexpected hr %#x.\n", j, i, hr);
17955 memset(&lock, 0, sizeof(lock));
17956 lock.dwSize = sizeof(lock);
17957 hr = IDirectDrawSurface7_Lock(src_surf, NULL, &lock, 0, NULL);
17958 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17959 pitch = U1(lock).lPitch;
17960 for (y = 0; y < src_format->y_blocks; ++y)
17962 memcpy((BYTE *)lock.lpSurface + y * pitch,
17963 (BYTE *)tests[i].src_data + y * src_format->x_blocks * src_format->block_size,
17964 src_format->block_size * src_format->x_blocks);
17966 hr = IDirectDrawSurface7_Unlock(src_surf, NULL);
17967 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17969 hr = IDirectDrawSurface7_Blt(dst_surf, NULL, src_surf, NULL, DDBLT_WAIT, NULL);
17970 if (!is_wine && FAILED(hr))
17972 /* Some software blits are rejected on Windows. */
17973 IDirectDrawSurface7_Release(dst_surf);
17974 IDirectDrawSurface7_Release(src_surf);
17975 skip("Skipping test (%u, %u), cannot blit %s -> %s, hr %#x.\n", j, i,
17976 src_format->name, dst_format->name, hr);
17977 continue;
17979 ok(hr == DD_OK, "Test (%u, %s -> %s), got unexpected hr %#x.\n", j,
17980 src_format->name, dst_format->name, hr);
17982 memset(&lock, 0, sizeof(lock));
17983 lock.dwSize = sizeof(lock);
17984 hr = IDirectDrawSurface7_Lock(dst_surf, NULL, &lock, 0, NULL);
17985 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
17986 pitch = U1(lock).lPitch;
17988 for (y = 0; y < dst_format->y_blocks; ++y)
17990 const void *expected_data = tests[i].expected_data;
17992 passed = !memcmp((BYTE*)lock.lpSurface + y * pitch,
17993 (BYTE *)expected_data + y * dst_format->x_blocks * dst_format->block_size,
17994 dst_format->block_size * dst_format->x_blocks);
17995 todo_wine_if(tests[i].todo)
17996 ok(passed, "Test (%u, %s -> %s), row %u, unexpected surface data.\n", j,
17997 src_format->name, dst_format->name, y);
17999 if (!passed && !(is_wine && tests[i].todo))
18001 for (x = 0; x < dst_format->x_blocks * dst_format->block_size / 4; ++x)
18003 trace("Test (%u, %u), x %u, y %u, got 0x%08x, expected 0x%08x.\n", j, i, x, y,
18004 *(unsigned int *)((BYTE *)lock.lpSurface + y * pitch + x * 4),
18005 *(unsigned int *)((BYTE *)expected_data + y * dst_format->x_blocks
18006 * dst_format->block_size + x * 4));
18009 if (!passed)
18010 break;
18012 hr = IDirectDrawSurface7_Unlock(dst_surf, NULL);
18013 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
18015 IDirectDrawSurface7_Release(dst_surf);
18016 IDirectDrawSurface7_Release(src_surf);
18020 IDirect3DDevice7_Release(device);
18021 refcount = IDirectDraw7_Release(ddraw);
18022 ok(!refcount, "%u references left.\n", refcount);
18023 DestroyWindow(window);
18026 static void test_compressed_surface_stretch(void)
18028 static const struct
18030 unsigned int src_width, src_height;
18031 unsigned int dst_width, dst_height;
18032 unsigned int src_x, src_y;
18033 unsigned int dst_x, dst_y;
18034 BOOL todo_src, todo_dst;
18036 test_sizes[] =
18038 {4, 4, 8, 8},
18039 {8, 8, 4, 4},
18040 {4, 4, 2, 2, 0, 0, 0, 0, FALSE, TRUE},
18041 {4, 4, 6, 6, 0, 0, 0, 0, FALSE, TRUE},
18042 {4, 4, 8, 8, 2, 2, 2, 2, TRUE, TRUE},
18045 static const struct
18047 DWORD src_caps, dst_caps;
18049 test_caps[] =
18051 #if 0
18052 /* Broken on Windows. */
18053 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY},
18054 #endif
18055 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY},
18056 {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY},
18057 {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY},
18060 static struct
18062 DDPIXELFORMAT fmt;
18063 const char *name;
18064 DWORD support_flag;
18066 test_formats[] =
18070 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
18071 {16}, {0x00007c00}, {0x000003e0}, {0x0000001f}, {0x00008000}
18073 "R5G5B5A1",
18077 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'),
18078 {0}, {0}, {0}, {0}, {0}
18080 "DXT1", SUPPORT_DXT1,
18084 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '3'),
18085 {0}, {0}, {0}, {0}, {0}
18087 "DXT3", SUPPORT_DXT3,
18091 unsigned int i, j, k, l, x, y, pitch;
18092 DDSURFACEDESC2 rb_surface_desc, src_surface_desc, dst_surface_desc, lock;
18093 IDirectDrawSurface7 *src_surf, *dst_surf, *rb_surf;
18094 IDirect3DDevice7 *device;
18095 RECT src_rect, dst_rect;
18096 DWORD supported_fmts;
18097 unsigned short *data;
18098 IDirectDraw7 *ddraw;
18099 ULONG refcount;
18100 HWND window;
18101 BOOL passed;
18102 DDBLTFX fx;
18103 HRESULT hr;
18105 window = create_window();
18106 if (!(device = create_device(window, DDSCL_NORMAL)))
18108 skip("Failed to create a 3D device, skipping test.\n");
18109 DestroyWindow(window);
18110 return;
18113 ddraw = create_ddraw();
18114 ok(!!ddraw, "Failed to create a ddraw object.\n");
18115 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
18116 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
18118 hr = IDirect3DDevice7_EnumTextureFormats(device, test_block_formats_creation_cb,
18119 &supported_fmts);
18120 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
18122 memset(&src_surface_desc, 0, sizeof(src_surface_desc));
18123 src_surface_desc.dwSize = sizeof(src_surface_desc);
18124 src_surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
18125 dst_surface_desc = src_surface_desc;
18127 memset(&rb_surface_desc, 0, sizeof(rb_surface_desc));
18128 rb_surface_desc.dwSize = sizeof(rb_surface_desc);
18129 rb_surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
18130 U4(rb_surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(rb_surface_desc).ddpfPixelFormat);
18131 U4(rb_surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
18132 U1(U4(rb_surface_desc).ddpfPixelFormat).dwRGBBitCount = 16;
18133 U2(U4(rb_surface_desc).ddpfPixelFormat).dwRBitMask = 0x00007c00;
18134 U3(U4(rb_surface_desc).ddpfPixelFormat).dwGBitMask = 0x000003e0;
18135 U4(U4(rb_surface_desc).ddpfPixelFormat).dwBBitMask = 0x0000001f;
18136 U5(U4(rb_surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0x00008000;
18137 rb_surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
18139 memset(&fx, 0, sizeof(fx));
18140 fx.dwSize = sizeof(fx);
18142 memset(&lock, 0, sizeof(lock));
18143 lock.dwSize = sizeof(lock);
18145 for (i = 0; i < ARRAY_SIZE(test_caps); ++i)
18147 src_surface_desc.ddsCaps.dwCaps = test_caps[i].src_caps;
18148 dst_surface_desc.ddsCaps.dwCaps = test_caps[i].dst_caps;
18150 for (j = 0; j < ARRAY_SIZE(test_sizes); ++j)
18152 SetRect(&src_rect, test_sizes[j].src_x, test_sizes[j].src_y,
18153 test_sizes[j].src_width, test_sizes[j].src_height);
18154 SetRect(&dst_rect, test_sizes[j].dst_x, test_sizes[j].dst_y,
18155 test_sizes[j].dst_width, test_sizes[j].dst_height);
18157 src_surface_desc.dwWidth = test_sizes[j].src_width;
18158 src_surface_desc.dwHeight = test_sizes[j].src_height;
18160 dst_surface_desc.dwWidth = (test_sizes[j].dst_width + 3) & ~3;
18161 dst_surface_desc.dwHeight = (test_sizes[j].dst_height + 3) & ~3;
18163 rb_surface_desc.dwWidth = max(src_surface_desc.dwWidth, dst_surface_desc.dwWidth);
18164 rb_surface_desc.dwHeight = max(src_surface_desc.dwHeight, dst_surface_desc.dwHeight);
18166 hr = IDirectDraw7_CreateSurface(ddraw, &rb_surface_desc, &rb_surf, NULL);
18167 ok(hr == DD_OK, "Test (%u, %u), got unexpected hr %#x.\n", i, j, hr);
18169 for (k = 0; k < ARRAY_SIZE(test_formats); ++k)
18171 U4(src_surface_desc).ddpfPixelFormat = test_formats[k].fmt;
18172 hr = IDirectDraw7_CreateSurface(ddraw, &src_surface_desc, &src_surf, NULL);
18173 ok(hr == DD_OK, "Test (%u, %u, %u), got unexpected hr %#x.\n", i, j, k, hr);
18175 U5(fx).dwFillColor = 0x801f;
18176 hr = IDirectDrawSurface7_Blt(rb_surf, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
18177 ok(hr == DD_OK, "Test (%u, %u, %u), got unexpected hr %#x.\n", i, j, k, hr);
18179 hr = IDirectDrawSurface7_Blt(src_surf, &src_rect, rb_surf, &src_rect, DDBLT_WAIT, NULL);
18181 todo_wine_if(test_formats[k].fmt.dwFlags == DDPF_FOURCC && test_sizes[j].todo_src)
18182 ok(hr == DD_OK, "Test (%u, %u, %u), got unexpected hr %#x.\n", i, j, k, hr);
18183 if (FAILED(hr))
18185 IDirectDrawSurface7_Release(src_surf);
18186 continue;
18189 for (l = 0; l < ARRAY_SIZE(test_formats); ++l)
18191 if (~supported_fmts & test_formats[l].support_flag)
18193 skip("%s format is not supported, skipping test %u.\n", test_formats[l].name, i);
18194 continue;
18197 U4(dst_surface_desc).ddpfPixelFormat = test_formats[l].fmt;
18199 hr = IDirectDraw7_CreateSurface(ddraw, &dst_surface_desc, &dst_surf, NULL);
18200 ok(hr == DD_OK, "Test (%u, %u, %u, %u), got unexpected hr %#x.\n", i, j, k, l, hr);
18202 memset(&lock, 0, sizeof(lock));
18203 lock.dwSize = sizeof(lock);
18205 /* r200 does not init vidmem DXT3 surfaces to 0 correctly. Do it manually.
18206 * We can't use DDBLT_COLORFILL on compressed surfaces, so we need memset.
18208 * Locking alone is not enough, so this isn't an accidental workaround that
18209 * forces a different codepath because the destination is currently in sysmem. */
18210 if (test_formats[l].fmt.dwFourCC == MAKEFOURCC('D', 'X', 'T', '3'))
18212 hr = IDirectDrawSurface7_Lock(dst_surf, NULL, &lock, 0, NULL);
18213 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
18214 memset(lock.lpSurface, 0, U1(lock).dwLinearSize);
18215 hr = IDirectDrawSurface7_Unlock(dst_surf, NULL);
18216 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
18219 hr = IDirectDrawSurface7_Blt(dst_surf, &dst_rect, src_surf, &src_rect, DDBLT_WAIT, NULL);
18220 todo_wine_if(test_formats[l].fmt.dwFlags == DDPF_FOURCC && test_sizes[j].todo_dst)
18221 ok(hr == DD_OK, "Test (%u, %u, %u, %u), got unexpected hr %#x.\n", i, j, k, l, hr);
18222 if (FAILED(hr))
18224 IDirectDrawSurface7_Release(dst_surf);
18225 continue;
18228 U5(fx).dwFillColor = 0xffffffff;
18229 hr = IDirectDrawSurface7_Blt(rb_surf, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
18230 ok(hr == DD_OK, "Test (%u, %u, %u, %u), got unexpected hr %#x.\n", i, j, k, l, hr);
18232 hr = IDirectDrawSurface7_Blt(rb_surf, &dst_rect, dst_surf, &dst_rect, DDBLT_WAIT, NULL);
18233 ok(hr == DD_OK, "Test (%u, %u, %u, %u), got unexpected hr %#x.\n", i, j, k, l, hr);
18234 hr = IDirectDrawSurface7_Lock(rb_surf, NULL, &lock, 0, NULL);
18235 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
18236 pitch = U1(lock).lPitch;
18238 passed = TRUE;
18239 for (y = dst_rect.top; y < dst_rect.bottom && passed; ++y)
18241 data = (unsigned short *)((BYTE *)lock.lpSurface + y * pitch);
18243 for (x = dst_rect.left; x < dst_rect.right && passed; ++x)
18245 passed = data[x] == 0x801f;
18246 ok(passed, "Test (%u, %u, %u, %u), x %u, y %u, "
18247 "got unexpected colour 0x%04x.\n", i, j, k, l, x, y, data[x]);
18250 hr = IDirectDrawSurface7_Unlock(rb_surf, NULL);
18251 IDirectDrawSurface7_Release(dst_surf);
18253 IDirectDrawSurface7_Release(src_surf);
18255 IDirectDrawSurface7_Release(rb_surf);
18259 IDirect3DDevice7_Release(device);
18260 refcount = IDirectDraw7_Release(ddraw);
18261 ok(!refcount, "%u references left.\n", refcount);
18262 DestroyWindow(window);
18265 struct find_different_mode_param
18267 unsigned int old_width;
18268 unsigned int old_height;
18269 unsigned int old_frequency;
18270 unsigned int new_width;
18271 unsigned int new_height;
18272 unsigned int new_frequency;
18273 unsigned int new_bpp;
18276 static HRESULT CALLBACK find_different_mode_callback(DDSURFACEDESC2 *surface_desc, void *context)
18278 struct find_different_mode_param *param = context;
18280 if (U1(U4(*surface_desc).ddpfPixelFormat).dwRGBBitCount != registry_mode.dmBitsPerPel)
18281 return DDENUMRET_OK;
18283 if (surface_desc->dwWidth != param->old_width && surface_desc->dwHeight != param->old_height &&
18284 surface_desc->dwRefreshRate != param->old_frequency)
18286 param->new_width = surface_desc->dwWidth;
18287 param->new_height = surface_desc->dwHeight;
18288 param->new_frequency = surface_desc->dwRefreshRate;
18289 param->new_bpp = surface_desc->ddpfPixelFormat.dwRGBBitCount;
18290 return DDENUMRET_CANCEL;
18293 return DDENUMRET_OK;
18296 static void test_cursor_clipping(void)
18298 struct find_different_mode_param param;
18299 DDSURFACEDESC2 surface_desc;
18300 RECT rect, clip_rect;
18301 IDirectDraw7 *ddraw;
18302 HWND window;
18303 HRESULT hr;
18304 BOOL ret;
18306 window = create_window();
18307 ok(!!window, "Failed to create a window.\n");
18308 ddraw = create_ddraw();
18309 ok(!!ddraw, "Failed to create a ddraw object.\n");
18311 memset(&surface_desc, 0, sizeof(surface_desc));
18312 surface_desc.dwSize = sizeof(surface_desc);
18313 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
18314 ok(hr == DD_OK, "GetDisplayMode failed, hr %#x.\n", hr);
18316 memset(&param, 0, sizeof(param));
18317 param.old_width = surface_desc.dwWidth;
18318 param.old_height = surface_desc.dwHeight;
18319 hr = IDirectDraw7_EnumDisplayModes(ddraw, 0, NULL, &param, find_different_mode_callback);
18320 ok(hr == DD_OK, "EnumDisplayModes failed, hr %#x.\n", hr);
18321 if (!(param.new_width && param.new_height))
18323 skip("Failed to find a different mode than %ux%u.\n", param.old_width, param.old_height);
18324 goto done;
18327 ret = ClipCursor(NULL);
18328 ok(ret, "ClipCursor failed, error %#x.\n", GetLastError());
18329 get_virtual_rect(&rect);
18330 ret = GetClipCursor(&clip_rect);
18331 ok(ret, "GetClipCursor failed, error %#x.\n", GetLastError());
18332 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
18333 wine_dbgstr_rect(&clip_rect));
18335 /* Set cooperative level to normal */
18336 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
18337 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
18338 flush_events();
18339 get_virtual_rect(&rect);
18340 ret = GetClipCursor(&clip_rect);
18341 ok(ret, "GetClipCursor failed, error %#x.\n", GetLastError());
18342 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
18343 wine_dbgstr_rect(&clip_rect));
18345 hr = set_display_mode(ddraw, param.new_width, param.new_height);
18346 ok(hr == DD_OK || hr == DDERR_UNSUPPORTED, "SetDisplayMode failed, hr %#x.\n", hr);
18347 if (FAILED(hr))
18349 win_skip("SetDisplayMode failed, hr %#x.\n", hr);
18350 goto done;
18352 flush_events();
18353 get_virtual_rect(&rect);
18354 ret = GetClipCursor(&clip_rect);
18355 ok(ret, "GetClipCursor failed, error %#x.\n", GetLastError());
18356 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
18357 wine_dbgstr_rect(&clip_rect));
18359 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
18360 ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
18361 flush_events();
18362 get_virtual_rect(&rect);
18363 ret = GetClipCursor(&clip_rect);
18364 ok(ret, "GetClipCursor failed, error %#x.\n", GetLastError());
18365 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
18366 wine_dbgstr_rect(&clip_rect));
18368 /* Switch to full screen cooperative level */
18369 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
18370 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
18371 flush_events();
18372 SetRect(&rect, 0, 0, param.old_width, param.old_height);
18373 ret = GetClipCursor(&clip_rect);
18374 ok(ret, "GetClipCursor failed, error %#x.\n", GetLastError());
18375 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
18376 wine_dbgstr_rect(&clip_rect));
18378 hr = set_display_mode(ddraw, param.new_width, param.new_height);
18379 ok(hr == DD_OK || hr == DDERR_UNSUPPORTED, "SetDisplayMode failed, hr %#x.\n", hr);
18380 if (FAILED(hr))
18382 win_skip("SetDisplayMode failed, hr %#x.\n", hr);
18383 goto done;
18385 flush_events();
18386 SetRect(&rect, 0, 0, param.new_width, param.new_height);
18387 ret = GetClipCursor(&clip_rect);
18388 ok(ret, "GetClipCursor failed, error %#x.\n", GetLastError());
18389 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
18390 wine_dbgstr_rect(&clip_rect));
18392 /* Restore display mode */
18393 hr = IDirectDraw7_RestoreDisplayMode(ddraw);
18394 ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
18395 flush_events();
18396 SetRect(&rect, 0, 0, param.old_width, param.old_height);
18397 ret = GetClipCursor(&clip_rect);
18398 ok(ret, "GetClipCursor failed, error %#x.\n", GetLastError());
18399 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
18400 wine_dbgstr_rect(&clip_rect));
18402 /* Switch to normal cooperative level */
18403 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
18404 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
18405 flush_events();
18406 get_virtual_rect(&rect);
18407 ret = GetClipCursor(&clip_rect);
18408 ok(ret, "GetClipCursor failed, error %#x.\n", GetLastError());
18409 ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect),
18410 wine_dbgstr_rect(&clip_rect));
18412 done:
18413 IDirectDraw7_Release(ddraw);
18414 DestroyWindow(window);
18417 static BOOL CALLBACK test_window_position_cb(HMONITOR monitor, HDC hdc, RECT *monitor_rect,
18418 LPARAM lparam)
18420 RECT primary_rect, window_rect;
18421 IDirectDraw7 *ddraw;
18422 HWND window;
18423 HRESULT hr;
18424 BOOL ret;
18426 ddraw = create_ddraw();
18427 ok(!!ddraw, "Failed to create a ddraw object.\n");
18428 window = CreateWindowA("static", "ddraw_test", WS_POPUP | WS_VISIBLE, monitor_rect->left,
18429 monitor_rect->top, monitor_rect->right - monitor_rect->left,
18430 monitor_rect->bottom - monitor_rect->top, NULL, NULL, NULL, NULL);
18431 ok(!!window, "Failed to create a window.\n");
18432 flush_events();
18434 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
18435 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
18436 flush_events();
18437 ret = GetWindowRect(window, &window_rect);
18438 ok(ret, "GetWindowRect failed, error %#x.\n", GetLastError());
18439 SetRect(&primary_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
18440 ok(EqualRect(&window_rect, &primary_rect), "Expect window rect %s, got %s.\n",
18441 wine_dbgstr_rect(&primary_rect), wine_dbgstr_rect(&window_rect));
18443 /* Window activation should restore the window to fit the whole primary monitor */
18444 ret = SetWindowPos(window, 0, monitor_rect->left, monitor_rect->top, 0, 0,
18445 SWP_NOZORDER | SWP_NOSIZE);
18446 ok(ret, "SetWindowPos failed, error %#x.\n", GetLastError());
18447 ret = SetForegroundWindow(GetDesktopWindow());
18448 ok(ret, "Failed to set foreground window.\n");
18449 flush_events();
18450 ret = ShowWindow(window, SW_RESTORE);
18451 ok(ret, "Failed to restore window, error %#x.\n", GetLastError());
18452 flush_events();
18453 ret = SetForegroundWindow(window);
18454 ok(ret, "SetForegroundWindow failed, error %#x.\n", GetLastError());
18455 flush_events();
18456 ret = GetWindowRect(window, &window_rect);
18457 ok(ret, "GetWindowRect failed, error %#x.\n", GetLastError());
18458 ok(EqualRect(&window_rect, &primary_rect), "Expect window rect %s, got %s.\n",
18459 wine_dbgstr_rect(&primary_rect), wine_dbgstr_rect(&window_rect));
18461 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
18462 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
18463 ret = GetWindowRect(window, &window_rect);
18464 ok(ret, "GetWindowRect failed, error %#x.\n", GetLastError());
18465 ok(EqualRect(&window_rect, &primary_rect), "Expect window rect %s, got %s.\n",
18466 wine_dbgstr_rect(&primary_rect), wine_dbgstr_rect(&window_rect));
18468 DestroyWindow(window);
18469 IDirectDraw7_Release(ddraw);
18470 return TRUE;
18473 static void test_window_position(void)
18475 EnumDisplayMonitors(NULL, NULL, test_window_position_cb, 0);
18478 static BOOL CALLBACK test_get_display_mode_cb(HMONITOR monitor, HDC hdc, RECT *monitor_rect,
18479 LPARAM lparam)
18481 DDSURFACEDESC2 surface_desc;
18482 IDirectDraw7 *ddraw;
18483 HWND window;
18484 HRESULT hr;
18485 BOOL ret;
18487 ddraw = create_ddraw();
18488 ok(!!ddraw, "Failed to create a ddraw object.\n");
18489 window = create_window();
18490 ok(!!window, "Failed to create a window.\n");
18492 /* Test that DirectDraw doesn't use the device window to determine which monitor to use */
18493 ret = SetWindowPos(window, 0, monitor_rect->left, monitor_rect->top, 0, 0,
18494 SWP_NOZORDER | SWP_NOSIZE);
18495 ok(ret, "SetWindowPos failed, error %#x.\n", GetLastError());
18497 surface_desc.dwSize = sizeof(surface_desc);
18498 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
18499 ok(hr == DD_OK, "GetDisplayMode failed, hr %#x.\n", hr);
18500 ok(surface_desc.dwWidth == GetSystemMetrics(SM_CXSCREEN), "Expect width %d, got %d.\n",
18501 GetSystemMetrics(SM_CXSCREEN), surface_desc.dwWidth);
18502 ok(surface_desc.dwHeight == GetSystemMetrics(SM_CYSCREEN), "Expect height %d, got %d.\n",
18503 GetSystemMetrics(SM_CYSCREEN), surface_desc.dwHeight);
18505 DestroyWindow(window);
18506 IDirectDraw7_Release(ddraw);
18507 return TRUE;
18510 static void test_get_display_mode(void)
18512 static const DWORD flags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_REFRESHRATE | DDSD_PIXELFORMAT | DDSD_PITCH;
18513 struct find_different_mode_param param;
18514 DDSURFACEDESC2 surface_desc;
18515 IDirectDraw7 *ddraw;
18516 DEVMODEW devmode;
18517 HWND window;
18518 HRESULT hr;
18519 BOOL ret;
18521 EnumDisplayMonitors(NULL, NULL, test_get_display_mode_cb, 0);
18523 ddraw = create_ddraw();
18524 ok(!!ddraw, "Failed to create a ddraw object.\n");
18525 window = create_window();
18526 ok(!!window, "Failed to create a window.\n");
18528 hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
18529 ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
18531 memset(&devmode, 0, sizeof(devmode));
18532 devmode.dmSize = sizeof(devmode);
18533 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
18534 ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
18536 surface_desc.dwSize = sizeof(surface_desc);
18537 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
18538 ok(hr == DD_OK, "GetDisplayMode failed, hr %#x.\n", hr);
18539 ok(surface_desc.dwSize == sizeof(surface_desc), "Expected dwSize %u, got %u.\n",
18540 sizeof(surface_desc), surface_desc.dwSize);
18541 ok(surface_desc.dwFlags == flags, "Expected dwFlags %#x, got %#x.\n", flags,
18542 surface_desc.dwFlags);
18543 ok(surface_desc.dwWidth == devmode.dmPelsWidth, "Expected width %u, got %u.\n",
18544 devmode.dmPelsWidth, surface_desc.dwWidth);
18545 ok(surface_desc.dwHeight == devmode.dmPelsHeight, "Expected height %u, got %u.\n",
18546 devmode.dmPelsHeight, surface_desc.dwHeight);
18547 ok(surface_desc.dwRefreshRate == devmode.dmDisplayFrequency, "Expected frequency %u, got %u.\n",
18548 devmode.dmDisplayFrequency, surface_desc.dwRefreshRate);
18549 ok(surface_desc.ddpfPixelFormat.dwSize == sizeof(surface_desc.ddpfPixelFormat),
18550 "Expected ddpfPixelFormat.dwSize %u, got %u.\n", sizeof(surface_desc.ddpfPixelFormat),
18551 surface_desc.ddpfPixelFormat.dwSize);
18552 ok(surface_desc.ddpfPixelFormat.dwRGBBitCount == devmode.dmBitsPerPel,
18553 "Expected ddpfPixelFormat.dwRGBBitCount %u, got %u.\n", devmode.dmBitsPerPel,
18554 surface_desc.ddpfPixelFormat.dwRGBBitCount);
18555 ok(surface_desc.lPitch == devmode.dmPelsWidth * devmode.dmBitsPerPel / 8,
18556 "Expected pitch %u, got %u.\n", devmode.dmPelsWidth * devmode.dmBitsPerPel / 8,
18557 surface_desc.lPitch);
18559 memset(&param, 0, sizeof(param));
18560 param.old_frequency = surface_desc.dwRefreshRate;
18561 hr = IDirectDraw7_EnumDisplayModes(ddraw, DDEDM_REFRESHRATES, NULL, &param,
18562 find_different_mode_callback);
18563 ok(hr == DD_OK, "EnumDisplayModes failed, hr %#x.\n", hr);
18564 if (!param.new_frequency)
18566 skip("Failed to find a display mode with a different frequency.\n");
18567 goto done;
18570 hr = IDirectDraw7_SetDisplayMode(ddraw, param.new_width, param.new_height, param.new_bpp,
18571 param.new_frequency, 0);
18572 ok(hr == DD_OK, "SetDisplayMode failed, hr %#x.\n", hr);
18573 hr = IDirectDraw7_GetDisplayMode(ddraw, &surface_desc);
18574 ok(hr == DD_OK, "GetDisplayMode failed, hr %#x.\n", hr);
18575 ok(surface_desc.dwWidth == param.new_width, "Expected width %u, got %u.\n", param.new_width,
18576 surface_desc.dwWidth);
18577 ok(surface_desc.dwHeight == param.new_height, "Expected height %u, got %u.\n", param.new_height,
18578 surface_desc.dwHeight);
18579 ok(surface_desc.dwRefreshRate == param.new_frequency, "Expected frequency %u, got %u.\n",
18580 param.new_frequency, surface_desc.dwRefreshRate);
18581 ok(surface_desc.ddpfPixelFormat.dwRGBBitCount == param.new_bpp,
18582 "Expected ddpfPixelFormat.dwRGBBitCount %u, got %u.\n", devmode.dmBitsPerPel,
18583 surface_desc.ddpfPixelFormat.dwRGBBitCount);
18585 done:
18586 DestroyWindow(window);
18587 IDirectDraw7_Release(ddraw);
18590 static void test_texture_wrong_caps(const GUID *device_guid)
18592 static struct
18594 struct vec3 position;
18595 struct vec2 texcoord;
18597 quad[] =
18599 {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
18600 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
18601 {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
18602 {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
18604 static DDPIXELFORMAT fmt =
18606 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
18607 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
18609 IDirectDrawSurface7 *surface, *rt;
18610 IDirect3DDevice7 *device;
18611 IDirectDraw7 *ddraw;
18612 DDSURFACEDESC2 ddsd;
18613 IDirect3D7 *d3d;
18614 D3DCOLOR color;
18615 ULONG refcount;
18616 HWND window;
18617 HRESULT hr;
18619 window = create_window();
18620 if (!(device = create_device_ex(window, DDSCL_NORMAL, device_guid)))
18622 skip("Failed to create a 3D device, skipping test.\n");
18623 DestroyWindow(window);
18624 return;
18626 hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
18627 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
18628 hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
18629 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
18630 hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
18631 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
18633 memset(&ddsd, 0, sizeof(ddsd));
18634 ddsd.dwSize = sizeof(ddsd);
18635 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
18636 ddsd.dwHeight = 16;
18637 ddsd.dwWidth = 16;
18638 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
18639 U4(ddsd).ddpfPixelFormat = fmt;
18640 hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL);
18641 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
18643 fill_surface(surface, 0xff00ff00);
18645 hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
18646 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
18648 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
18649 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
18650 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
18651 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
18652 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
18653 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
18654 hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
18655 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
18657 hr = IDirect3DDevice7_SetTexture(device, 0, surface);
18658 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
18660 hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0);
18661 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
18662 if (is_software_device_type(device_guid))
18663 fill_surface(rt, 0x000000ff);
18665 hr = IDirect3DDevice7_BeginScene(device);
18666 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
18667 hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,
18668 D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
18669 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
18670 hr = IDirect3DDevice7_EndScene(device);
18671 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
18673 color = get_surface_color(rt, 320, 240);
18674 ok(color == 0, "Got unexpected color 0x%08x.\n", color);
18676 IDirectDrawSurface7_Release(surface);
18677 IDirectDrawSurface7_Release(rt);
18678 IDirectDraw7_Release(ddraw);
18679 IDirect3D7_Release(d3d);
18680 refcount = IDirect3DDevice3_Release(device);
18681 ok(!refcount, "Device has %u references left.\n", refcount);
18682 DestroyWindow(window);
18685 static void run_for_each_device_type(void (*test_func)(const GUID *))
18687 test_func(hw_device_guid);
18688 test_func(&IID_IDirect3DRGBDevice);
18691 START_TEST(ddraw7)
18693 DDDEVICEIDENTIFIER2 identifier;
18694 HMODULE module, dwmapi;
18695 DEVMODEW current_mode;
18696 IDirectDraw7 *ddraw;
18697 IDirect3D7 *d3d;
18698 BOOL hal_ok;
18699 HRESULT hr;
18701 module = GetModuleHandleA("ddraw.dll");
18702 if (!(pDirectDrawCreateEx = (void *)GetProcAddress(module, "DirectDrawCreateEx")))
18704 win_skip("DirectDrawCreateEx not available, skipping tests.\n");
18705 return;
18708 if (!(ddraw = create_ddraw()))
18710 skip("Failed to create a ddraw object, skipping tests.\n");
18711 return;
18714 if (ddraw_get_identifier(ddraw, &identifier))
18716 trace("Driver string: \"%s\"\n", identifier.szDriver);
18717 trace("Description string: \"%s\"\n", identifier.szDescription);
18718 trace("Driver version %d.%d.%d.%d\n",
18719 HIWORD(U(identifier.liDriverVersion).HighPart), LOWORD(U(identifier.liDriverVersion).HighPart),
18720 HIWORD(U(identifier.liDriverVersion).LowPart), LOWORD(U(identifier.liDriverVersion).LowPart));
18723 if (IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d) == DD_OK)
18725 hr = IDirect3D7_EnumDevices(d3d, enum_devtype_cb, &hal_ok);
18726 ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
18727 if (hal_ok)
18728 hw_device_guid = &IID_IDirect3DTnLHalDevice;
18729 IDirectDraw7_Release(d3d);
18731 else
18733 trace("D3D interface is not available.\n");
18736 IDirectDraw7_Release(ddraw);
18738 memset(&current_mode, 0, sizeof(current_mode));
18739 current_mode.dmSize = sizeof(current_mode);
18740 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
18741 registry_mode.dmSize = sizeof(registry_mode);
18742 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
18743 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
18744 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
18746 skip("Current mode does not match registry mode, skipping test.\n");
18747 return;
18750 if ((dwmapi = LoadLibraryA("dwmapi.dll")))
18751 pDwmIsCompositionEnabled = (void *)GetProcAddress(dwmapi, "DwmIsCompositionEnabled");
18753 test_process_vertices();
18754 test_coop_level_create_device_window();
18755 test_clipper_blt();
18756 test_coop_level_d3d_state();
18757 test_surface_interface_mismatch();
18758 test_coop_level_threaded();
18759 run_for_each_device_type(test_depth_blit);
18760 test_texture_load_ckey();
18761 run_for_each_device_type(test_zenable);
18762 run_for_each_device_type(test_ck_rgba);
18763 test_ck_default();
18764 test_ck_complex();
18765 test_surface_qi();
18766 test_device_qi();
18767 test_wndproc();
18768 test_window_style();
18769 test_redundant_mode_set();
18770 test_coop_level_mode_set();
18771 test_coop_level_mode_set_multi();
18772 test_initialize();
18773 test_coop_level_surf_create();
18774 test_vb_discard();
18775 test_coop_level_multi_window();
18776 test_draw_strided();
18777 test_lighting();
18778 test_specular_lighting();
18779 test_clear_rect_count();
18780 test_coop_level_versions();
18781 test_fog_special();
18782 test_lighting_interface_versions();
18783 test_coop_level_activateapp();
18784 test_texturemanage();
18785 test_block_formats_creation();
18786 test_unsupported_formats();
18787 run_for_each_device_type(test_rt_caps);
18788 test_primary_caps();
18789 test_surface_lock();
18790 test_surface_discard();
18791 test_flip();
18792 test_set_surface_desc();
18793 test_user_memory_getdc();
18794 test_sysmem_overlay();
18795 test_primary_palette();
18796 test_surface_attachment();
18797 test_private_data();
18798 test_pixel_format();
18799 test_create_surface_pitch();
18800 test_mipmap();
18801 test_palette_complex();
18802 test_p8_blit();
18803 test_material();
18804 test_palette_gdi();
18805 test_palette_alpha();
18806 test_vb_writeonly();
18807 test_lost_device();
18808 test_resource_priority();
18809 test_surface_desc_lock();
18810 test_fog_interpolation();
18811 test_fog_process_vertices();
18812 test_negative_fixedfunction_fog();
18813 test_table_fog_zw();
18814 test_signed_formats();
18815 test_color_fill();
18816 test_texcoordindex();
18817 test_colorkey_precision();
18818 test_range_colorkey();
18819 test_shademode();
18820 test_lockrect_invalid();
18821 test_yv12_overlay();
18822 test_offscreen_overlay();
18823 test_overlay_rect();
18824 test_blt();
18825 test_blt_z_alpha();
18826 test_cross_device_blt();
18827 test_color_clamping();
18828 test_getdc();
18829 test_draw_primitive();
18830 test_edge_antialiasing_blending();
18831 test_display_mode_surface_pixel_format();
18832 test_surface_desc_size();
18833 test_get_surface_from_dc();
18834 test_ck_operation();
18835 test_vb_refcount();
18836 test_compute_sphere_visibility();
18837 test_clip_planes_limits();
18838 test_texture_stages_limits();
18839 test_set_render_state();
18840 test_map_synchronisation();
18841 test_depth_readback();
18842 test_clear();
18843 test_enum_surfaces();
18844 test_viewport();
18845 test_device_load();
18846 test_color_vertex();
18847 test_killfocus();
18848 test_sysmem_draw();
18849 test_gdi_surface();
18850 test_multiply_transform();
18851 test_alphatest();
18852 test_clipper_refcount();
18853 test_begin_end_state_block();
18854 test_caps();
18855 test_d32_support();
18856 test_surface_format_conversion_alpha();
18857 test_compressed_surface_stretch();
18858 test_cursor_clipping();
18859 test_window_position();
18860 test_get_display_mode();
18861 run_for_each_device_type(test_texture_wrong_caps);