d3d8/tests: Build without -DWINE_NO_LONG_TYPES.
[wine.git] / dlls / d3d9 / tests / d3d9ex.c
blob19c4eec7921ff1ec589fde1bcad4b02ce15e6a3e
1 /*
2 * Copyright (C) 2008 Stefan Dösinger(for CodeWeavers)
3 * Copyright (C) 2010 Louis Lenders
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 /* This file contains tests specific to IDirect3D9Ex and IDirect3DDevice9Ex, like
21 * how to obtain them. For testing rendering with extended functions use visual.c
24 #define COBJMACROS
25 #include "wine/test.h"
26 #include <initguid.h>
27 #include <d3d9.h>
29 static HMODULE d3d9_handle = 0;
30 static DEVMODEW registry_mode;
32 static HRESULT (WINAPI *pDirect3DCreate9Ex)(UINT SDKVersion, IDirect3D9Ex **d3d9ex);
34 #define CREATE_DEVICE_FULLSCREEN 0x01
35 #define CREATE_DEVICE_NOWINDOWCHANGES 0x02
36 #define CREATE_DEVICE_SWVP_ONLY 0x04
38 struct device_desc
40 HWND device_window;
41 unsigned int width;
42 unsigned int height;
43 DWORD flags;
46 static BOOL adapter_is_warp(const D3DADAPTER_IDENTIFIER9 *identifier)
48 return !strcmp(identifier->Driver, "d3d10warp.dll");
51 static BOOL compare_uint(unsigned int x, unsigned int y, unsigned int max_diff)
53 unsigned int diff = x > y ? x - y : y - x;
55 return diff <= max_diff;
58 static BOOL color_match(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
60 return compare_uint(c1 & 0xff, c2 & 0xff, max_diff)
61 && compare_uint((c1 >> 8) & 0xff, (c2 >> 8) & 0xff, max_diff)
62 && compare_uint((c1 >> 16) & 0xff, (c2 >> 16) & 0xff, max_diff)
63 && compare_uint((c1 >> 24) & 0xff, (c2 >> 24) & 0xff, max_diff);
66 static DWORD get_pixel_color(IDirect3DDevice9Ex *device, unsigned int x, unsigned int y)
68 IDirect3DSurface9 *surf = NULL, *target = NULL;
69 RECT rect = {x, y, x + 1, y + 1};
70 D3DLOCKED_RECT locked_rect;
71 D3DSURFACE_DESC desc;
72 HRESULT hr;
73 DWORD ret;
75 hr = IDirect3DDevice9Ex_GetRenderTarget(device, 0, &target);
76 if (FAILED(hr))
78 trace("Can't get the render target, hr %#lx.\n", hr);
79 return 0xdeadbeed;
82 hr = IDirect3DSurface9_GetDesc(target, &desc);
83 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
84 hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurface(device, desc.Width, desc.Height,
85 desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL);
86 if (FAILED(hr) || !surf)
88 trace("Can't create an offscreen plain surface to read the render target data, hr %#lx.\n", hr);
89 ret = 0xdeadbeef;
90 goto out;
93 hr = IDirect3DDevice9Ex_GetRenderTargetData(device, target, surf);
94 if (FAILED(hr))
96 trace("Can't read the render target data, hr %#lx.\n", hr);
97 ret = 0xdeadbeec;
98 goto out;
101 hr = IDirect3DSurface9_LockRect(surf, &locked_rect, &rect, D3DLOCK_READONLY);
102 if (FAILED(hr))
104 trace("Can't lock the offscreen surface, hr %#lx.\n", hr);
105 ret = 0xdeadbeeb;
106 goto out;
109 /* Remove the X channel for now. DirectX and OpenGL have different
110 * ideas how to treat it apparently, and it isn't really important
111 * for these tests. */
112 ret = ((DWORD *)locked_rect.pBits)[0] & 0x00ffffff;
113 hr = IDirect3DSurface9_UnlockRect(surf);
114 if (FAILED(hr))
115 trace("Can't unlock the offscreen surface, hr %#lx.\n", hr);
117 out:
118 if (target)
119 IDirect3DSurface9_Release(target);
120 if (surf)
121 IDirect3DSurface9_Release(surf);
122 return ret;
125 static HWND create_window(void)
127 return CreateWindowA("d3d9_test_wc", "d3d9_test", WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION,
128 0, 0, 640, 480, 0, 0, 0, 0);
131 /* try to make sure pending X events have been processed before continuing */
132 static void flush_events(void)
134 MSG msg;
135 int diff = 200;
136 int min_timeout = 100;
137 DWORD time = GetTickCount() + diff;
139 while (diff > 0)
141 if (MsgWaitForMultipleObjects(0, NULL, FALSE, min_timeout, QS_ALLINPUT) == WAIT_TIMEOUT)
142 break;
143 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
144 DispatchMessageA(&msg);
145 diff = time - GetTickCount();
149 static IDirect3DDevice9Ex *create_device(HWND focus_window, const struct device_desc *desc)
151 D3DPRESENT_PARAMETERS present_parameters = {0};
152 IDirect3DDevice9Ex *device;
153 D3DDISPLAYMODEEX mode, *m;
154 IDirect3D9Ex *d3d9;
155 DWORD behavior_flags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
157 if (FAILED(pDirect3DCreate9Ex(D3D_SDK_VERSION, &d3d9)))
158 return NULL;
160 present_parameters.BackBufferWidth = 640;
161 present_parameters.BackBufferHeight = 480;
162 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
163 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
164 present_parameters.hDeviceWindow = focus_window;
165 present_parameters.Windowed = TRUE;
166 present_parameters.EnableAutoDepthStencil = TRUE;
167 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
169 if (desc)
171 present_parameters.BackBufferWidth = desc->width;
172 present_parameters.BackBufferHeight = desc->height;
173 present_parameters.hDeviceWindow = desc->device_window;
174 present_parameters.Windowed = !(desc->flags & CREATE_DEVICE_FULLSCREEN);
175 if (desc->flags & CREATE_DEVICE_NOWINDOWCHANGES)
176 behavior_flags |= D3DCREATE_NOWINDOWCHANGES;
177 if (desc->flags & CREATE_DEVICE_SWVP_ONLY)
178 behavior_flags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
181 mode.Size = sizeof(mode);
182 mode.Width = present_parameters.BackBufferWidth;
183 mode.Height = present_parameters.BackBufferHeight;
184 mode.RefreshRate = 0;
185 mode.Format = D3DFMT_A8R8G8B8;
186 mode.ScanLineOrdering = 0;
188 m = present_parameters.Windowed ? NULL : &mode;
189 if (SUCCEEDED(IDirect3D9Ex_CreateDeviceEx(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
190 behavior_flags, &present_parameters, m, &device)))
191 goto done;
193 present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
194 if (SUCCEEDED(IDirect3D9Ex_CreateDeviceEx(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
195 behavior_flags, &present_parameters, m, &device)))
196 goto done;
198 behavior_flags ^= (D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_SOFTWARE_VERTEXPROCESSING);
200 if (SUCCEEDED(IDirect3D9Ex_CreateDeviceEx(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
201 behavior_flags, &present_parameters, m, &device)))
202 goto done;
204 device = NULL;
206 done:
207 IDirect3D9Ex_Release(d3d9);
208 return device;
211 static HRESULT reset_device(IDirect3DDevice9Ex *device, const struct device_desc *desc)
213 D3DPRESENT_PARAMETERS present_parameters = {0};
215 present_parameters.BackBufferWidth = 640;
216 present_parameters.BackBufferHeight = 480;
217 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
218 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
219 present_parameters.hDeviceWindow = NULL;
220 present_parameters.Windowed = TRUE;
221 present_parameters.EnableAutoDepthStencil = TRUE;
222 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
224 if (desc)
226 present_parameters.BackBufferWidth = desc->width;
227 present_parameters.BackBufferHeight = desc->height;
228 present_parameters.hDeviceWindow = desc->device_window;
229 present_parameters.Windowed = !(desc->flags & CREATE_DEVICE_FULLSCREEN);
232 return IDirect3DDevice9_Reset(device, &present_parameters);
235 static ULONG getref(IUnknown *obj) {
236 IUnknown_AddRef(obj);
237 return IUnknown_Release(obj);
240 static void test_qi_base_to_ex(void)
242 IDirect3D9 *d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
243 IDirect3D9Ex *d3d9ex = (void *) 0xdeadbeef;
244 IDirect3DDevice9 *device;
245 IDirect3DDevice9Ex *deviceEx = (void *) 0xdeadbeef;
246 IDirect3DSwapChain9 *swapchain = NULL;
247 IDirect3DSwapChain9Ex *swapchainEx = (void *)0xdeadbeef;
248 HRESULT hr;
249 HWND window = create_window();
250 D3DPRESENT_PARAMETERS present_parameters;
252 if (!d3d9)
254 skip("Direct3D9 is not available\n");
255 return;
258 hr = IDirect3D9_QueryInterface(d3d9, &IID_IDirect3D9Ex, (void **) &d3d9ex);
259 ok(hr == E_NOINTERFACE, "Got hr %#lx.\n", hr);
260 ok(d3d9ex == NULL, "QueryInterface returned interface %p, expected NULL\n", d3d9ex);
261 if(d3d9ex) IDirect3D9Ex_Release(d3d9ex);
263 memset(&present_parameters, 0, sizeof(present_parameters));
264 present_parameters.Windowed = TRUE;
265 present_parameters.hDeviceWindow = window;
266 present_parameters.SwapEffect = D3DSWAPEFFECT_COPY;
267 present_parameters.BackBufferWidth = 640;
268 present_parameters.BackBufferHeight = 480;
269 present_parameters.EnableAutoDepthStencil = FALSE;
270 present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
271 hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
272 if(FAILED(hr)) {
273 skip("Failed to create a regular Direct3DDevice9, skipping QI tests\n");
274 goto out;
277 hr = IDirect3DDevice9_QueryInterface(device, &IID_IDirect3DDevice9Ex, (void **) &deviceEx);
278 ok(hr == E_NOINTERFACE, "Got hr %#lx.\n", hr);
279 ok(deviceEx == NULL, "QueryInterface returned interface %p, expected NULL\n", deviceEx);
280 if(deviceEx) IDirect3DDevice9Ex_Release(deviceEx);
282 /* Get the implicit swapchain */
283 hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain);
284 ok(hr == S_OK, "Got hr %#lx.\n", hr);
285 if (SUCCEEDED(hr))
287 hr = IDirect3DSwapChain9_QueryInterface(swapchain, &IID_IDirect3DSwapChain9Ex, (void **)&swapchainEx);
288 ok(hr == E_NOINTERFACE, "Got hr %#lx.\n", hr);
289 ok(swapchainEx == NULL, "QueryInterface returned interface %p, expected NULL.\n", swapchainEx);
290 if (swapchainEx)
291 IDirect3DSwapChain9Ex_Release(swapchainEx);
293 if (swapchain)
294 IDirect3DSwapChain9_Release(swapchain);
296 IDirect3DDevice9_Release(device);
298 out:
299 IDirect3D9_Release(d3d9);
300 DestroyWindow(window);
303 static void test_qi_ex_to_base(void)
305 IDirect3D9 *d3d9 = (void *) 0xdeadbeef;
306 IDirect3D9Ex *d3d9ex;
307 IDirect3DDevice9 *device;
308 IDirect3DDevice9Ex *deviceEx = (void *) 0xdeadbeef;
309 IDirect3DSwapChain9 *swapchain = NULL;
310 IDirect3DSwapChain9Ex *swapchainEx = (void *)0xdeadbeef;
311 HRESULT hr;
312 HWND window = create_window();
313 D3DPRESENT_PARAMETERS present_parameters;
314 ULONG ref;
316 hr = pDirect3DCreate9Ex(D3D_SDK_VERSION, &d3d9ex);
317 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got hr %#lx.\n", hr);
318 if(FAILED(hr)) {
319 skip("Direct3D9Ex is not available\n");
320 goto out;
323 hr = IDirect3D9Ex_QueryInterface(d3d9ex, &IID_IDirect3D9, (void **) &d3d9);
324 ok(hr == S_OK, "Got hr %#lx.\n", hr);
325 ok(d3d9 != NULL && d3d9 != (void *) 0xdeadbeef,
326 "QueryInterface returned interface %p, expected != NULL && != 0xdeadbeef\n", d3d9);
327 ref = getref((IUnknown *) d3d9ex);
328 ok(ref == 2, "Unexpected refcount %lu.\n", ref);
329 ref = getref((IUnknown *) d3d9);
330 ok(ref == 2, "Unexpected refcount %lu.\n", ref);
332 memset(&present_parameters, 0, sizeof(present_parameters));
333 present_parameters.Windowed = TRUE;
334 present_parameters.hDeviceWindow = window;
335 present_parameters.SwapEffect = D3DSWAPEFFECT_COPY;
336 present_parameters.BackBufferWidth = 640;
337 present_parameters.BackBufferHeight = 480;
338 present_parameters.EnableAutoDepthStencil = FALSE;
339 present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
341 /* First, try to create a normal device with IDirect3D9Ex::CreateDevice and QI it for IDirect3DDevice9Ex */
342 hr = IDirect3D9Ex_CreateDevice(d3d9ex, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
343 if(FAILED(hr)) {
344 skip("Failed to create a regular Direct3DDevice9, skipping QI tests\n");
345 goto out;
348 hr = IDirect3DDevice9_QueryInterface(device, &IID_IDirect3DDevice9Ex, (void **) &deviceEx);
349 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
350 ok(deviceEx != NULL && deviceEx != (void *) 0xdeadbeef,
351 "QueryInterface returned interface %p, expected != NULL && != 0xdeadbeef\n", deviceEx);
352 ref = getref((IUnknown *) device);
353 ok(ref == 2, "Unexpected refcount %lu.\n", ref);
354 ref = getref((IUnknown *) deviceEx);
355 ok(ref == 2, "Unexpected refcount %lu.\n", ref);
356 if(deviceEx) IDirect3DDevice9Ex_Release(deviceEx);
357 IDirect3DDevice9_Release(device);
359 /* Next, try to create a normal device with IDirect3D9::CreateDevice(non-ex) and QI it */
360 hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
361 if(FAILED(hr)) {
362 skip("Failed to create a regular Direct3DDevice9, skipping QI tests\n");
363 goto out;
366 hr = IDirect3DDevice9_QueryInterface(device, &IID_IDirect3DDevice9Ex, (void **) &deviceEx);
367 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
368 ok(deviceEx != NULL && deviceEx != (void *) 0xdeadbeef,
369 "QueryInterface returned interface %p, expected != NULL && != 0xdeadbeef\n", deviceEx);
370 ref = getref((IUnknown *) device);
371 ok(ref == 2, "Unexpected refcount %lu.\n", ref);
372 ref = getref((IUnknown *) deviceEx);
373 ok(ref == 2, "Unexpected refcount %lu.\n", ref);
375 /* Get the implicit swapchain */
376 hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain);
377 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
378 if (SUCCEEDED(hr))
380 hr = IDirect3DSwapChain9_QueryInterface(swapchain, &IID_IDirect3DSwapChain9Ex, (void **)&swapchainEx);
381 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
382 ok(swapchainEx != NULL && swapchainEx != (void *)0xdeadbeef,
383 "QueryInterface returned interface %p, expected != NULL && != 0xdeadbeef.\n", swapchainEx);
384 if (swapchainEx)
385 IDirect3DSwapChain9Ex_Release(swapchainEx);
387 if (swapchain)
388 IDirect3DSwapChain9_Release(swapchain);
390 if(deviceEx) IDirect3DDevice9Ex_Release(deviceEx);
391 IDirect3DDevice9_Release(device);
393 IDirect3D9_Release(d3d9);
394 IDirect3D9Ex_Release(d3d9ex);
396 out:
397 DestroyWindow(window);
400 static void test_get_adapter_luid(void)
402 HWND window = create_window();
403 IDirect3D9Ex *d3d9ex;
404 UINT count;
405 HRESULT hr;
406 LUID luid;
408 hr = pDirect3DCreate9Ex(D3D_SDK_VERSION, &d3d9ex);
409 if (FAILED(hr))
411 skip("Direct3D9Ex is not available.\n");
412 DestroyWindow(window);
413 return;
416 count = IDirect3D9Ex_GetAdapterCount(d3d9ex);
417 if (!count)
419 skip("No adapters available.\n");
420 IDirect3D9Ex_Release(d3d9ex);
421 DestroyWindow(window);
422 return;
425 hr = IDirect3D9Ex_GetAdapterLUID(d3d9ex, D3DADAPTER_DEFAULT, &luid);
426 ok(SUCCEEDED(hr), "GetAdapterLUID failed, hr %#lx.\n", hr);
427 trace("Adapter luid: %08lx:%08lx.\n", luid.HighPart, luid.LowPart);
429 IDirect3D9Ex_Release(d3d9ex);
432 static void test_swapchain_get_displaymode_ex(void)
434 IDirect3DSwapChain9 *swapchain = NULL;
435 IDirect3DSwapChain9Ex *swapchainEx = NULL;
436 IDirect3DDevice9Ex *device;
437 D3DDISPLAYMODE mode;
438 D3DDISPLAYMODEEX mode_ex;
439 D3DDISPLAYROTATION rotation;
440 HWND window;
441 HRESULT hr;
443 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
444 0, 0, 640, 480, 0, 0, 0, 0);
445 if (!(device = create_device(window, NULL)))
447 skip("Failed to create a D3D device, skipping swapchain GetDisplayModeEx tests.\n");
448 goto out;
451 /* Get the implicit swapchain */
452 hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain);
453 if (FAILED(hr))
455 skip("Failed to get the implicit swapchain, skipping swapchain GetDisplayModeEx tests.\n");
456 goto out;
459 hr = IDirect3DSwapChain9_QueryInterface(swapchain, &IID_IDirect3DSwapChain9Ex, (void **)&swapchainEx);
460 IDirect3DSwapChain9_Release(swapchain);
461 if (FAILED(hr))
463 skip("Failed to QI for IID_IDirect3DSwapChain9Ex, skipping swapchain GetDisplayModeEx tests.\n");
464 goto out;
467 /* invalid size */
468 memset(&mode_ex, 0, sizeof(mode_ex));
469 hr = IDirect3DSwapChain9Ex_GetDisplayModeEx(swapchainEx, &mode_ex, &rotation);
470 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
472 mode_ex.Size = sizeof(D3DDISPLAYMODEEX);
473 rotation = (D3DDISPLAYROTATION)0xdeadbeef;
474 /* valid count and valid size */
475 hr = IDirect3DSwapChain9Ex_GetDisplayModeEx(swapchainEx, &mode_ex, &rotation);
476 ok(SUCCEEDED(hr), "GetDisplayModeEx failed, hr %#lx.\n", hr);
478 /* compare what GetDisplayMode returns with what GetDisplayModeEx returns */
479 hr = IDirect3DSwapChain9Ex_GetDisplayMode(swapchainEx, &mode);
480 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#lx.\n", hr);
482 ok(mode_ex.Size == sizeof(D3DDISPLAYMODEEX), "Size is %d.\n", mode_ex.Size);
483 ok(mode_ex.Width == mode.Width, "Width is %d instead of %d.\n", mode_ex.Width, mode.Width);
484 ok(mode_ex.Height == mode.Height, "Height is %d instead of %d.\n", mode_ex.Height, mode.Height);
485 ok(mode_ex.RefreshRate == mode.RefreshRate, "RefreshRate is %d instead of %d.\n",
486 mode_ex.RefreshRate, mode.RefreshRate);
487 ok(mode_ex.Format == mode.Format, "Format is %x instead of %x.\n", mode_ex.Format, mode.Format);
488 /* Don't know yet how to test for ScanLineOrdering, just testing that it
489 * is set to a value by GetDisplayModeEx(). */
490 ok(mode_ex.ScanLineOrdering != 0, "ScanLineOrdering returned 0.\n");
491 /* Don't know how to compare the rotation in this case, test that it is set */
492 ok(rotation != (D3DDISPLAYROTATION)0xdeadbeef, "rotation is %d, expected != 0xdeadbeef.\n", rotation);
494 trace("GetDisplayModeEx returned Width = %d, Height = %d, RefreshRate = %d, Format = %x, ScanLineOrdering = %x, rotation = %d.\n",
495 mode_ex.Width, mode_ex.Height, mode_ex.RefreshRate, mode_ex.Format, mode_ex.ScanLineOrdering, rotation);
497 /* test GetDisplayModeEx with null pointer for D3DDISPLAYROTATION */
498 memset(&mode_ex, 0, sizeof(mode_ex));
499 mode_ex.Size = sizeof(D3DDISPLAYMODEEX);
501 hr = IDirect3DSwapChain9Ex_GetDisplayModeEx(swapchainEx, &mode_ex, NULL);
502 ok(SUCCEEDED(hr), "GetDisplayModeEx failed, hr %#lx.\n", hr);
504 ok(mode_ex.Size == sizeof(D3DDISPLAYMODEEX), "Size is %d.\n", mode_ex.Size);
505 ok(mode_ex.Width == mode.Width, "Width is %d instead of %d.\n", mode_ex.Width, mode.Width);
506 ok(mode_ex.Height == mode.Height, "Height is %d instead of %d.\n", mode_ex.Height, mode.Height);
507 ok(mode_ex.RefreshRate == mode.RefreshRate, "RefreshRate is %d instead of %d.\n",
508 mode_ex.RefreshRate, mode.RefreshRate);
509 ok(mode_ex.Format == mode.Format, "Format is %x instead of %x.\n", mode_ex.Format, mode.Format);
510 /* Don't know yet how to test for ScanLineOrdering, just testing that it
511 * is set to a value by GetDisplayModeEx(). */
512 ok(mode_ex.ScanLineOrdering != 0, "ScanLineOrdering returned 0.\n");
514 IDirect3DSwapChain9Ex_Release(swapchainEx);
516 out:
517 if (device)
518 IDirect3DDevice9Ex_Release(device);
519 DestroyWindow(window);
522 static void test_get_adapter_displaymode_ex(void)
524 HWND window = create_window();
525 IDirect3D9 *d3d9 = (void *) 0xdeadbeef;
526 IDirect3D9Ex *d3d9ex;
527 UINT count;
528 HRESULT hr;
529 D3DDISPLAYMODE mode;
530 D3DDISPLAYMODEEX mode_ex;
531 D3DDISPLAYROTATION rotation;
532 DEVMODEW startmode, devmode;
533 LONG retval;
535 hr = pDirect3DCreate9Ex(D3D_SDK_VERSION, &d3d9ex);
536 if (FAILED(hr))
538 skip("Failed to create IDirect3D9Ex, hr %#lx.\n", hr);
539 DestroyWindow(window);
540 return;
543 count = IDirect3D9Ex_GetAdapterCount(d3d9ex);
544 if (!count)
546 skip("No adapters available.\n");
547 IDirect3D9Ex_Release(d3d9ex);
548 DestroyWindow(window);
549 return;
552 hr = IDirect3D9Ex_QueryInterface(d3d9ex, &IID_IDirect3D9, (void **) &d3d9);
553 ok(hr == S_OK, "Got hr %#lx.\n", hr);
554 ok(d3d9 != NULL && d3d9 != (void *) 0xdeadbeef,
555 "QueryInterface returned interface %p, expected != NULL && != 0xdeadbeef\n", d3d9);
557 memset(&startmode, 0, sizeof(startmode));
558 startmode.dmSize = sizeof(startmode);
559 retval = EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &startmode, 0);
560 ok(retval, "Failed to retrieve current display mode, retval %ld.\n", retval);
561 if (!retval) goto out;
563 devmode = startmode;
564 devmode.dmFields = DM_DISPLAYORIENTATION | DM_PELSWIDTH | DM_PELSHEIGHT;
565 S2(U1(devmode)).dmDisplayOrientation = DMDO_180;
566 retval = ChangeDisplaySettingsExW(NULL, &devmode, NULL, 0, NULL);
567 if (retval == DISP_CHANGE_BADMODE)
569 skip("Graphics mode is not supported.\n");
570 goto out;
573 ok(retval == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsEx failed with %ld.\n", retval);
574 /* try retrieve orientation info with EnumDisplaySettingsEx*/
575 devmode.dmFields = 0;
576 S2(U1(devmode)).dmDisplayOrientation = 0;
577 ok(EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &devmode, EDS_ROTATEDMODE),
578 "EnumDisplaySettingsEx failed.\n");
580 /*now that orientation has changed start tests for GetAdapterDisplayModeEx: invalid Size*/
581 memset(&mode_ex, 0, sizeof(mode_ex));
582 hr = IDirect3D9Ex_GetAdapterDisplayModeEx(d3d9ex, D3DADAPTER_DEFAULT, &mode_ex, &rotation);
583 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
585 mode_ex.Size = sizeof(D3DDISPLAYMODEEX);
586 /* invalid count*/
587 hr = IDirect3D9Ex_GetAdapterDisplayModeEx(d3d9ex, count + 1, &mode_ex, &rotation);
588 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
589 /*valid count and valid Size*/
590 hr = IDirect3D9Ex_GetAdapterDisplayModeEx(d3d9ex, D3DADAPTER_DEFAULT, &mode_ex, &rotation);
591 ok(SUCCEEDED(hr), "GetAdapterDisplayModeEx failed, hr %#lx.\n", hr);
593 /* Compare what GetAdapterDisplayMode returns with what GetAdapterDisplayModeEx returns*/
594 hr = IDirect3D9_GetAdapterDisplayMode(d3d9, D3DADAPTER_DEFAULT, &mode);
595 ok(SUCCEEDED(hr), "GetAdapterDisplayMode failed, hr %#lx.\n", hr);
597 ok(mode_ex.Size == sizeof(D3DDISPLAYMODEEX), "size is %d\n", mode_ex.Size);
598 ok(mode_ex.Width == mode.Width, "width is %d instead of %d\n", mode_ex.Width, mode.Width);
599 ok(mode_ex.Height == mode.Height, "height is %d instead of %d\n", mode_ex.Height, mode.Height);
600 ok(mode_ex.RefreshRate == mode.RefreshRate, "RefreshRate is %d instead of %d\n",
601 mode_ex.RefreshRate, mode.RefreshRate);
602 ok(mode_ex.Format == mode.Format, "format is %x instead of %x\n", mode_ex.Format, mode.Format);
603 /* Don't know yet how to test for ScanLineOrdering, just testing that it
604 * is set to a value by GetAdapterDisplayModeEx(). */
605 ok(mode_ex.ScanLineOrdering != 0, "ScanLineOrdering returned 0\n");
606 /* Check that orientation is returned correctly by GetAdapterDisplayModeEx
607 * and EnumDisplaySettingsEx(). */
608 ok(S2(U1(devmode)).dmDisplayOrientation == DMDO_180 && rotation == D3DDISPLAYROTATION_180,
609 "rotation is %d instead of %ld\n", rotation, S2(U1(devmode)).dmDisplayOrientation);
611 trace("GetAdapterDisplayModeEx returned Width = %d, Height = %d, RefreshRate = %d, Format = %x, ScanLineOrdering = %x, rotation = %d\n",
612 mode_ex.Width, mode_ex.Height, mode_ex.RefreshRate, mode_ex.Format, mode_ex.ScanLineOrdering, rotation);
614 /* test GetAdapterDisplayModeEx with null pointer for D3DDISPLAYROTATION */
615 memset(&mode_ex, 0, sizeof(mode_ex));
616 mode_ex.Size = sizeof(D3DDISPLAYMODEEX);
618 hr = IDirect3D9Ex_GetAdapterDisplayModeEx(d3d9ex, D3DADAPTER_DEFAULT, &mode_ex, NULL);
619 ok(SUCCEEDED(hr), "GetAdapterDisplayModeEx failed, hr %#lx.\n", hr);
621 ok(mode_ex.Size == sizeof(D3DDISPLAYMODEEX), "size is %d\n", mode_ex.Size);
622 ok(mode_ex.Width == mode.Width, "width is %d instead of %d\n", mode_ex.Width, mode.Width);
623 ok(mode_ex.Height == mode.Height, "height is %d instead of %d\n", mode_ex.Height, mode.Height);
624 ok(mode_ex.RefreshRate == mode.RefreshRate, "RefreshRate is %d instead of %d\n",
625 mode_ex.RefreshRate, mode.RefreshRate);
626 ok(mode_ex.Format == mode.Format, "format is %x instead of %x\n", mode_ex.Format, mode.Format);
627 /* Don't know yet how to test for ScanLineOrdering, just testing that it
628 * is set to a value by GetAdapterDisplayModeEx(). */
629 ok(mode_ex.ScanLineOrdering != 0, "ScanLineOrdering returned 0\n");
631 /* return to the default mode */
632 retval = ChangeDisplaySettingsExW(NULL, &startmode, NULL, 0, NULL);
633 ok(retval == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsEx failed with %ld.\n", retval);
634 out:
635 IDirect3D9_Release(d3d9);
636 IDirect3D9Ex_Release(d3d9ex);
637 DestroyWindow(window);
640 static void test_create_depth_stencil_surface_ex(void)
642 static const struct
644 DWORD usage;
645 HRESULT hr;
646 BOOL broken_warp;
648 tests[] =
650 {0, D3D_OK, FALSE},
651 {D3DUSAGE_DEPTHSTENCIL, D3DERR_INVALIDCALL, FALSE},
652 {D3DUSAGE_RESTRICTED_CONTENT, D3D_OK, TRUE},
655 D3DADAPTER_IDENTIFIER9 identifier;
656 D3DSURFACE_DESC surface_desc;
657 IDirect3DDevice9Ex *device;
658 IDirect3DSurface9 *surface;
659 IDirect3D9 *d3d;
660 unsigned int i;
661 HWND window;
662 HRESULT hr;
663 ULONG ref;
664 BOOL warp;
666 window = create_window();
668 if (!(device = create_device(window, NULL)))
670 skip("Failed to create a D3D device.\n");
671 DestroyWindow(window);
672 return;
675 hr = IDirect3DDevice9Ex_GetDirect3D(device, &d3d);
676 ok(SUCCEEDED(hr), "Failed to get Direct3D9, hr %#lx.\n", hr);
677 hr = IDirect3D9_GetAdapterIdentifier(d3d, D3DADAPTER_DEFAULT, 0, &identifier);
678 ok(SUCCEEDED(hr), "Failed to get adapter identifier, hr %#lx.\n", hr);
679 warp = adapter_is_warp(&identifier);
680 IDirect3D9_Release(d3d);
682 for (i = 0; i < ARRAY_SIZE(tests); ++i)
684 surface = (IDirect3DSurface9 *)0xdeadbeef;
685 hr = IDirect3DDevice9Ex_CreateDepthStencilSurfaceEx(device, 64, 64, D3DFMT_D24S8,
686 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL, tests[i].usage);
687 ok(hr == tests[i].hr || broken(warp && tests[i].broken_warp),
688 "Test %u: Got unexpected hr %#lx.\n", i, hr);
689 if (SUCCEEDED(hr))
691 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
692 ok(SUCCEEDED(hr), "Test %u: GetDesc failed, hr %#lx.\n", i, hr);
693 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Test %u: Got unexpected type %#x.\n",
694 i, surface_desc.Type);
695 ok(surface_desc.Pool == D3DPOOL_DEFAULT, "Test %u: Got unexpected pool %#x.\n",
696 i, surface_desc.Pool);
697 ok(surface_desc.Usage == (tests[i].usage | D3DUSAGE_DEPTHSTENCIL),
698 "Test %u: Got unexpected usage %#lx.\n", i, surface_desc.Usage);
700 ref = IDirect3DSurface9_Release(surface);
701 ok(!ref, "Test %u: Surface has %lu references left.\n", i, ref);
703 else
705 ok(surface == (IDirect3DSurface9 *)0xdeadbeef || broken(warp && tests[i].broken_warp),
706 "Test %u: Got unexpected surface pointer %p.\n", i, surface);
710 ref = IDirect3DDevice9Ex_Release(device);
711 ok(!ref, "Device has %lu references left.\n", ref);
712 DestroyWindow(window);
715 static void test_user_memory(void)
717 static const struct
719 float x, y, z;
720 float u, v;
722 quad[] =
724 {-1.0f, -1.0f, 0.0f, 0.0f, 1.0f},
725 {-1.0f, 1.0f, 0.0f, 0.0f, 0.0f},
726 { 1.0f, -1.0f, 0.0f, 1.0f, 1.0f},
727 { 1.0f, 1.0f, 0.0f, 1.0f, 0.0f},
729 IDirect3DDevice9Ex *device;
730 IDirect3DTexture9 *texture, *texture2;
731 IDirect3DCubeTexture9 *cube_texture;
732 IDirect3DVolumeTexture9 *volume_texture;
733 IDirect3DVertexBuffer9 *vertex_buffer;
734 IDirect3DIndexBuffer9 *index_buffer;
735 IDirect3DSurface9 *surface;
736 D3DLOCKED_RECT locked_rect;
737 unsigned int color, x, y;
738 ULONG refcount;
739 HWND window;
740 HRESULT hr;
741 void *mem;
742 char *ptr;
743 D3DCAPS9 caps;
745 window = create_window();
746 if (!(device = create_device(window, NULL)))
748 skip("Failed to create a D3D device, skipping tests.\n");
749 goto done;
752 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
753 ok(SUCCEEDED(hr), "Failed to get caps, hr %#lx.\n", hr);
755 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 128 * 128 * 4);
756 hr = IDirect3DDevice9Ex_CreateTexture(device, 128, 128, 0, 0, D3DFMT_A8R8G8B8,
757 D3DPOOL_SYSTEMMEM, &texture, &mem);
758 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
759 hr = IDirect3DDevice9Ex_CreateTexture(device, 1, 1, 0, 0, D3DFMT_A8R8G8B8,
760 D3DPOOL_SYSTEMMEM, &texture, &mem);
761 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
762 hr = IDirect3DDevice9Ex_CreateTexture(device, 128, 128, 2, 0, D3DFMT_A8R8G8B8,
763 D3DPOOL_SYSTEMMEM, &texture, &mem);
764 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
765 hr = IDirect3DDevice9Ex_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
766 D3DPOOL_SCRATCH, &texture, &mem);
767 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
769 hr = IDirect3DDevice9Ex_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
770 D3DPOOL_SYSTEMMEM, &texture, &mem);
771 ok(SUCCEEDED(hr), "Failed to create texture, hr %#lx.\n", hr);
772 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
773 ok(SUCCEEDED(hr), "Failed to lock texture, hr %#lx.\n", hr);
774 ok(locked_rect.Pitch == 128 * 4, "Got unexpected pitch %d.\n", locked_rect.Pitch);
775 ok(locked_rect.pBits == mem, "Got unexpected pBits %p, expected %p.\n", locked_rect.pBits, mem);
776 hr = IDirect3DTexture9_UnlockRect(texture, 0);
777 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#lx.\n", hr);
778 IDirect3DTexture9_Release(texture);
780 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
782 hr = IDirect3DDevice9Ex_CreateCubeTexture(device, 2, 1, 0, D3DFMT_A8R8G8B8,
783 D3DPOOL_SYSTEMMEM, &cube_texture, &mem);
784 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
786 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
788 hr = IDirect3DDevice9Ex_CreateVolumeTexture(device, 2, 2, 2, 1, 0, D3DFMT_A8R8G8B8,
789 D3DPOOL_SYSTEMMEM, &volume_texture, &mem);
790 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
793 hr = IDirect3DDevice9Ex_CreateIndexBuffer(device, 16, 0, D3DFMT_INDEX32, D3DPOOL_SYSTEMMEM,
794 &index_buffer, &mem);
795 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#lx.\n", hr);
796 hr = IDirect3DDevice9Ex_CreateVertexBuffer(device, 16, 0, 0, D3DPOOL_SYSTEMMEM,
797 &vertex_buffer, &mem);
798 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#lx.\n", hr);
800 hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurface(device, 128, 128, D3DFMT_A8R8G8B8,
801 D3DPOOL_SYSTEMMEM, &surface, &mem);
802 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
803 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
804 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
805 ok(locked_rect.Pitch == 128 * 4, "Got unexpected pitch %d.\n", locked_rect.Pitch);
806 ok(locked_rect.pBits == mem, "Got unexpected pBits %p, expected %p.\n", locked_rect.pBits, mem);
807 hr = IDirect3DSurface9_UnlockRect(surface);
808 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
809 IDirect3DSurface9_Release(surface);
811 hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurfaceEx(device, 128, 128, D3DFMT_A8R8G8B8,
812 D3DPOOL_SYSTEMMEM, &surface, &mem, 0);
813 todo_wine ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
814 if (SUCCEEDED(hr))
816 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
817 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
818 ok(locked_rect.Pitch == 128 * 4, "Got unexpected pitch %d.\n", locked_rect.Pitch);
819 ok(locked_rect.pBits == mem, "Got unexpected pBits %p, expected %p.\n", locked_rect.pBits, mem);
820 hr = IDirect3DSurface9_UnlockRect(surface);
821 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
822 IDirect3DSurface9_Release(surface);
825 hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurface(device, 128, 128, D3DFMT_A8R8G8B8,
826 D3DPOOL_SCRATCH, &surface, &mem);
827 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
828 hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurfaceEx(device, 128, 128, D3DFMT_A8R8G8B8,
829 D3DPOOL_SCRATCH, &surface, &mem, 0);
830 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
832 ptr = mem;
833 for (y = 0; y < 33; ++y)
834 for (x = 0; x < 33; ++x)
835 *ptr++ = x * 255 / 32;
837 hr = IDirect3DDevice9Ex_CreateTexture(device, 33, 33, 1, 0, D3DFMT_L8,
838 D3DPOOL_SYSTEMMEM, &texture, &mem);
839 ok(SUCCEEDED(hr), "Failed to create texture, hr %#lx.\n", hr);
840 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
841 ok(SUCCEEDED(hr), "Failed to lock texture, hr %#lx.\n", hr);
842 ok(locked_rect.Pitch == 33, "Got unexpected pitch %d.\n", locked_rect.Pitch);
843 ok(locked_rect.pBits == mem, "Got unexpected pBits %p, expected %p.\n", locked_rect.pBits, mem);
844 hr = IDirect3DTexture9_UnlockRect(texture, 0);
845 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#lx.\n", hr);
847 hr = IDirect3DDevice9Ex_CreateTexture(device, 33, 33, 1, 0, D3DFMT_L8,
848 D3DPOOL_DEFAULT, &texture2, NULL);
849 ok(SUCCEEDED(hr), "Failed to create texture, hr %#lx.\n", hr);
850 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texture,
851 (IDirect3DBaseTexture9 *)texture2);
852 ok(SUCCEEDED(hr), "Failed to update texture, hr %#lx.\n", hr);
854 hr = IDirect3DDevice9Ex_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0);
855 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
857 hr = IDirect3DDevice9Ex_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
858 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#lx.\n", hr);
859 hr = IDirect3DDevice9Ex_SetRenderState(device, D3DRS_LIGHTING, FALSE);
860 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#lx.\n", hr);
861 hr = IDirect3DDevice9Ex_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture2);
862 ok(SUCCEEDED(hr), "Failed to set texture, hr %#lx.\n", hr);
864 hr = IDirect3DDevice9Ex_BeginScene(device);
865 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
866 hr = IDirect3DDevice9Ex_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
867 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
868 hr = IDirect3DDevice9Ex_EndScene(device);
869 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
871 color = get_pixel_color(device, 320, 240);
872 ok(color_match(color, 0x007f7f7f, 2), "Got unexpected color %#x.\n", color);
873 hr = IDirect3DDevice9Ex_Present(device, NULL, NULL, NULL, NULL);
874 ok(SUCCEEDED(hr), "Failed to present, hr %#lx.\n", hr);
876 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
877 ok(SUCCEEDED(hr), "Failed to set texture, hr %#lx.\n", hr);
878 IDirect3DTexture9_Release(texture2);
879 IDirect3DTexture9_Release(texture);
880 HeapFree(GetProcessHeap(), 0, mem);
881 refcount = IDirect3DDevice9Ex_Release(device);
882 ok(!refcount, "Device has %lu references left.\n", refcount);
884 done:
885 DestroyWindow(window);
888 static void test_reset(void)
890 static const DWORD simple_vs[] =
892 0xfffe0101, /* vs_1_1 */
893 0x0000001f, 0x80000000, 0x900f0000, /* dcl_position0 v0 */
894 0x00000009, 0xc0010000, 0x90e40000, 0xa0e40000, /* dp4 oPos.x, v0, c0 */
895 0x00000009, 0xc0020000, 0x90e40000, 0xa0e40001, /* dp4 oPos.y, v0, c1 */
896 0x00000009, 0xc0040000, 0x90e40000, 0xa0e40002, /* dp4 oPos.z, v0, c2 */
897 0x00000009, 0xc0080000, 0x90e40000, 0xa0e40003, /* dp4 oPos.w, v0, c3 */
898 0x0000ffff, /* end */
901 unsigned int width, height, i, adapter_mode_count, offset, stride;
902 const DWORD orig_height = GetSystemMetrics(SM_CYSCREEN);
903 const DWORD orig_width = GetSystemMetrics(SM_CXSCREEN);
904 IDirect3DVertexBuffer9 *vb, *cur_vb;
905 IDirect3DIndexBuffer9 *ib, *cur_ib;
906 IDirect3DVertexShader9 *shader;
907 IDirect3DSwapChain9 *swapchain;
908 D3DDISPLAYMODE d3ddm, d3ddm2;
909 D3DPRESENT_PARAMETERS d3dpp;
910 IDirect3DDevice9Ex *device;
911 IDirect3DSurface9 *surface;
912 IDirect3DTexture9 *texture;
913 DEVMODEW devmode;
914 IDirect3D9 *d3d9;
915 D3DVIEWPORT9 vp;
916 ULONG refcount;
917 D3DCAPS9 caps;
918 DWORD value;
919 HWND window;
920 HRESULT hr;
921 RECT rect, client_rect;
922 LONG ret;
923 struct
925 UINT w;
926 UINT h;
927 } *modes = NULL;
928 UINT mode_count = 0;
930 window = create_window();
931 if (!(device = create_device(window, NULL)))
933 skip("Failed to create a D3D device, skipping test.\n");
934 DestroyWindow(window);
935 return;
938 hr = IDirect3DDevice9Ex_GetDirect3D(device, &d3d9);
939 ok(SUCCEEDED(hr), "Failed to get d3d9, hr %#lx.\n", hr);
940 hr = IDirect3DDevice9Ex_GetDeviceCaps(device, &caps);
941 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#lx.\n", hr);
943 IDirect3D9_GetAdapterDisplayMode(d3d9, D3DADAPTER_DEFAULT, &d3ddm);
944 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, d3ddm.Format);
945 modes = HeapAlloc(GetProcessHeap(), 0, sizeof(*modes) * adapter_mode_count);
946 for (i = 0; i < adapter_mode_count; ++i)
948 UINT j;
950 hr = IDirect3D9_EnumAdapterModes(d3d9, D3DADAPTER_DEFAULT, d3ddm.Format, i, &d3ddm2);
951 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#lx.\n", hr);
953 for (j = 0; j < mode_count; ++j)
955 if (modes[j].w == d3ddm2.Width && modes[j].h == d3ddm2.Height)
956 break;
958 if (j == mode_count)
960 modes[j].w = d3ddm2.Width;
961 modes[j].h = d3ddm2.Height;
962 ++mode_count;
965 /* We use them as invalid modes. */
966 if ((d3ddm2.Width == 801 && d3ddm2.Height == 600)
967 || (d3ddm2.Width == 32 && d3ddm2.Height == 32))
969 skip("This system supports a screen resolution of %dx%d, not running mode tests.\n",
970 d3ddm2.Width, d3ddm2.Height);
971 goto cleanup;
975 if (mode_count < 2)
977 skip("Less than 2 modes supported, skipping mode tests.\n");
978 goto cleanup;
981 i = 0;
982 if (modes[i].w == orig_width && modes[i].h == orig_height)
983 ++i;
985 memset(&d3dpp, 0, sizeof(d3dpp));
986 d3dpp.Windowed = FALSE;
987 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
988 d3dpp.BackBufferWidth = modes[i].w;
989 d3dpp.BackBufferHeight = modes[i].h;
990 d3dpp.BackBufferFormat = d3ddm.Format;
991 d3dpp.EnableAutoDepthStencil = TRUE;
992 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
993 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
994 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
995 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
996 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
998 width = GetSystemMetrics(SM_CXSCREEN);
999 height = GetSystemMetrics(SM_CYSCREEN);
1000 ok(width == modes[i].w, "Got screen width %u, expected %u.\n", width, modes[i].w);
1001 ok(height == modes[i].h, "Got screen height %u, expected %u.\n", height, modes[i].h);
1003 hr = IDirect3DDevice9Ex_GetScissorRect(device, &rect);
1004 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#lx.\n", hr);
1005 ok(rect.left == 0 && rect.top == 0 && rect.right == modes[i].w && rect.bottom == modes[i].h,
1006 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
1008 hr = IDirect3DDevice9Ex_GetViewport(device, &vp);
1009 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#lx.\n", hr);
1010 ok(vp.X == 0, "Got unexpected vp.X %lu.\n", vp.X);
1011 ok(vp.Y == 0, "Got unexpected vp.Y %lu.\n", vp.Y);
1012 ok(vp.Width == modes[i].w, "Got vp.Width %lu, expected %u.\n", vp.Width, modes[i].w);
1013 ok(vp.Height == modes[i].h, "Got vp.Height %lu, expected %u.\n", vp.Height, modes[i].h);
1014 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
1015 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
1017 i = 1;
1018 vp.X = 10;
1019 vp.Y = 20;
1020 vp.MinZ = 2.0f;
1021 vp.MaxZ = 3.0f;
1022 hr = IDirect3DDevice9Ex_SetViewport(device, &vp);
1023 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
1025 SetRect(&rect, 10, 20, 30, 40);
1026 hr = IDirect3DDevice9Ex_SetScissorRect(device, &rect);
1027 ok(SUCCEEDED(hr), "Failed to set scissor rect, hr %#lx.\n", hr);
1029 hr = IDirect3DDevice9_GetRenderState(device, D3DRS_LIGHTING, &value);
1030 ok(SUCCEEDED(hr), "Failed to get render state, hr %#lx.\n", hr);
1031 ok(!!value, "Got unexpected value %#lx for D3DRS_LIGHTING.\n", value);
1032 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1033 ok(SUCCEEDED(hr), "Failed to set render state, hr %#lx.\n", hr);
1035 memset(&d3dpp, 0, sizeof(d3dpp));
1036 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1037 d3dpp.Windowed = FALSE;
1038 d3dpp.BackBufferWidth = modes[i].w;
1039 d3dpp.BackBufferHeight = modes[i].h;
1040 d3dpp.BackBufferFormat = d3ddm.Format;
1041 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
1042 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
1043 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1044 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
1046 /* Render states are preserved in d3d9ex. */
1047 hr = IDirect3DDevice9_GetRenderState(device, D3DRS_LIGHTING, &value);
1048 ok(SUCCEEDED(hr), "Failed to get render state, hr %#lx.\n", hr);
1049 ok(!value, "Got unexpected value %#lx for D3DRS_LIGHTING.\n", value);
1051 hr = IDirect3DDevice9Ex_GetScissorRect(device, &rect);
1052 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#lx.\n", hr);
1053 ok(rect.left == 0 && rect.top == 0 && rect.right == modes[i].w && rect.bottom == modes[i].h,
1054 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
1056 hr = IDirect3DDevice9Ex_GetViewport(device, &vp);
1057 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#lx.\n", hr);
1058 ok(vp.X == 0, "Got unexpected vp.X %lu.\n", vp.X);
1059 ok(vp.Y == 0, "Got unexpected vp.Y %lu.\n", vp.Y);
1060 ok(vp.Width == modes[i].w, "Got vp.Width %lu, expected %u.\n", vp.Width, modes[i].w);
1061 ok(vp.Height == modes[i].h, "Got vp.Height %lu, expected %u.\n", vp.Height, modes[i].h);
1062 ok(vp.MinZ == 2.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
1063 ok(vp.MaxZ == 3.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
1065 width = GetSystemMetrics(SM_CXSCREEN);
1066 height = GetSystemMetrics(SM_CYSCREEN);
1067 ok(width == modes[i].w, "Got screen width %u, expected %u.\n", width, modes[i].w);
1068 ok(height == modes[i].h, "Got screen height %u, expected %u.\n", height, modes[i].h);
1070 hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain);
1071 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#lx.\n", hr);
1072 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1073 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#lx.\n", hr);
1074 ok(d3dpp.BackBufferWidth == modes[i].w, "Got backbuffer width %u, expected %u.\n",
1075 d3dpp.BackBufferWidth, modes[i].w);
1076 ok(d3dpp.BackBufferHeight == modes[i].h, "Got backbuffer height %u, expected %u.\n",
1077 d3dpp.BackBufferHeight, modes[i].h);
1078 IDirect3DSwapChain9_Release(swapchain);
1080 memset(&d3dpp, 0, sizeof(d3dpp));
1081 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1082 d3dpp.Windowed = TRUE;
1083 d3dpp.BackBufferWidth = 400;
1084 d3dpp.BackBufferHeight = 300;
1085 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1086 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
1087 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
1088 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1089 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
1091 width = GetSystemMetrics(SM_CXSCREEN);
1092 height = GetSystemMetrics(SM_CYSCREEN);
1093 ok(width == orig_width, "Got screen width %u, expected %lu.\n", width, orig_width);
1094 ok(height == orig_height, "Got screen height %u, expected %lu.\n", height, orig_height);
1096 hr = IDirect3DDevice9Ex_GetScissorRect(device, &rect);
1097 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#lx.\n", hr);
1098 ok(rect.left == 0 && rect.top == 0 && rect.right == 400 && rect.bottom == 300,
1099 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
1101 hr = IDirect3DDevice9Ex_GetViewport(device, &vp);
1102 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#lx.\n", hr);
1103 ok(vp.X == 0, "Got unexpected vp.X %lu.\n", vp.X);
1104 ok(vp.Y == 0, "Got unexpected vp.Y %lu.\n", vp.Y);
1105 ok(vp.Width == 400, "Got unexpected vp.Width %lu.\n", vp.Width);
1106 ok(vp.Height == 300, "Got unexpected vp.Height %lu.\n", vp.Height);
1107 ok(vp.MinZ == 2.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
1108 ok(vp.MaxZ == 3.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
1110 hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain);
1111 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#lx.\n", hr);
1112 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1113 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#lx.\n", hr);
1114 ok(d3dpp.BackBufferWidth == 400, "Got unexpected backbuffer width %u.\n", d3dpp.BackBufferWidth);
1115 ok(d3dpp.BackBufferHeight == 300, "Got unexpected backbuffer height %u.\n", d3dpp.BackBufferHeight);
1116 IDirect3DSwapChain9_Release(swapchain);
1118 memset(&devmode, 0, sizeof(devmode));
1119 devmode.dmSize = sizeof(devmode);
1120 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
1121 devmode.dmPelsWidth = modes[1].w;
1122 devmode.dmPelsHeight = modes[1].h;
1123 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
1124 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", ret);
1125 width = GetSystemMetrics(SM_CXSCREEN);
1126 height = GetSystemMetrics(SM_CYSCREEN);
1127 ok(width == modes[1].w, "Screen width is %u, expected %u.\n", width, modes[1].w);
1128 ok(height == modes[1].h, "Screen height is %u, expected %u.\n", height, modes[1].h);
1130 d3dpp.BackBufferWidth = 500;
1131 d3dpp.BackBufferHeight = 400;
1132 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1133 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
1134 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
1135 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1136 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
1138 width = GetSystemMetrics(SM_CXSCREEN);
1139 height = GetSystemMetrics(SM_CYSCREEN);
1140 ok(width == modes[1].w, "Screen width is %u, expected %u.\n", width, modes[1].w);
1141 ok(height == modes[1].h, "Screen height is %u, expected %u.\n", height, modes[1].h);
1143 hr = IDirect3DDevice9Ex_GetScissorRect(device, &rect);
1144 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#lx.\n", hr);
1145 ok(rect.left == 0 && rect.top == 0 && rect.right == 500 && rect.bottom == 400,
1146 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
1148 hr = IDirect3DDevice9Ex_GetViewport(device, &vp);
1149 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#lx.\n", hr);
1150 ok(vp.X == 0, "Got unexpected vp.X %lu.\n", vp.X);
1151 ok(vp.Y == 0, "Got unexpected vp.Y %lu.\n", vp.Y);
1152 ok(vp.Width == 500, "Got unexpected vp.Width %lu.\n", vp.Width);
1153 ok(vp.Height == 400, "Got unexpected vp.Height %lu.\n", vp.Height);
1154 ok(vp.MinZ == 2.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
1155 ok(vp.MaxZ == 3.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
1157 hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain);
1158 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#lx.\n", hr);
1159 memset(&d3dpp, 0, sizeof(d3dpp));
1160 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1161 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#lx.\n", hr);
1162 ok(d3dpp.BackBufferWidth == 500, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
1163 ok(d3dpp.BackBufferHeight == 400, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
1164 IDirect3DSwapChain9_Release(swapchain);
1166 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
1167 devmode.dmPelsWidth = orig_width;
1168 devmode.dmPelsHeight = orig_height;
1169 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
1170 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", ret);
1171 width = GetSystemMetrics(SM_CXSCREEN);
1172 height = GetSystemMetrics(SM_CYSCREEN);
1173 ok(width == orig_width, "Got screen width %u, expected %lu.\n", width, orig_width);
1174 ok(height == orig_height, "Got screen height %u, expected %lu.\n", height, orig_height);
1176 SetRect(&rect, 0, 0, 200, 150);
1177 ok(AdjustWindowRect(&rect, GetWindowLongW(window, GWL_STYLE), FALSE), "Failed to adjust window rect.\n");
1178 ok(SetWindowPos(window, NULL, 0, 0, rect.right - rect.left, rect.bottom - rect.top,
1179 SWP_NOMOVE | SWP_NOZORDER), "Failed to set window position.\n");
1181 /* Windows 10 gives us a different size than we requested with some DPI scaling settings (e.g. 172%). */
1182 ok(GetClientRect(window, &client_rect), "Failed to get client rect.\n");
1184 memset(&d3dpp, 0, sizeof(d3dpp));
1185 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1186 d3dpp.Windowed = TRUE;
1187 d3dpp.BackBufferWidth = 0;
1188 d3dpp.BackBufferHeight = 0;
1189 d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
1190 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
1191 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
1192 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1193 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1195 ok(d3dpp.BackBufferWidth == client_rect.right,
1196 "Got unexpected BackBufferWidth %u, expected %ld.\n", d3dpp.BackBufferWidth, client_rect.right);
1197 ok(d3dpp.BackBufferHeight == client_rect.bottom,
1198 "Got unexpected BackBufferHeight %u, expected %ld.\n", d3dpp.BackBufferHeight, client_rect.bottom);
1199 ok(d3dpp.BackBufferFormat == d3ddm.Format, "Got unexpected BackBufferFormat %#x, expected %#x.\n",
1200 d3dpp.BackBufferFormat, d3ddm.Format);
1201 ok(d3dpp.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", d3dpp.BackBufferCount);
1202 ok(!d3dpp.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
1203 ok(!d3dpp.MultiSampleQuality, "Got unexpected MultiSampleQuality %lu.\n", d3dpp.MultiSampleQuality);
1204 ok(d3dpp.SwapEffect == D3DSWAPEFFECT_DISCARD, "Got unexpected SwapEffect %#x.\n", d3dpp.SwapEffect);
1205 ok(!d3dpp.hDeviceWindow, "Got unexpected hDeviceWindow %p.\n", d3dpp.hDeviceWindow);
1206 ok(d3dpp.Windowed, "Got unexpected Windowed %#x.\n", d3dpp.Windowed);
1207 ok(!d3dpp.EnableAutoDepthStencil, "Got unexpected EnableAutoDepthStencil %#x.\n", d3dpp.EnableAutoDepthStencil);
1208 ok(!d3dpp.AutoDepthStencilFormat, "Got unexpected AutoDepthStencilFormat %#x.\n", d3dpp.AutoDepthStencilFormat);
1209 ok(!d3dpp.Flags, "Got unexpected Flags %#lx.\n", d3dpp.Flags);
1210 ok(!d3dpp.FullScreen_RefreshRateInHz, "Got unexpected FullScreen_RefreshRateInHz %u.\n",
1211 d3dpp.FullScreen_RefreshRateInHz);
1212 ok(!d3dpp.PresentationInterval, "Got unexpected PresentationInterval %#x.\n", d3dpp.PresentationInterval);
1214 hr = IDirect3DDevice9Ex_GetScissorRect(device, &rect);
1215 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#lx.\n", hr);
1216 ok(EqualRect(&rect, &client_rect), "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
1218 hr = IDirect3DDevice9Ex_GetViewport(device, &vp);
1219 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#lx.\n", hr);
1220 ok(vp.X == 0, "Got unexpected vp.X %lu.\n", vp.X);
1221 ok(vp.Y == 0, "Got unexpected vp.Y %lu.\n", vp.Y);
1222 ok(vp.Width == client_rect.right, "Got unexpected vp.Width %lu, expected %ld.\n",
1223 vp.Width, client_rect.right);
1224 ok(vp.Height == client_rect.bottom, "Got unexpected vp.Height %lu, expected %ld.\n",
1225 vp.Height, client_rect.bottom);
1226 ok(vp.MinZ == 2.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
1227 ok(vp.MaxZ == 3.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
1229 hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain);
1230 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#lx.\n", hr);
1231 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1232 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#lx.\n", hr);
1233 ok(d3dpp.BackBufferWidth == client_rect.right, "Got unexpected backbuffer width %u, expected %ld.\n",
1234 d3dpp.BackBufferWidth, client_rect.right);
1235 ok(d3dpp.BackBufferHeight == client_rect.bottom, "Got unexpected backbuffer height %u, expected %ld.\n",
1236 d3dpp.BackBufferHeight, client_rect.bottom);
1237 ok(d3dpp.BackBufferFormat == d3ddm.Format, "Got unexpected BackBufferFormat %#x, expected %#x.\n",
1238 d3dpp.BackBufferFormat, d3ddm.Format);
1239 ok(d3dpp.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", d3dpp.BackBufferCount);
1240 ok(!d3dpp.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
1241 ok(!d3dpp.MultiSampleQuality, "Got unexpected MultiSampleQuality %lu.\n", d3dpp.MultiSampleQuality);
1242 ok(d3dpp.SwapEffect == D3DSWAPEFFECT_DISCARD, "Got unexpected SwapEffect %#x.\n", d3dpp.SwapEffect);
1243 ok(d3dpp.hDeviceWindow == window, "Got unexpected hDeviceWindow %p, expected %p.\n", d3dpp.hDeviceWindow, window);
1244 ok(d3dpp.Windowed, "Got unexpected Windowed %#x.\n", d3dpp.Windowed);
1245 ok(!d3dpp.EnableAutoDepthStencil, "Got unexpected EnableAutoDepthStencil %#x.\n", d3dpp.EnableAutoDepthStencil);
1246 ok(!d3dpp.AutoDepthStencilFormat, "Got unexpected AutoDepthStencilFormat %#x.\n", d3dpp.AutoDepthStencilFormat);
1247 ok(!d3dpp.Flags, "Got unexpected Flags %#lx.\n", d3dpp.Flags);
1248 ok(!d3dpp.FullScreen_RefreshRateInHz, "Got unexpected FullScreen_RefreshRateInHz %u.\n",
1249 d3dpp.FullScreen_RefreshRateInHz);
1250 ok(!d3dpp.PresentationInterval, "Got unexpected PresentationInterval %#x.\n", d3dpp.PresentationInterval);
1251 IDirect3DSwapChain9_Release(swapchain);
1253 memset(&d3dpp, 0, sizeof(d3dpp));
1254 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1255 d3dpp.Windowed = TRUE;
1256 d3dpp.BackBufferWidth = 400;
1257 d3dpp.BackBufferHeight = 300;
1259 /* Reset with resources in the default pool succeeds in d3d9ex. */
1260 hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurface(device, 16, 16,
1261 D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &surface, NULL);
1262 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
1263 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
1264 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
1265 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1266 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
1267 IDirect3DSurface9_Release(surface);
1269 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
1271 IDirect3DVolumeTexture9 *volume_texture;
1273 hr = IDirect3DDevice9Ex_CreateVolumeTexture(device, 16, 16, 4, 1, 0,
1274 D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &volume_texture, NULL);
1275 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#lx.\n", hr);
1276 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
1277 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
1278 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1279 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
1280 IDirect3DVolumeTexture9_Release(volume_texture);
1282 else
1284 skip("Volume textures not supported.\n");
1287 /* Test with resources bound but otherwise not referenced. */
1288 hr = IDirect3DDevice9Ex_CreateVertexBuffer(device, 16, 0,
1289 D3DFVF_XYZ, D3DPOOL_DEFAULT, &vb, NULL);
1290 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1291 hr = IDirect3DDevice9Ex_SetStreamSource(device, 0, vb, 0, 16);
1292 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1293 refcount = IDirect3DVertexBuffer9_Release(vb);
1294 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
1295 hr = IDirect3DDevice9Ex_CreateIndexBuffer(device, 16, 0,
1296 D3DFMT_INDEX16, D3DPOOL_DEFAULT, &ib, NULL);
1297 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1298 hr = IDirect3DDevice9Ex_SetIndices(device, ib);
1299 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1300 refcount = IDirect3DIndexBuffer9_Release(ib);
1301 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
1302 hr = IDirect3DDevice9Ex_CreateTexture(device, 16, 16, 0, 0,
1303 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
1304 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1305 hr = IDirect3DDevice9Ex_SetTexture(device, i, (IDirect3DBaseTexture9 *)texture);
1306 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1308 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
1309 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1311 hr = IDirect3DDevice9Ex_GetIndices(device, &cur_ib);
1312 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1313 ok(cur_ib == ib, "Unexpected index buffer %p.\n", cur_ib);
1314 refcount = IDirect3DIndexBuffer9_Release(ib);
1315 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
1316 hr = IDirect3DDevice9Ex_GetStreamSource(device, 0, &cur_vb, &offset, &stride);
1317 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1318 ok(cur_vb == vb, "Unexpected index buffer %p.\n", cur_ib);
1319 ok(!offset, "Unexpected offset %u.\n", offset);
1320 ok(stride == 16, "Unexpected stride %u.\n", stride);
1321 refcount = IDirect3DVertexBuffer9_Release(vb);
1322 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
1323 refcount = IDirect3DTexture9_Release(texture);
1324 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
1326 /* Scratch and sysmem pools are fine too. */
1327 hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurface(device, 16, 16,
1328 D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
1329 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
1330 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
1331 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
1332 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1333 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
1334 IDirect3DSurface9_Release(surface);
1336 hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurface(device, 16, 16,
1337 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
1338 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
1339 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
1340 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
1341 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1342 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
1343 IDirect3DSurface9_Release(surface);
1345 /* The depth stencil should get reset to the auto depth stencil when present. */
1346 hr = IDirect3DDevice9Ex_SetDepthStencilSurface(device, NULL);
1347 ok(SUCCEEDED(hr), "Failed to set depth/stencil surface, hr %#lx.\n", hr);
1349 d3dpp.EnableAutoDepthStencil = TRUE;
1350 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1351 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
1352 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
1353 hr = IDirect3DDevice9Ex_GetDepthStencilSurface(device, &surface);
1354 ok(SUCCEEDED(hr), "Failed to get depth/stencil surface, hr %#lx.\n", hr);
1355 ok(!!surface, "Depth/stencil surface should not be NULL.\n");
1356 IDirect3DSurface9_Release(surface);
1358 d3dpp.EnableAutoDepthStencil = FALSE;
1359 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
1360 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
1361 hr = IDirect3DDevice9Ex_GetDepthStencilSurface(device, &surface);
1362 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
1363 ok(!surface, "Depth/stencil surface should be NULL.\n");
1365 /* References to implicit surfaces are allowed in d3d9ex. */
1366 hr = IDirect3DDevice9Ex_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
1367 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#lx.\n", hr);
1368 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
1369 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
1370 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1371 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
1372 IDirect3DSurface9_Release(surface);
1374 /* Shaders are fine. */
1375 hr = IDirect3DDevice9Ex_CreateVertexShader(device, simple_vs, &shader);
1376 ok(SUCCEEDED(hr), "Failed to create vertex shader, hr %#lx.\n", hr);
1377 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
1378 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
1379 IDirect3DVertexShader9_Release(shader);
1381 /* Try setting invalid modes. */
1382 memset(&d3dpp, 0, sizeof(d3dpp));
1383 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1384 d3dpp.Windowed = FALSE;
1385 d3dpp.BackBufferWidth = 32;
1386 d3dpp.BackBufferHeight = 32;
1387 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
1388 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
1389 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1390 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
1392 memset(&d3dpp, 0, sizeof(d3dpp));
1393 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1394 d3dpp.Windowed = FALSE;
1395 d3dpp.BackBufferWidth = 801;
1396 d3dpp.BackBufferHeight = 600;
1397 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
1398 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
1399 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1400 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
1402 hr = IDirect3D9_GetAdapterDisplayMode(d3d9, D3DADAPTER_DEFAULT, &d3ddm);
1403 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#lx.\n", hr);
1405 memset(&d3dpp, 0, sizeof(d3dpp));
1406 d3dpp.Windowed = TRUE;
1407 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1408 d3dpp.BackBufferFormat = d3ddm.Format;
1409 d3dpp.EnableAutoDepthStencil = FALSE;
1410 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1412 cleanup:
1413 HeapFree(GetProcessHeap(), 0, modes);
1414 IDirect3D9_Release(d3d9);
1415 refcount = IDirect3DDevice9Ex_Release(device);
1416 ok(!refcount, "Device has %lu references left.\n", refcount);
1417 DestroyWindow(window);
1420 static void test_reset_ex(void)
1422 unsigned int height, orig_height = GetSystemMetrics(SM_CYSCREEN);
1423 unsigned int width, orig_width = GetSystemMetrics(SM_CXSCREEN);
1424 unsigned int i, adapter_mode_count, mode_count = 0;
1425 D3DDISPLAYMODEEX mode, mode2, *modes;
1426 D3DDISPLAYMODEFILTER mode_filter;
1427 IDirect3DSwapChain9 *swapchain;
1428 D3DPRESENT_PARAMETERS d3dpp;
1429 IDirect3DDevice9Ex *device;
1430 IDirect3D9Ex *d3d9;
1431 DEVMODEW devmode;
1432 D3DVIEWPORT9 vp;
1433 ULONG refcount;
1434 DWORD value;
1435 HWND window;
1436 HRESULT hr;
1437 RECT rect, client_rect;
1438 LONG ret;
1440 window = create_window();
1441 if (!(device = create_device(window, NULL)))
1443 skip("Failed to create a D3D device.\n");
1444 DestroyWindow(window);
1445 return;
1448 hr = IDirect3DDevice9Ex_GetDirect3D(device, (IDirect3D9 **)&d3d9);
1449 ok(SUCCEEDED(hr), "Failed to get d3d9, hr %#lx.\n", hr);
1451 memset(&mode, 0, sizeof(mode));
1452 mode.Size = sizeof(mode);
1453 hr = IDirect3D9Ex_GetAdapterDisplayModeEx(d3d9, D3DADAPTER_DEFAULT, &mode, NULL);
1454 ok(SUCCEEDED(hr), "GetAdapterDisplayModeEx failed, hr %#lx.\n", hr);
1455 memset(&mode_filter, 0, sizeof(mode_filter));
1456 mode_filter.Size = sizeof(mode_filter);
1457 mode_filter.Format = mode.Format;
1458 adapter_mode_count = IDirect3D9Ex_GetAdapterModeCountEx(d3d9, D3DADAPTER_DEFAULT, &mode_filter);
1459 modes = HeapAlloc(GetProcessHeap(), 0, sizeof(*modes) * adapter_mode_count);
1460 for (i = 0; i < adapter_mode_count; ++i)
1462 unsigned int j;
1464 memset(&mode2, 0, sizeof(mode));
1465 mode2.Size = sizeof(mode2);
1466 hr = IDirect3D9Ex_EnumAdapterModesEx(d3d9, D3DADAPTER_DEFAULT, &mode_filter, i, &mode2);
1467 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#lx.\n", hr);
1469 for (j = 0; j < mode_count; ++j)
1471 if (modes[j].Width == mode2.Width && modes[j].Height == mode2.Height)
1472 break;
1474 if (j == mode_count)
1476 modes[j] = mode2;
1477 ++mode_count;
1481 if (mode_count < 2)
1483 skip("Less than 2 modes supported.\n");
1484 goto cleanup;
1487 i = 0;
1488 if (modes[i].Width == orig_width && modes[i].Height == orig_height)
1489 ++i;
1491 memset(&d3dpp, 0, sizeof(d3dpp));
1492 d3dpp.Windowed = FALSE;
1493 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1494 d3dpp.BackBufferWidth = modes[i].Width;
1495 d3dpp.BackBufferHeight = modes[i].Height;
1496 d3dpp.BackBufferFormat = modes[i].Format;
1497 d3dpp.EnableAutoDepthStencil = TRUE;
1498 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1499 modes[i].RefreshRate = 0;
1500 modes[i].ScanLineOrdering = 0;
1501 hr = IDirect3DDevice9Ex_ResetEx(device, &d3dpp, NULL);
1502 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
1503 hr = IDirect3DDevice9Ex_ResetEx(device, &d3dpp, &modes[i]);
1504 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
1505 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1506 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
1508 width = GetSystemMetrics(SM_CXSCREEN);
1509 height = GetSystemMetrics(SM_CYSCREEN);
1510 ok(width == modes[i].Width, "Got screen width %u, expected %u.\n", width, modes[i].Width);
1511 ok(height == modes[i].Height, "Got screen height %u, expected %u.\n", height, modes[i].Height);
1513 hr = IDirect3DDevice9Ex_GetScissorRect(device, &rect);
1514 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#lx.\n", hr);
1515 ok(rect.left == 0 && rect.top == 0 && rect.right == modes[i].Width && rect.bottom == modes[i].Height,
1516 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
1518 hr = IDirect3DDevice9Ex_GetViewport(device, &vp);
1519 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#lx.\n", hr);
1520 ok(vp.X == 0, "Got unexpected vp.X %lu.\n", vp.X);
1521 ok(vp.Y == 0, "Got unexpected vp.Y %lu.\n", vp.Y);
1522 ok(vp.Width == modes[i].Width, "Got vp.Width %lu, expected %u.\n", vp.Width, modes[i].Width);
1523 ok(vp.Height == modes[i].Height, "Got vp.Height %lu, expected %u.\n", vp.Height, modes[i].Height);
1524 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
1525 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
1527 i = 1;
1528 vp.X = 10;
1529 vp.Y = 20;
1530 vp.MinZ = 2.0f;
1531 vp.MaxZ = 3.0f;
1532 hr = IDirect3DDevice9Ex_SetViewport(device, &vp);
1533 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
1535 SetRect(&rect, 10, 20, 30, 40);
1536 hr = IDirect3DDevice9Ex_SetScissorRect(device, &rect);
1537 ok(SUCCEEDED(hr), "Failed to set scissor rect, hr %#lx.\n", hr);
1539 hr = IDirect3DDevice9_GetRenderState(device, D3DRS_LIGHTING, &value);
1540 ok(SUCCEEDED(hr), "Failed to get render state, hr %#lx.\n", hr);
1541 ok(!!value, "Got unexpected value %#lx for D3DRS_LIGHTING.\n", value);
1542 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1543 ok(SUCCEEDED(hr), "Failed to set render state, hr %#lx.\n", hr);
1545 memset(&d3dpp, 0, sizeof(d3dpp));
1546 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1547 d3dpp.Windowed = FALSE;
1548 d3dpp.BackBufferWidth = modes[i].Width;
1549 d3dpp.BackBufferHeight = modes[i].Height;
1550 d3dpp.BackBufferFormat = modes[i].Format;
1551 modes[i].RefreshRate = 0;
1552 modes[i].ScanLineOrdering = 0;
1553 hr = IDirect3DDevice9Ex_ResetEx(device, &d3dpp, &modes[i]);
1554 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
1555 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1556 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
1558 /* Render states are preserved in d3d9ex. */
1559 hr = IDirect3DDevice9_GetRenderState(device, D3DRS_LIGHTING, &value);
1560 ok(SUCCEEDED(hr), "Failed to get render state, hr %#lx.\n", hr);
1561 ok(!value, "Got unexpected value %#lx for D3DRS_LIGHTING.\n", value);
1563 hr = IDirect3DDevice9Ex_GetScissorRect(device, &rect);
1564 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#lx.\n", hr);
1565 ok(rect.left == 0 && rect.top == 0 && rect.right == modes[i].Width && rect.bottom == modes[i].Height,
1566 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
1568 hr = IDirect3DDevice9Ex_GetViewport(device, &vp);
1569 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#lx.\n", hr);
1570 ok(vp.X == 0, "Got unexpected vp.X %lu.\n", vp.X);
1571 ok(vp.Y == 0, "Got unexpected vp.Y %lu.\n", vp.Y);
1572 ok(vp.Width == modes[i].Width, "Got vp.Width %lu, expected %u.\n", vp.Width, modes[i].Width);
1573 ok(vp.Height == modes[i].Height, "Got vp.Height %lu, expected %u.\n", vp.Height, modes[i].Height);
1574 ok(vp.MinZ == 2.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
1575 ok(vp.MaxZ == 3.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
1577 width = GetSystemMetrics(SM_CXSCREEN);
1578 height = GetSystemMetrics(SM_CYSCREEN);
1579 ok(width == modes[i].Width, "Got screen width %u, expected %u.\n", width, modes[i].Width);
1580 ok(height == modes[i].Height, "Got screen height %u, expected %u.\n", height, modes[i].Height);
1582 hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain);
1583 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#lx.\n", hr);
1584 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1585 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#lx.\n", hr);
1586 ok(d3dpp.BackBufferWidth == modes[i].Width, "Got backbuffer width %u, expected %u.\n",
1587 d3dpp.BackBufferWidth, modes[i].Width);
1588 ok(d3dpp.BackBufferHeight == modes[i].Height, "Got backbuffer height %u, expected %u.\n",
1589 d3dpp.BackBufferHeight, modes[i].Height);
1590 IDirect3DSwapChain9_Release(swapchain);
1592 /* BackBufferWidth and BackBufferHeight have to match display mode. */
1593 memset(&d3dpp, 0, sizeof(d3dpp));
1594 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1595 d3dpp.Windowed = FALSE;
1596 d3dpp.BackBufferFormat = modes[i].Format;
1597 d3dpp.BackBufferWidth = modes[i].Width - 10;
1598 d3dpp.BackBufferHeight = modes[i].Height - 10;
1599 hr = IDirect3DDevice9Ex_ResetEx(device, &d3dpp, &modes[i]);
1600 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
1601 d3dpp.BackBufferWidth = modes[i].Width - 1;
1602 d3dpp.BackBufferHeight = modes[i].Height;
1603 hr = IDirect3DDevice9Ex_ResetEx(device, &d3dpp, &modes[i]);
1604 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
1605 d3dpp.BackBufferWidth = modes[i].Width;
1606 d3dpp.BackBufferHeight = modes[i].Height - 1;
1607 hr = IDirect3DDevice9Ex_ResetEx(device, &d3dpp, &modes[i]);
1608 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
1609 d3dpp.BackBufferWidth = 0;
1610 d3dpp.BackBufferHeight = 0;
1611 hr = IDirect3DDevice9Ex_ResetEx(device, &d3dpp, &modes[i]);
1612 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
1613 d3dpp.BackBufferWidth = modes[i].Width;
1614 d3dpp.BackBufferHeight = modes[i].Height;
1615 mode2 = modes[i];
1616 mode2.Width = 0;
1617 mode2.Height = 0;
1618 hr = IDirect3DDevice9Ex_ResetEx(device, &d3dpp, &mode2);
1619 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
1620 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1621 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
1623 d3dpp.BackBufferWidth = modes[i].Width;
1624 d3dpp.BackBufferHeight = modes[i].Height;
1625 hr = IDirect3DDevice9Ex_ResetEx(device, &d3dpp, &modes[i]);
1626 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1627 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1628 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
1630 hr = IDirect3DDevice9Ex_GetScissorRect(device, &rect);
1631 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#lx.\n", hr);
1632 ok(rect.left == 0 && rect.top == 0 && rect.right == modes[i].Width && rect.bottom == modes[i].Height,
1633 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
1635 hr = IDirect3DDevice9Ex_GetViewport(device, &vp);
1636 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#lx.\n", hr);
1637 ok(vp.X == 0, "Got unexpected vp.X %lu.\n", vp.X);
1638 ok(vp.Y == 0, "Got unexpected vp.Y %lu.\n", vp.Y);
1639 ok(vp.Width == modes[i].Width, "Got vp.Width %lu, expected %u.\n", vp.Width, modes[i].Width);
1640 ok(vp.Height == modes[i].Height, "Got vp.Height %lu, expected %u.\n", vp.Height, modes[i].Height);
1641 ok(vp.MinZ == 2.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
1642 ok(vp.MaxZ == 3.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
1644 width = GetSystemMetrics(SM_CXSCREEN);
1645 height = GetSystemMetrics(SM_CYSCREEN);
1646 ok(width == modes[i].Width, "Got screen width %u, expected %u.\n", width, modes[i].Width);
1647 ok(height == modes[i].Height, "Got screen height %u, expected %u.\n", height, modes[i].Height);
1649 hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain);
1650 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#lx.\n", hr);
1651 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1652 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#lx.\n", hr);
1653 ok(d3dpp.BackBufferWidth == modes[i].Width, "Got backbuffer width %u, expected %u.\n",
1654 d3dpp.BackBufferWidth, modes[i].Width);
1655 ok(d3dpp.BackBufferHeight == modes[i].Height, "Got backbuffer height %u, expected %u.\n",
1656 d3dpp.BackBufferHeight, modes[i].Height);
1657 IDirect3DSwapChain9_Release(swapchain);
1659 memset(&d3dpp, 0, sizeof(d3dpp));
1660 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1661 d3dpp.Windowed = TRUE;
1662 d3dpp.BackBufferWidth = 400;
1663 d3dpp.BackBufferHeight = 300;
1664 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1665 hr = IDirect3DDevice9Ex_ResetEx(device, &d3dpp, NULL);
1666 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
1667 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1668 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
1670 width = GetSystemMetrics(SM_CXSCREEN);
1671 height = GetSystemMetrics(SM_CYSCREEN);
1672 ok(width == orig_width, "Got screen width %u, expected %u.\n", width, orig_width);
1673 ok(height == orig_height, "Got screen height %u, expected %u.\n", height, orig_height);
1675 hr = IDirect3DDevice9Ex_GetScissorRect(device, &rect);
1676 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#lx.\n", hr);
1677 ok(rect.left == 0 && rect.top == 0 && rect.right == 400 && rect.bottom == 300,
1678 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
1680 hr = IDirect3DDevice9Ex_GetViewport(device, &vp);
1681 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#lx.\n", hr);
1682 ok(vp.X == 0, "Got unexpected vp.X %lu.\n", vp.X);
1683 ok(vp.Y == 0, "Got unexpected vp.Y %lu.\n", vp.Y);
1684 ok(vp.Width == 400, "Got unexpected vp.Width %lu.\n", vp.Width);
1685 ok(vp.Height == 300, "Got unexpected vp.Height %lu.\n", vp.Height);
1686 ok(vp.MinZ == 2.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
1687 ok(vp.MaxZ == 3.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
1689 hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain);
1690 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#lx.\n", hr);
1691 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1692 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#lx.\n", hr);
1693 ok(d3dpp.BackBufferWidth == 400, "Got unexpected backbuffer width %u.\n", d3dpp.BackBufferWidth);
1694 ok(d3dpp.BackBufferHeight == 300, "Got unexpected backbuffer height %u.\n", d3dpp.BackBufferHeight);
1695 IDirect3DSwapChain9_Release(swapchain);
1697 memset(&devmode, 0, sizeof(devmode));
1698 devmode.dmSize = sizeof(devmode);
1699 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
1700 devmode.dmPelsWidth = modes[1].Width;
1701 devmode.dmPelsHeight = modes[1].Height;
1702 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
1703 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", ret);
1704 width = GetSystemMetrics(SM_CXSCREEN);
1705 height = GetSystemMetrics(SM_CYSCREEN);
1706 ok(width == modes[1].Width, "Screen width is %u, expected %u.\n", width, modes[1].Width);
1707 ok(height == modes[1].Height, "Screen height is %u, expected %u.\n", height, modes[1].Height);
1709 d3dpp.BackBufferWidth = 500;
1710 d3dpp.BackBufferHeight = 400;
1711 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1712 hr = IDirect3DDevice9Ex_ResetEx(device, &d3dpp, &mode);
1713 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
1714 hr = IDirect3DDevice9Ex_ResetEx(device, &d3dpp, NULL);
1715 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
1716 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1717 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
1719 width = GetSystemMetrics(SM_CXSCREEN);
1720 height = GetSystemMetrics(SM_CYSCREEN);
1721 ok(width == modes[1].Width, "Screen width is %u, expected %u.\n", width, modes[1].Width);
1722 ok(height == modes[1].Height, "Screen height is %u, expected %u.\n", height, modes[1].Height);
1724 hr = IDirect3DDevice9Ex_GetScissorRect(device, &rect);
1725 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#lx.\n", hr);
1726 ok(rect.left == 0 && rect.top == 0 && rect.right == 500 && rect.bottom == 400,
1727 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
1729 hr = IDirect3DDevice9Ex_GetViewport(device, &vp);
1730 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#lx.\n", hr);
1731 ok(vp.X == 0, "Got unexpected vp.X %lu.\n", vp.X);
1732 ok(vp.Y == 0, "Got unexpected vp.Y %lu.\n", vp.Y);
1733 ok(vp.Width == 500, "Got unexpected vp.Width %lu.\n", vp.Width);
1734 ok(vp.Height == 400, "Got unexpected vp.Height %lu.\n", vp.Height);
1735 ok(vp.MinZ == 2.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
1736 ok(vp.MaxZ == 3.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
1738 hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain);
1739 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#lx.\n", hr);
1740 memset(&d3dpp, 0, sizeof(d3dpp));
1741 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1742 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#lx.\n", hr);
1743 ok(d3dpp.BackBufferWidth == 500, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
1744 ok(d3dpp.BackBufferHeight == 400, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
1745 IDirect3DSwapChain9_Release(swapchain);
1747 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
1748 devmode.dmPelsWidth = orig_width;
1749 devmode.dmPelsHeight = orig_height;
1750 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
1751 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", ret);
1752 width = GetSystemMetrics(SM_CXSCREEN);
1753 height = GetSystemMetrics(SM_CYSCREEN);
1754 ok(width == orig_width, "Got screen width %u, expected %u.\n", width, orig_width);
1755 ok(height == orig_height, "Got screen height %u, expected %u.\n", height, orig_height);
1757 SetRect(&rect, 0, 0, 200, 150);
1758 ok(AdjustWindowRect(&rect, GetWindowLongW(window, GWL_STYLE), FALSE), "Failed to adjust window rect.\n");
1759 ok(SetWindowPos(window, NULL, 0, 0, rect.right - rect.left, rect.bottom - rect.top,
1760 SWP_NOMOVE | SWP_NOZORDER), "Failed to set window position.\n");
1762 /* Windows 10 gives us a different size than we requested with some DPI scaling settings (e.g. 172%). */
1763 ok(GetClientRect(window, &client_rect), "Failed to get client rect.\n");
1765 memset(&d3dpp, 0, sizeof(d3dpp));
1766 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1767 d3dpp.Windowed = TRUE;
1768 d3dpp.BackBufferWidth = 0;
1769 d3dpp.BackBufferHeight = 0;
1770 d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
1771 hr = IDirect3DDevice9Ex_ResetEx(device, &d3dpp, NULL);
1772 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
1773 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1774 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
1776 ok(d3dpp.BackBufferWidth == client_rect.right,
1777 "Got unexpected BackBufferWidth %u, expected %ld.\n", d3dpp.BackBufferWidth, client_rect.right);
1778 ok(d3dpp.BackBufferHeight == client_rect.bottom,
1779 "Got unexpected BackBufferHeight %u, expected %ld.\n", d3dpp.BackBufferHeight, client_rect.bottom);
1780 ok(d3dpp.BackBufferFormat == mode.Format, "Got unexpected BackBufferFormat %#x, expected %#x.\n",
1781 d3dpp.BackBufferFormat, mode.Format);
1782 ok(d3dpp.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", d3dpp.BackBufferCount);
1783 ok(!d3dpp.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
1784 ok(!d3dpp.MultiSampleQuality, "Got unexpected MultiSampleQuality %lu.\n", d3dpp.MultiSampleQuality);
1785 ok(d3dpp.SwapEffect == D3DSWAPEFFECT_DISCARD, "Got unexpected SwapEffect %#x.\n", d3dpp.SwapEffect);
1786 ok(!d3dpp.hDeviceWindow, "Got unexpected hDeviceWindow %p.\n", d3dpp.hDeviceWindow);
1787 ok(d3dpp.Windowed, "Got unexpected Windowed %#x.\n", d3dpp.Windowed);
1788 ok(!d3dpp.EnableAutoDepthStencil, "Got unexpected EnableAutoDepthStencil %#x.\n", d3dpp.EnableAutoDepthStencil);
1789 ok(!d3dpp.AutoDepthStencilFormat, "Got unexpected AutoDepthStencilFormat %#x.\n", d3dpp.AutoDepthStencilFormat);
1790 ok(!d3dpp.Flags, "Got unexpected Flags %#lx.\n", d3dpp.Flags);
1791 ok(!d3dpp.FullScreen_RefreshRateInHz, "Got unexpected FullScreen_RefreshRateInHz %u.\n",
1792 d3dpp.FullScreen_RefreshRateInHz);
1793 ok(!d3dpp.PresentationInterval, "Got unexpected PresentationInterval %#x.\n", d3dpp.PresentationInterval);
1795 hr = IDirect3DDevice9Ex_GetScissorRect(device, &rect);
1796 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#lx.\n", hr);
1797 ok(EqualRect(&rect, &client_rect), "Got unexpected scissor rect %s, expected %s.\n",
1798 wine_dbgstr_rect(&rect), wine_dbgstr_rect(&client_rect));
1800 hr = IDirect3DDevice9Ex_GetViewport(device, &vp);
1801 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#lx.\n", hr);
1802 ok(vp.X == 0, "Got unexpected vp.X %lu.\n", vp.X);
1803 ok(vp.Y == 0, "Got unexpected vp.Y %lu.\n", vp.Y);
1804 ok(vp.Width == client_rect.right, "Got unexpected vp.Width %lu, expected %ld.\n",
1805 vp.Width, client_rect.right);
1806 ok(vp.Height == client_rect.bottom, "Got unexpected vp.Height %lu, expected %ld.\n",
1807 vp.Height, client_rect.bottom);
1808 ok(vp.MinZ == 2.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
1809 ok(vp.MaxZ == 3.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
1811 hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain);
1812 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#lx.\n", hr);
1813 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1814 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#lx.\n", hr);
1815 ok(d3dpp.BackBufferWidth == client_rect.right,
1816 "Got unexpected backbuffer width %u, expected %ld.\n", d3dpp.BackBufferWidth, client_rect.right);
1817 ok(d3dpp.BackBufferHeight == client_rect.bottom,
1818 "Got unexpected backbuffer height %u, expected %ld.\n", d3dpp.BackBufferHeight, client_rect.bottom);
1819 ok(d3dpp.BackBufferFormat == mode.Format, "Got unexpected BackBufferFormat %#x, expected %#x.\n",
1820 d3dpp.BackBufferFormat, mode.Format);
1821 ok(d3dpp.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", d3dpp.BackBufferCount);
1822 ok(!d3dpp.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
1823 ok(!d3dpp.MultiSampleQuality, "Got unexpected MultiSampleQuality %lu.\n", d3dpp.MultiSampleQuality);
1824 ok(d3dpp.SwapEffect == D3DSWAPEFFECT_DISCARD, "Got unexpected SwapEffect %#x.\n", d3dpp.SwapEffect);
1825 ok(d3dpp.hDeviceWindow == window, "Got unexpected hDeviceWindow %p, expected %p.\n", d3dpp.hDeviceWindow, window);
1826 ok(d3dpp.Windowed, "Got unexpected Windowed %#x.\n", d3dpp.Windowed);
1827 ok(!d3dpp.EnableAutoDepthStencil, "Got unexpected EnableAutoDepthStencil %#x.\n", d3dpp.EnableAutoDepthStencil);
1828 ok(!d3dpp.AutoDepthStencilFormat, "Got unexpected AutoDepthStencilFormat %#x.\n", d3dpp.AutoDepthStencilFormat);
1829 ok(!d3dpp.Flags, "Got unexpected Flags %#lx.\n", d3dpp.Flags);
1830 ok(!d3dpp.FullScreen_RefreshRateInHz, "Got unexpected FullScreen_RefreshRateInHz %u.\n",
1831 d3dpp.FullScreen_RefreshRateInHz);
1832 ok(!d3dpp.PresentationInterval, "Got unexpected PresentationInterval %#x.\n", d3dpp.PresentationInterval);
1833 IDirect3DSwapChain9_Release(swapchain);
1835 cleanup:
1836 HeapFree(GetProcessHeap(), 0, modes);
1837 IDirect3D9Ex_Release(d3d9);
1838 refcount = IDirect3DDevice9Ex_Release(device);
1839 ok(!refcount, "Device has %lu references left.\n", refcount);
1840 DestroyWindow(window);
1843 static void test_reset_resources(void)
1845 IDirect3DSurface9 *surface, *rt;
1846 IDirect3DTexture9 *texture;
1847 IDirect3DDevice9Ex *device;
1848 unsigned int i;
1849 D3DCAPS9 caps;
1850 HWND window;
1851 HRESULT hr;
1852 ULONG ref;
1854 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
1855 0, 0, 640, 480, 0, 0, 0, 0);
1856 if (!(device = create_device(window, NULL)))
1858 skip("Failed to create a D3D device, skipping tests.\n");
1859 goto done;
1862 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
1863 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#lx.\n", hr);
1865 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24S8,
1866 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
1867 ok(SUCCEEDED(hr), "Failed to create depth/stencil surface, hr %#lx.\n", hr);
1868 hr = IDirect3DDevice9_SetDepthStencilSurface(device, surface);
1869 ok(SUCCEEDED(hr), "Failed to set depth/stencil surface, hr %#lx.\n", hr);
1870 IDirect3DSurface9_Release(surface);
1872 for (i = 0; i < caps.NumSimultaneousRTs; ++i)
1874 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET,
1875 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
1876 ok(SUCCEEDED(hr), "Failed to create render target texture %u, hr %#lx.\n", i, hr);
1877 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
1878 ok(SUCCEEDED(hr), "Failed to get surface %u, hr %#lx.\n", i, hr);
1879 IDirect3DTexture9_Release(texture);
1880 hr = IDirect3DDevice9_SetRenderTarget(device, i, surface);
1881 ok(SUCCEEDED(hr), "Failed to set render target surface %u, hr %#lx.\n", i, hr);
1882 IDirect3DSurface9_Release(surface);
1885 hr = reset_device(device, NULL);
1886 ok(SUCCEEDED(hr), "Failed to reset device.\n");
1888 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &rt);
1889 ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#lx.\n", hr);
1890 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
1891 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#lx.\n", hr);
1892 ok(surface == rt, "Got unexpected surface %p for render target.\n", surface);
1893 IDirect3DSurface9_Release(surface);
1894 IDirect3DSurface9_Release(rt);
1896 for (i = 1; i < caps.NumSimultaneousRTs; ++i)
1898 hr = IDirect3DDevice9_GetRenderTarget(device, i, &surface);
1899 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
1902 ref = IDirect3DDevice9_Release(device);
1903 ok(!ref, "Unexpected refcount %lu.\n", ref);
1905 done:
1906 DestroyWindow(window);
1909 static void test_vidmem_accounting(void)
1911 IDirect3DDevice9Ex *device;
1912 unsigned int i;
1913 HWND window;
1914 HRESULT hr = D3D_OK;
1915 ULONG ref;
1916 UINT vidmem_start, vidmem_end;
1917 INT diff;
1918 IDirect3DTexture9 *textures[20];
1920 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
1921 0, 0, 640, 480, 0, 0, 0, 0);
1922 if (!(device = create_device(window, NULL)))
1924 skip("Failed to create a D3D device, skipping tests.\n");
1925 goto done;
1928 vidmem_start = IDirect3DDevice9_GetAvailableTextureMem(device);
1929 memset(textures, 0, sizeof(textures));
1930 for (i = 0; i < 20 && SUCCEEDED(hr); i++)
1932 hr = IDirect3DDevice9_CreateTexture(device, 1024, 1024, 1, D3DUSAGE_RENDERTARGET,
1933 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &textures[i], NULL);
1934 /* No D3DERR_OUTOFVIDEOMEMORY in d3d9ex */
1935 ok(SUCCEEDED(hr) || hr == E_OUTOFMEMORY, "Failed to create texture, hr %#lx.\n", hr);
1937 vidmem_end = IDirect3DDevice9_GetAvailableTextureMem(device);
1939 diff = vidmem_start - vidmem_end;
1940 diff = abs(diff);
1941 ok(diff < 1024 * 1024, "Expected a video memory difference of less than 1 MB, got %u MB.\n",
1942 diff / 1024 / 1024);
1944 for (i = 0; i < 20; i++)
1946 if (textures[i])
1947 IDirect3DTexture9_Release(textures[i]);
1950 ref = IDirect3DDevice9_Release(device);
1951 ok(!ref, "Unexpected refcount %lu.\n", ref);
1953 done:
1954 DestroyWindow(window);
1957 static void test_user_memory_getdc(void)
1959 IDirect3DDevice9Ex *device;
1960 unsigned int *data;
1961 HBITMAP bitmap;
1962 DIBSECTION dib;
1963 HWND window;
1964 HRESULT hr;
1965 ULONG ref;
1966 int size;
1967 IDirect3DSurface9 *surface;
1968 HDC dc;
1970 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
1971 0, 0, 640, 480, 0, 0, 0, 0);
1972 if (!(device = create_device(window, NULL)))
1974 skip("Failed to create a D3D device, skipping tests.\n");
1975 goto done;
1978 data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data) * 16 * 16);
1979 memset(data, 0xaa, sizeof(*data) * 16 * 16);
1980 hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurface(device, 16, 16,
1981 D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, (HANDLE *)&data);
1982 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
1984 hr = IDirect3DSurface9_GetDC(surface, &dc);
1985 ok(SUCCEEDED(hr), "Failed to get dc, hr %#lx.\n", hr);
1986 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
1987 ok(!!bitmap, "Failed to get bitmap.\n");
1988 size = GetObjectA(bitmap, sizeof(dib), &dib);
1989 ok(size == sizeof(dib), "Got unexpected size %d.\n", size);
1990 ok(dib.dsBm.bmBits == data, "Got unexpected bits %p, expected %p.\n", dib.dsBm.bmBits, data);
1991 BitBlt(dc, 0, 0, 16, 8, NULL, 0, 0, WHITENESS);
1992 BitBlt(dc, 0, 8, 16, 8, NULL, 0, 0, BLACKNESS);
1993 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
1994 ok(SUCCEEDED(hr), "Failed to release dc, hr %#lx.\n", hr);
1996 ok(data[0] == 0xffffffff, "Expected color 0xffffffff, got %#x.\n", data[0]);
1997 ok(data[8 * 16] == 0x00000000, "Expected color 0x00000000, got %#x.\n", data[8 * 16]);
1999 IDirect3DSurface9_Release(surface);
2000 HeapFree(GetProcessHeap(), 0, data);
2002 ref = IDirect3DDevice9_Release(device);
2003 ok(!ref, "Unexpected refcount %lu.\n", ref);
2005 done:
2006 DestroyWindow(window);
2009 static void test_lost_device(void)
2011 IDirect3DDevice9Ex *device;
2012 ULONG refcount;
2013 HWND window;
2014 HRESULT hr;
2015 BOOL ret;
2016 struct device_desc desc;
2018 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
2019 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2020 desc.device_window = window;
2021 desc.width = 640;
2022 desc.height = 480;
2023 desc.flags = CREATE_DEVICE_FULLSCREEN;
2024 if (!(device = create_device(window, &desc)))
2026 skip("Failed to create a D3D device, skipping tests.\n");
2027 goto done;
2030 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
2031 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2032 hr = IDirect3DDevice9Ex_Present(device, NULL, NULL, NULL, NULL);
2033 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2034 hr = IDirect3DDevice9Ex_PresentEx(device, NULL, NULL, NULL, NULL, 0);
2035 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2036 hr = IDirect3DDevice9Ex_CheckDeviceState(device, window);
2037 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2038 hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL);
2039 ok(hr == S_PRESENT_OCCLUDED || broken(hr == D3D_OK), "Got unexpected hr %#lx.\n", hr);
2041 ret = SetForegroundWindow(GetDesktopWindow());
2042 ok(ret, "Failed to set foreground window.\n");
2043 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
2044 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2045 hr = IDirect3DDevice9Ex_Present(device, NULL, NULL, NULL, NULL);
2046 ok(hr == S_PRESENT_OCCLUDED || hr == S_PRESENT_MODE_CHANGED || broken(hr == D3D_OK),
2047 "Got unexpected hr %#lx.\n", hr);
2048 hr = IDirect3DDevice9Ex_PresentEx(device, NULL, NULL, NULL, NULL, 0);
2049 ok(hr == S_PRESENT_OCCLUDED || hr == S_PRESENT_MODE_CHANGED, "Got unexpected hr %#lx.\n", hr);
2050 hr = IDirect3DDevice9Ex_CheckDeviceState(device, window);
2051 ok(hr == S_PRESENT_OCCLUDED, "Got unexpected hr %#lx.\n", hr);
2052 hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL);
2053 ok(hr == D3D_OK || hr == S_PRESENT_MODE_CHANGED, "Got unexpected hr %#lx.\n", hr);
2055 ret = SetForegroundWindow(window);
2056 ok(ret, "Failed to set foreground window.\n");
2057 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
2058 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2059 hr = IDirect3DDevice9Ex_Present(device, NULL, NULL, NULL, NULL);
2060 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2061 hr = IDirect3DDevice9Ex_PresentEx(device, NULL, NULL, NULL, NULL, 0);
2062 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2063 hr = IDirect3DDevice9Ex_CheckDeviceState(device, window);
2064 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2065 hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL);
2066 ok(hr == S_PRESENT_OCCLUDED || hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2068 desc.width = 1024;
2069 desc.height = 768;
2070 hr = reset_device(device, &desc);
2071 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2072 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
2073 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2074 hr = IDirect3DDevice9Ex_Present(device, NULL, NULL, NULL, NULL);
2075 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2076 hr = IDirect3DDevice9Ex_PresentEx(device, NULL, NULL, NULL, NULL, 0);
2077 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2078 hr = IDirect3DDevice9Ex_CheckDeviceState(device, window);
2079 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2080 hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL);
2081 ok(hr == S_PRESENT_OCCLUDED || hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2083 desc.flags = 0;
2084 hr = reset_device(device, &desc);
2085 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2086 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
2087 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2088 hr = IDirect3DDevice9Ex_Present(device, NULL, NULL, NULL, NULL);
2089 ok(hr == S_PRESENT_MODE_CHANGED || hr == D3D_OK /* Win10 */, "Got unexpected hr %#lx.\n", hr);
2090 hr = IDirect3DDevice9Ex_PresentEx(device, NULL, NULL, NULL, NULL, 0);
2091 ok(hr == S_PRESENT_MODE_CHANGED || hr == D3D_OK /* Win10 */, "Got unexpected hr %#lx.\n", hr);
2092 hr = IDirect3DDevice9Ex_CheckDeviceState(device, window);
2093 ok(hr == S_PRESENT_MODE_CHANGED || hr == D3D_OK /* Win10 */, "Got unexpected hr %#lx.\n", hr);
2094 hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL);
2095 ok(hr == S_PRESENT_MODE_CHANGED || hr == D3D_OK /* Win10 */, "Got unexpected hr %#lx.\n", hr);
2097 hr = reset_device(device, &desc);
2098 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2099 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
2100 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2101 hr = IDirect3DDevice9Ex_Present(device, NULL, NULL, NULL, NULL);
2102 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2103 hr = IDirect3DDevice9Ex_PresentEx(device, NULL, NULL, NULL, NULL, 0);
2104 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2105 hr = IDirect3DDevice9Ex_CheckDeviceState(device, window);
2106 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2107 hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL);
2108 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2110 ret = SetForegroundWindow(GetDesktopWindow());
2111 ok(ret, "Failed to set foreground window.\n");
2112 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
2113 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2114 hr = IDirect3DDevice9Ex_Present(device, NULL, NULL, NULL, NULL);
2115 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2116 hr = IDirect3DDevice9Ex_PresentEx(device, NULL, NULL, NULL, NULL, 0);
2117 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2118 hr = IDirect3DDevice9Ex_CheckDeviceState(device, window);
2119 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2120 hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL);
2121 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2123 ret = SetForegroundWindow(window);
2124 ok(ret, "Failed to set foreground window.\n");
2125 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
2126 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2127 hr = IDirect3DDevice9Ex_Present(device, NULL, NULL, NULL, NULL);
2128 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2129 hr = IDirect3DDevice9Ex_PresentEx(device, NULL, NULL, NULL, NULL, 0);
2130 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2131 hr = IDirect3DDevice9Ex_CheckDeviceState(device, window);
2132 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2133 hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL);
2134 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2136 desc.flags = CREATE_DEVICE_FULLSCREEN;
2137 hr = reset_device(device, &desc);
2138 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2139 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
2140 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2141 hr = IDirect3DDevice9Ex_Present(device, NULL, NULL, NULL, NULL);
2142 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2143 hr = IDirect3DDevice9Ex_PresentEx(device, NULL, NULL, NULL, NULL, 0);
2144 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2145 hr = IDirect3DDevice9Ex_CheckDeviceState(device, window);
2146 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2147 hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL);
2148 ok(hr == S_PRESENT_OCCLUDED || hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2150 ret = SetForegroundWindow(GetDesktopWindow());
2151 ok(ret, "Failed to set foreground window.\n");
2152 hr = IDirect3DDevice9Ex_Present(device, NULL, NULL, NULL, NULL);
2153 ok(hr == S_PRESENT_OCCLUDED || broken(hr == D3D_OK), "Got unexpected hr %#lx.\n", hr);
2154 hr = reset_device(device, &desc);
2155 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2156 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
2157 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2158 hr = IDirect3DDevice9Ex_Present(device, NULL, NULL, NULL, NULL);
2159 ok(hr == D3D_OK || broken(hr == S_FALSE), "Got unexpected hr %#lx.\n", hr);
2160 hr = IDirect3DDevice9Ex_PresentEx(device, NULL, NULL, NULL, NULL, 0);
2161 ok(hr == D3D_OK || broken(hr == S_FALSE), "Got unexpected hr %#lx.\n", hr);
2162 hr = IDirect3DDevice9Ex_CheckDeviceState(device, window);
2163 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2164 hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL);
2165 ok(hr == S_PRESENT_OCCLUDED || hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2167 refcount = IDirect3DDevice9Ex_Release(device);
2168 ok(!refcount, "Device has %lu references left.\n", refcount);
2169 done:
2170 DestroyWindow(window);
2173 static void test_unsupported_shaders(void)
2175 static const DWORD simple_vs[] =
2177 0xfffe0101, /* vs_1_1 */
2178 0x0000001f, 0x80000000, 0x900f0000, /* dcl_position0 v0 */
2179 0x00000001, 0xc00f0000, 0x90e40000, /* mov oPos, v0 */
2180 0x0000ffff, /* end */
2182 static const DWORD simple_ps[] =
2184 0xffff0101, /* ps_1_1 */
2185 0x00000001, 0x800f0000, 0x90e40000, /* mul r0, t0, r0 */
2186 0x0000ffff, /* end */
2188 static const DWORD vs_3_0[] =
2190 0xfffe0300, /* vs_3_0 */
2191 0x0200001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
2192 0x0200001f, 0x80000000, 0xe00f0000, /* dcl_position o0 */
2193 0x02000001, 0xe00f0000, 0x90e40000, /* mov o0, v0 */
2194 0x0000ffff, /* end */
2197 #if 0
2198 float4 main(const float4 color : COLOR) : SV_TARGET
2200 float4 o;
2202 o = color;
2204 return o;
2206 #endif
2207 static const DWORD ps_4_0[] =
2209 0x43425844, 0x4da9446f, 0xfbe1f259, 0x3fdb3009, 0x517521fa, 0x00000001, 0x000001ac, 0x00000005,
2210 0x00000034, 0x0000008c, 0x000000bc, 0x000000f0, 0x00000130, 0x46454452, 0x00000050, 0x00000000,
2211 0x00000000, 0x00000000, 0x0000001c, 0xffff0400, 0x00000100, 0x0000001c, 0x7263694d, 0x666f736f,
2212 0x52282074, 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, 0x39207265, 0x2e39322e,
2213 0x2e323539, 0x31313133, 0xababab00, 0x4e475349, 0x00000028, 0x00000001, 0x00000008, 0x00000020,
2214 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x4f4c4f43, 0xabab0052, 0x4e47534f,
2215 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000,
2216 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000038, 0x00000040, 0x0000000e,
2217 0x03001062, 0x001010f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2,
2218 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, 0x54415453, 0x00000074, 0x00000002, 0x00000000,
2219 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
2220 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2221 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2222 0x00000000, 0x00000000, 0x00000000,
2224 #if 0
2225 vs_1_1
2226 dcl_position v0
2227 def c255, 1.0, 1.0, 1.0, 1.0
2228 add r0, v0, c255
2229 mov oPos, r0
2230 #endif
2231 static const DWORD vs_1_255[] =
2233 0xfffe0101,
2234 0x0000001f, 0x80000000, 0x900f0000,
2235 0x00000051, 0xa00f00ff, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
2236 0x00000002, 0x800f0000, 0x90e40000, 0xa0e400ff,
2237 0x00000001, 0xc00f0000, 0x80e40000,
2238 0x0000ffff
2240 #if 0
2241 vs_1_1
2242 dcl_position v0
2243 def c256, 1.0, 1.0, 1.0, 1.0
2244 add r0, v0, c256
2245 mov oPos, r0
2246 #endif
2247 static const DWORD vs_1_256[] =
2249 0xfffe0101,
2250 0x0000001f, 0x80000000, 0x900f0000,
2251 0x00000051, 0xa00f0100, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
2252 0x00000002, 0x800f0000, 0x90e40000, 0xa0e40100,
2253 0x00000001, 0xc00f0000, 0x80e40000,
2254 0x0000ffff
2256 #if 0
2257 vs_3_0
2258 dcl_position v0
2259 dcl_position o0
2260 def c256, 1.0, 1.0, 1.0, 1.0
2261 add r0, v0, c256
2262 mov o0, r0
2263 #endif
2264 static const DWORD vs_3_256[] =
2266 0xfffe0300,
2267 0x0200001f, 0x80000000, 0x900f0000,
2268 0x0200001f, 0x80000000, 0xe00f0000,
2269 0x05000051, 0xa00f0100, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
2270 0x03000002, 0x800f0000, 0x90e40000, 0xa0e40100,
2271 0x02000001, 0xe00f0000, 0x80e40000,
2272 0x0000ffff
2274 #if 0
2275 /* This shader source generates syntax errors with the native shader assembler
2276 * due to the constant register index values.
2277 * The bytecode was modified by hand to use the intended values. */
2278 vs_3_0
2279 dcl_position v0
2280 dcl_position o0
2281 defi i16, 1, 1, 1, 1
2282 rep i16
2283 add r0, r0, v0
2284 endrep
2285 mov o0, r0
2286 #endif
2287 static const DWORD vs_3_i16[] =
2289 0xfffe0300,
2290 0x0200001f, 0x80000000, 0x900f0000,
2291 0x0200001f, 0x80000000, 0xe00f0000,
2292 0x05000030, 0xf00f0010, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
2293 0x01000026, 0xf0e40010,
2294 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
2295 0x00000027,
2296 0x02000001, 0xe00f0000, 0x80e40000,
2297 0x0000ffff
2299 #if 0
2300 /* This shader source generates syntax errors with the native shader assembler
2301 * due to the constant register index values.
2302 * The bytecode was modified by hand to use the intended values. */
2303 vs_3_0
2304 dcl_position v0
2305 dcl_position o0
2306 defb b16, true
2307 mov r0, v0
2308 if b16
2309 add r0, r0, v0
2310 endif
2311 mov o0, r0
2312 #endif
2313 static const DWORD vs_3_b16[] =
2315 0xfffe0300,
2316 0x0200001f, 0x80000000, 0x900f0000,
2317 0x0200001f, 0x80000000, 0xe00f0000,
2318 0x0200002f, 0xe00f0810, 0x00000001,
2319 0x02000001, 0x800f0000, 0x90e40000,
2320 0x01000028, 0xe0e40810,
2321 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
2322 0x0000002b,
2323 0x02000001, 0xe00f0000, 0x80e40000,
2324 0x0000ffff
2326 #if 0
2327 /* This shader source generates syntax errors with the native shader assembler
2328 * due to the constant register index values.
2329 * The bytecode was modified by hand to use the intended values. */
2330 ps_1_1
2331 def c8, 1.0, 1.0, 1.0, 1.0
2332 add r0, v0, c8
2333 #endif
2334 static const DWORD ps_1_8[] =
2336 0xffff0101,
2337 0x00000051, 0xa00f0008, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
2338 0x00000002, 0x800f0000, 0x90e40000, 0xa0e40008,
2339 0x0000ffff
2341 #if 0
2342 /* This shader source generates syntax errors with the native shader assembler
2343 * due to the constant register index values.
2344 * The bytecode was modified by hand to use the intended values. */
2345 ps_2_0
2346 def c32, 1.0, 1.0, 1.0, 1.0
2347 add oC0, v0, c32
2348 #endif
2349 static const DWORD ps_2_32[] =
2351 0xffff0200,
2352 0x05000051, 0xa00f0020, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
2353 0x03000002, 0x800f0000, 0x90e40000, 0xa0e40020,
2354 0x0000ffff
2356 #if 0
2357 /* This shader source generates syntax errors with the native shader assembler
2358 * due to the constant register index values.
2359 * The bytecode was modified by hand to use the intended values. */
2360 ps_3_0
2361 dcl_color0 v0
2362 def c224, 1.0, 1.0, 1.0, 1.0
2363 add oC0, v0, c224
2364 #endif
2365 static const DWORD ps_3_224[] =
2367 0xffff0300,
2368 0x0200001f, 0x8000000a, 0x900f0000,
2369 0x05000051, 0xa00f00e0, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
2370 0x03000002, 0x800f0800, 0x90e40000, 0xa0e400e0,
2371 0x0000ffff
2373 #if 0
2374 /* This shader source generates syntax errors with the native shader assembler
2375 * due to the constant register index values.
2376 * The bytecode was modified by hand to use the intended values. */
2377 ps_2_0
2378 defb b0, true
2379 defi i0, 1, 1, 1, 1
2380 rep i0
2381 if b0
2382 add r0, r0, v0
2383 endif
2384 endrep
2385 mov oC0, r0
2386 #endif
2387 static const DWORD ps_2_0_boolint[] =
2389 0xffff0200,
2390 0x0200002f, 0xe00f0800, 0x00000001,
2391 0x05000030, 0xf00f0000, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
2392 0x01000026, 0xf0e40000,
2393 0x01000028, 0xe0e40800,
2394 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
2395 0x0000002b,
2396 0x00000027,
2397 0x02000001, 0x800f0800, 0x80e40000,
2398 0x0000ffff
2401 IDirect3DVertexShader9 *vs = NULL;
2402 IDirect3DPixelShader9 *ps = NULL;
2403 IDirect3DDevice9Ex *device;
2404 ULONG refcount;
2405 D3DCAPS9 caps;
2406 HWND window;
2407 HRESULT hr;
2409 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2410 0, 0, 640, 480, 0, 0, 0, 0);
2411 if (!(device = create_device(window, NULL)))
2413 skip("Failed to create a D3D device, skipping tests.\n");
2414 DestroyWindow(window);
2415 return;
2418 hr = IDirect3DDevice9Ex_CreateVertexShader(device, simple_ps, &vs);
2419 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
2420 hr = IDirect3DDevice9Ex_CreatePixelShader(device, simple_vs, &ps);
2421 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
2422 hr = IDirect3DDevice9Ex_CreatePixelShader(device, ps_4_0, &ps);
2423 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
2425 hr = IDirect3DDevice9Ex_GetDeviceCaps(device, &caps);
2426 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#lx.\n", hr);
2428 if (caps.VertexShaderVersion < D3DVS_VERSION(3, 0))
2430 hr = IDirect3DDevice9Ex_CreateVertexShader(device, vs_3_0, &vs);
2431 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
2432 if (caps.VertexShaderVersion <= D3DVS_VERSION(1, 1) && caps.MaxVertexShaderConst < 256)
2434 hr = IDirect3DDevice9Ex_CreateVertexShader(device, vs_1_255, &vs);
2435 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
2437 else
2439 skip("GPU supports SM2+, skipping SM1 test.\n");
2442 skip("This GPU doesn't support SM3, skipping test with shader using unsupported constants.\n");
2444 else
2446 skip("This GPU supports SM3, skipping unsupported shader test.\n");
2448 hr = IDirect3DDevice9Ex_CreateVertexShader(device, vs_1_255, &vs);
2449 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2450 IDirect3DVertexShader9_Release(vs);
2451 hr = IDirect3DDevice9Ex_CreateVertexShader(device, vs_1_256, &vs);
2452 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
2453 hr = IDirect3DDevice9Ex_CreateVertexShader(device, vs_3_256, &vs);
2454 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
2455 hr = IDirect3DDevice9Ex_CreateVertexShader(device, vs_3_i16, &vs);
2456 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
2457 hr = IDirect3DDevice9Ex_CreateVertexShader(device, vs_3_b16, &vs);
2458 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
2461 if (caps.PixelShaderVersion < D3DPS_VERSION(3, 0))
2463 skip("This GPU doesn't support SM3, skipping test with shader using unsupported constants.\n");
2464 goto cleanup;
2466 hr = IDirect3DDevice9Ex_CreatePixelShader(device, ps_1_8, &ps);
2467 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
2468 hr = IDirect3DDevice9Ex_CreatePixelShader(device, ps_2_32, &ps);
2469 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
2470 hr = IDirect3DDevice9Ex_CreatePixelShader(device, ps_3_224, &ps);
2471 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
2472 hr = IDirect3DDevice9Ex_CreatePixelShader(device, ps_2_0_boolint, &ps);
2473 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
2474 if (ps)
2475 IDirect3DPixelShader9_Release(ps);
2477 cleanup:
2478 refcount = IDirect3DDevice9Ex_Release(device);
2479 ok(!refcount, "Device has %lu references left.\n", refcount);
2480 DestroyWindow(window);
2483 static HWND filter_messages;
2485 enum message_window
2487 DEVICE_WINDOW,
2488 FOCUS_WINDOW,
2491 struct message
2493 UINT message;
2494 enum message_window window;
2495 BOOL check_wparam;
2496 WPARAM expect_wparam;
2497 HRESULT device_state;
2498 WINDOWPOS *store_wp;
2501 static const struct message *expect_messages;
2502 static HWND device_window, focus_window;
2503 static LONG windowposchanged_received, syscommand_received;
2504 static IDirect3DDevice9Ex *focus_test_device;
2506 struct wndproc_thread_param
2508 HWND dummy_window;
2509 HANDLE window_created;
2510 HANDLE test_finished;
2511 BOOL running_in_foreground;
2514 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2516 HRESULT hr;
2518 if (filter_messages && filter_messages == hwnd)
2520 if (message != WM_DISPLAYCHANGE && message != WM_IME_NOTIFY)
2521 todo_wine ok(0, "Received unexpected message %#x for window %p.\n", message, hwnd);
2524 if (expect_messages)
2526 HWND w;
2528 switch (expect_messages->window)
2530 case DEVICE_WINDOW:
2531 w = device_window;
2532 break;
2534 case FOCUS_WINDOW:
2535 w = focus_window;
2536 break;
2538 default:
2539 w = NULL;
2540 break;
2543 if (hwnd == w && expect_messages->message == message)
2545 if (expect_messages->check_wparam)
2546 ok(wparam == expect_messages->expect_wparam,
2547 "Got unexpected wparam %#Ix for message %#x, expected %#Ix.\n",
2548 wparam, message, expect_messages->expect_wparam);
2550 if (expect_messages->store_wp)
2551 *expect_messages->store_wp = *(WINDOWPOS *)lparam;
2553 if (focus_test_device)
2555 hr = IDirect3DDevice9Ex_CheckDeviceState(focus_test_device, device_window);
2556 todo_wine_if(message != WM_ACTIVATEAPP && message != WM_DISPLAYCHANGE)
2557 ok(hr == expect_messages->device_state,
2558 "Got device state %#lx on message %#x, expected %#lx.\n",
2559 hr, message, expect_messages->device_state);
2562 ++expect_messages;
2566 /* KDE randomly does something with the hidden window during the
2567 * mode change that sometimes generates a WM_WINDOWPOSCHANGING
2568 * message. A WM_WINDOWPOSCHANGED message is not generated, so
2569 * just flag WM_WINDOWPOSCHANGED as bad. */
2570 if (message == WM_WINDOWPOSCHANGED)
2571 InterlockedIncrement(&windowposchanged_received);
2572 else if (message == WM_SYSCOMMAND)
2573 InterlockedIncrement(&syscommand_received);
2575 return DefWindowProcA(hwnd, message, wparam, lparam);
2578 static DWORD WINAPI wndproc_thread(void *param)
2580 struct wndproc_thread_param *p = param;
2581 DWORD res;
2582 BOOL ret;
2584 p->dummy_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2585 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
2586 registry_mode.dmPelsHeight, 0, 0, 0, 0);
2587 p->running_in_foreground = SetForegroundWindow(p->dummy_window);
2589 ret = SetEvent(p->window_created);
2590 ok(ret, "SetEvent failed, last error %#lx.\n", GetLastError());
2592 for (;;)
2594 MSG msg;
2596 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
2597 DispatchMessageA(&msg);
2598 res = WaitForSingleObject(p->test_finished, 100);
2599 if (res == WAIT_OBJECT_0)
2600 break;
2601 if (res != WAIT_TIMEOUT)
2603 ok(0, "Wait failed (%#lx), last error %#lx.\n", res, GetLastError());
2604 break;
2608 DestroyWindow(p->dummy_window);
2610 return 0;
2613 static void test_wndproc(void)
2615 unsigned int adapter_mode_count, i, d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
2616 struct wndproc_thread_param thread_params;
2617 struct device_desc device_desc;
2618 static WINDOWPOS windowpos;
2619 IDirect3DDevice9Ex *device;
2620 WNDCLASSA wc = {0};
2621 HANDLE thread;
2622 LONG_PTR proc;
2623 ULONG ref;
2624 DWORD res, tid;
2625 HWND tmp;
2626 HRESULT hr;
2627 D3DDISPLAYMODE d3ddm;
2628 DEVMODEW devmode;
2629 LONG change_ret, device_style;
2630 BOOL ret;
2631 IDirect3D9Ex *d3d9ex;
2633 static const struct message create_messages[] =
2635 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
2636 /* Do not test wparam here. If device creation succeeds,
2637 * wparam is WA_ACTIVE. If device creation fails (testbot)
2638 * wparam is set to WA_INACTIVE on some Windows versions. */
2639 {WM_ACTIVATE, FOCUS_WINDOW, FALSE, 0},
2640 {WM_SETFOCUS, FOCUS_WINDOW, FALSE, 0},
2641 {0, 0, FALSE, 0},
2643 static const struct message focus_loss_messages[] =
2645 /* WM_ACTIVATE (wparam = WA_INACTIVE) is sent on Windows. It is
2646 * not reliable on X11 WMs. When the window focus follows the
2647 * mouse pointer the message is not sent.
2648 * {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_INACTIVE}, */
2650 /* The S_PRESENT_MODE_CHANGED state is only there because we change the mode
2651 * before dropping focus. From the base d3d9 tests one might expect d3d9ex to
2652 * pick up the mode change by the time we receive WM_DISPLAYCHANGE, but as
2653 * the tests below show, a present call is needed for that to happen. I don't
2654 * want to call present in a focus loss message handler until we have an app
2655 * that does that. Without the previous change (+present) the state would be
2656 * D3D_OK all the way until the WM_ACTIVATEAPP message. */
2657 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0, S_PRESENT_MODE_CHANGED},
2658 /* WM_DISPLAYCHANGE is sent to the focus window too, but the order is
2659 * not deterministic. */
2660 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0, S_PRESENT_MODE_CHANGED},
2661 /* Windows sends WM_ACTIVATE to the device window, indicating that
2662 * SW_SHOWMINIMIZED is used instead of SW_MINIMIZE. Yet afterwards
2663 * the foreground and focus window are NULL. On Wine SW_SHOWMINIMIZED
2664 * leaves the device window active, breaking re-activation in the
2665 * lost device test.
2666 * {WM_ACTIVATE, DEVICE_WINDOW, TRUE, 0x200000 | WA_ACTIVE}, */
2667 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0, S_PRESENT_MODE_CHANGED},
2668 {WM_SIZE, DEVICE_WINDOW, TRUE, SIZE_MINIMIZED, S_PRESENT_MODE_CHANGED},
2669 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE, S_PRESENT_OCCLUDED},
2670 /* WM_ACTIVATEAPP is sent to the device window too, but the order is
2671 * not deterministic. It may be sent after the focus window handling
2672 * or before. */
2673 {0, 0, FALSE, 0, 0},
2675 static const struct message focus_loss_messages_nowc[] =
2677 /* WM_ACTIVATE (wparam = WA_INACTIVE) is sent on Windows. It is
2678 * not reliable on X11 WMs. When the window focus follows the
2679 * mouse pointer the message is not sent.
2680 * {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_INACTIVE}, */
2681 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
2682 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
2683 {0, 0, FALSE, 0},
2685 static const struct message focus_loss_messages_hidden[] =
2687 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
2688 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
2689 {0, 0, FALSE, 0},
2691 static const struct message focus_loss_messages_filtered[] =
2693 /* WM_ACTIVATE is delivered to the window proc because it is
2694 * generated by SetForegroundWindow before the d3d routine
2695 * starts it work. Don't check for it due to focus-follows-mouse
2696 * WMs though. */
2697 {WM_DISPLAYCHANGE, FOCUS_WINDOW, FALSE, 0},
2698 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
2699 {0, 0, FALSE, 0},
2701 static const struct message sc_restore_messages[] =
2703 /* WM_SYSCOMMAND is delivered only once, after d3d has already
2704 * processed it. Our wndproc has no way to prevent d3d from
2705 * handling the message. The second DefWindowProc call done by
2706 * our wndproc doesn't do any changes to the window because it
2707 * is already restored due to d3d's handling. */
2708 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
2709 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
2710 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_RESTORED},
2711 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_RESTORE},
2712 {0, 0, FALSE, 0},
2714 static const struct message sc_minimize_messages[] =
2716 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_MINIMIZE},
2717 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
2718 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
2719 {WM_MOVE, FOCUS_WINDOW, FALSE, 0},
2720 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_MINIMIZED},
2721 {0, 0, FALSE, 0},
2723 static const struct message sc_maximize_messages[] =
2725 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_MAXIMIZE},
2726 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
2727 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
2728 {WM_MOVE, FOCUS_WINDOW, FALSE, 0},
2729 /* WM_SIZE(SIZE_MAXIMIZED) is unreliable on native. */
2730 {0, 0, FALSE, 0},
2732 static const struct message mode_change_messages[] =
2734 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
2735 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
2736 {WM_SIZE, DEVICE_WINDOW, FALSE, 0},
2737 /* TODO: WM_DISPLAYCHANGE is sent to the focus window too, but the order is
2738 * differs between Wine and Windows. */
2739 /* TODO 2: Windows sends a second WM_WINDOWPOSCHANGING(SWP_NOMOVE | SWP_NOSIZE
2740 * | SWP_NOACTIVATE) in this situation, suggesting a difference in their ShowWindow
2741 * implementation. This SetWindowPos call could in theory affect the Z order. Wine's
2742 * ShowWindow does not send such a message because the window is already visible. */
2743 {0, 0, FALSE, 0},
2745 static const struct message mode_change_messages_hidden[] =
2747 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
2748 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
2749 {WM_SIZE, DEVICE_WINDOW, FALSE, 0},
2750 {WM_SHOWWINDOW, DEVICE_WINDOW, FALSE, 0},
2751 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0, ~0U, &windowpos},
2752 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
2753 /* TODO: WM_DISPLAYCHANGE is sent to the focus window too, but the order is
2754 * differs between Wine and Windows. */
2755 {0, 0, FALSE, 0},
2757 static const struct message mode_change_messages_nowc[] =
2759 {WM_DISPLAYCHANGE, FOCUS_WINDOW, FALSE, 0},
2760 {0, 0, FALSE, 0},
2762 static const struct
2764 DWORD create_flags;
2765 const struct message *focus_loss_messages;
2766 const struct message *mode_change_messages, *mode_change_messages_hidden;
2767 BOOL iconic;
2769 tests[] =
2773 focus_loss_messages,
2774 mode_change_messages,
2775 mode_change_messages_hidden,
2776 TRUE
2779 CREATE_DEVICE_NOWINDOWCHANGES,
2780 focus_loss_messages_nowc,
2781 mode_change_messages_nowc,
2782 mode_change_messages_nowc,
2783 FALSE
2787 hr = pDirect3DCreate9Ex(D3D_SDK_VERSION, &d3d9ex);
2788 if (FAILED(hr))
2790 skip("Failed to create IDirect3D9Ex, hr %#lx.\n", hr);
2791 return;
2794 adapter_mode_count = IDirect3D9Ex_GetAdapterModeCount(d3d9ex, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);
2795 for (i = 0; i < adapter_mode_count; ++i)
2797 hr = IDirect3D9Ex_EnumAdapterModes(d3d9ex, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8, i, &d3ddm);
2798 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#lx.\n", hr);
2800 if (d3ddm.Width == registry_mode.dmPelsWidth && d3ddm.Height == registry_mode.dmPelsHeight)
2801 continue;
2802 /* The r200 driver on Windows XP enumerates modes like 320x200 and 320x240 but
2803 * refuses to create a device at these sizes. */
2804 if (d3ddm.Width < 640 || d3ddm.Height < 480)
2805 continue;
2807 if (!user32_width)
2809 user32_width = d3ddm.Width;
2810 user32_height = d3ddm.Height;
2811 continue;
2814 /* Make sure the d3d mode is smaller in width or height and at most
2815 * equal in the other dimension than the mode passed to
2816 * ChangeDisplaySettings. Otherwise Windows shrinks the window to
2817 * the ChangeDisplaySettings parameters + 12. */
2818 if (d3ddm.Width == user32_width && d3ddm.Height == user32_height)
2819 continue;
2820 if (d3ddm.Width <= user32_width && d3ddm.Height <= user32_height)
2822 d3d_width = d3ddm.Width;
2823 d3d_height = d3ddm.Height;
2824 break;
2826 if (user32_width <= d3ddm.Width && user32_height <= d3ddm.Height)
2828 d3d_width = user32_width;
2829 d3d_height = user32_height;
2830 user32_width = d3ddm.Width;
2831 user32_height = d3ddm.Height;
2832 break;
2836 IDirect3D9Ex_Release(d3d9ex);
2838 if (!d3d_width)
2840 skip("Could not find adequate modes, skipping mode tests.\n");
2841 return;
2844 filter_messages = NULL;
2845 expect_messages = NULL;
2847 wc.lpfnWndProc = test_proc;
2848 wc.lpszClassName = "d3d9_test_wndproc_wc";
2849 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2851 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
2852 ok(!!thread_params.window_created, "CreateEvent failed, last error %#lx.\n", GetLastError());
2853 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
2854 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#lx.\n", GetLastError());
2856 memset(&devmode, 0, sizeof(devmode));
2857 devmode.dmSize = sizeof(devmode);
2859 for (i = 0; i < ARRAY_SIZE(tests); ++i)
2861 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2862 devmode.dmPelsWidth = user32_width;
2863 devmode.dmPelsHeight = user32_height;
2864 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2865 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", change_ret);
2867 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2868 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, user32_width, user32_height, 0, 0, 0, 0);
2869 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2870 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, user32_width, user32_height, 0, 0, 0, 0);
2871 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
2872 ok(!!thread, "Failed to create thread, last error %#lx.\n", GetLastError());
2874 res = WaitForSingleObject(thread_params.window_created, INFINITE);
2875 ok(res == WAIT_OBJECT_0, "Wait failed (%#lx), last error %#lx.\n", res, GetLastError());
2877 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2878 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
2879 (LONG_PTR)test_proc, proc);
2880 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2881 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
2882 (LONG_PTR)test_proc, proc);
2884 trace("device_window %p, focus_window %p, dummy_window %p.\n",
2885 device_window, focus_window, thread_params.dummy_window);
2887 tmp = GetFocus();
2888 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2889 if (thread_params.running_in_foreground)
2891 tmp = GetForegroundWindow();
2892 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2893 thread_params.dummy_window, tmp);
2895 else
2896 skip("Not running in foreground, skip foreground window test\n");
2898 flush_events();
2900 expect_messages = create_messages;
2902 device_desc.device_window = device_window;
2903 device_desc.width = d3d_width;
2904 device_desc.height = d3d_height;
2905 device_desc.flags = CREATE_DEVICE_FULLSCREEN | tests[i].create_flags;
2906 if (!(device = create_device(focus_window, &device_desc)))
2908 skip("Failed to create a D3D device, skipping tests.\n");
2909 goto done;
2912 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
2913 expect_messages->message, expect_messages->window, i);
2914 expect_messages = NULL;
2916 if (0) /* Disabled until we can make this work in a reliable way on Wine. */
2918 tmp = GetFocus();
2919 ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
2920 tmp = GetForegroundWindow();
2921 ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
2923 SetForegroundWindow(focus_window);
2924 flush_events();
2926 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2927 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
2928 (LONG_PTR)test_proc, proc);
2930 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2931 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#Ix.\n",
2932 (LONG_PTR)test_proc);
2934 /* Change the mode while the device is in use and then drop focus. */
2935 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2936 devmode.dmPelsWidth = user32_width;
2937 devmode.dmPelsHeight = user32_height;
2938 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2939 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx, i=%u.\n", change_ret, i);
2941 /* Native needs a present call to pick up the mode change. Windows 10 15.07 never picks up the mode change
2942 * in these calls and returns S_OK. This is a regression from Windows 8 and has been fixed in later Win10
2943 * builds. */
2944 hr = IDirect3DDevice9Ex_Present(device, NULL, NULL, NULL, NULL);
2945 todo_wine ok(hr == S_PRESENT_MODE_CHANGED || broken(hr == S_OK), "Got unexpected hr %#lx, i=%u.\n", hr, i);
2946 hr = IDirect3DDevice9Ex_CheckDeviceState(device, device_window);
2947 todo_wine ok(hr == S_PRESENT_MODE_CHANGED || broken(hr == S_OK), "Got unexpected hr %#lx, i=%u.\n", hr, i);
2949 expect_messages = tests[i].focus_loss_messages;
2950 /* SetForegroundWindow is a poor replacement for the user pressing alt-tab or
2951 * manually changing the focus. It generates the same messages, but the task
2952 * bar still shows the previous foreground window as active, and the window has
2953 * an inactive titlebar if reactivated with SetForegroundWindow. Reactivating
2954 * the device is difficult, see below. */
2955 SetForegroundWindow(GetDesktopWindow());
2956 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
2957 expect_messages->message, expect_messages->window, i);
2958 expect_messages = NULL;
2959 tmp = GetFocus();
2960 ok(tmp != device_window, "The device window is active, i=%u.\n", i);
2961 ok(tmp != focus_window, "The focus window is active, i=%u.\n", i);
2963 hr = IDirect3DDevice9Ex_CheckDeviceState(device, device_window);
2964 ok(hr == S_PRESENT_OCCLUDED, "Got unexpected hr %#lx, i=%u.\n", hr, i);
2966 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2967 ok(ret, "Failed to get display mode.\n");
2968 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2969 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpected screen size %lux%lu.\n",
2970 devmode.dmPelsWidth, devmode.dmPelsHeight);
2972 /* In d3d9ex the device and focus windows have to be minimized and restored,
2973 * otherwise native does not notice that focus has been restored. This is
2974 * independent of D3DCREATE_NOWINDOWCHANGES. */
2975 ShowWindow(device_window, SW_MINIMIZE);
2976 ShowWindow(device_window, SW_RESTORE);
2978 /* Reactivation messages like in d3d8/9 are random in native d3d9ex.
2979 * Sometimes they are sent, sometimes they are not (tested on Vista
2980 * and Windows 7). The minimizing and restoring of the device window
2981 * may have something to do with this, but if the messages are sent,
2982 * they are generated by the 3 calls below. */
2983 ShowWindow(focus_window, SW_MINIMIZE);
2984 ShowWindow(focus_window, SW_RESTORE);
2985 /* Set focus twice to make KDE and fvwm in focus-follows-mouse mode happy. */
2986 SetForegroundWindow(focus_window);
2987 flush_events();
2988 SetForegroundWindow(focus_window);
2989 flush_events();
2991 /* Calling Reset is not necessary in d3d9ex. */
2992 hr = IDirect3DDevice9Ex_CheckDeviceState(device, device_window);
2993 ok(hr == S_OK, "Got unexpected hr %#lx, i=%u.\n", hr, i);
2995 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2996 ok(ret, "Failed to get display mode.\n");
2997 ok(devmode.dmPelsWidth == d3d_width
2998 && devmode.dmPelsHeight == d3d_height, "Got unexpected screen size %lux%lu.\n",
2999 devmode.dmPelsWidth, devmode.dmPelsHeight);
3001 hr = reset_device(device, &device_desc);
3002 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
3004 /* Remove the WS_VISIBLE flag to test hidden windows. This is enough to trigger d3d's hidden
3005 * window codepath, but does not actually hide the window without a SetWindowPos(SWP_FRAMECHANGED)
3006 * call. This way we avoid focus changes and random failures on focus follows mouse WMs. */
3007 device_style = GetWindowLongA(device_window, GWL_STYLE);
3008 SetWindowLongA(device_window, GWL_STYLE, device_style & ~WS_VISIBLE);
3009 flush_events();
3011 expect_messages = focus_loss_messages_hidden;
3012 windowposchanged_received = 0;
3013 SetForegroundWindow(GetDesktopWindow());
3014 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3015 expect_messages->message, expect_messages->window, i);
3016 ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it, i=%u.\n", i);
3017 expect_messages = NULL;
3018 flush_events();
3020 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3021 ok(ret, "Failed to get display mode.\n");
3022 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth, "Got unexpected width %lu.\n", devmode.dmPelsWidth);
3023 ok(devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpected height %lu.\n", devmode.dmPelsHeight);
3025 /* SW_SHOWMINNOACTIVE is needed to make FVWM happy. SW_SHOWNOACTIVATE is needed to make windows
3026 * send SIZE_RESTORED after ShowWindow(SW_SHOWMINNOACTIVE). */
3027 ShowWindow(focus_window, SW_SHOWNOACTIVATE);
3028 ShowWindow(focus_window, SW_SHOWMINNOACTIVE);
3029 flush_events();
3031 syscommand_received = 0;
3032 expect_messages = sc_restore_messages;
3033 SendMessageA(focus_window, WM_SYSCOMMAND, SC_RESTORE, 0);
3034 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3035 expect_messages->message, expect_messages->window, i);
3036 ok(syscommand_received == 1, "Got unexpected number of WM_SYSCOMMAND messages: %ld.\n", syscommand_received);
3037 expect_messages = NULL;
3038 flush_events();
3040 expect_messages = sc_minimize_messages;
3041 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
3042 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3043 expect_messages->message, expect_messages->window, i);
3044 expect_messages = NULL;
3045 flush_events();
3047 expect_messages = sc_maximize_messages;
3048 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
3049 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3050 expect_messages->message, expect_messages->window, i);
3051 expect_messages = NULL;
3052 flush_events();
3054 SetForegroundWindow(GetDesktopWindow());
3055 ShowWindow(device_window, SW_MINIMIZE);
3056 ShowWindow(device_window, SW_RESTORE);
3057 ShowWindow(focus_window, SW_MINIMIZE);
3058 ShowWindow(focus_window, SW_RESTORE);
3059 SetForegroundWindow(focus_window);
3060 flush_events();
3062 filter_messages = focus_window;
3063 ref = IDirect3DDevice9Ex_Release(device);
3064 ok(!ref, "Unexpected refcount %lu, i=%u.\n", ref, i);
3066 /* Fix up the mode until Wine's device release behavior is fixed. */
3067 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3068 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", change_ret);
3070 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3071 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix, i=%u.\n",
3072 (LONG_PTR)test_proc, proc, i);
3074 /* Hide the device window. It prevents WM_ACTIVATEAPP messages from being sent
3075 * on native in the test below. It isn't needed anyways. Creating the third
3076 * device will show it again. */
3077 filter_messages = NULL;
3078 ShowWindow(device_window, SW_HIDE);
3079 /* Remove the maximized state from the SYSCOMMAND test while we're not
3080 * interfering with a device. */
3081 ShowWindow(focus_window, SW_SHOWNORMAL);
3082 filter_messages = focus_window;
3084 device_desc.device_window = focus_window;
3085 if (!(device = create_device(focus_window, &device_desc)))
3087 skip("Failed to create a D3D device, skipping tests.\n");
3088 goto done;
3090 filter_messages = NULL;
3091 SetForegroundWindow(focus_window); /* For KDE. */
3092 flush_events();
3094 expect_messages = focus_loss_messages_filtered;
3095 windowposchanged_received = 0;
3096 SetForegroundWindow(GetDesktopWindow());
3097 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3098 expect_messages->message, expect_messages->window, i);
3099 ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it, i=%u.\n", i);
3100 expect_messages = NULL;
3102 /* The window is iconic even though no message was sent. */
3103 ok(!IsIconic(focus_window) == !tests[i].iconic,
3104 "Expected IsIconic %u, got %u, i=%u.\n", tests[i].iconic, IsIconic(focus_window), i);
3106 ShowWindow(focus_window, SW_SHOWNOACTIVATE);
3107 flush_events();
3108 ShowWindow(focus_window, SW_SHOWMINNOACTIVE);
3109 flush_events();
3111 syscommand_received = 0;
3112 expect_messages = sc_restore_messages;
3113 SendMessageA(focus_window, WM_SYSCOMMAND, SC_RESTORE, 0);
3114 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3115 expect_messages->message, expect_messages->window, i);
3116 ok(syscommand_received == 1, "Got unexpected number of WM_SYSCOMMAND messages: %ld.\n", syscommand_received);
3117 expect_messages = NULL;
3118 flush_events();
3120 /* For FVWM. */
3121 ShowWindow(focus_window, SW_RESTORE);
3122 flush_events();
3124 expect_messages = sc_minimize_messages;
3125 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
3126 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3127 expect_messages->message, expect_messages->window, i);
3128 expect_messages = NULL;
3129 flush_events();
3131 expect_messages = sc_maximize_messages;
3132 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
3133 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3134 expect_messages->message, expect_messages->window, i);
3135 expect_messages = NULL;
3136 flush_events();
3138 /* This test can't activate, drop focus and restore focus like in plain d3d9 because d3d9ex
3139 * immediately restores the device on activation. There are plenty of WM_WINDOWPOSCHANGED
3140 * messages that are generated by ShowWindow, so testing for their absence is pointless. */
3141 ShowWindow(focus_window, SW_MINIMIZE);
3142 ShowWindow(focus_window, SW_RESTORE);
3143 SetForegroundWindow(focus_window);
3144 flush_events();
3146 filter_messages = focus_window;
3147 ref = IDirect3DDevice9Ex_Release(device);
3148 ok(!ref, "Unexpected refcount %lu, i=%u.\n", ref, i);
3150 device_desc.device_window = device_window;
3151 if (!(device = create_device(focus_window, &device_desc)))
3153 skip("Failed to create a D3D device, skipping tests.\n");
3154 goto done;
3156 filter_messages = NULL;
3157 flush_events();
3159 device_desc.width = user32_width;
3160 device_desc.height = user32_height;
3162 expect_messages = tests[i].mode_change_messages;
3163 filter_messages = focus_window;
3164 hr = reset_device(device, &device_desc);
3165 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
3166 filter_messages = NULL;
3168 /* The WINDOWPOS structure passed to the first WM_WINDOWPOSCHANGING differs between windows versions.
3169 * Prior to Win10 17.03 it is consistent with a MoveWindow(0, 0, width, height) call. Since Windows
3170 * 10 17.03 it has x = 0, y = 0, width = 0, height = 0, flags = SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE
3171 * | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER (0x1837). Visually
3172 * it is clear that the window has not been resized. In previous Windows version the window is resized. */
3174 flush_events();
3175 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3176 expect_messages->message, expect_messages->window, i);
3177 expect_messages = NULL;
3179 /* World of Warplanes hides the window by removing WS_VISIBLE and expects Reset() to show it again. */
3180 device_style = GetWindowLongA(device_window, GWL_STYLE);
3181 SetWindowLongA(device_window, GWL_STYLE, device_style & ~WS_VISIBLE);
3183 flush_events();
3184 device_desc.width = d3d_width;
3185 device_desc.height = d3d_height;
3186 memset(&windowpos, 0, sizeof(windowpos));
3188 expect_messages = tests[i].mode_change_messages_hidden;
3189 filter_messages = focus_window;
3190 hr = reset_device(device, &device_desc);
3191 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
3192 filter_messages = NULL;
3194 flush_events();
3195 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3196 expect_messages->message, expect_messages->window, i);
3197 expect_messages = NULL;
3199 if (!(tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES))
3201 ok(windowpos.hwnd == device_window
3202 && !windowpos.x && !windowpos.y && !windowpos.cx && !windowpos.cy
3203 && windowpos.flags == (SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE),
3204 "Got unexpected WINDOWPOS hwnd=%p, x=%d, y=%d, cx=%d, cy=%d, flags=%x\n",
3205 windowpos.hwnd, windowpos.x, windowpos.y, windowpos.cx,
3206 windowpos.cy, windowpos.flags);
3209 device_style = GetWindowLongA(device_window, GWL_STYLE);
3210 if (tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES)
3212 todo_wine ok(!(device_style & WS_VISIBLE), "Expected the device window to be hidden, i=%u.\n", i);
3213 ShowWindow(device_window, SW_MINIMIZE);
3214 ShowWindow(device_window, SW_RESTORE);
3216 else
3218 ok(device_style & WS_VISIBLE, "Expected the device window to be visible, i=%u.\n", i);
3221 proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
3222 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#Ix.\n",
3223 (LONG_PTR)test_proc);
3225 ref = IDirect3DDevice9Ex_Release(device);
3226 ok(!ref, "Unexpected refcount %lu.\n", ref);
3228 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3229 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#Ix, got %#Ix.\n",
3230 (LONG_PTR)DefWindowProcA, proc);
3232 done:
3233 filter_messages = NULL;
3234 expect_messages = NULL;
3235 DestroyWindow(device_window);
3236 DestroyWindow(focus_window);
3237 SetEvent(thread_params.test_finished);
3238 WaitForSingleObject(thread, INFINITE);
3239 CloseHandle(thread);
3242 CloseHandle(thread_params.test_finished);
3243 CloseHandle(thread_params.window_created);
3245 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
3248 static void test_wndproc_windowed(void)
3250 struct wndproc_thread_param thread_params;
3251 struct device_desc device_desc;
3252 IDirect3DDevice9Ex *device;
3253 WNDCLASSA wc = {0};
3254 HANDLE thread;
3255 LONG_PTR proc;
3256 HRESULT hr;
3257 ULONG ref;
3258 DWORD res, tid;
3259 HWND tmp;
3261 filter_messages = NULL;
3262 expect_messages = NULL;
3264 wc.lpfnWndProc = test_proc;
3265 wc.lpszClassName = "d3d9_test_wndproc_wc";
3266 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3268 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
3269 ok(!!thread_params.window_created, "CreateEvent failed, last error %#lx.\n", GetLastError());
3270 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
3271 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#lx.\n", GetLastError());
3273 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3274 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
3275 registry_mode.dmPelsHeight, 0, 0, 0, 0);
3276 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3277 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
3278 registry_mode.dmPelsHeight, 0, 0, 0, 0);
3279 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
3280 ok(!!thread, "Failed to create thread, last error %#lx.\n", GetLastError());
3282 res = WaitForSingleObject(thread_params.window_created, INFINITE);
3283 ok(res == WAIT_OBJECT_0, "Wait failed (%#lx), last error %#lx.\n", res, GetLastError());
3285 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3286 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
3287 (LONG_PTR)test_proc, proc);
3288 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3289 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
3290 (LONG_PTR)test_proc, proc);
3292 trace("device_window %p, focus_window %p, dummy_window %p.\n",
3293 device_window, focus_window, thread_params.dummy_window);
3295 tmp = GetFocus();
3296 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
3297 if (thread_params.running_in_foreground)
3299 tmp = GetForegroundWindow();
3300 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
3301 thread_params.dummy_window, tmp);
3303 else
3304 skip("Not running in foreground, skip foreground window test\n");
3306 filter_messages = focus_window;
3308 device_desc.device_window = device_window;
3309 device_desc.width = registry_mode.dmPelsWidth;
3310 device_desc.height = registry_mode.dmPelsHeight;
3311 device_desc.flags = 0;
3312 if (!(device = create_device(focus_window, &device_desc)))
3314 skip("Failed to create a D3D device, skipping tests.\n");
3315 goto done;
3318 tmp = GetFocus();
3319 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
3320 tmp = GetForegroundWindow();
3321 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
3322 thread_params.dummy_window, tmp);
3324 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3325 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
3326 (LONG_PTR)test_proc, proc);
3328 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3329 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
3330 (LONG_PTR)test_proc, proc);
3332 filter_messages = NULL;
3334 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
3335 hr = reset_device(device, &device_desc);
3336 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
3338 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3339 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
3340 (LONG_PTR)test_proc, proc);
3342 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3343 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#Ix.\n", (LONG_PTR)test_proc);
3345 device_desc.flags = 0;
3346 hr = reset_device(device, &device_desc);
3347 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
3349 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3350 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
3351 (LONG_PTR)test_proc, proc);
3353 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3354 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
3355 (LONG_PTR)test_proc, proc);
3357 filter_messages = focus_window;
3359 ref = IDirect3DDevice9Ex_Release(device);
3360 ok(!ref, "Unexpected refcount %lu.\n", ref);
3362 filter_messages = device_window;
3364 device_desc.device_window = focus_window;
3365 if (!(device = create_device(focus_window, &device_desc)))
3367 skip("Failed to create a D3D device, skipping tests.\n");
3368 goto done;
3371 filter_messages = NULL;
3373 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
3374 hr = reset_device(device, &device_desc);
3375 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
3377 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3378 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
3379 (LONG_PTR)test_proc, proc);
3381 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3382 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#Ix.\n", (LONG_PTR)test_proc);
3384 device_desc.flags = 0;
3385 hr = reset_device(device, &device_desc);
3386 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
3388 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3389 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
3390 (LONG_PTR)test_proc, proc);
3392 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3393 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
3394 (LONG_PTR)test_proc, proc);
3396 filter_messages = device_window;
3398 ref = IDirect3DDevice9Ex_Release(device);
3399 ok(!ref, "Unexpected refcount %lu.\n", ref);
3401 device_desc.device_window = device_window;
3402 if (!(device = create_device(focus_window, &device_desc)))
3404 skip("Failed to create a D3D device, skipping tests.\n");
3405 goto done;
3408 filter_messages = NULL;
3410 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
3411 hr = reset_device(device, &device_desc);
3412 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
3414 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3415 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
3416 (LONG_PTR)test_proc, proc);
3418 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3419 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#Ix.\n", (LONG_PTR)test_proc);
3421 device_desc.flags = 0;
3422 hr = reset_device(device, &device_desc);
3423 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
3425 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3426 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
3427 (LONG_PTR)test_proc, proc);
3429 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3430 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
3431 (LONG_PTR)test_proc, proc);
3433 filter_messages = device_window;
3435 ref = IDirect3DDevice9Ex_Release(device);
3436 ok(!ref, "Unexpected refcount %lu.\n", ref);
3438 done:
3439 filter_messages = NULL;
3441 SetEvent(thread_params.test_finished);
3442 WaitForSingleObject(thread, INFINITE);
3443 CloseHandle(thread_params.test_finished);
3444 CloseHandle(thread_params.window_created);
3445 CloseHandle(thread);
3447 DestroyWindow(device_window);
3448 DestroyWindow(focus_window);
3449 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
3452 static void test_window_style(void)
3454 RECT focus_rect, device_rect, fullscreen_rect, r, r2;
3455 LONG device_style, device_exstyle, expected_style;
3456 LONG focus_style, focus_exstyle;
3457 struct device_desc device_desc;
3458 LONG style;
3459 IDirect3DDevice9Ex *device;
3460 HRESULT hr;
3461 ULONG ref;
3462 BOOL ret;
3463 static const struct
3465 LONG style_flags;
3466 DWORD device_flags;
3467 LONG focus_loss_style;
3468 LONG create2_style, create2_exstyle;
3470 tests[] =
3472 {0, 0, 0, WS_VISIBLE, WS_EX_TOPMOST},
3473 {WS_VISIBLE, 0, WS_MINIMIZE, WS_VISIBLE, WS_EX_TOPMOST},
3474 {0, CREATE_DEVICE_NOWINDOWCHANGES, 0, 0, 0},
3475 {WS_VISIBLE, CREATE_DEVICE_NOWINDOWCHANGES, 0, 0, 0},
3477 unsigned int i;
3479 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
3481 for (i = 0; i < ARRAY_SIZE(tests); ++i)
3483 focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW | tests[i].style_flags,
3484 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
3485 device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW | tests[i].style_flags,
3486 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
3488 device_style = GetWindowLongA(device_window, GWL_STYLE);
3489 device_exstyle = GetWindowLongA(device_window, GWL_EXSTYLE);
3490 focus_style = GetWindowLongA(focus_window, GWL_STYLE);
3491 focus_exstyle = GetWindowLongA(focus_window, GWL_EXSTYLE);
3493 GetWindowRect(focus_window, &focus_rect);
3494 GetWindowRect(device_window, &device_rect);
3496 device_desc.device_window = device_window;
3497 device_desc.width = registry_mode.dmPelsWidth;
3498 device_desc.height = registry_mode.dmPelsHeight;
3499 device_desc.flags = CREATE_DEVICE_FULLSCREEN | tests[i].device_flags;
3500 if (!(device = create_device(focus_window, &device_desc)))
3502 skip("Failed to create a D3D device, skipping tests.\n");
3503 DestroyWindow(device_window);
3504 DestroyWindow(focus_window);
3505 return;
3508 style = GetWindowLongA(device_window, GWL_STYLE);
3509 expected_style = device_style;
3510 todo_wine ok(style == expected_style || broken(style == (expected_style & ~WS_OVERLAPPEDWINDOW)) /* w1064v1809 */,
3511 "Expected device window style %#lx, got %#lx, i=%u.\n",
3512 expected_style, style, i);
3513 style = GetWindowLongA(device_window, GWL_EXSTYLE);
3514 expected_style = device_exstyle;
3515 todo_wine ok(style == expected_style || broken(style == (expected_style & ~WS_EX_OVERLAPPEDWINDOW)) /* w1064v1809 */,
3516 "Expected device window extended style %#lx, got %#lx, i=%u.\n",
3517 expected_style, style, i);
3519 style = GetWindowLongA(focus_window, GWL_STYLE);
3520 ok(style == focus_style, "Expected focus window style %#lx, got %#lx, i=%u.\n",
3521 focus_style, style, i);
3522 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
3523 ok(style == focus_exstyle, "Expected focus window extended style %#lx, got %#lx, i=%u.\n",
3524 focus_exstyle, style, i);
3526 GetWindowRect(device_window, &r);
3527 if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
3528 todo_wine ok(EqualRect(&r, &device_rect), "Expected %s, got %s, i=%u.\n",
3529 wine_dbgstr_rect(&device_rect), wine_dbgstr_rect(&r), i);
3530 else
3531 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s, i=%u.\n",
3532 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r), i);
3533 GetClientRect(device_window, &r2);
3534 todo_wine ok(!EqualRect(&r, &r2) || broken(!(style & WS_THICKFRAME)) /* w1064v1809 */,
3535 "Client rect and window rect are equal, i=%u.\n", i);
3536 GetWindowRect(focus_window, &r);
3537 ok(EqualRect(&r, &focus_rect), "Expected %s, got %s, i=%u.\n",
3538 wine_dbgstr_rect(&focus_rect), wine_dbgstr_rect(&r), i);
3540 device_desc.flags = 0;
3541 hr = reset_device(device, &device_desc);
3542 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
3544 GetWindowRect(device_window, &r);
3545 if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
3546 todo_wine ok(EqualRect(&r, &device_rect), "Expected %s, got %s, i=%u.\n",
3547 wine_dbgstr_rect(&device_rect), wine_dbgstr_rect(&r), i);
3548 else
3549 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s, i=%u.\n",
3550 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r), i);
3552 style = GetWindowLongA(device_window, GWL_STYLE);
3553 expected_style = device_style;
3554 ok(style == expected_style, "Expected device window style %#lx, got %#lx, i=%u.\n",
3555 expected_style, style, i);
3556 style = GetWindowLongA(device_window, GWL_EXSTYLE);
3557 expected_style = device_exstyle;
3558 ok(style == expected_style, "Expected device window extended style %#lx, got %#lx, i=%u.\n",
3559 expected_style, style, i);
3561 style = GetWindowLongA(focus_window, GWL_STYLE);
3562 ok(style == focus_style, "Expected focus window style %#lx, got %#lx, i=%u.\n",
3563 focus_style, style, i);
3564 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
3565 ok(style == focus_exstyle, "Expected focus window extended style %#lx, got %#lx, i=%u.\n",
3566 focus_exstyle, style, i);
3568 ref = IDirect3DDevice9Ex_Release(device);
3569 ok(!ref, "Unexpected refcount %lu.\n", ref);
3571 style = GetWindowLongA(device_window, GWL_STYLE);
3572 expected_style = device_style;
3573 ok(style == expected_style, "Expected device window style %#lx, got %#lx, i=%u.\n",
3574 expected_style, style, i);
3575 style = GetWindowLongA(device_window, GWL_EXSTYLE);
3576 expected_style = device_exstyle;
3577 ok(style == expected_style, "Expected device window extended style %#lx, got %#lx, i=%u.\n",
3578 expected_style, style, i);
3580 style = GetWindowLongA(focus_window, GWL_STYLE);
3581 ok(style == focus_style, "Expected focus window style %#lx, got %#lx, i=%u.\n",
3582 focus_style, style, i);
3583 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
3584 ok(style == focus_exstyle, "Expected focus window extended style %#lx, got %#lx, i=%u.\n",
3585 focus_exstyle, style, i);
3587 /* The second time a device is created on the window the window becomes visible and
3588 * topmost if D3DCREATE_NOWINDOWCHANGES is not set. */
3589 device_desc.flags = CREATE_DEVICE_FULLSCREEN | tests[i].device_flags;
3590 device = create_device(focus_window, &device_desc);
3591 ok(!!device, "Failed to create a D3D device.\n");
3592 style = GetWindowLongA(device_window, GWL_STYLE);
3593 expected_style = device_style | tests[i].create2_style;
3594 todo_wine ok(style == expected_style || broken(style == (expected_style & ~WS_OVERLAPPEDWINDOW)) /* w1064v1809 */,
3595 "Expected device window style %#lx, got %#lx, i=%u.\n",
3596 expected_style, style, i);
3597 style = GetWindowLongA(device_window, GWL_EXSTYLE);
3598 expected_style = device_exstyle | tests[i].create2_exstyle;
3599 todo_wine ok(style == expected_style || broken(style == (expected_style & ~WS_EX_OVERLAPPEDWINDOW)) /* w1064v1809 */,
3600 "Expected device window extended style %#lx, got %#lx, i=%u.\n",
3601 expected_style, style, i);
3603 style = GetWindowLongA(focus_window, GWL_STYLE);
3604 ok(style == focus_style, "Expected focus window style %#lx, got %#lx, i=%u.\n",
3605 focus_style, style, i);
3606 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
3607 ok(style == focus_exstyle, "Expected focus window extended style %#lx, got %#lx, i=%u.\n",
3608 focus_exstyle, style, i);
3609 ref = IDirect3DDevice9Ex_Release(device);
3610 ok(!ref, "Unexpected refcount %lu.\n", ref);
3612 DestroyWindow(device_window);
3613 DestroyWindow(focus_window);
3614 focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW | tests[i].style_flags,
3615 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
3616 device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW | tests[i].style_flags,
3617 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
3619 device_desc.device_window = device_window;
3620 device = create_device(focus_window, &device_desc);
3621 ok(!!device, "Failed to create a D3D device.\n");
3622 ret = SetForegroundWindow(GetDesktopWindow());
3623 ok(ret, "Failed to set foreground window.\n");
3625 style = GetWindowLongA(device_window, GWL_STYLE);
3626 expected_style = device_style | tests[i].focus_loss_style;
3627 todo_wine ok(style == expected_style, "Expected device window style %#lx, got %#lx, i=%u.\n",
3628 expected_style, style, i);
3629 style = GetWindowLongA(device_window, GWL_EXSTYLE);
3630 expected_style = device_exstyle;
3631 todo_wine ok(style == expected_style, "Expected device window extended style %#lx, got %#lx, i=%u.\n",
3632 expected_style, style, i);
3634 style = GetWindowLongA(focus_window, GWL_STYLE);
3635 ok(style == focus_style, "Expected focus window style %#lx, got %#lx, i=%u.\n",
3636 focus_style, style, i);
3637 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
3638 ok(style == focus_exstyle, "Expected focus window extended style %#lx, got %#lx, i=%u.\n",
3639 focus_exstyle, style, i);
3641 ref = IDirect3DDevice9Ex_Release(device);
3642 ok(!ref, "Unexpected refcount %lu.\n", ref);
3644 DestroyWindow(device_window);
3645 DestroyWindow(focus_window);
3649 static void test_swapchain_parameters(void)
3651 IDirect3DDevice9Ex *device;
3652 IDirect3D9Ex *d3d9ex;
3653 HWND window;
3654 HRESULT hr;
3655 unsigned int i;
3656 D3DPRESENT_PARAMETERS present_parameters, present_parameters_windowed = {0}, present_parameters2;
3657 IDirect3DSwapChain9 *swapchain;
3658 D3DDISPLAYMODEEX mode = {0};
3659 static const struct
3661 BOOL windowed;
3662 UINT backbuffer_count;
3663 D3DSWAPEFFECT swap_effect;
3664 HRESULT hr;
3666 tests[] =
3668 /* Swap effect 0 is not allowed. */
3669 {TRUE, 1, 0, D3DERR_INVALIDCALL},
3670 {FALSE, 1, 0, D3DERR_INVALIDCALL},
3672 /* All (non-ex) swap effects are allowed in
3673 * windowed and fullscreen mode. */
3674 {TRUE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
3675 {TRUE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
3676 {FALSE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
3677 {FALSE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
3678 {FALSE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
3680 /* Only one backbuffer in copy mode. */
3681 {TRUE, 0, D3DSWAPEFFECT_COPY, D3D_OK},
3682 {TRUE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
3683 {TRUE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
3684 {FALSE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
3686 /* Ok with the others, in fullscreen and windowed mode. */
3687 {TRUE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
3688 {TRUE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
3689 {FALSE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
3690 {FALSE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
3692 /* D3D9Ex swap effects. Flipex works, Overlay is complicated
3693 * and depends on HW features, pixel format, etc. */
3694 {TRUE, 1, D3DSWAPEFFECT_FLIPEX, D3D_OK},
3695 {TRUE, 1, D3DSWAPEFFECT_FLIPEX + 1, D3DERR_INVALIDCALL},
3696 {FALSE, 1, D3DSWAPEFFECT_FLIPEX, D3D_OK},
3697 {FALSE, 1, D3DSWAPEFFECT_FLIPEX + 1, D3DERR_INVALIDCALL},
3699 /* 30 is the highest allowed backbuffer count. */
3700 {TRUE, 30, D3DSWAPEFFECT_DISCARD, D3D_OK},
3701 {TRUE, 31, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
3702 {TRUE, 30, D3DSWAPEFFECT_FLIP, D3D_OK},
3703 {TRUE, 31, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
3704 {FALSE, 30, D3DSWAPEFFECT_DISCARD, D3D_OK},
3705 {FALSE, 31, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
3706 {FALSE, 30, D3DSWAPEFFECT_FLIP, D3D_OK},
3707 {FALSE, 31, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
3710 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
3711 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3712 hr = pDirect3DCreate9Ex(D3D_SDK_VERSION, &d3d9ex);
3713 if (FAILED(hr))
3715 skip("Failed to create IDirect3D9Ex, hr %#lx.\n", hr);
3716 return;
3719 if (!(device = create_device(window, NULL)))
3721 skip("Failed to create a D3D device, skipping tests.\n");
3722 IDirect3D9Ex_Release(d3d9ex);
3723 DestroyWindow(window);
3724 return;
3726 IDirect3DDevice9Ex_Release(device);
3728 present_parameters_windowed.BackBufferWidth = registry_mode.dmPelsWidth;
3729 present_parameters_windowed.BackBufferHeight = registry_mode.dmPelsHeight;
3730 present_parameters_windowed.hDeviceWindow = window;
3731 present_parameters_windowed.BackBufferFormat = D3DFMT_X8R8G8B8;
3732 present_parameters_windowed.SwapEffect = D3DSWAPEFFECT_COPY;
3733 present_parameters_windowed.Windowed = TRUE;
3734 present_parameters_windowed.BackBufferCount = 1;
3736 mode.Size = sizeof(mode);
3737 mode.Width = registry_mode.dmPelsWidth;
3738 mode.Height = registry_mode.dmPelsHeight;
3739 mode.RefreshRate = 0;
3740 mode.Format = D3DFMT_X8R8G8B8;
3741 mode.ScanLineOrdering = 0;
3743 for (i = 0; i < ARRAY_SIZE(tests); ++i)
3745 memset(&present_parameters, 0, sizeof(present_parameters));
3746 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
3747 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
3748 present_parameters.hDeviceWindow = window;
3749 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
3751 present_parameters.SwapEffect = tests[i].swap_effect;
3752 present_parameters.Windowed = tests[i].windowed;
3753 present_parameters.BackBufferCount = tests[i].backbuffer_count;
3755 hr = IDirect3D9Ex_CreateDeviceEx(d3d9ex, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
3756 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters,
3757 tests[i].windowed ? NULL : &mode, &device);
3758 ok(hr == tests[i].hr, "Expected hr %#lx, got %#lx, test %u.\n", tests[i].hr, hr, i);
3759 if (SUCCEEDED(hr))
3761 UINT bb_count = tests[i].backbuffer_count ? tests[i].backbuffer_count : 1;
3763 hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain);
3764 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#lx, test %u.\n", hr, i);
3766 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &present_parameters2);
3767 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#lx, test %u.\n", hr, i);
3768 ok(present_parameters2.SwapEffect == tests[i].swap_effect, "Swap effect changed from %u to %u, test %u.\n",
3769 tests[i].swap_effect, present_parameters2.SwapEffect, i);
3770 ok(present_parameters2.BackBufferCount == bb_count, "Backbuffer count changed from %u to %u, test %u.\n",
3771 bb_count, present_parameters2.BackBufferCount, i);
3772 ok(present_parameters2.Windowed == tests[i].windowed, "Windowed changed from %u to %u, test %u.\n",
3773 tests[i].windowed, present_parameters2.Windowed, i);
3775 IDirect3DSwapChain9_Release(swapchain);
3776 IDirect3DDevice9Ex_Release(device);
3779 hr = IDirect3D9Ex_CreateDeviceEx(d3d9ex, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
3780 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters_windowed, NULL, &device);
3781 ok(SUCCEEDED(hr), "Failed to create device, hr %#lx, test %u.\n", hr, i);
3783 memset(&present_parameters, 0, sizeof(present_parameters));
3784 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
3785 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
3786 present_parameters.hDeviceWindow = window;
3787 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
3789 present_parameters.SwapEffect = tests[i].swap_effect;
3790 present_parameters.Windowed = tests[i].windowed;
3791 present_parameters.BackBufferCount = tests[i].backbuffer_count;
3793 hr = IDirect3DDevice9Ex_ResetEx(device, &present_parameters, tests[i].windowed ? NULL : &mode);
3794 ok(hr == tests[i].hr, "Expected hr %#lx, got %#lx, test %u.\n", tests[i].hr, hr, i);
3796 if (FAILED(hr))
3798 hr = IDirect3DDevice9Ex_ResetEx(device, &present_parameters_windowed, NULL);
3799 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx, test %u.\n", hr, i);
3801 IDirect3DDevice9Ex_Release(device);
3804 IDirect3D9Ex_Release(d3d9ex);
3805 DestroyWindow(window);
3808 static void test_backbuffer_resize(void)
3810 D3DPRESENT_PARAMETERS present_parameters = {0};
3811 IDirect3DSurface9 *backbuffer, *old_backbuffer;
3812 D3DSURFACE_DESC surface_desc;
3813 IDirect3DDevice9Ex *device;
3814 unsigned int color;
3815 ULONG refcount;
3816 HWND window;
3817 HRESULT hr;
3819 static const struct
3821 float position[3];
3822 DWORD diffuse;
3824 quad[] =
3826 {{-1.0f, -1.0f, 0.1f}, D3DCOLOR_ARGB(0xff, 0x00, 0xff, 0x00)},
3827 {{-1.0f, 1.0f, 0.1f}, D3DCOLOR_ARGB(0xff, 0x00, 0xff, 0x00)},
3828 {{ 1.0f, -1.0f, 0.1f}, D3DCOLOR_ARGB(0xff, 0x00, 0xff, 0x00)},
3829 {{ 1.0f, 1.0f, 0.1f}, D3DCOLOR_ARGB(0xff, 0x00, 0xff, 0x00)},
3832 window = create_window();
3833 if (!(device = create_device(window, NULL)))
3835 skip("Failed to create a D3D device.\n");
3836 DestroyWindow(window);
3837 return;
3840 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, FALSE);
3841 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#lx.\n", hr);
3842 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, FALSE);
3843 ok(SUCCEEDED(hr), "Failed to disable Z test, hr %#lx.\n", hr);
3844 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
3845 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#lx.\n", hr);
3846 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
3847 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#lx.\n", hr);
3849 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
3850 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#lx.\n", hr);
3851 hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
3852 ok(SUCCEEDED(hr), "Failed to set render target, hr %#lx.\n", hr);
3854 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 1.0f, 0);
3855 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
3856 color = get_pixel_color(device, 1, 1);
3857 ok(color == 0x00ff0000, "Got unexpected color 0x%08x.\n", color);
3859 present_parameters.BackBufferWidth = 800;
3860 present_parameters.BackBufferHeight = 600;
3861 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
3862 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
3863 present_parameters.hDeviceWindow = NULL;
3864 present_parameters.Windowed = TRUE;
3865 present_parameters.EnableAutoDepthStencil = TRUE;
3866 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
3867 hr = IDirect3DDevice9_Reset(device, &present_parameters);
3868 ok(SUCCEEDED(hr), "Failed to reset, hr %#lx.\n", hr);
3870 old_backbuffer = backbuffer;
3871 hr = IDirect3DSurface9_GetDesc(old_backbuffer, &surface_desc);
3872 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
3873 todo_wine ok(surface_desc.Width == 640, "Got unexpected width %u.\n", surface_desc.Width);
3874 todo_wine ok(surface_desc.Height == 480, "Got unexpected height %u.\n", surface_desc.Height);
3875 refcount = IDirect3DSurface9_Release(old_backbuffer);
3876 ok(!refcount, "Surface has %lu references left.\n", refcount);
3878 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
3879 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#lx.\n", hr);
3880 todo_wine ok(backbuffer != old_backbuffer, "Expected new backbuffer surface.\n");
3882 hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
3883 ok(SUCCEEDED(hr), "Failed to set render target, hr %#lx.\n", hr);
3885 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
3886 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
3887 color = get_pixel_color(device, 1, 1);
3888 ok(color == 0x00ffff00, "Got unexpected color 0x%08x.\n", color);
3889 color = get_pixel_color(device, 700, 500);
3890 ok(color == 0x00ffff00, "Got unexpected color 0x%08x.\n", color);
3892 hr = IDirect3DDevice9_BeginScene(device);
3893 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
3894 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
3895 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
3896 hr = IDirect3DDevice9_EndScene(device);
3897 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
3898 color = get_pixel_color(device, 1, 1);
3899 ok(color == 0x0000ff00, "Got unexpected color 0x%08x.\n", color);
3900 color = get_pixel_color(device, 700, 500);
3901 ok(color == 0x0000ff00, "Got unexpected color 0x%08x.\n", color);
3903 IDirect3DSurface9_Release(backbuffer);
3904 refcount = IDirect3DDevice9_Release(device);
3905 ok(!refcount, "Device has %lu references left.\n", refcount);
3906 DestroyWindow(window);
3909 static void test_format_unknown(void)
3911 IDirect3DDevice9Ex *device;
3912 ULONG refcount;
3913 HWND window;
3914 void *iface;
3915 HRESULT hr;
3917 window = create_window();
3918 if (!(device = create_device(window, NULL)))
3920 skip("Failed to create a D3D device.\n");
3921 DestroyWindow(window);
3922 return;
3925 iface = (void *)0xdeadbeef;
3926 hr = IDirect3DDevice9Ex_CreateRenderTarget(device, 64, 64,
3927 D3DFMT_UNKNOWN, D3DMULTISAMPLE_NONE, 0, FALSE, (IDirect3DSurface9 **)&iface, NULL);
3928 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
3929 ok(!iface, "Got unexpected iface %p.\n", iface);
3931 iface = (void *)0xdeadbeef;
3932 hr = IDirect3DDevice9Ex_CreateRenderTargetEx(device, 64, 64,
3933 D3DFMT_UNKNOWN, D3DMULTISAMPLE_NONE, 0, FALSE, (IDirect3DSurface9 **)&iface, NULL, 0);
3934 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
3935 ok(!iface, "Got unexpected iface %p.\n", iface);
3937 iface = (void *)0xdeadbeef;
3938 hr = IDirect3DDevice9Ex_CreateDepthStencilSurface(device, 64, 64,
3939 D3DFMT_UNKNOWN, D3DMULTISAMPLE_NONE, 0, TRUE, (IDirect3DSurface9 **)&iface, NULL);
3940 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
3941 ok(!iface, "Got unexpected iface %p.\n", iface);
3943 iface = (void *)0xdeadbeef;
3944 hr = IDirect3DDevice9Ex_CreateDepthStencilSurfaceEx(device, 64, 64,
3945 D3DFMT_UNKNOWN, D3DMULTISAMPLE_NONE, 0, TRUE, (IDirect3DSurface9 **)&iface, NULL, 0);
3946 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
3947 ok(!iface, "Got unexpected iface %p.\n", iface);
3949 iface = (void *)0xdeadbeef;
3950 hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurface(device, 64, 64,
3951 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DSurface9 **)&iface, NULL);
3952 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
3953 ok(!iface, "Got unexpected iface %p.\n", iface);
3955 iface = (void *)0xdeadbeef;
3956 hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurfaceEx(device, 64, 64,
3957 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DSurface9 **)&iface, NULL, 9);
3958 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
3959 todo_wine ok(!iface, "Got unexpected iface %p.\n", iface);
3961 iface = (void *)0xdeadbeef;
3962 hr = IDirect3DDevice9Ex_CreateTexture(device, 64, 64, 1, 0,
3963 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DTexture9 **)&iface, NULL);
3964 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
3965 ok(!iface, "Got unexpected iface %p.\n", iface);
3967 iface = (void *)0xdeadbeef;
3968 hr = IDirect3DDevice9Ex_CreateCubeTexture(device, 64, 1, 0,
3969 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DCubeTexture9 **)&iface, NULL);
3970 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
3971 ok(!iface, "Got unexpected iface %p.\n", iface);
3973 iface = (void *)0xdeadbeef;
3974 hr = IDirect3DDevice9Ex_CreateVolumeTexture(device, 64, 64, 1, 1, 0,
3975 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DVolumeTexture9 **)&iface, NULL);
3976 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
3977 ok(!iface, "Got unexpected iface %p.\n", iface);
3979 refcount = IDirect3DDevice9Ex_Release(device);
3980 ok(!refcount, "Device has %lu references left.\n", refcount);
3981 DestroyWindow(window);
3984 static void test_device_caps(void)
3986 IDirect3DDevice9Ex *device;
3987 ULONG refcount;
3988 D3DCAPS9 caps;
3989 HWND window;
3990 HRESULT hr;
3992 window = create_window();
3993 if (!(device = create_device(window, NULL)))
3995 skip("Failed to create a D3D device.\n");
3996 DestroyWindow(window);
3997 return;
4000 hr = IDirect3DDevice9Ex_GetDeviceCaps(device, &caps);
4001 ok(SUCCEEDED(hr), "Failed to get caps, hr %#lx.\n", hr);
4003 ok(!(caps.Caps & ~(D3DCAPS_OVERLAY | D3DCAPS_READ_SCANLINE)),
4004 "Caps field has unexpected flags %#lx.\n", caps.Caps);
4005 ok(!(caps.Caps2 & ~(D3DCAPS2_FULLSCREENGAMMA | D3DCAPS2_CANCALIBRATEGAMMA | D3DCAPS2_RESERVED
4006 | D3DCAPS2_CANMANAGERESOURCE | D3DCAPS2_DYNAMICTEXTURES | D3DCAPS2_CANAUTOGENMIPMAP
4007 | D3DCAPS2_CANSHARERESOURCE)),
4008 "Caps2 field has unexpected flags %#lx.\n", caps.Caps2);
4009 /* AMD doesn't filter all the ddraw / d3d9 caps. Consider that behavior
4010 * broken. */
4011 ok(!(caps.Caps3 & ~(D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD
4012 | D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION | D3DCAPS3_COPY_TO_VIDMEM
4013 | D3DCAPS3_COPY_TO_SYSTEMMEM | D3DCAPS3_DXVAHD | D3DCAPS3_DXVAHD_LIMITED
4014 | D3DCAPS3_RESERVED)),
4015 "Caps3 field has unexpected flags %#lx.\n", caps.Caps3);
4016 ok(!(caps.PrimitiveMiscCaps & ~(D3DPMISCCAPS_MASKZ | D3DPMISCCAPS_LINEPATTERNREP
4017 | D3DPMISCCAPS_CULLNONE | D3DPMISCCAPS_CULLCW | D3DPMISCCAPS_CULLCCW
4018 | D3DPMISCCAPS_COLORWRITEENABLE | D3DPMISCCAPS_CLIPPLANESCALEDPOINTS
4019 | D3DPMISCCAPS_CLIPTLVERTS | D3DPMISCCAPS_TSSARGTEMP | D3DPMISCCAPS_BLENDOP
4020 | D3DPMISCCAPS_NULLREFERENCE | D3DPMISCCAPS_INDEPENDENTWRITEMASKS
4021 | D3DPMISCCAPS_PERSTAGECONSTANT | D3DPMISCCAPS_FOGANDSPECULARALPHA
4022 | D3DPMISCCAPS_SEPARATEALPHABLEND | D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
4023 | D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING | D3DPMISCCAPS_FOGVERTEXCLAMPED
4024 | D3DPMISCCAPS_POSTBLENDSRGBCONVERT)),
4025 "PrimitiveMiscCaps field has unexpected flags %#lx.\n", caps.PrimitiveMiscCaps);
4026 ok(!(caps.RasterCaps & ~(D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_ZTEST
4027 | D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_FOGTABLE
4028 | D3DPRASTERCAPS_MIPMAPLODBIAS | D3DPRASTERCAPS_ZBUFFERLESSHSR
4029 | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_ANISOTROPY | D3DPRASTERCAPS_WBUFFER
4030 | D3DPRASTERCAPS_WFOG | D3DPRASTERCAPS_ZFOG | D3DPRASTERCAPS_COLORPERSPECTIVE
4031 | D3DPRASTERCAPS_SCISSORTEST | D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS
4032 | D3DPRASTERCAPS_DEPTHBIAS | D3DPRASTERCAPS_MULTISAMPLE_TOGGLE))
4033 || broken(!(caps.RasterCaps & ~0x0f736191)),
4034 "RasterCaps field has unexpected flags %#lx.\n", caps.RasterCaps);
4035 /* D3DPBLENDCAPS_SRCCOLOR2 and D3DPBLENDCAPS_INVSRCCOLOR2 are only
4036 * advertised on the reference rasterizer and WARP. */
4037 ok(!(caps.SrcBlendCaps & ~(D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR
4038 | D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA
4039 | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_DESTCOLOR
4040 | D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT | D3DPBLENDCAPS_BOTHSRCALPHA
4041 | D3DPBLENDCAPS_BOTHINVSRCALPHA | D3DPBLENDCAPS_BLENDFACTOR))
4042 || broken(!(caps.SrcBlendCaps & ~(D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR
4043 | D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA
4044 | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_DESTCOLOR
4045 | D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT | D3DPBLENDCAPS_BOTHSRCALPHA
4046 | D3DPBLENDCAPS_BOTHINVSRCALPHA | D3DPBLENDCAPS_BLENDFACTOR
4047 | D3DPBLENDCAPS_SRCCOLOR2 | D3DPBLENDCAPS_INVSRCCOLOR2))),
4048 "SrcBlendCaps field has unexpected flags %#lx.\n", caps.SrcBlendCaps);
4049 ok(!(caps.DestBlendCaps & ~(D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR
4050 | D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA
4051 | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_DESTCOLOR
4052 | D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT | D3DPBLENDCAPS_BOTHSRCALPHA
4053 | D3DPBLENDCAPS_BOTHINVSRCALPHA | D3DPBLENDCAPS_BLENDFACTOR))
4054 || broken(!(caps.SrcBlendCaps & ~(D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR
4055 | D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA
4056 | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_DESTCOLOR
4057 | D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT | D3DPBLENDCAPS_BOTHSRCALPHA
4058 | D3DPBLENDCAPS_BOTHINVSRCALPHA | D3DPBLENDCAPS_BLENDFACTOR
4059 | D3DPBLENDCAPS_SRCCOLOR2 | D3DPBLENDCAPS_INVSRCCOLOR2))),
4060 "DestBlendCaps field has unexpected flags %#lx.\n", caps.DestBlendCaps);
4061 ok(!(caps.TextureCaps & ~(D3DPTEXTURECAPS_PERSPECTIVE | D3DPTEXTURECAPS_POW2
4062 | D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_SQUAREONLY
4063 | D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE | D3DPTEXTURECAPS_ALPHAPALETTE
4064 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PROJECTED
4065 | D3DPTEXTURECAPS_CUBEMAP | D3DPTEXTURECAPS_VOLUMEMAP | D3DPTEXTURECAPS_MIPMAP
4066 | D3DPTEXTURECAPS_MIPVOLUMEMAP | D3DPTEXTURECAPS_MIPCUBEMAP
4067 | D3DPTEXTURECAPS_CUBEMAP_POW2 | D3DPTEXTURECAPS_VOLUMEMAP_POW2
4068 | D3DPTEXTURECAPS_NOPROJECTEDBUMPENV)),
4069 "TextureCaps field has unexpected flags %#lx.\n", caps.TextureCaps);
4070 ok(!(caps.TextureFilterCaps & ~(D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MINFLINEAR
4071 | D3DPTFILTERCAPS_MINFANISOTROPIC | D3DPTFILTERCAPS_MINFPYRAMIDALQUAD
4072 | D3DPTFILTERCAPS_MINFGAUSSIANQUAD | D3DPTFILTERCAPS_MIPFPOINT
4073 | D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_CONVOLUTIONMONO
4074 | D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MAGFLINEAR
4075 | D3DPTFILTERCAPS_MAGFANISOTROPIC | D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD
4076 | D3DPTFILTERCAPS_MAGFGAUSSIANQUAD)),
4077 "TextureFilterCaps field has unexpected flags %#lx.\n", caps.TextureFilterCaps);
4078 ok(!(caps.CubeTextureFilterCaps & ~(D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MINFLINEAR
4079 | D3DPTFILTERCAPS_MINFANISOTROPIC | D3DPTFILTERCAPS_MINFPYRAMIDALQUAD
4080 | D3DPTFILTERCAPS_MINFGAUSSIANQUAD | D3DPTFILTERCAPS_MIPFPOINT
4081 | D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MAGFLINEAR
4082 | D3DPTFILTERCAPS_MAGFANISOTROPIC | D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD
4083 | D3DPTFILTERCAPS_MAGFGAUSSIANQUAD)),
4084 "CubeTextureFilterCaps field has unexpected flags %#lx.\n", caps.CubeTextureFilterCaps);
4085 ok(!(caps.VolumeTextureFilterCaps & ~(D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MINFLINEAR
4086 | D3DPTFILTERCAPS_MINFANISOTROPIC | D3DPTFILTERCAPS_MINFPYRAMIDALQUAD
4087 | D3DPTFILTERCAPS_MINFGAUSSIANQUAD | D3DPTFILTERCAPS_MIPFPOINT
4088 | D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MAGFLINEAR
4089 | D3DPTFILTERCAPS_MAGFANISOTROPIC | D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD
4090 | D3DPTFILTERCAPS_MAGFGAUSSIANQUAD)),
4091 "VolumeTextureFilterCaps field has unexpected flags %#lx.\n", caps.VolumeTextureFilterCaps);
4092 ok(!(caps.LineCaps & ~(D3DLINECAPS_TEXTURE | D3DLINECAPS_ZTEST | D3DLINECAPS_BLEND
4093 | D3DLINECAPS_ALPHACMP | D3DLINECAPS_FOG | D3DLINECAPS_ANTIALIAS)),
4094 "LineCaps field has unexpected flags %#lx.\n", caps.LineCaps);
4095 ok(!(caps.StencilCaps & ~(D3DSTENCILCAPS_KEEP | D3DSTENCILCAPS_ZERO | D3DSTENCILCAPS_REPLACE
4096 | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INVERT
4097 | D3DSTENCILCAPS_INCR | D3DSTENCILCAPS_DECR | D3DSTENCILCAPS_TWOSIDED)),
4098 "StencilCaps field has unexpected flags %#lx.\n", caps.StencilCaps);
4099 ok(!(caps.VertexProcessingCaps & ~(D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7
4100 | D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER
4101 | D3DVTXPCAPS_TWEENING | D3DVTXPCAPS_TEXGEN_SPHEREMAP
4102 | D3DVTXPCAPS_NO_TEXGEN_NONLOCALVIEWER)),
4103 "VertexProcessingCaps field has unexpected flags %#lx.\n", caps.VertexProcessingCaps);
4104 /* Both Nvidia and AMD give 10 here. */
4105 ok(caps.MaxActiveLights <= 10,
4106 "MaxActiveLights field has unexpected value %lu.\n", caps.MaxActiveLights);
4107 /* AMD gives 6, Nvidia returns 8. */
4108 ok(caps.MaxUserClipPlanes <= 8,
4109 "MaxUserClipPlanes field has unexpected value %lu.\n", caps.MaxUserClipPlanes);
4111 refcount = IDirect3DDevice9Ex_Release(device);
4112 ok(!refcount, "Device has %lu references left.\n", refcount);
4113 DestroyWindow(window);
4116 static void test_frame_latency(void)
4118 IDirect3DDevice9Ex *device;
4119 ULONG refcount;
4120 UINT latency;
4121 HWND window;
4122 HRESULT hr;
4124 window = create_window();
4125 if (!(device = create_device(window, NULL)))
4127 skip("Failed to create a D3D device.\n");
4128 DestroyWindow(window);
4129 return;
4132 hr = IDirect3DDevice9Ex_GetMaximumFrameLatency(device, &latency);
4133 ok(SUCCEEDED(hr), "Failed to get max frame latency, hr %#lx.\n", hr);
4134 ok(latency == 3, "Unexpected default max frame latency %u.\n", latency);
4136 hr = IDirect3DDevice9Ex_SetMaximumFrameLatency(device, 1);
4137 ok(SUCCEEDED(hr), "Failed to set max frame latency, hr %#lx.\n", hr);
4139 hr = IDirect3DDevice9Ex_GetMaximumFrameLatency(device, &latency);
4140 ok(SUCCEEDED(hr), "Failed to get max frame latency, hr %#lx.\n", hr);
4141 ok(latency == 1, "Unexpected max frame latency %u.\n", latency);
4143 hr = IDirect3DDevice9Ex_SetMaximumFrameLatency(device, 0);
4144 ok(SUCCEEDED(hr), "Failed to set max frame latency, hr %#lx.\n", hr);
4146 hr = IDirect3DDevice9Ex_GetMaximumFrameLatency(device, &latency);
4147 ok(SUCCEEDED(hr), "Failed to get max frame latency, hr %#lx.\n", hr);
4148 ok(latency == 3 || !latency, "Unexpected default max frame latency %u.\n", latency);
4150 hr = IDirect3DDevice9Ex_SetMaximumFrameLatency(device, 30);
4151 ok(SUCCEEDED(hr), "Failed to set max frame latency, hr %#lx.\n", hr);
4153 hr = IDirect3DDevice9Ex_SetMaximumFrameLatency(device, 31);
4154 ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#lx.\n", hr);
4156 refcount = IDirect3DDevice9Ex_Release(device);
4157 ok(!refcount, "Device has %lu references left.\n", refcount);
4158 DestroyWindow(window);
4161 static void test_resource_access(void)
4163 IDirect3DSurface9 *backbuffer, *depth_stencil;
4164 D3DFORMAT colour_format, depth_format, format;
4165 BOOL depth_2d, depth_cube, depth_plain;
4166 D3DADAPTER_IDENTIFIER9 identifier;
4167 struct device_desc device_desc;
4168 D3DSURFACE_DESC surface_desc;
4169 IDirect3DDevice9Ex *device;
4170 unsigned int i, j;
4171 IDirect3D9 *d3d;
4172 ULONG refcount;
4173 HWND window;
4174 HRESULT hr;
4175 BOOL warp;
4177 enum surface_type
4179 SURFACE_2D,
4180 SURFACE_CUBE,
4181 SURFACE_RT,
4182 SURFACE_RT_EX,
4183 SURFACE_DS,
4184 SURFACE_DS_EX,
4185 SURFACE_PLAIN,
4186 SURFACE_PLAIN_EX,
4189 enum resource_format
4191 FORMAT_COLOUR,
4192 FORMAT_ATI2,
4193 FORMAT_DEPTH,
4196 static const struct
4198 D3DPOOL pool;
4199 enum resource_format format;
4200 DWORD usage;
4201 BOOL valid;
4203 tests[] =
4205 /* 0 */
4206 {D3DPOOL_DEFAULT, FORMAT_COLOUR, 0, TRUE},
4207 {D3DPOOL_DEFAULT, FORMAT_ATI2, 0, TRUE},
4208 {D3DPOOL_DEFAULT, FORMAT_DEPTH, 0, TRUE},
4209 {D3DPOOL_DEFAULT, FORMAT_COLOUR, D3DUSAGE_RENDERTARGET, TRUE},
4210 {D3DPOOL_DEFAULT, FORMAT_DEPTH, D3DUSAGE_RENDERTARGET, FALSE},
4211 {D3DPOOL_DEFAULT, FORMAT_COLOUR, D3DUSAGE_DEPTHSTENCIL, FALSE},
4212 {D3DPOOL_DEFAULT, FORMAT_DEPTH, D3DUSAGE_DEPTHSTENCIL, TRUE},
4213 /* 7 */
4214 {D3DPOOL_DEFAULT, FORMAT_COLOUR, D3DUSAGE_DYNAMIC, TRUE},
4215 {D3DPOOL_DEFAULT, FORMAT_ATI2, D3DUSAGE_DYNAMIC, TRUE},
4216 {D3DPOOL_DEFAULT, FORMAT_DEPTH, D3DUSAGE_DYNAMIC, TRUE},
4217 {D3DPOOL_DEFAULT, FORMAT_COLOUR, D3DUSAGE_DYNAMIC | D3DUSAGE_RENDERTARGET, FALSE},
4218 {D3DPOOL_DEFAULT, FORMAT_DEPTH, D3DUSAGE_DYNAMIC | D3DUSAGE_RENDERTARGET, FALSE},
4219 {D3DPOOL_DEFAULT, FORMAT_COLOUR, D3DUSAGE_DYNAMIC | D3DUSAGE_DEPTHSTENCIL, FALSE},
4220 {D3DPOOL_DEFAULT, FORMAT_DEPTH, D3DUSAGE_DYNAMIC | D3DUSAGE_DEPTHSTENCIL, FALSE},
4221 /* 14 */
4222 {D3DPOOL_MANAGED, FORMAT_COLOUR, 0, FALSE},
4223 {D3DPOOL_MANAGED, FORMAT_ATI2, 0, FALSE},
4224 {D3DPOOL_MANAGED, FORMAT_DEPTH, 0, FALSE},
4225 {D3DPOOL_MANAGED, FORMAT_COLOUR, D3DUSAGE_RENDERTARGET, FALSE},
4226 {D3DPOOL_MANAGED, FORMAT_DEPTH, D3DUSAGE_RENDERTARGET, FALSE},
4227 {D3DPOOL_MANAGED, FORMAT_COLOUR, D3DUSAGE_DEPTHSTENCIL, FALSE},
4228 {D3DPOOL_MANAGED, FORMAT_DEPTH, D3DUSAGE_DEPTHSTENCIL, FALSE},
4229 /* 21 */
4230 {D3DPOOL_SYSTEMMEM, FORMAT_COLOUR, 0, TRUE},
4231 {D3DPOOL_SYSTEMMEM, FORMAT_ATI2, 0, TRUE},
4232 {D3DPOOL_SYSTEMMEM, FORMAT_DEPTH, 0, FALSE},
4233 {D3DPOOL_SYSTEMMEM, FORMAT_COLOUR, D3DUSAGE_RENDERTARGET, FALSE},
4234 {D3DPOOL_SYSTEMMEM, FORMAT_DEPTH, D3DUSAGE_RENDERTARGET, FALSE},
4235 {D3DPOOL_SYSTEMMEM, FORMAT_COLOUR, D3DUSAGE_DEPTHSTENCIL, FALSE},
4236 {D3DPOOL_SYSTEMMEM, FORMAT_DEPTH, D3DUSAGE_DEPTHSTENCIL, FALSE},
4237 /* 28 */
4238 {D3DPOOL_SCRATCH, FORMAT_COLOUR, 0, TRUE},
4239 {D3DPOOL_SCRATCH, FORMAT_ATI2, 0, TRUE},
4240 {D3DPOOL_SCRATCH, FORMAT_DEPTH, 0, FALSE},
4241 {D3DPOOL_SCRATCH, FORMAT_COLOUR, D3DUSAGE_RENDERTARGET, FALSE},
4242 {D3DPOOL_SCRATCH, FORMAT_DEPTH, D3DUSAGE_RENDERTARGET, FALSE},
4243 {D3DPOOL_SCRATCH, FORMAT_COLOUR, D3DUSAGE_DEPTHSTENCIL, FALSE},
4244 {D3DPOOL_SCRATCH, FORMAT_DEPTH, D3DUSAGE_DEPTHSTENCIL, FALSE},
4246 static const struct
4248 const char *name;
4249 enum surface_type type;
4251 surface_types[] =
4253 {"2D", SURFACE_2D},
4254 {"CUBE", SURFACE_CUBE},
4255 {"RT", SURFACE_RT},
4256 {"RT_EX", SURFACE_RT_EX},
4257 {"DS", SURFACE_DS},
4258 {"DS_EX", SURFACE_DS_EX},
4259 {"PLAIN", SURFACE_PLAIN},
4260 {"PLAIN_EX", SURFACE_PLAIN_EX},
4263 window = create_window();
4264 device_desc.device_window = window;
4265 device_desc.width = 16;
4266 device_desc.height = 16;
4267 device_desc.flags = 0;
4268 if (!(device = create_device(window, &device_desc)))
4270 skip("Failed to create a D3D device.\n");
4271 DestroyWindow(window);
4272 return;
4274 hr = IDirect3DDevice9Ex_GetDirect3D(device, &d3d);
4275 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4276 hr = IDirect3D9_GetAdapterIdentifier(d3d, D3DADAPTER_DEFAULT, 0, &identifier);
4277 ok(SUCCEEDED(hr), "Failed to get adapter identifier, hr %#lx.\n", hr);
4278 warp = adapter_is_warp(&identifier);
4280 hr = IDirect3DDevice9Ex_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
4281 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4282 hr = IDirect3DSurface9_GetDesc(backbuffer, &surface_desc);
4283 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4284 colour_format = surface_desc.Format;
4286 hr = IDirect3DDevice9Ex_GetDepthStencilSurface(device, &depth_stencil);
4287 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4288 hr = IDirect3DSurface9_GetDesc(depth_stencil, &surface_desc);
4289 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4290 depth_format = surface_desc.Format;
4292 depth_2d = SUCCEEDED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
4293 D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, depth_format));
4294 depth_cube = SUCCEEDED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
4295 D3DFMT_X8R8G8B8, 0, D3DRTYPE_CUBETEXTURE, depth_format));
4296 depth_plain = SUCCEEDED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
4297 D3DFMT_X8R8G8B8, 0, D3DRTYPE_SURFACE, depth_format));
4299 hr = IDirect3DDevice9Ex_SetFVF(device, D3DFVF_XYZRHW);
4300 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4302 for (i = 0; i < ARRAY_SIZE(surface_types); ++i)
4304 for (j = 0; j < ARRAY_SIZE(tests); ++j)
4306 IDirect3DCubeTexture9 *texture_cube;
4307 IDirect3DBaseTexture9 *texture;
4308 IDirect3DTexture9 *texture_2d;
4309 IDirect3DSurface9 *surface;
4310 HRESULT expected_hr;
4311 D3DLOCKED_RECT lr;
4313 if (tests[j].format == FORMAT_ATI2)
4314 format = MAKEFOURCC('A','T','I','2');
4315 else if (tests[j].format == FORMAT_DEPTH)
4316 format = depth_format;
4317 else
4318 format = colour_format;
4320 if (tests[j].format == FORMAT_ATI2 && FAILED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT,
4321 D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, format)))
4323 skip("ATI2N texture not supported.\n");
4324 continue;
4327 switch (surface_types[i].type)
4329 case SURFACE_2D:
4330 hr = IDirect3DDevice9Ex_CreateTexture(device, 16, 16, 1,
4331 tests[j].usage, format, tests[j].pool, &texture_2d, NULL);
4332 todo_wine_if(!tests[j].valid && tests[j].format == FORMAT_DEPTH
4333 && !tests[j].usage && tests[j].pool != D3DPOOL_MANAGED)
4334 ok(hr == (tests[j].valid && (tests[j].format != FORMAT_DEPTH || depth_2d)
4335 ? D3D_OK : D3DERR_INVALIDCALL),
4336 "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
4337 if (FAILED(hr))
4338 continue;
4340 hr = IDirect3DTexture9_GetSurfaceLevel(texture_2d, 0, &surface);
4341 ok(hr == D3D_OK, "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
4342 IDirect3DTexture9_Release(texture_2d);
4343 break;
4345 case SURFACE_CUBE:
4346 hr = IDirect3DDevice9Ex_CreateCubeTexture(device, 16, 1,
4347 tests[j].usage, format, tests[j].pool, &texture_cube, NULL);
4348 todo_wine_if(!tests[j].valid && tests[j].format == FORMAT_DEPTH
4349 && !tests[j].usage && tests[j].pool != D3DPOOL_MANAGED)
4350 ok(hr == (tests[j].valid && (tests[j].format != FORMAT_DEPTH || depth_cube)
4351 ? D3D_OK : D3DERR_INVALIDCALL),
4352 "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
4353 if (FAILED(hr))
4354 continue;
4356 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture_cube,
4357 D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
4358 ok(hr == D3D_OK, "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
4359 IDirect3DCubeTexture9_Release(texture_cube);
4360 break;
4362 case SURFACE_RT:
4363 hr = IDirect3DDevice9Ex_CreateRenderTarget(device, 16, 16, format,
4364 D3DMULTISAMPLE_NONE, 0, tests[j].usage & D3DUSAGE_DYNAMIC, &surface, NULL);
4365 ok(hr == (tests[j].format == FORMAT_COLOUR ? D3D_OK : D3DERR_INVALIDCALL),
4366 "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
4367 if (FAILED(hr))
4368 continue;
4369 break;
4371 case SURFACE_RT_EX:
4372 hr = IDirect3DDevice9Ex_CreateRenderTargetEx(device, 16, 16, format, D3DMULTISAMPLE_NONE,
4373 0, tests[j].pool != D3DPOOL_DEFAULT, &surface, NULL, tests[j].usage);
4374 ok(hr == (tests[j].format == FORMAT_COLOUR && !tests[j].usage ? D3D_OK : D3DERR_INVALIDCALL),
4375 "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
4376 if (FAILED(hr))
4377 continue;
4378 break;
4380 case SURFACE_DS:
4381 hr = IDirect3DDevice9Ex_CreateDepthStencilSurface(device, 16, 16, format,
4382 D3DMULTISAMPLE_NONE, 0, tests[j].usage & D3DUSAGE_DYNAMIC, &surface, NULL);
4383 ok(hr == (tests[j].format == FORMAT_DEPTH ? D3D_OK : D3DERR_INVALIDCALL),
4384 "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
4385 if (FAILED(hr))
4386 continue;
4387 break;
4389 case SURFACE_DS_EX:
4390 hr = IDirect3DDevice9Ex_CreateDepthStencilSurfaceEx(device, 16, 16, format, D3DMULTISAMPLE_NONE,
4391 0, tests[j].pool != D3DPOOL_DEFAULT, &surface, NULL, tests[j].usage);
4392 ok(hr == (tests[j].format == FORMAT_DEPTH && !tests[j].usage ? D3D_OK : D3DERR_INVALIDCALL),
4393 "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
4394 if (FAILED(hr))
4395 continue;
4396 break;
4398 case SURFACE_PLAIN:
4399 hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurface(device,
4400 16, 16, format, tests[j].pool, &surface, NULL);
4401 todo_wine_if(tests[j].format == FORMAT_ATI2 && tests[j].pool != D3DPOOL_MANAGED
4402 && tests[j].pool != D3DPOOL_SCRATCH)
4403 ok(hr == (tests[j].pool != D3DPOOL_MANAGED && (tests[j].format != FORMAT_DEPTH || depth_plain)
4404 && (tests[j].format != FORMAT_ATI2 || tests[j].pool == D3DPOOL_SCRATCH)
4405 ? D3D_OK : D3DERR_INVALIDCALL),
4406 "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
4407 if (FAILED(hr))
4408 continue;
4409 break;
4411 case SURFACE_PLAIN_EX:
4412 hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurfaceEx(device,
4413 16, 16, format, tests[j].pool, &surface, NULL, tests[j].usage);
4414 todo_wine
4415 ok(hr == (!tests[j].usage && tests[j].pool != D3DPOOL_MANAGED
4416 && (tests[j].format != FORMAT_DEPTH || depth_plain)
4417 && (tests[j].format != FORMAT_ATI2 || tests[j].pool == D3DPOOL_SCRATCH)
4418 ? D3D_OK : D3DERR_INVALIDCALL),
4419 "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
4420 if (FAILED(hr))
4421 continue;
4422 break;
4424 default:
4425 ok(0, "Invalid surface type %#x.\n", surface_types[i].type);
4426 continue;
4429 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
4430 ok(hr == D3D_OK, "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
4431 if (surface_types[i].type == SURFACE_RT || surface_types[i].type == SURFACE_RT_EX)
4433 ok(surface_desc.Usage == D3DUSAGE_RENDERTARGET, "Test %s %u: Got unexpected usage %#lx.\n",
4434 surface_types[i].name, j, surface_desc.Usage);
4435 ok(surface_desc.Pool == D3DPOOL_DEFAULT, "Test %s %u: Got unexpected pool %#x.\n",
4436 surface_types[i].name, j, surface_desc.Pool);
4438 else if (surface_types[i].type == SURFACE_DS || surface_types[i].type == SURFACE_DS_EX)
4440 ok(surface_desc.Usage == D3DUSAGE_DEPTHSTENCIL, "Test %s %u: Got unexpected usage %#lx.\n",
4441 surface_types[i].name, j, surface_desc.Usage);
4442 ok(surface_desc.Pool == D3DPOOL_DEFAULT, "Test %s %u: Got unexpected pool %#x.\n",
4443 surface_types[i].name, j, surface_desc.Pool);
4445 else if (surface_types[i].type == SURFACE_PLAIN || surface_types[i].type == SURFACE_PLAIN_EX)
4447 ok(!surface_desc.Usage, "Test %s %u: Got unexpected usage %#lx.\n",
4448 surface_types[i].name, j, surface_desc.Usage);
4449 ok(surface_desc.Pool == tests[j].pool, "Test %s %u: Got unexpected pool %#x.\n",
4450 surface_types[i].name, j, surface_desc.Pool);
4452 else
4454 ok(surface_desc.Usage == tests[j].usage, "Test %s %u: Got unexpected usage %#lx.\n",
4455 surface_types[i].name, j, surface_desc.Usage);
4456 ok(surface_desc.Pool == tests[j].pool, "Test %s %u: Got unexpected pool %#x.\n",
4457 surface_types[i].name, j, surface_desc.Pool);
4460 hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
4461 if (surface_desc.Pool != D3DPOOL_DEFAULT || surface_desc.Usage & D3DUSAGE_DYNAMIC
4462 || (surface_types[i].type == SURFACE_RT && tests[j].usage & D3DUSAGE_DYNAMIC)
4463 || (surface_types[i].type == SURFACE_RT_EX && tests[j].pool != D3DPOOL_DEFAULT)
4464 || surface_types[i].type == SURFACE_PLAIN || surface_types[i].type == SURFACE_PLAIN_EX
4465 || tests[j].format == FORMAT_ATI2)
4466 expected_hr = D3D_OK;
4467 else
4468 expected_hr = D3DERR_INVALIDCALL;
4469 ok(hr == expected_hr, "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
4470 hr = IDirect3DSurface9_UnlockRect(surface);
4471 todo_wine_if(expected_hr != D3D_OK && surface_types[i].type == SURFACE_2D)
4472 ok(hr == expected_hr, "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
4474 if (SUCCEEDED(IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DBaseTexture9, (void **)&texture)))
4476 hr = IDirect3DDevice9Ex_SetTexture(device, 0, texture);
4477 ok(hr == D3D_OK, "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
4478 hr = IDirect3DDevice9Ex_SetTexture(device, 0, NULL);
4479 ok(hr == D3D_OK, "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
4480 IDirect3DBaseTexture9_Release(texture);
4483 hr = IDirect3DDevice9Ex_SetRenderTarget(device, 0, surface);
4484 ok(hr == (surface_desc.Usage & D3DUSAGE_RENDERTARGET ? D3D_OK : D3DERR_INVALIDCALL),
4485 "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
4486 hr = IDirect3DDevice9Ex_SetRenderTarget(device, 0, backbuffer);
4487 ok(hr == D3D_OK, "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
4489 hr = IDirect3DDevice9Ex_SetDepthStencilSurface(device, surface);
4490 ok(hr == (surface_desc.Usage & D3DUSAGE_DEPTHSTENCIL ? D3D_OK : D3DERR_INVALIDCALL),
4491 "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
4492 hr = IDirect3DDevice9Ex_SetDepthStencilSurface(device, depth_stencil);
4493 ok(hr == D3D_OK, "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
4495 IDirect3DSurface9_Release(surface);
4499 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4501 IDirect3DVolumeTexture9 *texture;
4502 D3DVOLUME_DESC volume_desc;
4503 IDirect3DVolume9 *volume;
4504 HRESULT expected_hr;
4505 D3DLOCKED_BOX lb;
4507 if (tests[i].format == FORMAT_DEPTH)
4508 continue;
4510 if (tests[i].format == FORMAT_ATI2)
4511 format = MAKEFOURCC('A','T','I','2');
4512 else
4513 format = colour_format;
4515 hr = IDirect3DDevice9Ex_CreateVolumeTexture(device, 16, 16, 1, 1,
4516 tests[i].usage, format, tests[i].pool, &texture, NULL);
4517 ok((hr == (!(tests[i].usage & ~D3DUSAGE_DYNAMIC)
4518 && (tests[i].format != FORMAT_ATI2 || tests[i].pool == D3DPOOL_SCRATCH)
4519 && tests[i].pool != D3DPOOL_MANAGED ? D3D_OK : D3DERR_INVALIDCALL))
4520 || (tests[i].format == FORMAT_ATI2 && (hr == D3D_OK || warp)),
4521 "Test %u: Got unexpected hr %#lx.\n", i, hr);
4522 if (FAILED(hr))
4523 continue;
4525 hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
4526 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
4528 hr = IDirect3DVolume9_GetDesc(volume, &volume_desc);
4529 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
4530 ok(volume_desc.Usage == tests[i].usage, "Test %u: Got unexpected usage %#lx.\n", i, volume_desc.Usage);
4531 ok(volume_desc.Pool == tests[i].pool, "Test %u: Got unexpected pool %#x.\n", i, volume_desc.Pool);
4533 hr = IDirect3DVolume9_LockBox(volume, &lb, NULL, 0);
4534 if (volume_desc.Pool != D3DPOOL_DEFAULT || volume_desc.Usage & D3DUSAGE_DYNAMIC)
4535 expected_hr = D3D_OK;
4536 else
4537 expected_hr = D3DERR_INVALIDCALL;
4538 ok(hr == expected_hr || (volume_desc.Pool == D3DPOOL_DEFAULT && hr == D3D_OK),
4539 "Test %u: Got unexpected hr %#lx.\n", i, hr);
4540 hr = IDirect3DVolume9_UnlockBox(volume);
4541 ok(hr == expected_hr || (volume_desc.Pool == D3DPOOL_DEFAULT && hr == D3D_OK),
4542 "Test %u: Got unexpected hr %#lx.\n", i, hr);
4544 hr = IDirect3DDevice9Ex_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
4545 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
4546 hr = IDirect3DDevice9Ex_SetTexture(device, 0, NULL);
4547 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
4549 IDirect3DVolume9_Release(volume);
4550 IDirect3DVolumeTexture9_Release(texture);
4553 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4555 D3DINDEXBUFFER_DESC ib_desc;
4556 IDirect3DIndexBuffer9 *ib;
4557 void *data;
4559 hr = IDirect3DDevice9Ex_CreateIndexBuffer(device, 16, tests[i].usage,
4560 tests[i].format == FORMAT_COLOUR ? D3DFMT_INDEX32 : D3DFMT_INDEX16, tests[i].pool, &ib, NULL);
4561 ok(hr == (tests[i].pool == D3DPOOL_SCRATCH || tests[i].pool == D3DPOOL_MANAGED
4562 || (tests[i].usage & ~D3DUSAGE_DYNAMIC) ? D3DERR_INVALIDCALL : D3D_OK),
4563 "Test %u: Got unexpected hr %#lx.\n", i, hr);
4564 if (FAILED(hr))
4565 continue;
4567 hr = IDirect3DIndexBuffer9_GetDesc(ib, &ib_desc);
4568 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
4569 ok(ib_desc.Usage == tests[i].usage, "Test %u: Got unexpected usage %#lx.\n", i, ib_desc.Usage);
4570 ok(ib_desc.Pool == tests[i].pool, "Test %u: Got unexpected pool %#x.\n", i, ib_desc.Pool);
4572 hr = IDirect3DIndexBuffer9_Lock(ib, 0, 0, &data, 0);
4573 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
4574 hr = IDirect3DIndexBuffer9_Unlock(ib);
4575 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
4577 hr = IDirect3DDevice9Ex_SetIndices(device, ib);
4578 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
4579 hr = IDirect3DDevice9Ex_SetIndices(device, NULL);
4580 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
4582 IDirect3DIndexBuffer9_Release(ib);
4585 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4587 D3DVERTEXBUFFER_DESC vb_desc;
4588 IDirect3DVertexBuffer9 *vb;
4589 void *data;
4591 hr = IDirect3DDevice9Ex_CreateVertexBuffer(device, 16, tests[i].usage,
4592 tests[i].format == FORMAT_COLOUR ? 0 : D3DFVF_XYZRHW, tests[i].pool, &vb, NULL);
4593 ok(hr == (tests[i].pool == D3DPOOL_SCRATCH || tests[i].pool == D3DPOOL_MANAGED
4594 || (tests[i].usage & ~D3DUSAGE_DYNAMIC) ? D3DERR_INVALIDCALL : D3D_OK),
4595 "Test %u: Got unexpected hr %#lx.\n", i, hr);
4596 if (FAILED(hr))
4597 continue;
4599 hr = IDirect3DVertexBuffer9_GetDesc(vb, &vb_desc);
4600 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
4601 ok(vb_desc.Usage == tests[i].usage, "Test %u: Got unexpected usage %#lx.\n", i, vb_desc.Usage);
4602 ok(vb_desc.Pool == tests[i].pool, "Test %u: Got unexpected pool %#x.\n", i, vb_desc.Pool);
4604 hr = IDirect3DVertexBuffer9_Lock(vb, 0, 0, &data, 0);
4605 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
4606 hr = IDirect3DVertexBuffer9_Unlock(vb);
4607 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
4609 hr = IDirect3DDevice9Ex_SetStreamSource(device, 0, vb, 0, 16);
4610 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
4611 hr = IDirect3DDevice9Ex_SetStreamSource(device, 0, NULL, 0, 0);
4612 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
4614 IDirect3DVertexBuffer9_Release(vb);
4617 IDirect3DSurface9_Release(depth_stencil);
4618 IDirect3DSurface9_Release(backbuffer);
4619 refcount = IDirect3DDevice9Ex_Release(device);
4620 ok(!refcount, "Device has %lu references left.\n", refcount);
4621 IDirect3D9_Release(d3d);
4622 DestroyWindow(window);
4625 static void test_sysmem_draw(void)
4627 static const DWORD texture_data[4] = {0xffff0000, 0xff00ff00, 0xff0000ff, 0xffffffff};
4628 static const D3DVERTEXELEMENT9 decl_elements[] =
4630 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4631 {1, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4632 D3DDECL_END()
4634 static const short indices[] = {0, 1, 2, 3};
4635 static const struct
4637 struct vec3
4639 float x, y, z;
4640 } position;
4641 DWORD diffuse;
4643 quad[] =
4645 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
4646 {{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
4647 {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
4648 {{ 1.0f, 1.0f, 0.0f}, 0xffffffff},
4650 static const struct vec3 quad_s0[] =
4652 {-1.0f, -1.0f, 0.0f},
4653 {-1.0f, 1.0f, 0.0f},
4654 { 1.0f, -1.0f, 0.0f},
4655 { 1.0f, 1.0f, 0.0f},
4657 static const DWORD quad_s1[] =
4659 0xffff0000,
4660 0xff00ff00,
4661 0xff0000ff,
4662 0xffffffff,
4664 IDirect3DVertexDeclaration9 *vertex_declaration;
4665 IDirect3DVertexBuffer9 *vb, *vb_s0, *vb_s1;
4666 IDirect3DTexture9 *texture;
4667 IDirect3DDevice9Ex *device;
4668 IDirect3DIndexBuffer9 *ib;
4669 unsigned int colour;
4670 D3DLOCKED_RECT lr;
4671 ULONG refcount;
4672 HWND window;
4673 HRESULT hr;
4674 BYTE *data;
4676 window = create_window();
4677 if (!(device = create_device(window, NULL)))
4679 skip("Failed to create a D3D device.\n");
4680 DestroyWindow(window);
4681 return;
4684 hr = IDirect3DDevice9Ex_SetRenderState(device, D3DRS_LIGHTING, FALSE);
4685 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4687 hr = IDirect3DDevice9Ex_CreateVertexBuffer(device, sizeof(quad), 0, 0, D3DPOOL_SYSTEMMEM, &vb, NULL);
4688 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4689 hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad), (void **)&data, 0);
4690 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4691 memcpy(data, quad, sizeof(quad));
4692 hr = IDirect3DVertexBuffer9_Unlock(vb);
4693 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4695 hr = IDirect3DDevice9Ex_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x77777777, 0.0f, 0);
4696 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4698 hr = IDirect3DDevice9Ex_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
4699 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4700 hr = IDirect3DDevice9Ex_SetStreamSource(device, 0, vb, 0, sizeof(*quad));
4701 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4703 hr = IDirect3DDevice9Ex_BeginScene(device);
4704 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4705 hr = IDirect3DDevice9Ex_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
4706 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4707 hr = IDirect3DDevice9Ex_EndScene(device);
4708 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4710 colour = get_pixel_color(device, 320, 240);
4711 ok(color_match(colour, 0x00007f7f, 1), "Got unexpected colour 0x%08x.\n", colour);
4713 hr = IDirect3DDevice9Ex_CreateIndexBuffer(device, sizeof(indices), 0,
4714 D3DFMT_INDEX16, D3DPOOL_SYSTEMMEM, &ib, NULL);
4715 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4716 hr = IDirect3DIndexBuffer9_Lock(ib, 0, sizeof(indices), (void **)&data, 0);
4717 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4718 memcpy(data, indices, sizeof(indices));
4719 hr = IDirect3DIndexBuffer9_Unlock(ib);
4720 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4722 hr = IDirect3DDevice9Ex_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x77777777, 0.0f, 0);
4723 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4725 hr = IDirect3DDevice9Ex_SetIndices(device, ib);
4726 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4728 hr = IDirect3DDevice9Ex_BeginScene(device);
4729 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4730 hr = IDirect3DDevice9Ex_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 0, 4, 0, 2);
4731 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4732 hr = IDirect3DDevice9Ex_EndScene(device);
4733 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4735 colour = get_pixel_color(device, 320, 240);
4736 ok(color_match(colour, 0x00007f7f, 1), "Got unexpected colour 0x%08x.\n", colour);
4738 hr = IDirect3DDevice9Ex_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
4739 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4740 hr = IDirect3DDevice9Ex_SetVertexDeclaration(device, vertex_declaration);
4741 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4743 hr = IDirect3DDevice9Ex_CreateVertexBuffer(device, sizeof(quad_s0), 0, 0, D3DPOOL_SYSTEMMEM, &vb_s0, NULL);
4744 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4745 hr = IDirect3DVertexBuffer9_Lock(vb_s0, 0, sizeof(quad_s0), (void **)&data, 0);
4746 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4747 memcpy(data, quad_s0, sizeof(quad_s0));
4748 hr = IDirect3DVertexBuffer9_Unlock(vb_s0);
4749 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4750 hr = IDirect3DDevice9Ex_CreateVertexBuffer(device, sizeof(quad_s1), 0, 0, D3DPOOL_SYSTEMMEM, &vb_s1, NULL);
4751 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4752 hr = IDirect3DVertexBuffer9_Lock(vb_s1, 0, sizeof(quad_s1), (void **)&data, 0);
4753 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4754 memcpy(data, quad_s1, sizeof(quad_s1));
4755 hr = IDirect3DVertexBuffer9_Unlock(vb_s1);
4756 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4758 hr = IDirect3DDevice9Ex_SetStreamSource(device, 0, vb_s0, 0, sizeof(*quad_s0));
4759 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4760 hr = IDirect3DDevice9Ex_SetStreamSource(device, 1, vb_s1, 0, sizeof(*quad_s1));
4761 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4763 hr = IDirect3DDevice9Ex_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x77777777, 0.0f, 0);
4764 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4766 hr = IDirect3DDevice9Ex_BeginScene(device);
4767 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4768 hr = IDirect3DDevice9Ex_DrawIndexedPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 0, 4, 0, 2);
4769 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4770 hr = IDirect3DDevice9Ex_EndScene(device);
4771 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4773 colour = get_pixel_color(device, 320, 240);
4774 ok(color_match(colour, 0x00007f7f, 1), "Got unexpected colour 0x%08x.\n", colour);
4776 hr = IDirect3DDevice9Ex_CreateTexture(device, 2, 2, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
4777 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4778 memset(&lr, 0, sizeof(lr));
4779 hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
4780 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4781 memcpy(lr.pBits, texture_data, sizeof(texture_data));
4782 hr = IDirect3DTexture9_UnlockRect(texture, 0);
4783 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4785 hr = IDirect3DDevice9Ex_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
4786 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4788 hr = IDirect3DDevice9Ex_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x77777777, 0.0f, 0);
4789 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4791 hr = IDirect3DDevice9Ex_SetFVF(device, D3DFVF_XYZ);
4792 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4794 hr = IDirect3DDevice9Ex_BeginScene(device);
4795 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4796 hr = IDirect3DDevice9Ex_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
4797 ok(hr == D3D_OK || hr == E_FAIL, "Got unexpected hr %#lx.\n", hr);
4798 hr = IDirect3DDevice9Ex_EndScene(device);
4799 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4801 hr = IDirect3DDevice9Ex_Present(device, NULL, NULL, NULL, NULL);
4802 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4804 IDirect3DTexture9_Release(texture);
4805 IDirect3DVertexBuffer9_Release(vb_s1);
4806 IDirect3DVertexBuffer9_Release(vb_s0);
4807 IDirect3DVertexDeclaration9_Release(vertex_declaration);
4808 IDirect3DIndexBuffer9_Release(ib);
4809 IDirect3DVertexBuffer9_Release(vb);
4810 refcount = IDirect3DDevice9Ex_Release(device);
4811 ok(!refcount, "Device has %lu references left.\n", refcount);
4812 DestroyWindow(window);
4815 static void test_pinned_buffers(void)
4817 static const struct
4819 DWORD device_flags;
4820 DWORD usage;
4821 D3DPOOL pool;
4823 tests[] =
4825 {CREATE_DEVICE_SWVP_ONLY, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DPOOL_DEFAULT},
4826 {0, 0, D3DPOOL_SYSTEMMEM},
4828 static const unsigned int vertex_count = 1024;
4829 struct device_desc device_desc;
4830 IDirect3DVertexBuffer9 *buffer;
4831 IDirect3DDevice9Ex *device;
4832 D3DVERTEXBUFFER_DESC desc;
4833 unsigned int i, test;
4834 struct vec3
4836 float x, y, z;
4837 } *ptr, *ptr2;
4838 UINT refcount;
4839 HWND window;
4840 HRESULT hr;
4842 window = create_window();
4844 for (test = 0; test < ARRAY_SIZE(tests); ++test)
4846 device_desc.device_window = window;
4847 device_desc.width = 640;
4848 device_desc.height = 480;
4849 device_desc.flags = tests[test].device_flags;
4850 if (!(device = create_device(window, &device_desc)))
4852 skip("Test %u: failed to create a D3D device.\n", test);
4853 continue;
4856 hr = IDirect3DDevice9Ex_CreateVertexBuffer(device, vertex_count * sizeof(*ptr),
4857 tests[test].usage, 0, tests[test].pool, &buffer, NULL);
4858 ok(hr == D3D_OK, "Test %u: got unexpected hr %#lx.\n", test, hr);
4859 hr = IDirect3DVertexBuffer9_GetDesc(buffer, &desc);
4860 ok(hr == D3D_OK, "Test %u: got unexpected hr %#lx.\n", test, hr);
4861 ok(desc.Pool == tests[test].pool, "Test %u: got unexpected pool %#x.\n", test, desc.Pool);
4862 ok(desc.Usage == tests[test].usage, "Test %u: got unexpected usage %#lx.\n", test, desc.Usage);
4864 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, vertex_count * sizeof(*ptr), (void **)&ptr, D3DLOCK_DISCARD);
4865 ok(hr == D3D_OK, "Test %u: got unexpected hr %#lx.\n", test, hr);
4866 for (i = 0; i < vertex_count; ++i)
4868 ptr[i].x = i * 1.0f;
4869 ptr[i].y = i * 2.0f;
4870 ptr[i].z = i * 3.0f;
4872 hr = IDirect3DVertexBuffer9_Unlock(buffer);
4873 ok(hr == D3D_OK, "Test %u: got unexpected hr %#lx.\n", test, hr);
4875 hr = IDirect3DDevice9Ex_SetFVF(device, D3DFVF_XYZ);
4876 ok(hr == D3D_OK, "Test %u: got unexpected hr %#lx.\n", test, hr);
4877 hr = IDirect3DDevice9Ex_SetStreamSource(device, 0, buffer, 0, sizeof(*ptr));
4878 ok(hr == D3D_OK, "Test %u: got unexpected hr %#lx.\n", test, hr);
4879 hr = IDirect3DDevice9Ex_BeginScene(device);
4880 ok(hr == D3D_OK, "Test %u: got unexpected hr %#lx.\n", test, hr);
4881 hr = IDirect3DDevice9Ex_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
4882 ok(hr == D3D_OK, "Test %u: got unexpected hr %#lx.\n", test, hr);
4883 hr = IDirect3DDevice9Ex_EndScene(device);
4884 ok(hr == D3D_OK, "Test %u: got unexpected hr %#lx.\n", test, hr);
4886 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, vertex_count * sizeof(*ptr2), (void **)&ptr2, D3DLOCK_DISCARD);
4887 ok(hr == D3D_OK, "Test %u: got unexpected hr %#lx.\n", test, hr);
4888 ok(ptr2 == ptr, "Test %u: got unexpected ptr2 %p, expected %p.\n", test, ptr2, ptr);
4889 for (i = 0; i < vertex_count; ++i)
4891 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
4893 ok(FALSE, "Test %u: got unexpected vertex %u {%.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e}.\n",
4894 test, i, ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
4895 break;
4898 hr = IDirect3DVertexBuffer9_Unlock(buffer);
4899 ok(hr == D3D_OK, "Test %u: got unexpected hr %#lx.\n", test, hr);
4901 IDirect3DVertexBuffer9_Release(buffer);
4902 refcount = IDirect3DDevice9Ex_Release(device);
4903 ok(!refcount, "Test %u: device has %u references left.\n", test, refcount);
4905 DestroyWindow(window);
4908 static void test_desktop_window(void)
4910 IDirect3DVertexShader9 *shader;
4911 IDirect3DDevice9Ex *device;
4912 unsigned int color;
4913 ULONG refcount;
4914 HWND window;
4915 HRESULT hr;
4917 static const DWORD simple_vs[] =
4919 0xfffe0101, /* vs_1_1 */
4920 0x0000001f, 0x80000000, 0x900f0000, /* dcl_position0 v0 */
4921 0x00000009, 0xc0010000, 0x90e40000, 0xa0e40000, /* dp4 oPos.x, v0, c0 */
4922 0x00000009, 0xc0020000, 0x90e40000, 0xa0e40001, /* dp4 oPos.y, v0, c1 */
4923 0x00000009, 0xc0040000, 0x90e40000, 0xa0e40002, /* dp4 oPos.z, v0, c2 */
4924 0x00000009, 0xc0080000, 0x90e40000, 0xa0e40003, /* dp4 oPos.w, v0, c3 */
4925 0x0000ffff, /* end */
4928 window = create_window();
4929 if (!(device = create_device(window, NULL)))
4931 skip("Failed to create a D3D device, skipping tests.\n");
4932 DestroyWindow(window);
4933 return;
4935 IDirect3DDevice9Ex_Release(device);
4936 DestroyWindow(window);
4938 device = create_device(GetDesktopWindow(), NULL);
4939 ok(!!device, "Failed to create a D3D device.\n");
4941 hr = IDirect3DDevice9Ex_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 1.0f, 0);
4942 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
4943 color = get_pixel_color(device, 1, 1);
4944 ok(color == 0x00ff0000, "Got unexpected color 0x%08x.\n", color);
4946 hr = IDirect3DDevice9Ex_Present(device, NULL, NULL, NULL, NULL);
4947 ok(SUCCEEDED(hr), "Failed to present, hr %#lx.\n", hr);
4949 refcount = IDirect3DDevice9Ex_Release(device);
4950 ok(!refcount, "Device has %lu references left.\n", refcount);
4952 /* test device with NULL HWND */
4953 device = create_device(NULL, NULL);
4954 ok(!!device, "Failed to create a D3D device\n");
4956 hr = IDirect3DDevice9Ex_CreateVertexShader(device, simple_vs, &shader);
4957 ok(SUCCEEDED(hr), "Failed to create vertex shader, hr %#lx.\n", hr);
4958 IDirect3DVertexShader9_Release(shader);
4960 IDirect3DDevice9Ex_Release(device);
4963 START_TEST(d3d9ex)
4965 DEVMODEW current_mode;
4966 WNDCLASSA wc = {0};
4968 d3d9_handle = LoadLibraryA("d3d9.dll");
4969 if (!d3d9_handle)
4971 skip("Could not load d3d9.dll\n");
4972 return;
4975 pDirect3DCreate9Ex = (void *)GetProcAddress(d3d9_handle, "Direct3DCreate9Ex");
4976 if (!pDirect3DCreate9Ex) {
4977 win_skip("Failed to get address of Direct3DCreate9Ex\n");
4978 return;
4981 memset(&current_mode, 0, sizeof(current_mode));
4982 current_mode.dmSize = sizeof(current_mode);
4983 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
4984 registry_mode.dmSize = sizeof(registry_mode);
4985 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
4986 if (current_mode.dmPelsWidth != registry_mode.dmPelsWidth
4987 || current_mode.dmPelsHeight != registry_mode.dmPelsHeight)
4989 skip("Current mode does not match registry mode, skipping test.\n");
4990 return;
4993 wc.lpfnWndProc = DefWindowProcA;
4994 wc.lpszClassName = "d3d9_test_wc";
4995 RegisterClassA(&wc);
4997 test_qi_base_to_ex();
4998 test_qi_ex_to_base();
4999 test_swapchain_get_displaymode_ex();
5000 test_get_adapter_luid();
5001 test_get_adapter_displaymode_ex();
5002 test_create_depth_stencil_surface_ex();
5003 test_user_memory();
5004 test_reset();
5005 test_reset_ex();
5006 test_reset_resources();
5007 test_vidmem_accounting();
5008 test_user_memory_getdc();
5009 test_lost_device();
5010 test_unsupported_shaders();
5011 test_wndproc();
5012 test_wndproc_windowed();
5013 test_window_style();
5014 test_swapchain_parameters();
5015 test_backbuffer_resize();
5016 test_format_unknown();
5017 test_device_caps();
5018 test_frame_latency();
5019 test_resource_access();
5020 test_sysmem_draw();
5021 test_pinned_buffers();
5022 test_desktop_window();
5024 UnregisterClassA("d3d9_test_wc", GetModuleHandleA(NULL));